您好,登錄后才能下訂單哦!
本篇內容主要講解“如何用SpringBoot+SpringSecurity實現基于真實數據的授權認證”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“如何用SpringBoot+SpringSecurity實現基于真實數據的授權認證”吧!
Spring Security是一個功能強大且高度可定制的身份驗證和訪問控制框架,Spring Security主要做兩個事情,認證、授權。我之前寫過一篇關于SpringSecurity的博客,但是當時只是介紹了基于mock數據的案例,本期就來介紹一下基于真實數據的認證授權實現。
為了更好的展示SpringSecurity,我們先搭建一個簡單的web項目出來。引入thymeleaf依賴
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency> <groupId>org.thymeleaf</groupId> <artifactId>thymeleaf-spring5</artifactId> </dependency> <dependency> <groupId>org.thymeleaf.extras</groupId> <artifactId>thymeleaf-extras-java8time</artifactId> </dependency>
新建一個登陸頁,一個首頁,然后幾個不同等級的展示頁面: login.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>登陸頁</title> </head> <body> <div> <form> <h3>登陸頁</h3> <input type="text" id="username" placeholder="username"> <input type="password" id="password" placeholder="password"> <button type="button">登陸</button> </form> </div> </body> </html>
index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>首頁</title> </head> <body> <div> <h3>首頁</h3> <a href="/login">登陸</a> <div > <div > <h4>level1</h4> <a href="/level1/1">level-1-1</a> <hr> <a href="/level1/2">level-1-2</a> </div> <div > <h4>level2</h4> <a href="/level2/1">level-2-1</a> <hr> <a href="/level2/2">level-2-2</a> </div> <div > <h4>level3</h4> <a href="/level3/1">level-3-1</a> <hr> <a href="/level3/2">level-3-2</a> </div> </div> </div> </body> </html>
另外還有幾個不同等級的頁面
分別在body中寫上自己對應的編號。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> level-1-1 </body> </html>
最后編寫一個controller來接收請求:
@Controller public class RouteController { @RequestMapping({"/","/index"}) public String index(){ return "index"; } @RequestMapping("/login") public String toLogin(){ return "login"; } @RequestMapping("/level1/{id}") public String level1(@PathVariable("id")String id){ return "level1/"+id; } @RequestMapping("/level2/{id}") public String level2(@PathVariable("id")String id){ return "level2/"+id; } @RequestMapping("/level3/{id}") public String level3(@PathVariable("id")String id){ return "level3/"+id; } }
最終的效果如下:
最終實現等級不同的level頁面根據不同權限進行跳轉。
后臺基于Mybatis和Mysql數據庫實現,因此我們除了引入SpringSecurity的依賴之外,還需要引入Mybatis相關依賴:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1.3</version> </dependency>
在配置文件中添加數據源相關信息,以及Mybatis的配置:
spring.datasource.url=jdbc:mysql://localhost:3306/security?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8 spring.datasource.username=root spring.datasource.password=123456 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver mybatis.mapper-locations=classpath:mapper/*.xml
認證和授權在表設計上應該分在兩個表內,一個表存儲用戶信息包括密碼等,另一個表存儲授權信息,還需要一個表建立用戶和授權之間的關聯,給出最終的表結構:
CREATE TABLE `roles` ( `id` int(4) NOT NULL, `rolename` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; CREATE TABLE `sysuser` ( `id` int(4) NOT NULL, `username` varchar(255) NOT NULL, `password` varchar(255) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; CREATE TABLE `user_role` ( `id` int(4) NOT NULL, `user_id` int(4) DEFAULT NULL, `role_id` int(4) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
接下來是針對這三張表的實體類,Mapper接口以及xml文件,你可以不看代碼,主要實現一個通過用戶名查找用戶以及相關權限的操作:
@Data public class Roles { private Integer id; private String roleName; } @Data public class SysUser { private Integer id; private String userName; private String password; private List<Roles> roles; }
Mapper接口:
public interface UserMapper { public SysUser getUserByUserName(@Param("userName") String userName); }
xml實現:
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.javayz.springsecurity.mapper.UserMapper"> <resultMap id="userMap" type="com.javayz.springsecurity.entity.SysUser"> <id property="id" column="ID"/> <result property="userName" column="username"/> <result property="password" column="password"/> <collection property="roles" ofType="com.javayz.springsecurity.entity.Roles"> <result column="name" property="roleName"/> </collection> </resultMap> <select id="getUserByUserName" parameterType="String" resultMap="userMap"> select sysuser.*,roles.rolename from sysuser LEFT JOIN user_role on sysuser.id= user_role.user_id LEFT JOIN roles on user_role.role_id=roles.id where username= #{userName} </select> </mapper>
SpringSecurity的認證過程是這樣的,首先通過用戶名或者其他唯一的ID在數據庫里找到這個用戶,用戶的密碼以非對稱加密的方式存儲。取到用戶后將前臺傳入的密碼加密后和數據庫中已經加密好的字段進行對比,從而通過認證。
上面這個過程中的第一步通過用戶名找到用戶的操作需要通過Service服務來實現,并且這個Service服務需要繼承SpringSecurity中的UserDetailsService接口。這個接口返回一個SpringSecurity的User對象。
@Service public class UserService implements UserDetailsService { @Resource private UserMapper userMapper; //根據用戶名找到對應的用戶信息 @Override public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException { SysUser sysUser = userMapper.getUserByUserName(s); if (sysUser!=null){ List<GrantedAuthority> roles=new ArrayList<>(); sysUser.getRoles().stream().forEach(x->{ roles.add(new SimpleGrantedAuthority(x.getRoleName())); }); return new User(sysUser.getUserName(),sysUser.getPassword(),roles); } throw new UsernameNotFoundException("用戶未找到"); } }
上面的步驟都完成后就開始配置Security了,寫一個配置方法SecurityConfig,代碼層面很簡單,認證傳入userService對象,會自動把數據庫中取出的密碼和前端傳過來的密碼進行對照。同時在userService中還傳入了roles集合,在授權處給不同的頁面附上不同的權限即可。
@EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private UserService userService; //授權 @Override protected void configure(HttpSecurity http) throws Exception { //首頁所有人都能訪問,level頁面只有有權限的人才能訪問 http.authorizeRequests() .antMatchers("/").permitAll() .antMatchers("/level1/**").hasRole("vip1") .antMatchers("/level2/**").hasRole("vip2") .antMatchers("/level3/**").hasRole("vip3"); //沒有權限默認跳到登陸頁,默認會重定向到/login http.formLogin(); } //認證 @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(userService).passwordEncoder(new BCryptPasswordEncoder()); } }
我在認證的時候使用的密碼加密方式是BCryptPasswordEncoder,因此存入數據庫中的密碼也需要被加密,常用的方式就是在注冊時通過同樣的方式對密碼進行加密存入數據庫中:
String password="xxx"; BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder(); String encode=bCryptPasswordEncoder.encode(password);
到此,相信大家對“如何用SpringBoot+SpringSecurity實現基于真實數據的授權認證”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。