预检在一个Angular客户端失败但在另一个Angular客户端失败

时间:2017-10-22 17:20:05

标签: angularjs asp.net-web-api cors

我使用个人帐户身份验证模板创建了一个WebApi应用程序,并且我已启用CORS以允许各种客户端使用我的服务。我将CORS配置为允许所有来源(" *")。我还创建了一个Angular前端,它成功检索一个令牌,以便在调用安全路由时使用。但是,由于飞行前检查失败,客户端无法调用“注销”操作。

在解决问题时,我使用this article中的说明创建了一个单独的解决方案。新的解决方案很有效,因此我将新解决方案的客户指向我原来的WebApi项目,它也很有效。这让我相信Angular客户之间存在一些不同之处,但我还没有找到显着的差异。

有人可以查看下面的代码并指出有效的客户端和失败的客户端之间的区别吗?

这是应用程序中的Angular代码:

应用配置

app.config(['$httpProvider', function ($httpProvider) {
    $httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=utf-8';
    // Override $http service's default transformRequest
    $httpProvider.defaults.transformRequest = [function (data) {
    // Converts an object to x-www-form-urlencoded serialization.
    }];
}]);

在我的工厂

var deferred = $q.defer();
$http({
    method: 'POST',
    url: logoutUrl,
    headers: getHeaders(),
}).then(function (data, status, headers, cfg) {
    accessToken = null;
    deferred.resolve({ status: 'success' });
}, function (err, status) {
    console.log(err);
    deferred.reject(status);
});
return deferred.promise;

function getHeaders() {
    if (accessToken) {
        return { "Authorization": "Bearer " + accessToken };
    }
}

这是通过的原始HTTP请求。 OPTIONS预检检查通过,因此POST将通过。

OPTIONS http://localhost:56508/api/Account/Logout HTTP/1.1
Host: localhost:56508
Connection: keep-alive
Access-Control-Request-Method: POST
Origin: http://localhost:42458
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36
Access-Control-Request-Headers: authorization
Accept: */*
DNT: 1
Referer: http://localhost:42458/
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.8

POST http://localhost:56508/api/Account/Logout HTTP/1.1
Host: localhost:56508
Connection: keep-alive
Content-Length: 0
Accept: application/json, text/plain, */*
Origin: http://localhost:42458
Authorization: Bearer fNKcX_jCNhQuIhorMw-QPyezReQJd5ehoVhqegUmSQZxdbHp-T6L4RPehSl6ihSpNbYH58uhELwNHV0bEAyRj0G7bmFv4O5GIqBDyiOIB-YBfez5zHRNHbMe_iTdtBwdgOdbLh5PNSNIOi4ffU6H-py4oko0rMkLSP_hFSl2TGcbJwuJkrmHmahmLyeyQ-OO8KI4Kc-WoTaIVw3dJ5LDxbdSFF9aWoaCVGDfbP1tcp-aTMmydqZLnkX5DAGQPDawsiuXuWuwvUDPz6f4K5F78r4D8ldl8cCSO0uniSv3mIZYbgDuzwfjIrV_lN5pFYHg38f-7RcwvE-TARr0wJ1dNcM9XnNTJRXxsJRpJP-LAG369smEnRk2Z2D7Gds0KCAK7zKcwRyJh8u7_YCLcMVJR97mhJk-n4zEfnD3yxa0VsiNHkHiAAjtXF78ASWBW2LXXYlvn0Mu0tcltZ7Qur9-TslHjUhD1BmNkQzwTkQte3kbMk7HsCDZCWaxr-j_8ApD
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36
DNT: 1
Referer: http://localhost:42458/
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.8

这是应用程序中失败的Angular代码:

在我的工厂

var deferred = $q.defer();
$http({
    method: 'POST',
    url: logoutUrl,
    headers: {
        'Authorization': 'Bearer ' + accessToken
        ,'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8'
    },
}).then(function (data, status, headers, cfg) {
    accessToken = null;
    deferred.resolve({ status: 'success' });
}, function (err, status) {
    console.log(err);
    deferred.reject(status);
});
return deferred.promise;

这是通过的原始HTTP请求。 OPTIONS预检检查在这里失败,因此POST没有通过。

OPTIONS http://localhost:56508/api/Account/Logout HTTP/1.1
Host: localhost:56508
Connection: keep-alive
Access-Control-Request-Method: POST
Origin: http://localhost:45743
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36
Access-Control-Request-Headers: authorization
Accept: */*
DNT: 1
Referer: http://localhost:45743/
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.8

1 个答案:

答案 0 :(得分:0)

我了解到问题不在于我的$ http请求或CORS。之所以出现此问题,是因为我将异步函数调用为同步函数,并且在有机会完成之前取消了请求。

这是一个写得很差的代码示例。 Logout函数封装$ http请求。

    authService.logout();
    $window.location.href = location.origin;

以下是应该编写的代码示例。此代码按预期工作。

    authService.logout().then(function success(data){
        $window.location.href = location.origin;
    }, function failure(data) {
        $window.location.href = location.origin;
    });

无需等待解析的承诺导致$ http执行错误回调,但错误对象不可用。因此,我认为预检失败了,实际上POST已经被客户提前取消了。