feat(security): 添加自定义认证和授权异常处理器

- 新增 JwtAccessDeniedHandler 处理权限不足异常
- 新增 JwtAuthenticationEntryPoint 处理认证失败异常- 在 SecurityConfig 中集成自定义异常处理器
- 优化 GlobalExceptionHandler 中的异常日志输出
This commit is contained in:
2025-08-01 08:58:41 +08:00
parent 950955800d
commit 7a7247a851
4 changed files with 97 additions and 7 deletions

View File

@@ -1,9 +1,7 @@
package com.test.bijihoudaun.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import com.test.bijihoudaun.config.security.JwtAccessDeniedHandler;
import com.test.bijihoudaun.config.security.JwtAuthenticationEntryPoint;
import com.test.bijihoudaun.interceptor.JwtAuthenticationTokenFilter;
import com.test.bijihoudaun.util.JwtTokenUtil;
import org.springframework.beans.factory.annotation.Autowired;
@@ -29,6 +27,12 @@ public class SecurityConfig {
@Autowired
private JwtTokenUtil jwtTokenUtil;
@Autowired
private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
@Autowired
private JwtAccessDeniedHandler jwtAccessDeniedHandler;
@Value("${jwt.header}")
private String tokenHeader;
@@ -51,6 +55,11 @@ public class SecurityConfig {
.requestMatchers("/doc.html", "/webjars/**", "/v3/api-docs/**", "/api/user/login", "/api/user/register").permitAll()
.requestMatchers(org.springframework.http.HttpMethod.GET).permitAll()
.anyRequest().authenticated()
)
// 添加自定义的异常处理器
.exceptionHandling(exceptions -> exceptions
.authenticationEntryPoint(jwtAuthenticationEntryPoint)
.accessDeniedHandler(jwtAccessDeniedHandler)
);
// 在这里添加JWT过滤器

View File

@@ -0,0 +1,35 @@
package com.test.bijihoudaun.config.security;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.test.bijihoudaun.common.response.R;
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 org.springframework.stereotype.Component;
import java.io.IOException;
/**
* 自定义授权失败处理器
* 当认证成功的用户尝试访问其没有权限的资源时,此处理器被调用。
*/
@Component
public class JwtAccessDeniedHandler implements AccessDeniedHandler {
@Override
public void handle(HttpServletRequest request,
HttpServletResponse response,
AccessDeniedException accessDeniedException) throws IOException, ServletException {
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json");
response.setStatus(HttpServletResponse.SC_FORBIDDEN); // 403
R<String> result = R.fail("权限不足,无法访问此资源");
ObjectMapper objectMapper = new ObjectMapper();
response.getWriter().write(objectMapper.writeValueAsString(result));
}
}

View File

@@ -0,0 +1,37 @@
package com.test.bijihoudaun.config.security;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.test.bijihoudaun.common.response.R;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;
import java.io.IOException;
/**
* 自定义认证失败处理器
* 当用户尝试访问受保护的资源而未提供有效凭证时例如token无效或过期此处理器被调用。
*/
@Component
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request,
HttpServletResponse response,
AuthenticationException authException) throws IOException, ServletException {
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json");
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); // 401
// 创建一个包含中文错误信息的R对象
R<String> result = R.fail("认证失败,请重新登录");
// 使用ObjectMapper将对象转换为JSON字符串并写入响应
ObjectMapper objectMapper = new ObjectMapper();
response.getWriter().write(objectMapper.writeValueAsString(result));
}
}