Angular 2 - 预检响应具有无效的 HTTP 状态代码 401

Posted

技术标签:

【中文标题】Angular 2 - 预检响应具有无效的 HTTP 状态代码 401【英文标题】:Angular 2 - Response for preflight has invalid HTTP status code 401 【发布时间】:2017-12-31 01:24:18 【问题描述】:

我知道这里已经解决了很多相同的问题, 但不幸的是,他们都没有帮助我:-(。 这是我的问题:我尝试从本地主机连接到服务器上的 REST 服务。它适用于 FF REST 插件,但我的应用程序导致以下错误:

选项http://.../my_REST_Service/ 401(未授权) XMLHttpRequest 无法加载 http://.../my_REST_Service/。 预检响应包含无效的 HTTP 状态代码 401

我如何尝试获取我想要的数据:

@Injectable()
export class ModelsComponent implements OnInit 

    private restRoot = 'http://.../my_REST_Service';
    private data;

    constructor(private http: Http)  

    ngOnInit() 
        this.getModels().subscribe(res => 
            this.data = res; 
            console.log(this.data);
        );
    

    authHeaders() 
        let username: string = 'xxxx';
        let password: string = 'xxxx';

        let token: string = btoa(username + ":" + password);

        let headers: Headers = new Headers();
        headers.append('Access-Control-Expose-Headers', 'Authorization');
        headers.append('Authorization', 'Basic ' + token);
        headers.append("Access-Control-Allow-Origin", "http://localhost:4200/");
        headers.append("Access-Control-Allow-Methods", "*");
        headers.append("Access-Control-Allow-Headers", "Accept,Accept-Charset,Accept-Encoding,Accept-Language,Authorization,Connection,Content-Type,Cookie,DNT,Host,Keep-Alive,Origin,Referer,User-Agent,X-CSRF-Token,X-Requested-With");
        headers.append("Access-Control-Allow-Credentials", "true");

        return headers;
    

    getModels(): Observable<any> 
        return this.http.get(this.restRoot, 
                    headers: this.authHeaders(), 
                    withCredentials: true        <- from a similar issue
               ).map(res => res.json());
    

我的服务器是这样配置的:

Header set Access-Control-Allow-Origin "http://localhost:4200"
Header set Access-Control-Allow-Headers "Accept,Accept-Charset,Accept-Encoding,Accept-Language,Authorization,Connection,Content-Type,Cookie,DNT,Host,Keep-Alive,Origin,Referer,User-Agent,X-CSRF-Token,X-Requested-With"
Header set Access-Control-Allow-Methods "*"
Header set Access-Control-Allow-Credentials "true"   
Header set Access-Control-Expose-Headers "Authorization"       <- from a similar issue

我知道还有其他相同/类似的已解决问题。但我仍然不知道该做什么或如何去做。 如果有人可以帮助我编写代码,我将不胜感激!

【问题讨论】:

不要在您的请求中放置访问控制标头!它们是响应标头! 【参考方案1】:

在服务器端,如果使用 Node.js,您可以考虑授权所有 OPTIONS 请求,这样浏览器就不需要验证来检查服务器/REST API 上授权了哪些方法。

考虑如下代码:

if (req.method === 'OPTIONS') 
    res.status(200).end();
 else 
    next();

【讨论】:

【参考方案2】:

浏览器在执行HttpGet 之前执行OPTIONS 请求,您需要添加与HttpGet 具有相同路由的端点,将其设为HttpOptions 请求,从该端点删除身份验证并返回200 OK 来自它,这应该可以解决您的问题。

【讨论】:

不是 Angular 正在执行 OPTIONS 请求,而是浏览器。 感谢您的回答,但我不确定我是否正确。我是否必须在我的 Angular 代码中发出没有身份验证的 HttpOptions 请求,还是必须从 REST 端点中删除身份验证?问题是使用的 REST-API 默认情况下需要对有效用户进行身份验证,并且无法从中删除身份验证。还是我完全误解了你的答案? 您需要为 HttpOptions 创建一个 REST 端点。它将与您的其他端点完全相同,只有 http 动词是 HttpOptions。此端点将仅返回状态 200 Ok 响应。此端点应允许匿名身份验证,因为选项请求不包含授权。 好吧,那不可能。我使用具有多个端点的修复 REST 服务。也许我找到了一种完全关闭授权的方法。【参考方案3】:

“我的服务器是这样配置的”——这几乎是无关紧要的。查看报错信息:“Response for preflight has invalid HTTP status code 401”

它没有说明您在 Access-Control-Allow-Thing 中提到的任何事情。

浏览器正在发出 OPTIONS 请求,询问是否允许跨源请求。 响应显示“您的用户名和密码错误”。

由于浏览器没有收到跨域请求的权限:没有发送用户名和密码

您需要在您的服务器上找到执行授权的代码,并从该测试中排除 OPTIONS 请求。任何人都应该能够提出 OPTIONS 请求,而不仅仅是拥有用户名和密码的人。

【讨论】:

您认为在某些情况下排除 OPTIONS 请求可能是安全问题吗? @KyleVassella — 仅当您对它们做出不恰当的响应时(例如,将它们视为 POST 请求并将数据存储在数据库中)。

以上是关于Angular 2 - 预检响应具有无效的 HTTP 状态代码 401的主要内容,如果未能解决你的问题,请参考以下文章

预检响应在 Angular Js1 和 Webapi 2 上具有无效的 HTTP 状态代码 405

Angular 5:预检响应具有无效的 HTTP 状态代码 403

Angular $http:预检响应具有无效的 HTTP 状态代码 403

通过基本身份验证访问 REST 的 Angular2 抛出“预检响应具有无效的 HTTP 状态代码 401”

预检响应具有无效的 HTTP 状态代码:401 角度

AngularJS HTTP 标头配置。预检响应具有无效的 HTTP 状态代码 401