本文介绍了即使我在请求中发送凭据,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 令牌过滤器,它始终检查授权标头.然后我将它修改如下,现在它按预期工作

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:

  1. 您的代码告诉您的浏览器它想要发送带有 Authorization 标头的请求.
  2. 您的浏览器说,好的,带有 Authorization 标头的请求要求我执行 CORS 预检 OPTIONS 以确保服务器允许带有 Authorization 标题.
  3. 您的浏览器向服务器发送 OPTIONS 请求没有 Authorization 标头,因为 OPTIONS 的全部目的代码> 检查是否可以包含该标题.
  4. 您的服务器看到 OPTIONS 请求,但不是以表明它允许请求中的 Authorization 标头的方式响应它,而是用 401 拒绝它,因为它缺少标题.
  5. 您的浏览器期望针对 CORS 预检得到 200 或 204 响应,但得到的是 401 响应.因此,您的浏览器会立即停止,不再尝试从您的代码发出 POST 请求.
  1. Your code’s telling your browser it wants to send a request with the Authorization header.
  2. Your browser says, OK, requests with the Authorization header require me to do a CORS preflight OPTIONS to make sure the server allows requests with the Authorization header.
  3. Your browser sends the OPTIONS request to the server without the Authorization header, because the whole purpose of the OPTIONS check is to see if it’s OK to include that header.
  4. Your server sees the OPTIONS request but instead of responding to it in a way that indicates it allows the Authorization header in requests, it rejects it with a 401 since it lacks the header.
  5. 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-HeadersAccess-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.

并且在您的请求中存在 AuthorizationContent-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:

这篇关于即使我在请求中发送凭据,HTTP 状态代码 401的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-25 10:28