网站首页 > 资源文章 正文
上一篇文章中使用SpringSecurity实现基于MySQL的数据认证,我介绍了如何在SpringSecurity中使用数据库中的用户数据进行认证,这篇文章主要讲下怎么实现RBAC的权限认证,这就可以基本满足大多数情况下对权限认证的需求。
上篇文章其实已经将设置的用户权限取到了,这一步我们只需要自定义权限认证的逻辑,并交给SpringSecurity使用。
自定义权限认证的逻辑
@Component("authUserAccessConfig")
public class AuthUserAccessConfig {
private static final Logger logger = LoggerFactory.getLogger(AuthUserAccessConfig.class);
/**
* 判断当前访问的uri是否有权限
* @param request
* @param authentication
* @return
*/
public boolean hasPermission(HttpServletRequest request, Authentication authentication) {
Object principal = authentication.getPrincipal();
String uri = request.getRequestURI();
// ajax请求都放行
// if (isAjax(request)) {
// return true;
// }
// 认证阶段放行
if (isAuth(uri)) {
return true;
}
// 认证成功的情况 - 判断权限相关
if (principal instanceof UserDetailsPojo) {
UserDetailsPojo authUser = (UserDetailsPojo) principal;
// 判断权限
String chkAuthUri = UriUtil.getChkAuthUri(uri);
// 获取登录用户的权限
Set<String> authMenuSet = authUser.getAuthMenuSet();
return authMenuSet.contains(chkAuthUri);
}
return false;
}
/**
* 判断请求是否是ajax
* @param request
* @return
*/
public boolean isAjax(HttpServletRequest request) {
return "XMLHttpRequest".equals(request.getHeader("X-Requested-With"));
}
public boolean isAuth(String uri) {
if (uri.equals("/login")) {
return true;
}
if (uri.equals("/error")) {
return true;
}
return false;
}
}
这里面会用到上篇文章定义的UserDetails的额外属性 Set<String> authMenuSet
// getter、setter就省略了
public class UserDetailsPojo implements UserDetails {
private static final long serialVersionUID = -987887L;
private String password;
private String username;
private Collection<? extends GrantedAuthority> authorities;
// 下面两个属性都是自定义添加的了 Set<String>是用来实现RBAC的权限认证
private Set<String> authMenuSet = new HashSet<>();
private long id;
}
通过authMenuSet保存的uri权限,进行判断当前用户是否有访问权限
配置自定义权限认证逻辑
@EnableWebSecurity
public class AuthConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.headers().frameOptions().disable();
http.authorizeRequests()
// 二者保其一 !!!!
.anyRequest().access("@authUserAccessConfig.hasPermission(request, authentication)")
// 所有请求都要是认证完成的
// .anyRequest().authenticated()
;
}
}
配置完成后所有的未被过滤的请求都会执行上面自定义的权限认证逻辑。
另外,我们也可以自定义当权限认证失败时该做什么动作。
自定义权限认证失败的动作
要实现自定义权限认证失败的逻辑,只需要实现AccessDeniedHandler接口并在SpringSecurity的配置类完成配置就可以了。
一般访问的请求会分为两种
- 异步请求Ajax
- 页面请求
所以当异步请求权限认证失败时,应该返回统一的接口响应格式的数据;当普通页面请求权限认证失败时,应该返回页面的403请求或其他4xx
1)创建实现AccessDeniedHandler接口的类
@Component
public class AuthAccessDeniedHandler implements AccessDeniedHandler {
private final Logger logger = LoggerFactory.getLogger(AuthAccessDeniedHandler.class);
@Override
public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AccessDeniedException e) throws IOException, ServletException {
logger.info("认证失败逻辑...");
if (!httpServletResponse.isCommitted()) {
if (isAjax(httpServletRequest)) {
logger.error(e.getMessage());
// 响应json格式数据
NetUtil.returnForbidden(httpServletResponse);
} else {
logger.error("跳转403页面了");
// 跳转到无权限页面
httpServletRequest.setAttribute(WebAttributes.ACCESS_DENIED_403, e);
httpServletResponse.setStatus(HttpStatus.FORBIDDEN.value());
RequestDispatcher dispatcher = httpServletRequest.getRequestDispatcher("/admin/auth/403");
dispatcher.forward(httpServletRequest, httpServletResponse);
}
}
}
/**
* 判断是否是ajax
* @param request
* @return
*/
public boolean isAjax(HttpServletRequest request) {
return "XMLHttpRequest".equals(request.getHeader("X-Requested-With"));
}
}
2)配置自定义权限认证失败逻辑
@EnableWebSecurity
public class AuthConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
// 自定义验证权限失败处理器
http.exceptionHandling().accessDeniedHandler(new AuthAccessDeniedHandler());
}
}
完整SpringSecurity配置代码
@EnableWebSecurity
public class AuthConfig extends WebSecurityConfigurerAdapter {
@Autowired
UserDetailsConfig userDetailsConfig;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsConfig).passwordEncoder(new BCryptPasswordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.headers().frameOptions().disable();
http.authorizeRequests()
// 设置自定义的登录页可访问权限
.antMatchers("/sys/custom/login", "/login").permitAll()
.antMatchers("/druid/**").permitAll()
// 二者保其一 !!!!
.anyRequest().access("@authUserAccessConfig.hasPermission(request, authentication)")
// 所有请求都要是认证完成的
// .anyRequest().authenticated()
;
// 自定义验证权限失败处理器
http.exceptionHandling().accessDeniedHandler(new AuthAccessDeniedHandler());
// 自定义登录页
http.formLogin().loginPage("/sys/custom/login")
.usernameParameter("username")
.passwordParameter("password")
.failureUrl("/sys/custom/login?error=true")
.loginProcessingUrl("/login");
http.csrf().disable();
http.logout();
}
@Override
public void configure(WebSecurity web) throws Exception {
// 过滤所有前端资源
web.ignoring().antMatchers("/upfile/**", "/css/**", "/lib/**", "/js/**", "/font/**", "/images/**", "/favicon.ico");
}
}
小白升级打怪的过程中,最难的还是发现趁手的武器装备。
我是小白,我为小白代言。
猜你喜欢
- 2024-12-16 允许root用户SSH登录(SHH远程登陆: Access Denied )
- 2024-12-16 nginx: [emerg] bind() to 0.0.0.0:6666 failed (13: Permission denied)
- 2024-12-16 发邮件的时候,是不是经常碰到550错误呢?
- 2024-12-16 git push 报错:remote: Permission to xxxx.git denied to XX
- 2024-12-16 robocopy的详细参数 robocopy 参数
- 2024-12-16 树莓派ssh出现Permission denied, please try again
- 2024-12-16 爱而不得的伤感文案/A sentimental copy of love denied
- 2024-12-16 有玩家修改本地配置文件,实现作弊功能,和平精英:最高封号十年
- 2024-12-16 edge浏览器兼容性问题,错误代码:STATUS_
- 2024-12-16 实战Spring Boot security+JWT 前后端分离架构认证登录
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- 电脑显示器花屏 (79)
- 403 forbidden (65)
- linux怎么查看系统版本 (54)
- 补码运算 (63)
- 缓存服务器 (61)
- 定时重启 (59)
- plsql developer (73)
- 对话框打开时命令无法执行 (61)
- excel数据透视表 (72)
- oracle认证 (56)
- 网页不能复制 (84)
- photoshop外挂滤镜 (58)
- 网页无法复制粘贴 (55)
- vmware workstation 7 1 3 (78)
- jdk 64位下载 (65)
- phpstudy 2013 (66)
- 卡通形象生成 (55)
- psd模板免费下载 (67)
- shift (58)
- localhost打不开 (58)
- 检测代理服务器设置 (55)
- frequency (66)
- indesign教程 (55)
- 运行命令大全 (61)
- ping exe (64)
本文暂时没有评论,来添加一个吧(●'◡'●)