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

如何在Spring Boot中用Spring Security实现Bearer头硬编码校验?

问题描述

我想对服务器做认证,不需要处理登录等逻辑,只验证请求头里的Authorization字段的Bearer Token,和硬编码的值对比,匹配就放行,不匹配就拒绝。我写了两个过滤器,但试了很多次还是返回401未授权错误。我看过连接数据库验证用户的文章,但只想通过过滤器校验请求头Token。

编辑1:
现在我知道Spring Security有15个过滤器,怎么确保系统只校验自定义请求头,忽略其他校验逻辑?


现有代码

SecurityConfig.java

package com.company.framework.filter;

import javax.servlet.http.HttpServletResponse;

import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
@EnableWebSecurity
public class SecurityConfig{

    @Autowired private AuthFilter filtet;

    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        System.out.println("reaching here3 ");
        http
            .csrf().disable()
            .authorizeRequests()
                .antMatchers("/api/v1/open/**").permitAll()
                .and()
            .exceptionHandling()
                .authenticationEntryPoint(
         (request, response,     authException) ->
                                    response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Error here")
                    )
                .and()
            .sessionManagement()
                .and()
            .httpBasic().disable();

        http
            .addFilter(filtet);
        return http.build();
    }
}

AuthFilter.java

package com.company.framework.filter;

import java.io.IOException;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

@Component
public class AuthFilter extends OncePerRequestFilter{

    @Override
    protected void doFilterInternal(HttpServletRequest request,HttpServletResponse response,FilterChain filterChain) throws ServletException, IOException {
    
        String authHeader = request.getHeader("Authorization");
        System.out.println("here ");
        System.out.println(authHeader+"1");
        if (authHeader != null && authHeader.length() == 0 && authHeader.startsWith("Bearer ")) {
            String jwt = authHeader.substring(7);
            System.out.println(authHeader+"2");
            if (jwt == null) {
                response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Invalid JWT Token in Bearer Header");
            } else {
                String rev = "bfrek";
                if (jwt.equals(rev)) {
                    response.setStatus(200);
                } else {
                    response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Invalid JWT Token");
                }
            }
        }
        filterChain.doFilter(request, response);
    }
}

问题分析与修复方案

核心问题

  1. AuthFilter逻辑错误:条件authHeader != null && authHeader.length() == 0 && authHeader.startsWith("Bearer ")矛盾,length() == 0会直接跳过有效Token的校验;且验证通过后仅设置200状态,未告知Spring Security已完成认证,后续过滤器仍会拦截请求。
  2. SecurityConfig配置缺失:未声明非开放接口需要认证,也未禁用不必要的会话机制,自定义过滤器的位置也未正确插入Spring Security链中。

修复后代码

1. 修正AuthFilter.java

package com.company.framework.filter;

import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

@Component
public class AuthFilter extends OncePerRequestFilter {

    // 硬编码的有效Token
    private static final String VALID_TOKEN = "bfrek";

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        // 跳过开放接口的校验
        if (request.getRequestURI().startsWith("/api/v1/open/")) {
            filterChain.doFilter(request, response);
            return;
        }

        String authHeader = request.getHeader("Authorization");
        // 校验请求头格式
        if (authHeader == null || !authHeader.startsWith("Bearer ")) {
            response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "缺少有效的Bearer Token");
            return;
        }

        String token = authHeader.substring(7).trim();
        // 对比Token值
        if (!VALID_TOKEN.equals(token)) {
            response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "无效的Token");
            return;
        }

        // 验证通过,向Spring Security上下文注入认证信息
        Authentication authentication = new UsernamePasswordAuthenticationToken("system", null, null);
        SecurityContextHolder.getContext().setAuthentication(authentication);

        // 放行请求
        filterChain.doFilter(request, response);
    }
}

2. 修正SecurityConfig.java

package com.company.framework.filter;

import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
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.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Autowired
    private AuthFilter authFilter;

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            // 禁用CSRF(无状态接口无需)
            .csrf().disable()
            // 授权规则:开放接口允许所有人,其余需认证
            .authorizeRequests()
                .antMatchers("/api/v1/open/**").permitAll()
                .anyRequest().authenticated()
                .and()
            // 禁用HTTP Basic认证
            .httpBasic().disable()
            // 设置无状态会话,不维护会话信息
            .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
            // 自定义未授权响应
            .exceptionHandling()
                .authenticationEntryPoint((request, response, authException) ->
                    response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "未授权访问")
                );

        // 将自定义过滤器插入到Spring Security认证过滤器之前
        http.addFilterBefore(authFilter, UsernamePasswordAuthenticationFilter.class);

        return http.build();
    }
}

关键修复点

  • 修正Token校验逻辑:去掉矛盾的长度判断,先校验请求头格式再对比Token值。
  • 注入认证上下文:验证通过后向SecurityContextHolder设置认证信息,告知Spring Security请求已授权。
  • 简化并完善Security配置:
    • 明确非开放接口的认证要求;
    • 设置无状态会话,禁用不必要的会话机制;
    • 将自定义过滤器插入到Spring Security默认认证过滤器之前,确保优先执行;
    • 清理冗余配置,减少不必要的过滤器执行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 22:30:53