2016-12-01 124 views
3

我在寻找最好的架构解决方案。Angular JS身份验证维护

我有以下的html:

<body ng-controller="individualFootprintController as $ctrl"> 
<div ng-hide="$ctrl.authenticated"> 
      <h1>Login</h1> 
      With Corporate Account: <a href="/login/corporate">click here</a> 
</div> 

和控制器:

function individualFootprintController($http) { 
     var self = this; 
     $http.get("/is_auth").success(function() { 
      self.authenticated = true; 
     }) 
      .error(function() { 
       self.authenticated = false; 
      } 
     ); 
} 

问题:

1)这是控制器具有这种逻辑适当的地方吗?

2)我想要有实际的“is_authenticated”值。如果我只想触发一次请求,如何才能做到这一点

回答

0

推测后端身份验证需要某种实际的令牌。即您不只是在某处设置了一个true/false标志并将其称为身份验证,但为了能够与后端进行通信,您需要在请求中包含用户名/密码/ cookie /令牌,否则请求将被拒绝。

控制器是一个糟糕的地方来存储这样的事情,因为控制器不是永久的。或者至少你不应该尽可能使它们永久。另外,将令牌存储在控制器中不允许任何其他访问。

  1. 无论您是否登录,都应基于您是否拥有有效的身份验证令牌。
  2. 此令牌必须存储在规范的地方,最适合于这是一项服务。
  3. 其他服务从那里获取令牌,并根据令牌是否可用来决定应用程序当前是否“已登录”。

的应当如何构建一个草图:

app.service('AuthService', function() { 
    this.token = null; 
}); 

app.service('FooService', function (AuthService, $http) { 
    $http.get(..., AuthService.token, ...) 
}); 

app.controller('LoginStatusController', function (AuthService) { 
    Object.defineProperty(this, 'isLoggedIn', { 
     get: function() { return AuthService.token != null; } 
    }); 
}); 
<div ng-controller="LoginStatusController as ctrl"> 
    <div ng-hide="ctrl.isLoggedIn"> 

当你实际登录并获得令牌,你设置AuthService.token,这将是提供给所有其他服务和控制器。如果令牌变为无效或未设置,则所有服务和控制器将失去其已认证状态。

+0

他使用Cookie认证。 –

+0

在jwt auth scenari中,“我有一个标记”这一事实并不意味着你已经过身份验证。通过身份验证更像是“我的令牌有效”,必须经常检查。 –

+0

如果令牌是隐含的,那么只需用'true' /'false'标志替换它即可。是的,直到你尝试它,你才会知道你的代币是否有效。所以当它失败时,将其无效。 – deceze

0

我最常做的是:

使用ui-router

  • 趁着resolve钩(这解决了一些指定参数和其注入控制器),并定义我的路线为主路由器的子路由器,用于检查每个路由器上的认证变化

    scripts/services/user.js

    angular.module('yourmodule') 
        .service('userSrv', function ($http, $q) { 
        var srv = {}; 
    
        srv.getAuthenticatedUser = function() { 
         return $http.get("/authenticated_user"); 
        }; 
    
        return srv; 
        }); 
    

    脚本/路线。JS

    angular 
    .module('yourmodule') 
    .config(function ($stateProvider) { 
        $stateProvider 
        .state('authenticated', { 
         abstract: true, 
         template: '<ui-view />', 
         controller: 'AuthenticatedCtrl', 
         resolve: { 
         signedInUser: function(userSrv, $q) { 
          return userSrv.getAuthenticatedUser() 
          .then(function(null, function() { 
          //Catch any auth error, likely 403 
          //And transform it to null "signedInUser" 
          //This is the place to handle error (log, display flash) 
          return $q.resolve(null); 
          }); 
         } 
         } 
        }) 
        .state('authenticated.myspace', { 
         url: '/myspace', 
         templateUrl: 'views/myspace.html' 
        }); 
    }); 
    
  • 把你的观点内线优势$范围继承

    脚本/控制器/ authenticated.js

    angular.module('yourmodule') 
        .controller('AuthenticatedCtrl', function (signedInUser, $scope, $state) { 
        //Here you set current user to the scope 
        $scope.signedInUser= signedInUser; 
    
        $scope.logout = function() { 
        //this is where you would put your logout code. 
        //$state.go('login'); 
        }; 
    }); 
    

    的意见/ myspace.html

    <!-- here you call parent state controller $scope property --> 
    <div ng-hide="signedInUser"> 
        <h1>Login</h1> 
        With Corporate Account: <a href="/login/corporate">click here</a> 
    </div> 
    

1)我想要有实际的“is_authenticated”值。如果我只想触发一次请求,如何才能做到这一点 我的解决方案要求经过验证的用户对每次路由更改。这似乎很奇怪,但这实际上是可行和快速的。查询不应该> 30ms,这是一个非常小的选择。尽管如此,询问“我是否已通过身份验证”和“获取已通过身份验证的用户”是相同的事情,除了一个返回一个布尔值,另一个返回用户。我建议,就像我刚刚指出的那样,通过请求经过身份验证的用户处理“我通过身份验证”问题,然后用“if(user)”(空值处理)对其进行布置。

2)这个控制器是否适合拥有这个逻辑? 是的,没有。正如你所看到的,控制器是“将用户设置为范围事物”的地方,但范围继承允许您不必为每条路径重复它。虽然,http api逻辑应该被移植到一个服务上,并且路由事件(“获取这个页面的认证用户,请”是一个路由事件恕我直言)应该设置在一个单独的文件中。

注意:如果你需要完整的路线“保护”(如对未通过认证,问另外一个问题,我会很高兴回答这个问题重定向)