AccessDeniedHandler 接口负责处理用户在没有足够权限访问某资源时的行为。当用户尝试访问他们没有权限的资源时,这个处理器被触发。
官方是给了几个默认的处理器,当然,我们也可以自己自定义处理器,那么先简单介绍一下官方的处理器,然后再自己写一个自定义处理器。
当用户访问一个无权限访问的接口时,触发的处理器。
AccessDeniedHandlerImpl 中可以设置一个重定向的路径,其中 AccessDeniedHandlerImpl 中还会返回一个 403 的状态码。
@Override
protected void configure(HttpSecurity http) throws Exception {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowCredentials(true);
http
// 退出登录
.exceptionHandling()
// 无权限访问资源处理器
.accessDeniedHandler(accessDeniedHandler());
}
@Bean
public AccessDeniedHandler accessDeniedHandler() {
AccessDeniedHandlerImpl accessDeniedHandler = new AccessDeniedHandlerImpl();
// 设置重定向的错误页面
accessDeniedHandler.setErrorPage("/access-denied");
return accessDeniedHandler;
}
InvalidSessionAccessDeniedHandler 是当用户的会话时间到期后,执行的处理器。
@Override
protected void configure(HttpSecurity http) throws Exception {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowCredentials(true);
http
// 退出登录
.exceptionHandling()
// 无权限访问资源处理器
.accessDeniedHandler(accessDeniedHandler());
}
@Bean
public AccessDeniedHandler accessDeniedHandler() {
// 会话时间到期后执行的处理器
return new InvalidSessionAccessDeniedHandler(invalidSessionStrategy());
}
@Bean
public InvalidSessionStrategy invalidSessionStrategy() {
// 使用 SimpleRedirectInvalidSessionStrategy 或自定义实现
return new SimpleRedirectInvalidSessionStrategy("/session-invalid");
}
RequestMatcherDelegatingAccessDeniedHandler 是用来灵活处理不同类型请求的访问拒绝逻辑,比如URL模式、HTTP方法等。
@Override
protected void configure(HttpSecurity http) throws Exception {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowCredentials(true);
http
// 退出登录
.exceptionHandling()
// 无权限访问资源处理器
.accessDeniedHandler(accessDeniedHandler());
}
@Bean
public AccessDeniedHandler accessDeniedHandler() {
LinkedHashMap<RequestMatcher, AccessDeniedHandler> handlerMap = new LinkedHashMap<>();
AccessDeniedHandlerImpl userAccessDeniedHandler = new AccessDeniedHandlerImpl();
// 设置重定向的错误页面
userAccessDeniedHandler.setErrorPage("/user-access-denied");
handlerMap.put(new AntPathRequestMatcher("/user/**"), userAccessDeniedHandler);
RequestMatcherDelegatingAccessDeniedHandler accessDeniedHandler = new RequestMatcherDelegatingAccessDeniedHandler(
handlerMap,
// 默认的执行处理器
new AccessDeniedHandlerImpl());
return accessDeniedHandler;
}
DelegatingAccessDeniedHandler 是根据你出现权限访问错误后,根据出现的错误进行设置规则。
@Override
protected void configure(HttpSecurity http) throws Exception {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowCredentials(true);
http
// 退出登录
.exceptionHandling()
// 无权限访问资源处理器
.accessDeniedHandler(accessDeniedHandler());
}
@Bean
public AccessDeniedHandler accessDeniedHandler() {
LinkedHashMap<Class<? extends AccessDeniedException>, AccessDeniedHandler> handlers = new LinkedHashMap<>();
// 出现 AuthorizationServiceException 时执行
handlers.put(AuthorizationServiceException.class, new AccessDeniedHandlerImpl());
// 出现 MissingCsrfTokenException 时执行
handlers.put(MissingCsrfTokenException.class, new AccessDeniedHandlerImpl());
return new DelegatingAccessDeniedHandler(
handlers,
// 默认执行的处理方式
new AccessDeniedHandlerImpl());
}
package com.security.handler.access;
import com.alibaba.fastjson2.JSON;
import com.security.controller.vo.ResponseResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.stereotype.Component;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Component
@Slf4j
public class CustomAccessDeniedHandlerImpl implements AccessDeniedHandler {
@Override
public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
log.info("CustomAccessDeniedHandlerImpl 授权失败处理 ...");
/**
* 设置响应状态值
*/
response.setStatus(403);
response.setContentType("application/json");
response.setCharacterEncoding("utf-8");
String json = JSON.toJSONString(
ResponseResult.builder()
.code(403)
.message("认证失败!")
.build());
// JSON信息
response.getWriter().println(json);
}
}
package com.security.config;
import com.security.handler.access.CustomAccessDeniedHandlerImpl;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.web.cors.CorsConfiguration;
@Configuration
@EnableWebSecurity
// 开启限制访问资源所需权限
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfigurationTest extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowCredentials(true);
http
// 退出登录
.exceptionHandling()
// 无权限访问资源处理器
.accessDeniedHandler(accessDeniedHandler());
}
@Bean
public AccessDeniedHandler accessDeniedHandler() {
return new CustomAccessDeniedHandlerImpl();
}
}