You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Spring Security Webflux中自定义默认未授权响应体?

解决方案

要在Spring Boot Webflux中自定义401未授权响应的JSON格式,你需要通过以下步骤实现:

1. 创建自定义错误响应DTO

首先定义一个与目标JSON结构匹配的实体类,用来生成响应内容:

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class ErrorResponse {
    private String statusCode;
    private String statusMessage;
    private String timestamp;

    public ErrorResponse(String statusCode, String statusMessage) {
        this.statusCode = statusCode;
        this.statusMessage = statusMessage;
        // 生成符合要求的时间格式
        this.timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss zzz yyyy"));
    }

    // Getter和Setter方法
    public String getStatusCode() { return statusCode; }
    public void setStatusCode(String statusCode) { this.statusCode = statusCode; }
    public String getStatusMessage() { return statusMessage; }
    public void setStatusMessage(String statusMessage) { this.statusMessage = statusMessage; }
    public String getTimestamp() { return timestamp; }
    public void setTimestamp(String timestamp) { this.timestamp = timestamp; }
}

2. 实现自定义认证入口点

创建ServerAuthenticationEntryPoint的实现类,负责在401时生成自定义响应:

import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.server.ServerAuthenticationEntryPoint;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;
import com.fasterxml.jackson.databind.ObjectMapper;

@Component
public class CustomAuthenticationEntryPoint implements ServerAuthenticationEntryPoint {

    private final ObjectMapper objectMapper;

    // 注入Spring自动配置的ObjectMapper
    public CustomAuthenticationEntryPoint(ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
    }

    @Override
    public Mono<Void> commence(ServerHttpResponse response, AuthenticationException ex) {
        // 设置响应状态码为401
        response.setStatusCode(HttpStatus.UNAUTHORIZED);
        // 设置响应内容类型为JSON
        response.getHeaders().set(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);

        // 构建错误响应对象
        ErrorResponse errorResponse = new ErrorResponse("401", "Unauthorized");
        try {
            // 将对象序列化为JSON字节数组
            byte[] jsonBytes = objectMapper.writeValueAsBytes(errorResponse);
            DataBuffer buffer = response.bufferFactory().wrap(jsonBytes);
            // 写入响应并完成
            return response.writeWith(Mono.just(buffer));
        } catch (Exception e) {
            // 序列化失败时直接结束响应
            return response.setComplete();
        }
    }
}

3. 更新Spring Security配置

在SecurityWebFilterChain中配置自定义的认证入口点,替换HTTP Basic认证的默认处理逻辑:

import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.web.server.SecurityWebFilterChain;

@EnableWebFluxSecurity
public class SecurityConfig {

    @Bean
    public SecurityWebFilterChain securityFilterChain(ServerHttpSecurity http, CustomAuthenticationEntryPoint authenticationEntryPoint) {
        return http
                .cors().and()
                .csrf().disable()
                .securityContextRepository(NoOpServerSecurityContextRepository.getInstance())
                .formLogin().disable()
                .authorizeExchange()
                    .pathMatchers("/api/v1/get-token").hasRole("API")
                    .anyExchange().authenticated()
                .and()
                .httpBasic()
                    // 绑定自定义的认证入口点
                    .authenticationEntryPoint(authenticationEntryPoint)
                .and()
                .build();
    }
}

效果验证

当用户未提供有效认证信息访问受保护接口时,系统会返回如下格式的响应:

{
    "statusCode": "401",
    "statusMessage": "Unauthorized",
    "timestamp": "Sun May 07 10:30:23 GMT 2023"
}

内容的提问来源于stack exchange,提问作者James

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 15:27:31