在 Spring Boot 3.4.x 中,HttpSecurity 的 and() 方法已经被标记为过时,因此我们需要采用新的 Lambda 风格 API 来配置安全性。你可以将 exceptionHandling() 移到 HttpSecurity 的顶层配置中,而不是在 authorizeHttpRequests 的内部。
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() + ""}");
    }
}
@Configuration
public class HandlerConfig {
    @Bean
    @ConditionalOnMissingBean
    AuthenticationEntryPoint authenticationEntryPoint() {
        return new CustomAuthenticationEntryPoint();
    }
    @Bean
    @ConditionalOnMissingBean
    public AccessDeniedHandler accessDeniedHandler() {
        return new CustomAccessDeineHandler();
    }
}
@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 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();
    }
}
 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 {
                
    }
}
com.xxx.uaa.keycloak.config.UaaProperty
com.xxx.uaa.keycloak.config.WebSecurityConfig
com.xxx.uaa.keycloak.config.HandlerConfig
Lambda 风格 API:使用 exceptionHandling(exceptionHandling -> ...) 的方式来设置 authenticationEntryPoint 和 accessDeniedHandler,这符合新的配置风格,避免了使用过时的方法。
结构清晰:通过这种方法,你的代码结构更加清晰,逻辑分离也更明显。
保持原有逻辑:其余部分的逻辑保持不变,仍然可以根据需要添加其他的配置。
 登录查看全部
登录查看全部
                参与评论
手机查看
返回顶部