How to use SpringBoot+SpringSecurity to realize authorization and authentication based on real data
This article mainly explains "how to use SpringBoot+SpringSecurity to achieve authorization authentication based on real data." Interested friends may wish to take a look. The method introduced in this paper is simple, fast and practical. Let's take you to learn "How to use SpringBoot+SpringSecurity to achieve authorization authentication based on real data"!
(i) Overview
Spring Security is a powerful and highly customizable authentication and access control framework that does two things: authentication and authorization. I wrote a blog about Spring Security earlier, but it was only a mock data-based example. This issue is about authentication authorization based on real data.
(II) Early project construction
To better demonstrate Spring Security, let's build a simple web project first. Introducing thymeleaf dependency
org.springframework.boot spring-boot-starter-thymeleaf org.thymeleaf thymeleaf-spring5 org.thymeleaf.extras thymeleaf-extras-java8time
Create a new landing page, a home page, and then several different levels of display pages: login.html
landing page landing page landing
index.html
home home landing level1 level-1-1 level-1-2 level2 level-2-1 level-2-2 level3 level-3-1 level-3-2
There are also several different levels of pages
Write your own number in the body.
Titlelevel-1-1
Finally, write a controller to receive the request:
@Controllerpublic 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; }}
The final effect is as follows:
Finally, different level pages with different levels are jumped according to different permissions.
后台基于Mybatis和Mysql数据库实现,因此我们除了引入SpringSecurity的依赖之外,还需要引入Mybatis相关依赖:
org.springframework.boot spring-boot-starter-security org.springframework.boot spring-boot-starter-jdbc mysql mysql-connector-java runtime org.mybatis.spring.boot mybatis-spring-boot-starter 2.1.3
在配置文件中添加数据源相关信息,以及Mybatis的配置:
spring.datasource.url=jdbc:mysql://localhost:3306/security?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8spring.datasource.username=rootspring.datasource.password=123456spring.datasource.driver-class-name=com.mysql.cj.jdbc.Drivermybatis.mapper-locations=classpath:mapper/*.xml(三)认证与授权的实现3.1 表结构设计
认证和授权在表设计上应该分在两个表内,一个表存储用户信息包括密码等,另一个表存储授权信息,还需要一个表建立用户和授权之间的关联,给出最终的表结构:
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文件,你可以不看代码,主要实现一个通过用户名查找用户以及相关权限的操作:
@Datapublic class Roles { private Integer id; private String roleName;}@Datapublic class SysUser { private Integer id; private String userName; private String password; private List roles;}
Mapper接口:
public interface UserMapper { public SysUser getUserByUserName(@Param("userName") String userName);}
xml实现:
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} 3.2 认证过程
SpringSecurity的认证过程是这样的,首先通过用户名或者其他唯一的ID在数据库里找到这个用户,用户的密码以非对称加密的方式存储。取到用户后将前台传入的密码加密后和数据库中已经加密好的字段进行对比,从而通过认证。
上面这个过程中的第一步通过用户名找到用户的操作需要通过Service服务来实现,并且这个Service服务需要继承SpringSecurity中的UserDetailsService接口。这个接口返回一个SpringSecurity的User对象。
@Servicepublic 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 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("用户未找到"); }}3.3 Security拦截配置
上面的步骤都完成后就开始配置Security了,写一个配置方法SecurityConfig,代码层面很简单,认证传入userService对象,会自动把数据库中取出的密码和前端传过来的密码进行对照。同时在userService中还传入了roles集合,在授权处给不同的页面附上不同的权限即可。
@EnableWebSecuritypublic 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()); }}3.4 其他注意点
我在认证的时候使用的密码加密方式是BCryptPasswordEncoder,因此存入数据库中的密码也需要被加密,常用的方式就是在注册时通过同样的方式对密码进行加密存入数据库中:
String password="xxx";BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();String encode=bCryptPasswordEncoder.encode(password);到此,相信大家对"如何用SpringBoot+SpringSecurity实现基于真实数据的授权认证"有了更深的了解,不妨来实际操作一番吧!这里是网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!