Spring Security自定义用户认证
Posted 红尘年少
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring Security自定义用户认证相关的知识,希望对你有一定的参考价值。
具体代码地址 https://gitee.com/chuzhuyong/HandleSafer
自定义用户认证
通过自定义WebSecurityConfigurerAdapter类型的Bean组件,并重写configure(Authentication ManagerBuilder auth)方法,
可以实现自定义用户认证。
一、内存身份认证
In-Memory Authentication(内存身份认证)是最简单的身份认证方式,主要用于Security安全认证体验和测试
1.自定义WebSecurityConfigurerAdapter配置类
2.使用内存进行身份认证
//开启MVC Security安全支持 @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override public void configure(AuthenticationManagerBuilder auth) throws Exception { // 密码需要设置编码器 BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(); // 1、使用内存用户信息,作为测试使用 auth.inMemoryAuthentication().passwordEncoder(encoder) .withUser("czy").password(encoder.encode("123")).roles("common") .and() .withUser("tom").password(encoder.encode("456")).roles("vip"); } }
3.效果测试
输入正确的用户名和密码后进入首页
输入错误的用户名或者密码,将会显示错误
二、JDBC身份认证
1.数据准备
创建t_customer、t_authority和t_customer_authority三张表
# 选择使用数据库 USE springbootdata; # 创建表t_customer并插入相关数据 DROP TABLE IF EXISTS `t_customer`; CREATE TABLE `t_customer` ( `id` int(20) NOT NULL AUTO_INCREMENT, `username` varchar(200) DEFAULT NULL, `password` varchar(200) DEFAULT NULL, `valid` tinyint(1) NOT NULL DEFAULT \'1\', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8; INSERT INTO `t_customer` VALUES (\'1\', \'shitou\', \'$2a$10$5ooQI8dir8jv0/gCa1Six.GpzAdIPf6pMqdminZ/3ijYzivCyPlfK\', \'1\'); INSERT INTO `t_customer` VALUES (\'2\', \'李四\', \'$2a$10$5ooQI8dir8jv0/gCa1Six.GpzAdIPf6pMqdminZ/3ijYzivCyPlfK\', \'1\'); # 创建表t_authority并插入相关数据 DROP TABLE IF EXISTS `t_authority`; CREATE TABLE `t_authority` ( `id` int(20) NOT NULL AUTO_INCREMENT, `authority` varchar(20) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8; INSERT INTO `t_authority` VALUES (\'1\', \'ROLE_common\'); INSERT INTO `t_authority` VALUES (\'2\', \'ROLE_vip\'); # 创建表t_customer_authority并插入相关数据 DROP TABLE IF EXISTS `t_customer_authority`; CREATE TABLE `t_customer_authority` ( `id` int(20) NOT NULL AUTO_INCREMENT, `customer_id` int(20) DEFAULT NULL, `authority_id` int(20) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8; INSERT INTO `t_customer_authority` VALUES (\'1\', \'1\', \'1\'); INSERT INTO `t_customer_authority` VALUES (\'2\', \'2\', \'2\');
2.添加JDBC连接数据库的依赖启动器
3、数据库连接配置
#mysql相关配置
spring.datasource.url=jdbc:mysql://192.168.152.120:3306/springbootdata?serverTimeZone=UTC
spring.datasource.username=root
spring.datasource.password=1
#Redis相关配置
spring.redis.host=192.168.152.120
spring.redis.port=6379
spring.redis.password=1
4、使用JDBC进行身份认证
// 2.使用JDBC进行身份验证 String userSQL ="select username,password,valid from t_customer "+ "where username = ?"; String authoritySQL="select c.username,a.authority from t_customer c, "+"t_authority a,t_customer_authority ca where "+"ca.customer_id=c.id and ca.authority_id=a.id and c.username =?"; auth.jdbcAuthentication().passwordEncoder(encoder).dataSource(dataSource) .usersByUsernameQuery(userSQL).authoritiesByUsernameQuery(authoritySQL);
5、效果测试:同理
三、UserDetailsService身份认证
1、定义查询用户及角色信息的服务接口
package com.uos.safe.service; import com.uos.safe.domain.Authority; import com.uos.safe.domain.Customer; import com.uos.safe.repository.AuthorityRepository; import com.uos.safe.repository.CustomerRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; import java.util.List; //对用户数据结合Redis缓存进行业务处理 @Service public class CustomerService { @Autowired private CustomerRepository customerRepository; @Autowired private AuthorityRepository authorityRepository; @Autowired private RedisTemplate redisTemplate; //业务控制:使用唯一用户名查询用户信息 public Customer getCustomer(String username){ Customer customer = null; Object o = redisTemplate.opsForValue().get("customer_"+username); if (o != null){ customer = (Customer) o; }else { customer = customerRepository.findByUsername(username); if (customer != null){ redisTemplate.opsForValue().set("customer_"+username,customer); } } return customer; } // 业务控制:使用唯一用户名查询用户权限 public List<Authority> getCustomerAuthority(String username){ List<Authority> authorities = null; Object o = redisTemplate.opsForValue().get("authorities_"+username); if (o != null){ authorities = (List<Authority>) o; }else { authorities = authorityRepository.findAuthoritiesByUsername(username); if (authorities.size() > 0){ redisTemplate.opsForValue().set("authorities_"+username,authorities); } } return authorities; } }
2、定义UserDetailsService用于封装认证用户信息
package com.uos.safe.service; import com.uos.safe.domain.Authority; import com.uos.safe.domain.Customer; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.stereotype.Service; import java.util.List; import java.util.stream.Collectors; /*自定义一个 UserDetailsService实现类进行用户认证信息封装*/ @Service public class UserDetailsServiceImpl implements UserDetailsService { @Autowired CustomerService customerService; @Override public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException { // 通过业务方法获取用户权限信息 Customer customer = customerService.getCustomer(s); List<Authority> authorities = customerService.getCustomerAuthority(s); // 对用户权限进行封装 List<SimpleGrantedAuthority> list = authorities.stream() .map(authority -> new SimpleGrantedAuthority(authority.getAuthority())) .collect(Collectors.toList()); // 返回封装的UserDetails用户详情类 if (customer != null) { UserDetails userDetails = new User(customer.getUsername(),customer.getPassword(),list); return userDetails; } else { // 如果查询的用户不存在(用户名不存在),必须抛出异常 throw new UsernameNotFoundException("当前用户不存在!"); } } }
3、使用UserDetailsService进行身份认证
4、效果测试:同理
以上是关于Spring Security自定义用户认证的主要内容,如果未能解决你的问题,请参考以下文章
Spring Security 实现自定义登录和认证:使用自定义的用户进行认证