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

Postman向Spring登录接口传空值问题排查求助

问题分析与解决方案

核心问题根源

Spring Security默认的表单登录过滤器仅处理application/x-www-form-urlencoded格式请求,JSON格式请求不会自动解析为认证所需的UsernamePasswordAuthenticationToken;同时Basic Auth需要在配置中明确启用,否则请求头无法被正确识别,最终导致后端getUserByUsername方法接收到null值抛出异常。


解决方案1:扩展支持JSON格式的表单登录

通过自定义过滤器替换默认的UsernamePasswordAuthenticationFilter,实现JSON请求的用户名密码解析:

1. 自定义JSON认证过滤器

import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import java.io.IOException;
import java.util.Map;

public class JsonUsernamePasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
    private final ObjectMapper objectMapper = new ObjectMapper();

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        if ("application/json".equals(request.getContentType())) {
            try {
                Map<String, String> credentials = objectMapper.readValue(request.getInputStream(), Map.class);
                String username = credentials.get(getUsernameParameter());
                String password = credentials.get(getPasswordParameter());
                UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
                setDetails(request, authRequest);
                return this.getAuthenticationManager().authenticate(authRequest);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return super.attemptAuthentication(request, response);
    }
}

2. 在SecurityFilterChain中配置替换默认过滤器

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                .authorizeHttpRequests(auth -> auth
                        .requestMatchers("/login").permitAll()
                        .anyRequest().authenticated()
                )
                .formLogin(form -> form
                        .loginProcessingUrl("/login")
                )
                .httpBasic(basic -> basic
                        .realmName("MyApp")
                )
                .addFilterAt(jsonUsernamePasswordAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);

        return http.build();
    }

    @Bean
    public JsonUsernamePasswordAuthenticationFilter jsonUsernamePasswordAuthenticationFilter() throws Exception {
        JsonUsernamePasswordAuthenticationFilter filter = new JsonUsernamePasswordAuthenticationFilter();
        filter.setAuthenticationManager(authenticationManager(null));
        filter.setFilterProcessesUrl("/login");
        return filter;
    }

    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration authConfig) throws Exception {
        return authConfig.getAuthenticationManager();
    }
}

解决方案2:确保Basic Auth请求正确配置

使用Postman发送Basic Auth请求时需注意:

  • 必须携带请求头:Authorization: Basic <base64编码的username:password>,可通过Postman内置的Basic Auth自动生成该头
  • 不要同时发送表单参数和Basic Auth头,避免认证流程冲突
  • 确认Security配置中已启用httpBasic()(上述配置已包含)

关键测试与排查步骤

  1. Postman请求格式校验:
    • JSON请求需设置Content-Type: application/json,请求体格式为{"username":"你的用户名","password":"你的密码"}
    • Basic Auth请求不要添加额外的表单参数或JSON体
  2. 开启Security debug日志:
    在application.yml中添加日志配置,追踪认证流程中用户名是否被正确提取:
    logging:
      level:
        org.springframework.security: DEBUG
    
  3. 验证Basic Auth编码正确性:
    手动执行echo -n "username:password" | base64,对比Postman生成的编码是否一致

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 04:10:36