springboot~3.x版本的认证逻辑

在 Spring Boot 3.4.x 中,HttpSecurityand() 方法已经被标记为过时,因此我们需要采用新的 Lambda 风格 API 来配置安全性。你可以将 exceptionHandling() 移到 HttpSecurity 的顶层配置中,而不是在 authorizeHttpRequests 的内部。

authenticationEntryPoint和accessDeniedHandler的自定义

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 CustomAccessDeineHandler implements AccessDeniedHandler {
 @Override
 public void handle(HttpServletRequest request,
 HttpServletResponse response,
 AccessDeniedException accessDeniedException) throws IOException {
 response.setContentType("application/json");
 response.setStatus(HttpServletResponse.SC_FORBIDDEN);
 response.getWriter().write("{\"error\": \"forbidden\", \"message\": \"" + accessDeniedException.getMessage() + "\"}");
 }
}
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import java.io.IOException;
/**
 * 默认的认证入口点,当用户未通过认证时会触发此类,返回401状态码和错误信息。
 * @author lind
 * @date 2025/5/28 16:59
 * @since 1.0.0
 */
public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint {
 @Override
 public void commence(HttpServletRequest request,
 HttpServletResponse response,
 AuthenticationException authException) throws IOException {
 response.setContentType("application/json");
 response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
 response.getWriter().write("{\"error\": \"Unauthorized\", \"message\": \"" + authException.getMessage() + "\"}");
 }
}

HandlerConfig注册bean

@Configuration
public class HandlerConfig {
 @Bean
 @ConditionalOnMissingBean
 AuthenticationEntryPoint authenticationEntryPoint() {
 return new CustomAuthenticationEntryPoint();
 }
 @Bean
 @ConditionalOnMissingBean
 public AccessDeniedHandler accessDeniedHandler() {
 return new CustomAccessDeineHandler();
 }
}

WebSecurityConfig代码

@EnableWebSecurity
public class WebSecurityConfig {
 private UaaProperty uaaProperty;
 private AuthenticationEntryPoint authenticationEntryPoint;
 private AccessDeniedHandler accessDeniedHandler;
 public WebSecurityConfig(UaaProperty uaaProperty, AuthenticationEntryPoint authenticationEntryPoint, AccessDeniedHandler accessDeniedHandler) {
 this.uaaProperty = uaaProperty;
 this.authenticationEntryPoint = authenticationEntryPoint;
 this.accessDeniedHandler = accessDeniedHandler;
 }
 @Bean
 public JwtAuthenticationFilter jwtAuthenticationFilter() {
 return new JwtAuthenticationFilter(uaaProperty);
 }
 @Bean
 public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
 Set<String> set = new HashSet<>();
 if (uaaProperty.getPermitUrl() != null && uaaProperty.getPermitUrl().length > 0) {
 Collections.addAll(set, uaaProperty.getPermitUrl());
 }
 http.csrf(csrf -> csrf.disable())
 .authorizeHttpRequests(authorize -> authorize
 .requestMatchers(set.toArray(new String[]{})).permitAll()
 .anyRequest().authenticated()
 )
 .exceptionHandling(exceptionHandling ->
 exceptionHandling
 .authenticationEntryPoint(authenticationEntryPoint)
 .accessDeniedHandler(accessDeniedHandler)
 )
 .addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
 return http.build();
 }
}

JwtAuthenticationFilter实现自定义验证逻辑

public class JwtAuthenticationFilter extends OncePerRequestFilter {
 // 配置白名单策略,不走当前doFilterInternal
 @Override
 protected boolean shouldNotFilter(HttpServletRequest request) {
 
 }
 @Override
 protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
 throws ServletException, IOException {
 
 }
}

新版3.x的SPI风格自动装配

  • resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
com.xxx.uaa.keycloak.config.UaaProperty
com.xxx.uaa.keycloak.config.WebSecurityConfig
com.xxx.uaa.keycloak.config.HandlerConfig

关键点解释

  1. Lambda 风格 API:使用 exceptionHandling(exceptionHandling -> ...) 的方式来设置 authenticationEntryPointaccessDeniedHandler,这符合新的配置风格,避免了使用过时的方法。

  2. 结构清晰:通过这种方法,你的代码结构更加清晰,逻辑分离也更明显。

  3. 保持原有逻辑:其余部分的逻辑保持不变,仍然可以根据需要添加其他的配置。

注意事项

  • 确保你的 Spring Security 版本已经更新到 5.4 或更高版本,以支持这种新的配置方式。
  • 如果你有其他的异常处理或安全配置,也可以在同一链中继续添加。
作者:张占岭原文地址:https://www.cnblogs.com/lori/p/18901689

%s 个评论

要回复文章请先登录注册