即使我在请求中发送凭据,HTTP 状态码 401

HTTP status code 401 even though I’m sending credentials in the request(即使我在请求中发送凭据,HTTP 状态码 401)
本文介绍了即使我在请求中发送凭据,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:

  1. 您的代码告诉您的浏览器它想要发送带有 Authorization 标头的请求.
  2. 您的浏览器说,好的,带有 Authorization 标头的请求要求我执行 CORS 预检 OPTIONS 以确保服务器允许带有 Authorization<的请求/code> 标题.
  3. 您的浏览器发送 OPTIONS 请求到服务器没有 Authorization 标头,因为 OPTIONS 的全部目的code> 检查是否可以包含该标头.
  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:

  • 为 OPTIONS Http 方法禁用 Spring Security
  • Spring CorsFilter 似乎无法正常工作,但仍会收到 401 的预检请求
  • 对预检的响应无效HTTP 状态码 401 - Spring
  • AngularJS &带有 ROLE_ANONYMOUS 的 Spring Security 仍然返回 401

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

本站部分内容来源互联网,如果有图片或者内容侵犯了您的权益,请联系我们,我们会在确认后第一时间进行删除!

相关文档推荐

SCRIPT5: Access is denied in IE9 on xmlhttprequest(SCRIPT5:在 IE9 中对 xmlhttprequest 的访问被拒绝)
XMLHttpRequest module not defined/found(XMLHttpRequest 模块未定义/未找到)
Show a progress bar for downloading files using XHR2/AJAX(显示使用 XHR2/AJAX 下载文件的进度条)
How can I open a JSON file in JavaScript without jQuery?(如何在没有 jQuery 的情况下在 JavaScript 中打开 JSON 文件?)
quot;Origin null is not allowed by Access-Control-Allow-Originquot; in Chrome. Why?(“Access-Control-Allow-Origin 不允许 Origin null在铬.为什么?)
How to get response url in XMLHttpRequest?(如何在 XMLHttpRequest 中获取响应 url?)