简体   繁体   English

AngularJS中的授权标头不起作用

[英]Authorization header in AngularJS not working

I am using the Django REST token authentication for my API. 我正在为我的API使用Django REST令牌认证。

I posted my credentials to obtain token endpoint. 我发布了凭证以获得令牌端点。 However when I try to set the header in a correct way it keeps responding with a http 401 error. 但是,当我尝试以正确的方式设置标头时,它始终以http 401错误响应。 I tried it using curl -X GET http://127.0.0.1:8000/events/ -H 'Authorization: Token 4d92d36768ca5d555b59cf68899eceab39c23704 ' and that does work! 我尝试使用curl -X GET http://127.0.0.1:8000/events/ -H 'Authorization: Token 4d92d36768ca5d555b59cf68899eceab39c23704 ' ,它确实起作用了! This is my code: 这是我的代码:

app.controller('HomeController', ['$scope','$http', function($scope,$http) {
    $scope.username = '';
    $scope.password = '';
    $scope.submitLogin = function () {
        var credentials = {
            username : $scope.username,
            password : $scope.password,
        };

        var req = $http.post('http://127.0.0.1:8000/api-token-auth/', credentials);
        req.success(function(data, status, headers, config) {
            $scope.token = data.token;
            var str1 = 'Token ';
            $scope.tokenheader = str1.concat($scope.token);
            $http.defaults.headers.common.Authorization = $scope.tokenheader;
        });
        req.error(function(data, status, headers, config) {
            alert( "failure message: " + JSON.stringify({data: data}));
        });
    };
    $scope.getEvents = function () {
        var req = {
            method: 'GET',
            url: 'http://127.0.0.1:8000/events/',
        }
        $http(req).then( 
           function() {
                       console.log('succes')
           }, 
           function(){
                       console.log('fail') 
        });
    };
}]);

And the error message in chrome dev tools: chrome开发工具中的错误消息:

 XMLHttpRequest cannot load http://127.0.0.1:8000/events/. Response for preflight has invalid HTTP status code 401 

How do I get rid of this 401 error? 我如何摆脱这个401错误?

Edit: I just found out the fault lies in the fact that I did not have CORS installed on my API. 编辑:我只是发现错误在于我的API上未安装CORS。 I was using a CORS plugin in chrome that worked for the authentication part of my api but not for my events url! 我在Chrome中使用了CORS插件,该插件可用于api的身份验证部分,但不能用于事件url!

You need to add Token to the headers: 您需要将Token添加到标题中:

get($http, "/some_url", {headers: {"Authorization": "Token " + $your_token}}
    ....
    ....
);

Response code 401 means Unauthorized. 响应码401表示未授权。 If you are using Token based authentication then in case of fail it would be 403, Forbidden. 如果您使用的是基于令牌的身份验证,则在失败的情况下将为403(禁止)。 So my guess would be that it's username/password who is messing with it. 因此,我的猜测是,用户名/密码会令人困惑。 In your curl example you are not using them. 在您的curl示例中,您没有使用它们。

Did you check that the token is actually added to your request? 您是否检查过令牌实际上已添加到您的请求中?

You can do this for example using the Chrome developers tools. 例如,您可以使用Chrome开发者工具来执行此操作。

Personally I prefer to use the $httpprovider.interceptor as described in: 就个人而言,我更喜欢使用$ httpprovider.interceptor,如以下所述:

angularjs $httpProvider interceptor documentation angularjs $ httpProvider拦截器文档

This ensures that the tokens are always present on any call. 这样可以确保令牌始终出现在任何呼叫中。

If you are accessing more than one API, you should consider adding something like: 如果您要访问多个API,则应考虑添加以下内容:

           $httpProvider.interceptors.push(['$q', '$location', '$log', 'loginService', 'restHelperService',
            function ($q, $location, $log, loginService, restHelperService) {
                return {
                    request: function (config) {
                        // check if the request comes with an url
                        if (config.url) {
                            // check that the call is to the REST api, if yes add token
                            if (restHelperService.isRestCall(config.url)) {
                                // add auth header or revert to login
                                if (loginService.userIsLoggedIn()) {
                                    config.headers = config.headers || {};
                                    config.headers.Authorization = 'Token ' + loginService.getToken().token;
                                } else {
                                    $location.path('/login');
                                }
                            }
                        }
                        return config;
                    },
                    responseError: function (response) {
                        if (response.status === 401 || response.status === 403) {
                            // clear auth token if the REST call failed with the current token
                            if (response.config && response.config.url && restHelperService.isRestCall(response.config.url)) {
                                $log.debug(" restCall failed due to bad credentials, resetting credentials");
                                loginService.resetCredentials();
                                $location.path('/login');
                            }
                        }
                        return $q.reject(response);
                    }
                };
            }]);
    }])

This avoid issues that will arise when you start adding the token to API calls that don't expect them. 这样可以避免在您开始将令牌添加到不需要令牌的API调用中时出现的问题。 Also the code ensures that a user will be automatically redirected to the login page if the credentials are not valid. 此外,该代码还确保如果凭据无效,则用户将被自动重定向到登录页面。

The example, I'm using two additional services. 在示例中,我使用了两个附加服务。 A loginService that manages the tokens and a restHelperService that manages the urls of the REST framework. 管理令牌的loginService和管理REST框架的url的restHelperService。

I would recommend doing the same as else it will be hard to access the credentials from outside your controller. 我建议您这样做,否则将很难从控制器外部访问凭据。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM