即使我在请求

时间:2017-07-31 00:19:34

标签: angular spring-boot cors httprequest

最近我向我的Springboot和基于Angualr2的应用程序引入了JWT身份验证。 在那里我尝试通过在我的Angualr代码中传递JWT令牌来执行POST请求



save(jobId: number, taskId: number, note: Note) {

   return this.http.post(environment.APIENDPOINT + '/jobs/' + jobId + '/tasks/' + taskId + '/notes', note, this.setHeaders()).map((response: Response) => response.json());

}






private setHeaders() {
        // create authorization header with jwt token
        let currentUser = JSON.parse(localStorage.getItem('currentUser'));
        console.log("Current token---"+ currentUser.token);
        if (currentUser && currentUser.token) {

  let headers = new Headers();
  headers.append('Content-Type', 'application/json');
  headers.append('authorization','Bearer '+ currentUser.token);
            
   let r = new RequestOptions({ headers: headers })
   return r;

        }
    }




但是在服务器端它返回状态代码401.问题是在Springboot端它检查授权头如下,它返回null

String authToken = request.getHeader("authorization ");

然后我查看了请求标头,它在Access-Control-Request-Headers下有如下的授权标头。但它对服务器端是不可见的。

enter image description here

然后我进一步阅读并发现这可能是CORS配置的问题。所以我修改了我的CORS配置过滤器,使addExposedHeader如下所示

@Bean
public CorsFilter corsFilter() {
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    CorsConfiguration config = new CorsConfiguration();
    config.setAllowCredentials(true);
    config.addAllowedOrigin("*");
    config.addAllowedHeader("*");
    config.addExposedHeader("authorization");
    config.addAllowedMethod("OPTIONS");
    config.addAllowedMethod("GET");
    config.addAllowedMethod("POST");
    config.addAllowedMethod("PUT");
    config.addAllowedMethod("DELETE");

    //config.addExposedHeader("Content-Type");
    source.registerCorsConfiguration("/**", config);
    return new CorsFilter(source);
}

服务器仍抱怨无法找到Authorization标头。我在这里错过了什么吗?感谢您的帮助

解决方案

在阅读下面的sideshowbarker评论后,我能够理解这个问题背后的基础知识。 在我的项目中,我有一个JWT令牌过滤器,并且内部始终检查授权标头。然后我修改了它,如下所示,现在它按预期工作

protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
try {

    if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
        response.setStatus(HttpServletResponse.SC_OK);
    }else{
        String authToken = request.getHeader(this.tokenHeader);
        jWTTokenAuthenticationService.parseClaimsFromToken(authToken);
        --
    }
    chain.doFilter(request, response);
}Catch(AuthenticationException authEx){
    SecurityContextHolder.clearContext();
    if (entryPoint != null) {
        entryPoint.commence(request, response, authEx);
    }
}

}

1 个答案:

答案 0 :(得分:10)

您需要将服务器配置为不需要OPTIONS请求的授权(即请求发送到的服务器 - 而不是服务于您的前端代码的服务器)。

那是因为发生了什么:

  1. 您的代码告诉您的浏览器,它希望使用Authorization标题发送请求。
  2. 您的浏览器说,好的,带有Authorization标头的请求要求我执行CORS预检OPTIONS,以确保服务器允许使用Authorization标头的请求。
  3. 您的浏览器会将OPTIONS请求发送到服务器而没有Authorization标题,因为OPTIONS检查的全部目的是查看是否可以包括那个标题。
  4. 您的服务器看到OPTIONS请求,但不会以指示它允许请求中的Authorization标头的方式对其进行响应,而是由于缺少标头而拒绝它,因为它没有标头。
  5. 您的浏览器需要200或204的CORS预检响应,而是获得401响应。因此,您的浏览器就会停在那里,并且永远不会尝试代码中的POST请求。
  6. 进一步详情:

    问题屏幕截图中的Access-Control-Request-HeadersAccess-Control-Request-Method请求标头表示浏览器正在执行CORS preflight OPTIONS request

    请求中AuthorizationContent-Type: application/json请求标头的存在是触发浏览器执行CORS预检的原因 - 在尝试{之前}向服务器发送OPTIONS请求您的代码中有{1}}个请求。由于POST预检失败,浏览器就会停在那里,从不尝试OPTIONS

    因此,您必须弄清楚发送请求的服务器上当前服务器端代码的哪一部分导致它需要POST请求的授权,并更改它以使其响应{{1无需授权即可获得200或204成功响应。

    有关特别是针对Spring服务器执行此操作的特定帮助,请参阅以下答案: