首页 文章

如何使用AngularJS在浏览器cookie中存储身份验证承载令牌

提问于
浏览
12

我使用ASP.net Identity创建了一个承载令牌 . 在AngularJS中,我编写了这个函数来获取授权数据 .

$scope.GetAuthorizeData = function () {
$http({
            method: 'GET',
            url: "/api/Values",
            headers: { 'authorization': 'bearer <myTokenId>' },
}).success(function (data) {
            alert("Authorized :D");
            $scope.values = data;
        }).error(function () {
            alert("Failed :(");
        });
    };

所以 I want to store this token into Browser cookies . 如果此处存在此令牌,则获取令牌并从IIS服务器获取数据,否则重定向到登录页面以登录以获取新令牌 .

同样,如果用户点击退出按钮,它应该从浏览器cookie中删除令牌 .

How to do this ? It it possible ? Is it proper way to authenticate and authorize a user ? What to do if there are multiple users token ?

2 回答

  • 15

    使用 ngCookies 模块,AngularJS API中提供了 $cookies 服务 . 它可以像下面这样使用:

    function controller($cookies) {
        //set cookie
        $cookies.put('token', 'myBearerToken');
    
        //get cookie
        var token=$cookies.get('token');
    
        //remove token
        $cookies.remove('token');
    }
    controller.$inject=['$cookies'];
    

    对于你的情况,它将是:

    //inject $cookies into controller
    $scope.GetAuthorizeData = function () {
        $http({
            method: 'GET',
            url: "/api/Values",
            headers: { 'authorization': 'bearer <myTokenId>' },
        })
        .success(function (data) {
            $cookies.put('token', data);
        }).error(function () {
            alert("Failed :(");
        });
    };
    

    您还必须添加angular-cookies module代码 . 并将其添加到您的角度应用程序: angular.module('myApp', ['ngCookies']); . Docs for Angular Cookies.

    我还建议使用 Http interceptor ,它将为每个请求设置承载标头,而不必为每个请求自己手动设置 .

    //Create a http interceptor factory
    function accessTokenHttpInterceptor($cookies) {
        return {
            //For each request the interceptor will set the bearer token header.
            request: function($config) {
                //Fetch token from cookie
                var token=$cookies.get['token'];
    
                //set authorization header
                $config.headers['Authorization'] = 'Bearer '+token;
                return $config;
            },
            response: function(response) {
                //if you get a token back in your response you can use 
                //the response interceptor to update the token in the 
                //stored in the cookie
                if (response.config.headers.yourTokenProperty) {
                      //fetch token
                      var token=response.config.headers.yourTokenProperty;
    
                      //set token
                      $cookies.put('token', token);
                }
                return response;
            }
        };
    }
    accessTokenHttpInterceptor.$inject=['$cookies'];
    
    //Register the http interceptor to angular config.
    function httpInterceptorRegistry($httpProvider) {
        $httpProvider.interceptors.push('accessTokenHttpInterceptor');
    }
    httpInterceptorRegistry.$inject=['$httpProvider'];
    
    //Assign to module
    angular
        .module('myApp')
        .config(httpInterceptorRegistry)
        .factory('accessTokenHttpInterceptor', accessTokenHttpInterceptor)
    

    http interceptor 置于原位后,您无需为每个请求设置 Authorization header .

    function service($http) {
        this.fetchToken=function() {
            //Authorization header will be set before sending request.
            return $http
                .get("/api/some/endpoint")
                .success(function(data) {
                     console.log(data);
                     return data;
                })
        }
    }
    service.$inject=['$http']
    

    正如鲍里斯所说:还有其他方法可以解决这个问题 . 您也可以使用 localStorage 来存储令牌 . 这也可以与http拦截器一起使用 . 只需将实现从cookie更改为localStorage即可 .

    function controller($window) {
        //set token
        $window.localStorage['jwt']="myToken";
    
        //get token
        var token=$window.localStorage['jwt'];
    }
    controller.$inject=['$window'];
    
  • 18

    我建议不要将数据保存在cookie中,出于安全考虑,您应该将cookie设置为安全和HttpOnly(无法从javascript访问) . 如果您没有使用SSL,我建议您转到 https .

    我会在json响应中从auth endpoints 传递令牌:

    {
        tokenData: 'token'
    }
    

    您可以使用 $window 服务在 sessionStorage 中保存令牌数据:

    $window.sessionStorage.setItem('userInfo-token', 'tokenData');
    

    一旦用户关闭页面,它将被清除,您可以通过将其设置为空字符串来手动删除它:

    $window.sessionStorage.setItem('userInfo-token', '');
    

    编辑:

    用于捕获数据的拦截器实现,改编自cbass(未经测试,您可以检查对象以获取响应/请求以提供信息):

    //Create a http interceptor factory
    function accessTokenHttpInterceptor($window) {
        return {
            //For each request the interceptor will set the bearer token header.
            request: function($config) {
                //Fetch token from cookie
                var token=$window.sessionStorage.getItem('userInfo-token');
    
                //set authorization header
                $config.headers['Authorization'] = 'Bearer '+token;
                return $config;
            },
            response: function(response) {
                //if you get a token back in your response you can use 
                //the response interceptor to update the token in the 
                //stored in the cookie
                if (response.config.url === 'api/token' && response.config.data.tokenData) {
                      //fetch token
                      var token=response.config.data.tokenData;
    
                      //set token
                      $window.sessionStorage.setItem('userInfo-token', token);
                }
                return response;
            }
        };
    }
    
    accessTokenHttpInterceptor.$inject=['$window'];
    

相关问题