Spring Boot CORS 配置不接受授权标头

Posted

技术标签:

【中文标题】Spring Boot CORS 配置不接受授权标头【英文标题】:Spring Boot CORS configuration is not accepting authorization header 【发布时间】:2017-06-21 07:17:54 【问题描述】:

Angular2 应用正在向 Spring Boot 发送带有 X-AUTH-TOKEN 标头值的 HTTP GET 请求。每次request.getHeader("X-AUTH-TOKEN") 返回null

有趣的是,如果我从 ARC 客户端或任何其他 rest 客户端发送请求,它工作正常。

我还花费了大量时间确保 Angular HTTP GET 请求正在发送 JWT 令牌。

角度代码

getCandidatesByUserId(userId: number): Observable<Candidate[]> 
    let headers = new Headers( 'X-AUTH-TOKEN': 'let-jwt-test-token-in' );
    console.log('Token is '+ headers.get('X-AUTH-TOKEN'));
    return this.http.get(this.url+userId+'/candidates', 
      headers: headers
    )
      .map((response: Response) => <Candidate[]> response.json())
      .do(data => console.log('All: '+ JSON.stringify(data)))
      .catch(this.handleError);
  

JWTFilter

@Override
    public void doFilter(ServletRequest request, ServletResponse res, FilterChain filterChain)
            throws IOException, ServletException 

        try 
            final HttpServletResponse response = (HttpServletResponse) res;
            response.setHeader("Access-Control-Allow-Origin", "*");
            response.setHeader("Access-Control-Allow-Credentials", "true");
            response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");
            response.setHeader("Access-Control-Max-Age", "3600");
            response.setHeader("Access-Control-Allow-Headers", "X-AUTH-TOKEN, Content-Type, Accept");
            response.setHeader("Access-Control-Expose-Headers", "X-AUTH-TOKEN, Content-Type");

            HttpServletRequest httpRequest = (HttpServletRequest) request;
            Map<String, String> blackListedTokenMap =
                    (Map<String, String>) ((HttpServletRequest) request)
                            .getSession()
                            .getServletContext()
                            .getAttribute(WebAppListener.TOKEN_BLACK_LIST_MAP);
            String authToken = authenticationService.getToken(httpRequest);
            if (authToken != null && blackListedTokenMap.containsValue(authToken)) 
                throw new RuntimeException("token invalidated");
            
            UserAuthentication authentication = (UserAuthentication) authenticationService.getAuthentication(httpRequest);
            SecurityContextHolder.getContext().setAuthentication(authentication);
            filterChain.doFilter(request, response);
            SecurityContextHolder.getContext().setAuthentication(null);
         catch (RuntimeException e) 
            ((HttpServletResponse) res).sendError(HttpServletResponse.SC_UNAUTHORIZED);
        
    

SpringSecurityConfig

@Override
    protected void configure(HttpSecurity http) throws Exception 

        http
            .csrf()
                .csrfTokenRepository(new HttpSessionCsrfTokenRepository())
                .requireCsrfProtectionMatcher(new AntPathRequestMatcher("*/*"));
        http
            .exceptionHandling()
                .and()
            .anonymous()
                .and()
            .servletApi()
                .and()
            .headers()
                .cacheControl();

        http
                //.addFilterBefore(corsFilter, ChannelProcessingFilter.class)
            .authorizeRequests()
                .antMatchers("/resources/**").permitAll()// allow for static resources
                .antMatchers("/signup").permitAll()
                .antMatchers("/forgot").permitAll()
                .antMatchers("/login").permitAll()
                .antMatchers("/reset").permitAll()
                .antMatchers("/health").permitAll()
                .antMatchers("/hello").permitAll()
                .antMatchers("/").permitAll()
                .antMatchers("/reset_pw").permitAll()
                .anyRequest().authenticated()
                .and()
            .addFilterAfter(new JJWTFilter(tokenAuthenticationService),
                        UsernamePasswordAuthenticationFilter.class);
    

控制台日志

【问题讨论】:

你用的是spring boot吗?我最近有一个类似的问题。一个应用程序在过滤器上使用 Authorization 标头而崩溃。它是空的。确定 @EnableWebMvc 注释搞砸了。 @LucasHolt 是的。我在后端使用SpringBoot,但在任何地方都没有使用@EnableWebMvc 嗨,有这方面的消息吗?我有同样的问题。我可以通过邮递员拨打电话,但不能通过我的 Angular 应用程序拨打电话。 【参考方案1】:

我解决了:

//Define class with this annotation

@Configuration

public class CorsConfig 

    @Bean
    public FilterRegistrationBean corsFilter() 
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true);
        config.addAllowedOrigin("*");
        config.addAllowedHeader("*");
        config.addAllowedMethod("OPTIONS");
        config.addAllowedMethod("HEAD");
        config.addAllowedMethod("GET");
        config.addAllowedMethod("PUT");
        config.addAllowedMethod("POST");
        config.addAllowedMethod("DELETE");
        config.addAllowedMethod("PATCH");
        source.registerCorsConfiguration("/**", config);
        // return new CorsFilter(source);
        final FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
        bean.setOrder(0);
        return bean;
    

    @Bean
    public WebMvcConfigurer mvcConfigurer() 
        return new WebMvcConfigurerAdapter() 
            public void addCorsMappings(CorsRegistry registry) 
                registry.addMapping("/**").allowedMethods("GET", "PUT", "POST", "GET", "OPTIONS");
            
        ;
    

你可以定义这个类并在你的启动弹簧类中添加@ComponentScan(basePackageClasses= CorsConfig.class)

或者只是在引导类中使用上述方法。

那么应该可以了。

【讨论】:

以上是关于Spring Boot CORS 配置不接受授权标头的主要内容,如果未能解决你的问题,请参考以下文章

Angular 的 Spring Boot 授权服务器访问 - 不断给出 CORS 错误

Spring Boot Oauth2 授权服务器不接受有效令牌

Keycloak Spring boot 后端和 Angular 前端,CORS 错误

Spring Boot Security 忽略 cors 配置

部署到 Google App Engine 时 Spring Boot CORS 配置不起作用

Spring Boot CORS 通过配置启用