SpringSecurity 动态加载用户角色权限数据

- UserDetails接口表达你是谁?你有什么角色权限?
- UserDeatilsService接口表达式时如何动态加载UserDetails数据
- 集成持久层框架(MyBatis Plus)
- 如何加载用户角色权限数据?结合RBAC权限管理模型理解SQL
- SpringSecurity配置动态加载的实现
- 实现效果测试
一、实现UserDetails接口
public class MyUserDetails implements UserDetails {
String password;
String username;
boolean accountNonExpired;
boolean accountNonLocked;
boolean credentialsNonExpired;
boolean enabled;
Collection<? extends GrantedAuthority> authorities;
public void setPassword(String password) {
this.password = password;
}
public void setUsername(String username) {
this.username = username;
}
public void setAccountNonExpired(boolean accountNonExpired) {
this.accountNonExpired = accountNonExpired;
}
public void setAccountNonLocked(boolean accountNonLocked) {
this.accountNonLocked = accountNonLocked;
}
public void setCredentialsNonExpired(boolean credentialsNonExpired) {
this.credentialsNonExpired = credentialsNonExpired;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public void setAuthorities(Collection<? extends GrantedAuthority> authorities) {
this.authorities = authorities;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return authorities;
}
@Override
public String getPassword() {
return password;
}
@Override
public String getUsername() {
return username;
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return enabled;
}
}
二、UserDetailsService接口
@Component
public class MyUserDetailsService implements UserDetailsService {
@Resource
MyUserDetailsServiceMapper myUserDetailsServiceMapper;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
MyUserDetails myUserDetails = myUserDetailsServiceMapper.findByUserName(username);
if (myUserDetails == null){
throw new UsernameNotFoundException("用户名不存在");
}
List<String> roleCodes = myUserDetailsServiceMapper.findRoleByUserName(username);
List<String> authorities = myUserDetailsServiceMapper.findAuthorityByRoleCodes(roleCodes);
roleCodes = roleCodes.stream()
.map(rc -> "ROLE_" + rc)
.collect(Collectors.toList());
authorities.addAll(roleCodes);
myUserDetails.setAuthorities(AuthorityUtils.commaSeparatedStringToAuthorityList(
String.join(",", authorities)
));
return myUserDetails;
}
}
三、集成持久层框架(MyBatis Plus)
public interface MyUserDetailsServiceMapper {
@Select("SELECT username, password, enabled " +
"FROM sys_user u " +
"WHERE u.username = #{username}")
MyUserDetails findByUserName(@Param("username") String username);
@Select("SELECT role_code " +
"FROM sys_role r " +
"LEFT JOIN sys_user_role ur ON r.id = ur.role_id " +
"LEFT JOIN sys_user u ON u.id = ur.user_id " +
"WHERE u.username = #{userId}")
List<String> findRoleByUserName(@Param("userId") String userId);
@Select({
"<script>",
"SELECT url ",
"FROM sys_menu m ",
"LEFT JOIN sys_role_menu rm ON m.id = rm.menu_id ",
"LEFT JOIN sys_role r ON r.id = rm.role_id ",
"WHERE r.role_code IN ",
"<foreach collection='roleCodes' item='roleCode' open='(' separator=',' close=')'>",
"#{roleCode}",
"</foreach>",
"</script>"
})
List<String> findAuthorityByRoleCodes(@Param("roleCodes") List<String> roleCodes);
}
四、数据库表
sys_user

sys_role

sys_menu

sys_user_role

sys_role_menu

五、测试
admin用户可以访问所有路径
user用户只能访问业务一和业务二