场景
AccessDeniedHandler 访问一个需要需要认证的资源,身份认证成功(登录成功) 但是角色和权限不足时 该接口会被调用, 用来返回: 重定向到错误页面、返回特定的错误响应等
AuthenticationEntryPoint 接口是 Spring Security 中的一个接口,用于处理在用户尝试访问受保护资源时出现的身份验证异常。它定义了一个方法 commence,该方法在身份验证失败时被调用,允许应用程序自定义处理方式,例如重定向到登录页面、返回特定的错误响应等。
实现
/**
* @version V1.0
* @author: carsonlius
* @date: 2023/12/20 16:09
* @company
* @description AccessDeniedHandler 接口是 Spring Security 中用于处理访问被拒绝(Access Denied)的情况的接口。
* 当经过身份验证的用户尝试访问某个受保护的资源,但由于其角色或权限不足而被拒绝访问时,AccessDeniedHandler 接口的实现类将会被调用,
* 允许应用程序自定义如何处理这种访问拒绝的情况。
*/
@Component
@Slf4j
public class AccessDeniedHandlerImpl implements AccessDeniedHandler {
@Override
public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
log.warn("[commence][访问 URL({}) 时,用户权限不够]", request.getRequestURI());
// 返回 403
ServletUtils.writeJSON(response, CommonResult.error(GlobalErrorCodeConstants.FORBIDDEN));
}
}
/**
* @version V1.0
* @author: carsonlius
* @date: 2023/12/20 16:02
* @company
* @description AuthenticationEntryPoint 接口是 Spring Security 中的一个接口,
* 用于处理在用户尝试访问受保护资源时出现的身份验证异常。它定义了一个方法 commence,该方法在身份验证失败时被调用,
* 允许应用程序自定义处理方式,例如重定向到登录页面、返回特定的错误响应等。
*/
@Component
@Slf4j
public class AuthenticationEntryPointImpl implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
log.debug("[commence][访问 URL({}) 时,没有登录]", request.getRequestURI());
// 返回 401
ServletUtils.writeJSON(response, CommonResult.error(GlobalErrorCodeConstants.UNAUTHORIZED));
}
}
配置
/**
* 配置 URL 的安全配置
* <p>
* anyRequest | 匹配所有请求路径
* access | SpringEl表达式结果为true时可以访问
* anonymous | 匿名可以访问
* denyAll | 用户不能访问
* fullyAuthenticated | 用户完全认证可以访问(非remember-me下自动登录)
* hasAnyAuthority | 如果有参数,参数表示权限,则其中任何一个权限可以访问
* hasAnyRole | 如果有参数,参数表示角色,则其中任何一个角色可以访问
* hasAuthority | 如果有参数,参数表示权限,则其权限可以访问
* hasIpAddress | 如果有参数,参数表示IP地址,如果用户IP和参数匹配,则可以访问
* hasRole | 如果有参数,参数表示角色,则其角色可以访问
* permitAll | 用户可以任意访问
* rememberMe | 允许通过remember-me登录的用户访问
* authenticated | 用户登录后可访问
*/
@Bean
protected SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
// 登出
httpSecurity.cors().and() // 开启跨域
.csrf().disable() // csrf禁用,因为不使用session
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) // STATELESS(无状态): 表示应用程序是无状态的,不会创建会话。这意味着每个请求都是独立的,不依赖于之前的请求。适用于 RESTful 风格的应用。
.and().headers().frameOptions().disable()
.and().exceptionHandling().authenticationEntryPoint(authenticationEntryPoint) // 身份未认证时响应
.accessDeniedHandler(accessDeniedHandler); // 身份已经认证(登录),但是没有权限的情况的响应
return httpSecurity.build();
}