String getUsername();
boolean isAccountNonExpired();
boolean isAccountNonLocked();
boolean isCredentialsNonExpired();
boolean isEnabled();
}
UserDetails的主要实现类是:org.springframework.security.core.userdetails.User
[](()案例整合
==================================================================
整合SpringBoot+SpringSecurity+MyBatis-Plus完成登录和授权
数据库采用RBAC(基于角色的权限控制)结构
用户和角色,角色和权限都是多对多关系
主要有5张表
-
user 用户表
-
role 角色表
-
permission 权限表
-
user_role 用户角色表
-
role_permission 角色权限表
用户密码采用BCryptPasswordEncoder进行了加密
项目依赖
org.springframework.boot
spring-boot-starter-security
org.springframework.boot
spring-boot-starter-thymeleaf
org.springframework.boot
spring-boot-starter-web
org.projectlombok
lombok
true
com.baomidou
mybatis-plus-boot-starter
3.4.1
mysql
mysql-connector-java
runtime
application.properties
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/blb_erp2?serverTimezone=UTC&useUnicode=true&useSSL=false&characterEncoding=utf8
spring.datasource.username=root
spring.datasource.password=123456
mybatis-plus.type-aliases-package=com.xray.spring_security_db_demo.entity
mybatis-plus.mapper-locations=classpath:mapper/*.xml
实体类User、Role、Permission略
UserMapper接口
如果要进行用户授权,就需要通过用户名查询角色和权限
public interface UserMapper extends BaseMapper {
/**
- 根据用户名查询所有角色
*/
List selectRolesByUsername(String username);
/**
- 根据用户名查询所有权限
*/
List selectPermissionsByUsername(String username);
}
UserMapper.xml映射文件
<?xml version="1.0" encoding="UTF-8"?>select r.* from user u join user_role ur on u.id = ur.user_id
join role r on r.id = ur.role_id
where u.username = #{username}
select p.* from user u join user_role ur on u.id = ur.user_id
join role r on r.id = ur.role_id
join role_permission rp on r.id = rp.role_id
join permission p on p.id = rp.fun_id
where u.username = #{username}
实现UserDetail 《一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》无偿开源 威信搜索公众号【编程进阶路】 sService接口
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
@Autowired
private UserMapper userMapper;
@Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
//根据用户名查询用户
User user = userMapper.selectOne(new QueryWrapper().lambda().eq(User::getUsername, s));
if(user == null){
throw new UsernameNotFoundException(“Username is not exists”);
}
StringBuilder authorities = new StringBuilder();
//查询角色
List roles = userMapper.selectRolesByUsername(s);
//查询权限
List permissions = userMapper.selectPermissionsByUsername(s);
//拼接角色到字符串中,角色需要以ROLE_开头
roles.forEach(role -> authorities.append(“ROLE_”+role.getName()+“,”));
//拼接权限名称
permissions.forEach(permission -> authorities.append(permission.getName()+“,”));
authorities.deleteCharAt(authorities.length() - 1);
//将用户名、密码以及所有角色和权限包装到userdetails.User对象中,返回
org.springframework.security.core.userdetails.User user1 = new org.springframework.security.core.userdetails.User(user.getUsername(),
user.getPassword(), AuthorityUtils.commaSeparatedStringToAuthorityList(authorities.toString()));
return user1;
}
}
在配置类中,将内存中的用户改为数据库的自定义验证
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsService userDetailsService;
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//配置数据库自定义验证
auth.userDetailsService(userDetailsService);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
//配置放行
.antMatchers(“/login”).permitAll()
//访问url需要某个权限
.antMatchers(“/user/**”).hasAuthority(“销售管理”)
//需要角色
.antMatchers(“/admin/**”).hasRole(“管理员”)
//除放行外,其他都要验证
.anyRequest().authenticated()
.and()
//配置登录页面和登录后跳转的页面
.formLogin().loginPage(“/login”).defaultSuccessUrl(“/main”)
.and()
//配置注销页面和注销后的页面