【问题标题】:Angular 2 Token: Response for preflight has invalid HTTP status code 400Angular 2 令牌:预检响应具有无效的 HTTP 状态代码 400
【发布时间】:2016-12-17 08:13:44
【问题描述】:

我有一个运行 Visual Studio Code 的 Angular2/TypeScript 应用程序。

在 VS 2015 中运行的 API。这是 API 项目:http://www.asp.net/web-api/overview/security/individual-accounts-in-web-api

我可以使用 API 并创建新用户,但是当我尝试登录(使用 Token 功能)时,我收到以下错误: XMLHttpRequest 无法加载https://localhost:44305/Token。预检响应包含无效的 HTTP 状态代码 400

标题如下所示:

Request URL:https://localhost:44305/Token
Request Method:OPTIONS
Status Code:400 
Remote Address:[::1]:44305
Response Headers
cache-control:no-cache
content-length:34
content-type:application/json;charset=UTF-8
date:Wed, 10 Aug 2016 19:12:57 GMT
expires:-1
pragma:no-cache
server:Microsoft-IIS/10.0
status:400
x-powered-by:ASP.NET
x-sourcefiles:=?UTF-8?B?QzpcQ2hlY2tvdXRcQVBJXzJ2czJcQVBJXEFQSVxUb2tlbg==?=
Request Headers
:authority:localhost:44305
:method:OPTIONS
:path:/Token
:scheme:https
accept:*/*
accept-encoding:gzip, deflate, sdch, br
accept-language:en-US,en;q=0.8,da;q=0.6,nb;q=0.4
access-control-request-headers:authorization
access-control-request-method:POST
cache-control:no-cache
origin:http://evil.com/
pragma:no-cache
referer:http://localhost:3000/signin
user-agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36

我的 Angular 服务如下所示:

 loginAccount(account: Account): Observable<string> {        
    var obj = { Email: account.Email, Password: account.Password, grant_type: 'password' };
        let headers = new Headers({ 'Content-Type': 'application/json' });
        let options = new RequestOptions( {method: RequestMethod.Post, headers: headers });

        let body = JSON.stringify(obj);
        console.log('loginAccount with:' + body);

         return this._http.post('https://localhost:44305/Token',  body, options)
                             .map(this.extractData)
                             .catch(this.handleError);
}

当我使用 API 项目中的 AJAX 功能时:http://www.asp.net/web-api/overview/security/individual-accounts-in-web-api 那么它工作正常吗?我在 Angular POST 请求中做错了什么?

【问题讨论】:

    标签: api angular typescript


    【解决方案1】:

    我找到了解决方案。感谢 API 网站上的 cmets:http://www.asp.net/web-api/overview/security/individual-accounts-in-web-api

    我必须为 application/x-www-form-urlencoded 设置正确的标题; charset=UTF-8 并序列化我发布的对象。我找不到 Angular 序列化器方法,所以我用 JavaScript 制作了自己的(从另一个 stackoverflow 站点复制)。

    这是用户在使用 Angular2 和 TypeScript 时登录 API 并请求令牌时的最终调用:

     loginAccount(account: Account): Observable<string> {        
        var obj = { UserName: account.Email, Password: account.Password, grant_type: 'password' };
    
            let headers = new Headers({ 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' });
            let options = new RequestOptions( {method: RequestMethod.Post, headers: headers });
    
            let body = this.serializeObj(obj);
    
             return this._http.post('https://localhost:44305/Token',  body, options)
                                 .map(this.extractData)
                                 .catch(this.handleError);
    }
    
    private serializeObj(obj) {
        var result = [];
        for (var property in obj)
            result.push(encodeURIComponent(property) + "=" + encodeURIComponent(obj[property]));
    
        return result.join("&");
    }
    

    【讨论】:

    • 谢谢。不过最好能发'Content-Type': 'application/json'
    • 任何解决这个问题的人,请建议:在服务器端设置所有标头后,我仍然面临预检响应无效 HTTP 状态代码 400
    【解决方案2】:

    上周我也面临同样的问题,并在谷歌和堆栈溢出上进行了搜索,但所有解决方案都在脉络中。但经过大量阅读和调查后,我们发现了以下解决方案,我们仅在 POST 方法中遇到问题,GET 调用成功。

    我们需要首先对选项对象进行字符串化,而不是直接传递选项,例如 JSON.stringify(options)

    CreateUser(user:IUser): Observable<void> {
            let headers = new Headers();
            headers.append('Content-Type', 'application/json');
            headers.append('Accept', 'application/json');
            let options = new RequestOptions({ headers: headers });
            return this._http.post('http://localhost:22736/api/Employee/Create', **JSON.stringify(options)**)
                .map((res: Response) => {
                    return res.json();
                })
                .catch(this.handleError);
        }
    

    它对我有用,希望它对其他人也有帮助。

    【讨论】:

      【解决方案3】:

      我发现在 Angular 4 中你必须这样。

      public addQuestion(data: any): Observable<Response>  {
      
          let headersObj = new Headers();
          headersObj.set('Content-Type', 'application/x-www-form-urlencoded');
      
          let requestArg: RequestOptionsArgs = { headers: headersObj, method: "POST" };
      
          var params = new URLSearchParams();
          for(let key of Object.keys(data)){ 
            params.set(key,data[key]);
          };
      
          return this.http.post(BaseApi.endpoint + 'Question', params.toString(), requestArg)
          .map((res: Response) => res.json().data);
      
        }
      

      【讨论】:

      • 我在PUT 上仍然遇到此解决方案的问题。这仅适用于POST 请求吗?
      【解决方案4】:

      另一个原生解决方案是使用HttpParams 类,它是toString() 方法:

       let headers = new Headers({ 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' });
          let options = { headers, observe: 'response' };
      
         const body = new HttpParams()
            .set('grant_type', 'password')
            .set('username', accountInfo.username)
            .set('password', accountInfo.password);
      
          return this._http.post('https://localhost:44305/Token',  body.toString(), options)
      

      toString() - 将正文序列化为编码字符串,其中 键值对(用 = 分隔)用 &s 分隔。

      注意。它也可以在不设置标题的情况下工作

      【讨论】:

        猜你喜欢
        • 2016-01-18
        • 2018-09-13
        • 2023-04-10
        • 2017-05-10
        • 2016-02-08
        • 2018-01-25
        • 2016-05-19
        • 2017-08-24
        • 2018-09-06
        相关资源
        最近更新 更多