JWT spring security Authentication过滤器丢失标头信息

Posted

技术标签:

【中文标题】JWT spring security Authentication过滤器丢失标头信息【英文标题】:JWT spring security Authentication filter losts headers information 【发布时间】:2018-02-09 11:24:19 【问题描述】:

我根据这篇文章使用 Spring Security 基础使用 JWT 制作了 REST Security - https://www.toptal.com/java/rest-security-with-jwt-spring-security-and-java

特别是,我有一个过滤器,它使用请求的“授权”标头中的令牌对用户进行身份验证:

public class JwtAuthenticationFilter extends AbstractAuthenticationProcessingFilter 

public JwtAuthenticationFilter() 
    super("/**");


@Override
protected boolean requiresAuthentication(HttpServletRequest request, HttpServletResponse response) 
    return true;


@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException 

    String header = request.getHeader("Authorization");

    if (header == null || !header.startsWith("Bearer ")) 
        throw new JwtTokenMissingException("No JWT token found in request headers");
    

    String authToken = header.substring(7);

    JwtAuthenticationToken authRequest = new JwtAuthenticationToken(authToken);

    return getAuthenticationManager().authenticate(authRequest);


@Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult)
        throws IOException, ServletException 
    super.successfulAuthentication(request, response, chain, authResult);

    // As this authentication is in HTTP header, after success we need to continue the request normally
    // and return the response as if the resource was not secured at all
    chain.doFilter(request, response);


因此,在处理请求时,我的过滤器每次都没有在 HttpServletRequest 对象中找到 Authorization 和任何其他 Headers 信息,并且应用程序给出了用户未通过身份验证的答案。 当我停用 JWT 安全过滤器时,同一请求中包含所有标头。

有人对如何解决此问题有任何想法吗?

我的配置文件是:

?xml version="1.0" encoding="UTF-8"?>
<beans:beans
    xmlns="http://www.springframework.org/schema/security"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:beans="http://www.springframework.org/schema/beans"
    xsi:schemaLocation="
      http://www.springframework.org/schema/security
  http://www.springframework.org/schema/security/spring-security-4.2.xsd
  http://www.springframework.org/schema/beans
  http://www.springframework.org/schema/beans/spring-beans-4.2.xsd">

<!--activate @PreFilter, @PreAuthorize, @PostFilter, @PostAuthorize annotations on any spring beans in the context-->
<global-method-security pre-post-annotations="enabled" />

<!--define the login and signup endpoints to skip security-->
<http pattern="/authenticate" security="none"/>

<!--we define the filter chain applied to all requests while adding two important configs: Entry point reference and -->
<!--setting the session creation to stateless (we do not want the session created for security purposes as -->
<!--we are using tokens for each request)-->
<http pattern="/**" entry-point-ref="restAuthenticationEntryPoint" create-session="stateless">
    <!--We do not need csrf protection because our tokens are immune to it-->
    <csrf disabled="true"/>
    <!--we plug in our special authentication filter within the Spring’s predefined filter chain,-->
    <!--just before the form login filter-->
    <custom-filter before="FORM_LOGIN_FILTER" ref="jwtAuthenticationFilter"/>
</http>

<!--This bean is the declaration of our authentification filter; since it is extending Spring’s -->
<!--AbstractAuthenticationProcessingFilter, we need to declare it in XML to wire its properties -->
<!--(auto wire does not work here)-->
<beans:bean id="jwtAuthenticationFilter" class="by.eventcat.rest.security.JwtAuthenticationFilter">
    <beans:property name="authenticationManager" ref="authenticationManager" />
    <!--The default success handler of AbstractAuthenticationProcessingFilter is not good enough for REST purposes -->
    <!--because it redirects the user to a success page; that is why we set our own here-->
    <beans:property name="authenticationSuccessHandler" ref="jwtAuthenticationSuccessHandler" />
</beans:bean>

<authentication-manager alias="authenticationManager">
    <!--The declaration of the provider created by the authenticationManager is used by our filter to authenticate users-->
    <authentication-provider ref="jwtAuthenticationProvider" />
</authentication-manager>

<beans:bean id="restAuthenticationEntryPoint" class="by.eventcat.rest.security.RestAuthenticationEntryPoint"/>
<beans:bean id="jwtAuthenticationProvider" class="by.eventcat.rest.security.JwtAuthenticationProvider"/>
<beans:bean id="jwtUtil" class="by.eventcat.rest.security.JwtUtil"/>

【问题讨论】:

我可以看看你的安全配置吗? 是的,我现在将编辑我的问题 【参考方案1】:

我已将 CORS 配置添加到我的应用程序中,这不仅会影响响应,还会影响请求。所以,我在 web.xml 中添加了:

<!--CORS configuration--> 
<filter>
    <filter-name>corsFilter</filter-name>
    <filter-class>by.eventcat.rest.MyCorsFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>corsFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

而 MyCorsFilter 是:

public class MyCorsFilter extends CorsFilter 

public MyCorsFilter() 
    super(configurationSource());


private static UrlBasedCorsConfigurationSource configurationSource() 
    CorsConfiguration config = new CorsConfiguration();
    config.addAllowedOrigin("*");
    config.addAllowedMethod("*");
    config.addAllowedHeader("*");
    config.setAllowCredentials(true);
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    source.registerCorsConfiguration("/**", config);
    return source;



【讨论】:

以上是关于JWT spring security Authentication过滤器丢失标头信息的主要内容,如果未能解决你的问题,请参考以下文章

Spring Security----JWT详解

Spring Security+JWT简述

单点登录JWT与Spring Security OAuth

Spring Security OAuth2 v5:NoSuchBeanDefinitionException:'org.springframework.security.oauth2.jwt.Jwt

spring boot + spring security + jwt + React 不工作

Spring Boot + Security + JWT 无法生成令牌