精华 AngularJS中基于cookie的权限认证【译】
发布于 2年前 作者 DongHongfei 17222 次浏览 来自 分享

单页应用(Single Page Apps)正在AngularJS的引领下统治着世界(好屌的样子)。我们在Web 2.0 时代学到的很多东西都已不再适用,在权限认证方面就感觉到了很大的不同。

对于不同的构建发布AngularJS app方式有很多处理权限认证的方法,我希望这篇文章可以让你搞清楚其中的一种。

CORS

CORS常常被误认为是由远程服务器配置的。CORS代表了Cross-Origin-Resource-Sharing(跨域资源共享),最初的设计是为了访问当前页面当前资源(原文:origin)(或域)之外的服务。

就像许多浏览器特征一样,CORS被广泛的认为是可行的。所有主流的浏览器像Chrome, Firefox, 和IE都支持,你可以使用这些浏览器来享受CORS带来的安全认证的好处。

这同时也意味着某些浏览器不支持它,这些浏览器跟咱们这里讨论的没啥关系。一个应用最广泛的例子就是本地的Web View比如Cordova和Phonegap(以及hence,Ionic apps),然而这些工具通常有一些关于白名单的配置选项,所以你可以用那种方法添加一些安全认证。

Configuring CORS on the Server

CORS工作的方式就是服务器决定接受哪个域来作为它的客户端。这就意味着一些开放API,如Twitter就可能允许任何客户端访问,或者一个封闭的API就可能决定仅仅允许某些正在运行的app的访问。

我不会深入讨论怎么在服务器上配置CORS的问题,这个只要在请求头的部分做一些设置就好了,在nginx上怎么做你可以参考这里。

如果你打算在单页应用做基于session的认证,有一个头你必须要设置,Access-Control-Allow-Credentials: true ,我们接下来就来看看咋做。

AngularJS Auth

如果你用标准的 $http 服务来接受远程APIs,就只需要你的服务器配置了允许你的域的请求就可以了,你也没必要保存cookies。

但很多情况下,例如登陆,我们需要设置和保存cookie的信息,但很多浏览器默认是不允许这样的,有时候你可能想破脑袋也想不明白为啥保存不了cookie的信息。

输入:withCredentials。withCredentials是一个设置在底层 XMLHttpRequest (AJAX)对象的标记,但是在AngularJS中我们可以在$http这样配置就可以做任何事了:

angular.module('myApp')
.config(['$httpProvider', function($httpProvider) {
  $httpProvider.defaults.withCredentials = true;
}])

CSRF

许多服务器使用CSRF来作为一种安全特性,同样,你可以在hybrid app依然这样做。CSRF是一种确保客户端发出的一个请求和服务器接受的是同一个请求。这种方式可以防止有人嗅探到你的cookie的session数据之后伪装成你(比如改个密码啥的).

为了使用CSRF,我们可以告诉 $http 来使用特殊的cookie名字来为CSRF设置正确的头(也要取决于你的服务器端框架,这里是使用Django的例子):

angular.module('myApp', ['ngCookies'])

.run(['$http', '$cookies', function($http, $cookies) {
  $http.defaults.headers.post['X-CSRFToken'] = $cookies.csrftoken;
}]);

我发现这个很好使,如果CSRF的token改变了中间会话(比如一个新用户登录了),这里的token并不会更新。为了解决这个问题,我们可以使用HTTP拦截器来为我们的每一次请求设置正确的CSRF头:

angular.module('myApp')

.provider('myCSRF',[function(){
  var headerName = 'X-CSRFToken';
  var cookieName = 'csrftoken';
  var allowedMethods = ['GET'];

  this.setHeaderName = function(n) {
    headerName = n;
  }
  this.setCookieName = function(n) {
    cookieName = n;
  }
  this.setAllowedMethods = function(n) {
    allowedMethods = n;
  }
  this.$get = ['$cookies', function($cookies){
    return {
      'request': function(config) {
        if(allowedMethods.indexOf(config.method) === -1) {
          // do something on success
          config.headers[headerName] = $cookies[cookieName];
        }
        return config;
      }
    }
  }];
}]).config(function($httpProvider) {
  $httpProvider.interceptors.push('myCSRF');
});

这个会把除了allowedMethods以外的所有CSRF请求头设置为正确的值。

Credentials and CORS

有一点需要注意,在 你的app使用 withCredentials: true 和CORS配置服务器的时候你不可以 Access-Control-Allow-Origin 头设置为 '*’,它必须配置到几个可以选择的源上。如果你非要这么做不可,我建议你不要用基于cookie的认证了,你可以用基于token的认证。

Token Auth

上面介绍的对于基于cookie认证的大部分服务器端是可行的,然而,有一些API 是希望 基于 HTTP 或者基于 token认证的系统。 如果你正在试图避免基于cookie认证的跨域问题,这些方法可能比较适合你。这儿还有一篇很牛B的文章你可以看下,AngularJS使用基于token认证的。 未来我们可能会在基于token认证的问题上重温这个话题。

原文地址

2 回复

学习了写的不错!!

不错,有待实践

回到顶部