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

时间:2017-02-03 20:17:12

标签: spring angular spring-boot spring-security

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

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

我还花了很多时间确保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);
    }

控制台日志 enter image description here

1 个答案:

答案 0 :(得分:0)

我决定:

//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)

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

然后应该工作。