在那里我尝试通过在我的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下有如下的授权标头.但它对服务器端是不可见的.
然后我进一步阅读并发现这可能是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令牌过滤器,在里面它始终检查Authorization标头.然后我将其修改如下,现在它按预期工作
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); } }
}
那是因为发生的事情是这样的:
>您的代码告诉您的浏览器它想要使用Authorization标头发送请求.
>您的浏览器说,好的,带有Authorization标头的请求要求我执行CORS预检OPTIONS,以确保服务器允许使用Authorization标头的请求.
>您的浏览器在没有Authorization标头的情况下将OPTIONS请求发送到服务器,因为OPTIONS检查的全部目的是查看是否可以包含该标头.
>您的服务器看到OPTIONS请求,但不是以指示它允许请求中的Authorization标头的方式响应它,而是由于它缺少标头而拒绝它使用401.
>您的浏览器需要对CORS预检做出200或204的响应,而是获得401响应.所以你的浏览器就在那里停止,从不尝试从你的代码中发出POST请求.
更多细节:
问题屏幕截图中的Access-Control-Request-Headers和Access-Control-Request-Method请求标头表明浏览器正在执行CORS preflight OPTIONS request.
在您的请求中存在Authorization和Content-Type:application / json请求标头是您的浏览器执行CORS预检的原因 – 在您的代码中尝试POST请求之前向服务器发送OPTIONS请求.因为OPTIONS预检失败,浏览器就会停在那里,从不尝试POST.
因此,您必须弄清楚发送请求的服务器上当前服务器端代码的哪一部分导致它需要OPTIONS请求的授权,并进行更改,以便它在没有授权的情况下以200或204成功响应响应OPTIONS被要求.
有关为特定的Spring服务器执行此操作的特定帮助,请参阅以下答案:
> Disable Spring Security for OPTIONS Http Method
> Spring CorsFilter does not seem to work still receiving a 401 on preflight requests
> Response for preflight has invalid HTTP status code 401 – Spring
> AngularJS & Spring Security with ROLE_ANONYMOUS still returns 401