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

如何配置springdoc-openapi使Spring Security表单登录支持form-urlencoded?

解决SpringDoc表单登录端点请求体类型配置问题

问题背景

使用SpringBoot 2.7.5 + Spring Security 5.7.4集成springdoc-openapi-ui时,通过springdoc.show-login-endpoint=true暴露的登录端点仅支持application/json请求体,导致UsernamePasswordAuthenticationFilter无法获取用户名和密码,需将请求体改为application/x-www-form-urlencoded。

解决方案

通过自定义OpenApiCustomizer修改登录端点的请求体配置,同时确保Spring Security配置正确。

1. 自定义OpenAPI配置类

创建配置类覆盖登录端点的请求体定义,将媒体类型改为表单格式:

import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.Operation;
import io.swagger.v3.oas.models.PathItem;
import io.swagger.v3.oas.models.media.Content;
import io.swagger.v3.oas.models.media.MediaType;
import io.swagger.v3.oas.models.media.Schema;
import io.swagger.v3.oas.models.parameters.RequestBody;
import org.springdoc.core.customizers.OpenApiCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class SpringDocConfig {

    @Bean
    public OpenApiCustomizer loginEndpointCustomizer() {
        return openApi -> {
            // 定位登录端点路径(默认是"/login",自定义登录路径需同步修改)
            PathItem loginPath = openApi.getPaths().get("/login");
            if (loginPath != null) {
                Operation postLoginOp = loginPath.getPost();
                if (postLoginOp != null) {
                    // 构建表单类型请求体
                    RequestBody formRequestBody = new RequestBody()
                            .description("登录凭证")
                            .content(new Content()
                                    .addMediaType("application/x-www-form-urlencoded",
                                            new MediaType().schema(new Schema<>()
                                                    .type("object")
                                                    .addProperty("username", new Schema<>().type("string"))
                                                    .addProperty("password", new Schema<>().type("string")))));
                    postLoginOp.setRequestBody(formRequestBody);
                }
            }
        };
    }
}

2. 配置Spring Security

确保Swagger相关路径允许匿名访问,同时表单登录配置正确:

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 org.springframework.security.web.SecurityFilterChain;

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
                .authorizeHttpRequests(auth -> auth
                        // 允许Swagger资源无需认证
                        .antMatchers("/swagger-ui/**", "/v3/api-docs/**").permitAll()
                        // 保护目标端点
                        .antMatchers("/foos/**").authenticated()
                        .anyRequest().permitAll()
                )
                .formLogin(form -> form
                        // 登录处理路径需与OpenAPI配置中的路径一致
                        .loginProcessingUrl("/login")
                        .permitAll()
                )
                .csrf(csrf -> csrf.disable()); // 若需CSRF保护,可根据业务调整

        return http.build();
    }
}

原理说明

  • Spring Security的UsernamePasswordAuthenticationFilter默认从请求参数中提取username和password,而非JSON请求体,因此将Swagger登录端点的请求体改为表单格式后,凭证可被正确识别。
  • 自定义的OpenApiCustomizer会修改OpenAPI文档中登录端点的POST请求定义,替换原有JSON媒体类型为表单类型,Swagger UI将自动渲染表单输入框供用户提交凭证。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 16:21:53