springsecurity:权限与异常处理
权限即不同用户可以使用不同功能
实现前置:
在上一次登录与校验中,我们将authentication存入到SecurityContextHolder中,后续我们需要从FilterSecurityInterceptor取出并进行验证
基于注解实现
开启相关配置(放在config里)
@EnableGlobalMethodSecurity(prePostEnabled = true) //适用于springboot2
@EnableMethodSecurity(prePostEnabled = true) //适用于springboot3
对应主要注解
@PreAuthorize("hasAuthority('ROLE_USER')")
需要修改的有两部分:
1.在我们自定义的UserDetailService中我们重写了loadUserByUsername:返回的LoginUser还包括了权限。在上一次,我们仅仅向里封装了一个User信息。除此以外,我们还需要一个权限信息,因此基于上次的User信息,我们对LoginUser增加了成员变量
@Data
@NoArgsConstructor
public class LoginUser implements UserDetails {
private User user;
private List<String> permissions;
// 这里不进行序列化/反序列化的原因是SimpleGrantedAuthority没实现序列化,而且我们已经有permissions,可直接通过get方法获取authorities
// 其实他可以不做成员变量,但是这样可以节省系统开销:不必多次创建authorities
@JSONField(serialize = false)
private List<SimpleGrantedAuthority> authorities;
public LoginUser(User user, List<String> permissions) {
this.user = user;
this.permissions = permissions;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
if(this.authorities!=null){
return this.authorities;
}
//如何选定的simplegrantedauthority:
// 通过查看grantedAuhority源码,通过ctrl+alt点击这个接口,我们发现他有三个实现类,我们从中选择其一
// 本方法即把string转换为相关的权限类型以便于preAuthorize(hasAuthority(''))使用
this.authorities=this.permissions.stream().map(SimpleGrantedAuthority::new).collect(Collectors.toList());
return this.authorities;
}
@Override
public String getPassword() {
return user.getPassword();
}
@Override
public String getUsername() {
return user.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;
}
}
2.在拦截器中写入对应的权限信息
SecurityContextHolder.getContext(). setAuthentication(new UsernamePasswordAuthenticationToken(loginUser,null,loginUser.getAuthorities()));
异常:异常一般有两种:登录不上去,权限不够
1.登录失败(身份入口)新增异常处理
@Component
public class AuthenticationEntryPointImpl implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
ResponseResult result = new ResponseResult(HttpStatus.UNAUTHORIZED.value(),"用户认证失败!请重新登录");
String json= JSON.toJSONString(result);
WebUtil.renderString(response, json);
}
}
2.权限不足新增异常处理
@Component
public class AccessDeniedHandlerImpl implements AccessDeniedHandler {
@Override
public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
ResponseResult result = new ResponseResult(HttpStatus.FORBIDDEN.value(),"用户权限不足!");
String json= JSON.toJSONString(result);
WebUtil.renderString(response, json);
}
}
WebUtil
public class WebUtil {
/**
* 将字符串渲染到客户端
*
* @param response 渲染对象
* @param string 待渲染的字符串
* @return null
*/
public static String renderString(HttpServletResponse response, String string) {
try {
response.setStatus(200);
response.setContentType("application/json");
response.setCharacterEncoding("utf-8");
response.getWriter().print(string);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
修改securityConfig
// 添加异常处理器
http
.exceptionHandling()
.authenticationEntryPoint(authenticationEntryPoint)
.accessDeniedHandler(accessDeniedHandler);
标签:
软件工程日报
, springsecurity
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」
2022-07-23 week4