angularjs 用户认证解决方案

PHPABC angularjs 1,095 次浏览 , 没有评论

作为一个全栈ajax的mvvm框架,angularjs可谓如火如荼,可真正做到全栈ajax,首要面对的问题就是用户身份验证。

本文的身份验证不采用cookie,而采用基于http Authorize 请求头的方式验证用户,此方式能做到永远只有一个用户同时在线(服务端同一时间只会接受一个合法的token请求,其他的请求返回401)

这里我采用service保存用户信息,service如下

  .factory('Authorize', function() {    return {     uid: '',     token: '',     logout: function() {      this.uid = '';      this.token = '';      localStorage.removeItem('authorize.uid');      localStorage.removeItem('authorize.token');     }    }   }) 

由于service是单例的。保存在service很合适,再看登录检测。

验证流程

app运行时主动读取localStorage中的authorize.uid和authorize.token字段,将这两个字段发送至后端接口验证,如果验证成功返回用户信息,验证失败返回http 401错误(未授权)。

如果localStorage没有上述两个字段,则检测url中是否有,如果有则写入本地localStorage之后发送至后端验证,如果没有,跳转至后端服务器的oauth接口进行授权拿之后,将openid和token写入queryString并回调到app页面,代码如下:

    Authorize.uid = $location.search().uid || localStorage.getItem('authorize.uid');     Authorize.token = $location.search().token || localStorage.getItem('authorize.token');     if (!Authorize.uid || !Authorize.token) {      if (!Platform.isWechat) {       Authorize.uid = 1001;       Authorize.token = '2ddha3nry8';      }      else {       location.href = CONFIG.api + '/auth/oauth?callback=' + encodeURIComponent($location.protocol() + "://" + $location.host() + ":" + $location.port() + "/#" + $location.path());       return;      }     }     //写入本地     localStorage.setItem('authorize.uid', Authorize.uid);     localStorage.setItem('authorize.token', Authorize.token);     //读取用户数据     var user = User.get({uid: Authorize.uid}, function() {      $rootScope.user = user;     }); 

读取用户数据这边,采用的$resource服务封装,这里就不说了。

请求过程中的授权处理

接下来是比较重要的一点,如何在登陆后在每次请求头中注入Authorize信息,方法是采用拦截器。

有一个问题,如果由于刷新过快,检测用户回调还没执行完,这时候访问所有接口都是401,这里就需要在$httpProvider上注入拦截器进行请求恢复了。代码如下:

.factory('AuthInjector', function($q, Authorize, $injector, CONFIG) {    return {     request: function(config) {      if (Authorize.token) {       config.headers.Authorization = 'Bearer ' + Authorize.token;      }      return config;     },     response: function(response) {      var defer = $q.defer();      defer.resolve(response);      return defer.promise;     },     requestError: function(error) {     },     responseError: function(error) {      //如果401且本地存在uid,则刷新accessToken      if (error.status == 401) {       //刷新请求       var $http = $injector.get("$http");       $http({        method: 'GET',        url: CONFIG.api + '/auth/token',        params: {         uid: Authorize.uid        }       }).success(function(data) {        Authorize.token = data.token;        //写入本地        localStorage.setItem('authorize.token', data.token);        return $http(error.config);       });      }      else if (error.status == 422) {       var resp;       angular.forEach(error.data, function(item) {        if (resp == undefined) {         resp = item;        }       });       return $q.reject(resp);      }      return $q.reject({       message: '请求失败'      });     }    }   }) 

原理就是所有的http请求一旦返回401就进行重新登录请求,最后一句

return $http(error.config);

会将之前报401错误的请求恢复并重新执行一遍。

大体就是这么多,总结一下就是

app.run中检测登录

Authorize服务保存用户信息

httpProvider中注入拦截器实现Authorize头的自动添加和401结果的请求恢复

发表评论

电子邮件地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据

Go