CORS:响应中缺少授权标头(jQuery / Spring)

Posted

技术标签:

【中文标题】CORS:响应中缺少授权标头(jQuery / Spring)【英文标题】:CORS: Missing Authorization Header in Response (jQuery / Spring) 【发布时间】:2018-12-31 01:25:43 【问题描述】:

我有一个在 localhost:8080 上运行的 Spring-Boot Web-Server 和一个在 localhost:80 上带有一些“静态”html/js 的 Apache HTTP-Server。我用 JWT-Authorization 实现了一个 RESTful-API。

如果我确实在与 REST-API 相同的服务器上提供静态 html/js,当我请求 /login-Endpoint 时,我成功地将 JWT-Token 检索为“Authorization”-Header。

但是当我做同样的事情时,在我的 Apache 服务器上提供静态源时,Authorization-Header 丢失了。我的 javascript

 $.ajax(
            type: "POST",
            url: "http://localhost:8080/login",
            data: JSON.stringify(data),
            contentType: "application/json",
            dataType: "json",
            success: function (data) 
                alert(data);
            ,
            failure: function (errMsg) 
                alert(errMsg);
            ,
            complete: function (resp) 
                console.log(resp.getAllResponseHeaders());
                console.log(resp.getResponseHeader("authorization"));
            
        );

console.log(resp.getAllResponseHeaders()):

pragma: no-cache cache-control: no-cache, no-store, max-age=0, must-revalidate expires: 0

console.log(resp.getResponseHeader("authorization")):

null

我已经做了很多研究,我认为原因是 CORS 配置错误。

我的 WebSecurity-Class 看起来像这样 - 尽可能多地允许(出于测试目的):

@EnableWebSecurity public class WebSecurity extends WebSecurityConfigurerAdapter 

@Autowired
private PasswordEncoder passwordEncoder;

@Autowired
private UserDetailsServiceImpl userDetailsService;

@Override
protected void configure(HttpSecurity http) throws Exception 
    http.cors().and().csrf().disable().authorizeRequests()
            .antMatchers(HttpMethod.POST, SecurityConstants.SIGN_UP_URL).permitAll().anyRequest().authenticated().and()
            .addFilter(new JWTAuthenticationFilter(authenticationManager()))
            .addFilter(new JWTAuthorizationFilter(authenticationManager()))
            // this disables session creation on Spring Security
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);


@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception 
    auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder);


 @Bean
    public CorsConfigurationSource corsConfigurationSource() 
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(Arrays.asList("*"));
        configuration.setAllowedMethods(Arrays.asList("*"));
        configuration.setAllowedHeaders(Arrays.asList("*"));
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    

还有什么建议吗?

(我调试了我的 Java-Code 并且 JWT-Token 成功添加到响应中 - 但我的 js 没有收到它..)

【问题讨论】:

通常 JWTAuthorizationFilter 与授权标头一起使用。过滤器验证标头授权中的 jwt。请查看以下链接以了解更多关于 JWTAuthorizationFilter auth0.com/blog/implementing-jwt-authentication-on-spring-boot 您应该在 AJAX 请求中传递 Authorization 标头以获得成功的结果或从 CORS 中删除过滤器 @VinuBibin :这正是我用于构建 Spring-setup 的资源。正如我所提到的 - 如果 html/js 源在同一台服务器上提供,那么一切正常。但是,如果 html/js-sources 在不同的服务器 (CORS) 上提供,则缺少授权标头.. 您能否在您的问题中添加带有标头的请求和响应的痕迹?同时在浏览器中显示错误消息(使用浏览器的开发工具)。 【参考方案1】:

您的 CORS 配置对我来说似乎不正确。

您可以在 Spring 中配置多个级别的 CORS

全局 CORS 配置

为整个应用启用 CORS 非常简单:

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter 

    @Override
    public void addCorsMappings(CorsRegistry registry) 
        registry.addMapping("/**");
    

如果你使用的是 Spring Boot,建议只声明一个 WebMvcConfigurer bean

@Configuration
public class MyConfiguration 

    @Bean
    public WebMvcConfigurer corsConfigurer() 
        return new WebMvcConfigurerAdapter() 
            @Override
            public void addCorsMappings(CorsRegistry registry) 
                registry.addMapping("/**");
            
        ;
    

方法级别

@RestController
@RequestMapping("/account")
public class AccountController 

    @CrossOrigin
    @GetMapping("/id")
    public Account retrieve(@PathVariable Long id) 
        // ...
    

    @DeleteMapping("/id")
    public void remove(@PathVariable Long id) 
        // ...
    

班级等级

@CrossOrigin
@RestController
@RequestMapping("/account")
public class AccountController 

    @GetMapping("/id")
    public Account retrieve(@PathVariable Long id) 
        // ...
    

    @DeleteMapping("/id")
    public void remove(@PathVariable Long id) 
        // ...
    

更多详情here

编辑 1

如果你使用的是 Spring Security,你可以这样配置

@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter 

    @Override
    protected void configure(HttpSecurity http) throws Exception 
        http
            // by default uses a Bean by the name of corsConfigurationSource
            .cors().and()
            ...
    

    @Bean
    CorsConfigurationSource corsConfigurationSource() 
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(Arrays.asList("https://example.com"));
        configuration.setAllowedMethods(Arrays.asList("GET","POST"));
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    

更多详情here

【讨论】:

没有这样的全局 CORS 配置。您的 global 配置仅适用于 Spring MVC 调度程序 servlet。它比 OP 问题中的 Spring Security 配置更本地化,它适用于所有 URL,除非您明确忽略某些 URL。 是的,我错过了安全部分。谢谢你的收获。我已经更新了我的答案。

以上是关于CORS:响应中缺少授权标头(jQuery / Spring)的主要内容,如果未能解决你的问题,请参考以下文章

django-cors-headers 和 nginx 配置:预检响应缺少 CORS 标头

当提供商因缺少授权标头而拒绝飞行前请求时,让客户端 CORS 工作

*** API 响应中缺少 CORS 标头“Access-Control-Allow-Origin”[重复]

JQuery、CORS 和自定义响应标头

当提供商因缺少授权标头而拒绝飞行前请求时,使客户端CORS正常工作

被 CORS 阻止:预检响应中的 Access-Control-Allow-Headers 不允许请求标头字段授权