注意点:
1. 需要有一定SpringSecurity基础,因为只讲重点!
2. SpringSecurity版本6.1.0
认证
核心点
1. 这里只做账号密码认证, 不用关心权限!
2. 这里核心就是 把用户输入的账号密码和数据库中的账号密码传给SpringSecurity
SpringSecurity会帮我们做比较
核心代码
步骤一: 传入用户输入的账号和密码给SpringSecurity
public Result login(@RequestBody @Valid LoginDTO dto) {
String password = dto.getPassword();
Authentication usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(dto.getUsername(), password);
Authentication authentication = authenticationManager.authenticate(usernamePasswordAuthenticationToken);
LoginUserBO user = (LoginUserBO) authentication.getPrincipal();
String token = JwtUtil.createJWT(user.getSysUser());
return Result.success(token);
}
步骤二: 查询数据库的账号和密码传给SpringSecurity
//实现UserDetailService
public class UserDetailsServiceImpl implements UserDetailsService {
@Resource
private SysUserService sysUserService;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
SysUser sysUser = sysUserService.queryByUserName(username);
Optional.ofNullable(sysUser).orElseThrow(() -> new UsernameNotFoundException("user does not exist!"));
return new LoginUserBO(sysUser);
}
}
//LoginUserBO 实现 UserDetails
public class LoginUserBO implements Serializable, UserDetails {
private SysUser sysUser;
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return Collections.emptyList();
}
@Override
public String getPassword() {
return sysUser.getPassword();
}
@Override
public String getUsername() {
return sysUser.getUsername();
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
}
源码-校验密码
上面就是认证的核心流程了 跟着我的截图点进去 最后一张就是源码-比较密码的代码了
授权
核心点
1. 你定义的SpringSecurityConfig一定要加 @EnableMethodSecurity!
否者 @PreAuthorize("hasAuthority('permission_flag')") 不会生效
2. 在每次请求接口的时候把权限丢给SpringSecurity, 可以把权限丢缓存或者用其他方式
核心代码
...
@Log4j2
@Component
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
...
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
...
...
...
//省略了JWT的校验代码
//下面是把权限丢给SpringSecurity
Long roleId = Long.valueOf(claims.get("roleId").toString());
List<SimpleGrantedAuthority> rolePermissionList = getRolePermission(roleId);
//封装Authentication
Authentication usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(claims, null, rolePermissionList);
//存入SecurityContextHolder
SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
//放行,让后面的过滤器执行
filterChain.doFilter(request, response);
}
}
源码-校验权限
上面就是授权的核心流程了 跟着我的截图点进去 最后一张就是源码-鉴权的代码了
搞定!下班回家了