最近我向我的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下有如下的授权标头。但它对服务器端是不可见的。
然后我进一步阅读并发现这可能是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);
}
}
}
答案 0 :(得分:10)
您需要将服务器配置为不需要OPTIONS
请求的授权(即请求发送到的服务器 - 而不是服务于您的前端代码的服务器)。
那是因为发生了什么:
Authorization
标题发送请求。Authorization
标头的请求要求我执行CORS预检OPTIONS
,以确保服务器允许使用Authorization
标头的请求。OPTIONS
请求发送到服务器而没有Authorization
标题,因为OPTIONS
检查的全部目的是查看是否可以包括那个标题。OPTIONS
请求,但不会以指示它允许请求中的Authorization
标头的方式对其进行响应,而是由于缺少标头而拒绝它,因为它没有标头。POST
请求。进一步详情:
问题屏幕截图中的Access-Control-Request-Headers
和Access-Control-Request-Method
请求标头表示浏览器正在执行CORS preflight OPTIONS request。
请求中Authorization
和Content-Type: application/json
请求标头的存在是触发浏览器执行CORS预检的原因 - 在尝试{之前}向服务器发送OPTIONS
请求您的代码中有{1}}个请求。由于POST
预检失败,浏览器就会停在那里,从不尝试OPTIONS
。
因此,您必须弄清楚发送请求的服务器上当前服务器端代码的哪一部分导致它需要POST
请求的授权,并更改它以使其响应{{1无需授权即可获得200或204成功响应。
有关特别是针对Spring服务器执行此操作的特定帮助,请参阅以下答案: