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

时间:2015-12-31 11:33:15

标签: javascript angularjs asp.net-web-api asp.net-identity

我使用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 :(");
  });
};

所以我想将此令牌存储到浏览器cookie 中。如果此处存在此令牌,则获取令牌并从IIS服务器获取数据,否则重定向到登录页面以登录以获取新令牌。

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

怎么做?有可能吗?是验证和授权用户的正确方法吗?如果有多个用户令牌怎么办?

2 个答案:

答案 0 :(得分:18)

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

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

{
    tokenData: 'token'
}

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

$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'];

答案 1 :(得分:15)

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

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'];