即使我在请求中发送凭据,HTTP 状态码 401
最近我在我的基于 Springboot 和 Angualr2 的应用程序中引入了 JWT 身份验证.在那里,我尝试通过在我的 Angualr 代码中传递 JWT 令牌来执行 POST 请求
Recently i have introduced JWT authentication to my Springboot and Angualr2 based App. In There i tried to do a POST request by passing the JWT token as below in my Angualr code
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
However in the server side it returns status code 401. The issue is in the Springboot side it checks the authorization header as below and it returns null
String authToken = request.getHeader("authorization ");
然后我查看了请求标头,它在 Access-Control-Request-Headers 下具有授权标头,如下所示.但是对服务器端是不可见的.
Then i had a look at the request header and it has the authorization header under Access-Control-Request-Headers as below. But it is not visible to the server side.
然后我进一步阅读,发现这可能是 CORS 配置的问题.所以我修改了我的 CORS 配置过滤器,使其 addExposedHeader 如下所示
Then i read further and found that this could be an issue with CORS configuration. So i have modified my CORS configuration filter to have addExposedHeader as below
@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);
}
服务器仍然抱怨找不到授权标头.我在这里错过了什么吗?感谢您的帮助
Still the server complains that it can not find the Authorization header. Did i miss any thing here? Appreciate your help
解决方案
在阅读了下面sideshowbarker 的评论后,我能够理解问题背后的基础知识.在我的项目中,我有一个 JWT 令牌过滤器,在里面它总是检查 Authorization 标头.然后我对其进行了如下修改,现在它可以按预期工作了
After reading the sideshowbarker's comment below, i was able to understand the basics behind the issue. In My Project I have a JWT token filter and inside that it always checks the Authorization header. Then i have modified it as below and now it works as expected
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);
}
}
}
推荐答案
您需要将服务器配置为不需要 OPTIONS
请求的授权(即请求发送到的服务器 -不是为您的前端代码提供服务的那个).
You need to configure the server to not require authorization for OPTIONS
requests (that is, the server the request is being sent to — not the one serving your frontend code).
那是因为发生的事情是这样的:
That’s because what’s happening is this:
- 您的代码告诉您的浏览器它想要发送带有
Authorization
标头的请求. - 您的浏览器说,好的,带有
Authorization
标头的请求要求我执行 CORS 预检OPTIONS
以确保服务器允许带有Authorization<的请求/code> 标题.
- 您的浏览器发送
OPTIONS
请求到服务器没有Authorization
标头,因为OPTIONS 的全部目的code> 检查是否可以包含该标头.
- 您的服务器看到
OPTIONS
请求,但不是以表明它允许请求中的Authorization
标头的方式对其进行响应,而是使用 401 拒绝它,因为它缺少标题. - 您的浏览器期望 CORS 预检得到 200 或 204 响应,但实际上却得到了 401 响应.因此,您的浏览器会停在那里并且永远不会尝试来自您的代码的
POST
请求.
- Your code’s telling your browser it wants to send a request with the
Authorization
header. - Your browser says, OK, requests with the
Authorization
header require me to do a CORS preflightOPTIONS
to make sure the server allows requests with theAuthorization
header. - Your browser sends the
OPTIONS
request to the server without theAuthorization
header, because the whole purpose of theOPTIONS
check is to see if it’s OK to include that header. - Your server sees the
OPTIONS
request but instead of responding to it in a way that indicates it allows theAuthorization
header in requests, it rejects it with a 401 since it lacks the header. - Your browser expects a 200 or 204 response for the CORS preflight but instead gets that 401 response. So your browser stops right there and never tries the
POST
request from your code.
<小时>
更多细节:
Further details:
问题截图中的 Access-Control-Request-Headers
和 Access-Control-Request-Method
请求标头表明浏览器正在执行 CORS 预检选项请求.
The Access-Control-Request-Headers
and Access-Control-Request-Method
request headers in the screenshot in the question indicate the browser’s doing a CORS preflight OPTIONS request.
您的请求中存在 Authorization
和 Content-Type: application/json
请求标头会触发您的浏览器执行 CORS 预检 - 通过发送 <在您的代码中尝试 POST
请求之前,请先向服务器发出 code>OPTIONS 请求.并且因为 OPTIONS
预检失败,浏览器会停在那里并且永远不会尝试 POST
.
And the presence of the Authorization
and Content-Type: application/json
request headers in your request are what trigger your browser do that CORS preflight — by sending an OPTIONS
request to the server before trying the POST
request in your code. And because that OPTIONS
preflight fails, the browser stops right there and never attempts the POST
.
所以你必须弄清楚请求被发送到服务器上的当前服务器端代码的哪一部分导致它需要对 OPTIONS
请求的授权,并更改它以便它响应OPTIONS
带有 200 或 204 成功响应,无需授权.
So you must figure out what part of the current server-side code on the server the request is being sent to causes it to require authorization for OPTIONS
requests, and change that so it instead responds to OPTIONS
with a 200 or 204 success response without authorization being required.
有关 OPTIONS
的具体帮助 - 特别是启用 Spring 服务器,请参阅以下答案:
For specific help on OPTIONS
-enabling a Spring server in particular, see the following answers:
- 为 OPTIONS Http 方法禁用 Spring Security
- Spring CorsFilter 似乎无法正常工作,但仍会收到 401 的预检请求
- 对预检的响应无效HTTP 状态码 401 - Spring
- AngularJS &带有 ROLE_ANONYMOUS 的 Spring Security 仍然返回 401
相关文章