如何在@PreAuthorize认证失败时重定向至自定义页面?
没问题,这事儿我熟!要搞定@PreAuthorize认证失败后重定向到自定义页面,咱们可以通过Spring Security的AccessDeniedHandler来实现,这是最直接靠谱的方案。下面给你一步步拆解,照着做就行:
解决方案步骤
1. 自定义AccessDeniedHandler
首先写一个类实现Spring Security的AccessDeniedHandler接口,在handle方法里指定重定向的目标页面。这个类就是用来接管“权限不足”时的处理逻辑:
import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import org.springframework.security.access.AccessDeniedException; import org.springframework.security.web.access.AccessDeniedHandler; import java.io.IOException; public class CustomAccessDeniedHandler implements AccessDeniedHandler { @Override public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException { // 这里替换成你的自定义错误页面路径,比如/error/403 response.sendRedirect(request.getContextPath() + "/error/403"); } }
2. 配置SecurityFilterChain,替换默认处理逻辑
接下来在Spring Security的配置类里,把咱们自定义的handler配置进去,覆盖掉默认的“权限不足”提示逻辑。别忘了开启方法级安全(@EnableMethodSecurity),这样@PreAuthorize注解才会生效:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.access.AccessDeniedHandler; @Configuration @EnableWebSecurity @EnableMethodSecurity(prePostEnabled = true) // 必须开启这个才能用@PreAuthorize public class SecurityConfig { @Bean public AccessDeniedHandler customAccessDeniedHandler() { return new CustomAccessDeniedHandler(); } @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests(auth -> auth // 一定要允许访问自定义错误页面,不然重定向时会被再次拦截 .requestMatchers("/error/**").permitAll() .anyRequest().authenticated() ) // 把自定义的handler绑定到异常处理逻辑里 .exceptionHandling(ex -> ex .accessDeniedHandler(customAccessDeniedHandler()) ); return http.build(); } }
3. 编写错误页面控制器和HTML页面
然后需要一个控制器来映射咱们刚才指定的/error/403路径,返回自定义的HTML页面:
import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; @Controller public class ErrorController { @GetMapping("/error/403") public String accessDenied() { // 返回视图名称,对应你模板文件夹里的页面,比如用Thymeleaf的话就是templates/error/403.html return "error/403"; } }
最后创建你的自定义错误页面,比如src/main/resources/templates/error/403.html(假设用Thymeleaf模板引擎),可以加上自己的样式和提示内容:
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>权限不足</title> <!-- 这里可以加你自己的CSS样式 --> </head> <body> <div style="text-align: center; margin-top: 100px;"> <h1>😅 抱歉,您没有访问该资源的权限!</h1> <p>请联系管理员获取对应权限,或者返回<a href="/">首页</a></p> </div> </body> </html>
小提醒
- 一定要确保自定义错误页面的路径被
permitAll()允许,不然重定向的时候会因为未授权再次被拦截,陷入死循环。 - 如果需要记录权限拦截的日志,可以在
CustomAccessDeniedHandler的handle方法里加上日志代码,比如log.error("用户[{}]访问被拒绝: {}", request.getRemoteUser(), accessDeniedException.getMessage())。 - 如果你用的是其他模板引擎(比如FreeMarker),只需要调整视图对应的页面路径就行,逻辑都是一样的。
内容的提问来源于stack exchange,提问作者Newbie_Coder
相关产品推荐
相关产品推荐

