AngularJS认证+ REST的API [英] AngularJS Authentication + RESTful API

查看:349
本文介绍了AngularJS认证+ REST的API的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

本已涵盖在几个不同的问题,在几个不同的教程,但所有我遇到了previous资源不太一针见血的头部。

This has been covered in a few different questions, and in a few different tutorials, but all of the previous resources I've encountered don't quite hit the nail on the head.


  • 通过登录后从 http://client.foo http://api.foo/login

  • 有一个登录GUI /组件状态,提供了一个注销路由用户

  • 可以更新的UI在用户注销/注销。
     的这一直是最令人沮丧的

  • 保护我的路线检查认证状态(他们应该需要它)和相应的用户重定向到登录页面

  • Login via POST from http://client.foo to http://api.foo/login
  • Have a "logged in" GUI/component state for the user that provides a logout route
  • Be able to "update" the UI when the user logs out / logs out. This has been the most frustrating
  • Secure my routes to check for authenticated-state (should they need it) and redirect the user to the login page accordingly

  • 每次我导航到不同的页面,我需要调用 api.foo/status 来确定用户是否登录。(ATM我M使用防爆航线preSS)这引起打嗝的角度决定了像的东西NG-秀=user.is_authenticated

  • 当我成功登录/注销,我需要刷新页面(我不希望有这样做),以填充之类的东西 {{} user.first_name} 或注销的情况下,空的值OUT。

  • Every time I navigate to a different page, I need to make the call to api.foo/status to determine whether or not user is logged in. (ATM I'm using Express for routes) This causes a hiccup as Angular determines things like ng-show="user.is_authenticated"
  • When I successfully login/logout, I need to refresh the page (I don't want to have to do this) in order to populate things like {{user.first_name}}, or in the case of logging out, empty that value out.
// Sample response from `/status` if successful 

{
   customer: {...},
   is_authenticated: true,
   authentication_timeout: 1376959033,
   ...
}

我已经试过


  • http://witoldsz.github.io/angular-http-auth/1

  • http://www.frederiknakstad.com/authentication-in-single-page-applications-with-angular-js/2

  • https://github.com/mgonto/restangular (对于我的生活我无法弄清楚如何 POST 后的数据,而不是查询参数打开该文档一无所获的事情。

  • What I've tried

    • http://witoldsz.github.io/angular-http-auth/1
    • http://www.frederiknakstad.com/authentication-in-single-page-applications-with-angular-js/2
    • https://github.com/mgonto/restangular (For the life of me I could not figure out how to POST with post data and not query params. The docs turned up nothing on the matter.

      • 这好像每个教程依赖于一些数据库(大量的Mongo,沙发,PHP + MySQL的,循环往复的)解决方案,并没有完全依赖于通信与一个RESTful API坚持已登录状态。登录后,额外职位/获取与 withCredentials发:真正的,所以这不是问题

      • 我找不到任何的例子/教程/回购那些角+ REST +验证,SANS后端语言。

      • It seems as though every tutorial relies on some database (lots of Mongo, Couch, PHP+MySQL, ad infinitum) solution, and none rely purely on communication with a RESTful API to persist logged-in states. Once logged in, additional POSTs/GETs are sent with withCredentials:true, so that's not the issue
      • I cannot find ANY examples/tutorials/repos that do Angular+REST+Auth, sans a backend language.

      不可否认,我是新来的角,也不会是,如果我在一个荒谬的方式接近这一惊讶;我会很高兴,如果有人提出一个替代方案,即使它的汤到坚果。

      Admittedly, I'm new to Angular, and would not be surprised if I'm approaching this in a ridiculous way; I'd be thrilled if someone suggest an alternative—even if it's soup-to-nuts.

      我用防爆preSS 主要是因为我真的很喜欢 - 我不是嫁给了防爆preSS '路径,如果将放弃我想要做的仅仅是可能有角的路由。

      I'm using Express mostly because I really love Jade and Stylus— I'm not married to the Express' routing and will give it up if what I want to do is only possible with Angular's routing.

      预先感谢任何帮助任何人都可以提供。请不要问我谷歌,因为我有大约26页的紫色链接。 ; - )

      Thanks in advance for any help anyone can provide. And please don't ask me to Google it, because I have about 26 pages of purple links. ;-)

      1 该解决方案依赖于角的$ httpBackend戏弄,目前还不清楚如何使它跟一个真正的服务器。

      1This solution relies on Angular's $httpBackend mock, and it's unclear how to make it talk to a real server.

      2 这是最接近的,但因为我有一个现成的API,我需要,我不能使用护照的localStrategy'进行身份验证,它似乎以写一个OAuth服务......只有我打算用。

      2This was the closest, but since I have an existing API I need to authenticate with, I could not use passport's 'localStrategy', and it seemed insane to write an OAUTH service...that only I intended to use.

      推荐答案

      这是从我的博客后采取的URL路径的授权和安全元素的这里,但我将简要地总结要点: - )

      This is taken from my blog post on url route authorisation and element security here but I will briefly summaries the main points :-)

      在前端Web应用程序安全性仅仅是一个起点措施来阻止乔公,然而,随着一些网络知识,任何用户都可以绕过它,所以你应该始终有保障的服务器端也是如此。

      在安全性的东西主要关注在角是路线的安全,在角度定义路线幸运的是,当你创建一个对象,一个对象,可以有其他属性。基石到我的方法就是将一个安全对象添加到该路由对象基本上定义了用户必须在角色中,以便能够访问特定路由。

      The main concern around security stuff in angular is route security, luckily when defining a route in angular you are create an object, an object that can have other properties. The cornerstone to my approach is to add a security object to this route object which basically defines the roles the user must be in to be able to access a particular route.

       // route which requires the user to be logged in and have the 'Admin' or 'UserManager' permission
          $routeProvider.when('/admin/users', {
              controller: 'userListCtrl',
              templateUrl: 'js/modules/admin/html/users.tmpl.html',
              access: {
                  requiresLogin: true,
                  requiredPermissions: ['Admin', 'UserManager'],
                  permissionType: 'AtLeastOne'
              });
      

      整个方法的重点围绕着一个授权服务基本上做的检查,以查看用户是否具有所需的权限。此服务抽象从该溶液中的其他部分的关注远做,将已经从服务器登录期间检索到的用户和他们的实际许可。虽然code是相当冗长它在我的博客文章充分说明。但是,它基本上处理权限检查和授权两种模式。首先,用户必须拥有至少在定义的权限的,第二个是,用户必须具有所有已定义的权限。

      The whole approach focuses around an authorisation service which basically does the check to see if the user has the required permissions. This service abstract the concerns away from the other parts of this solution to do with the user and their actual permission that would have been retrieved from the server during login. While the code is quite verbose it is fully explained in my blog post. However, it basically handle the permission check and two modes of authorisation. The first is that the user must have at least on of the defined permissions, the second is the user must have all of the defined permissions.

      angular.module(jcs.modules.auth.name).factory(jcs.modules.auth.services.authorization, [  
      'authentication',  
      function (authentication) {  
       var authorize = function (loginRequired, requiredPermissions, permissionCheckType) {
          var result = jcs.modules.auth.enums.authorised.authorised,
              user = authentication.getCurrentLoginUser(),
              loweredPermissions = [],
              hasPermission = true,
              permission, i;
      
          permissionCheckType = permissionCheckType || jcs.modules.auth.enums.permissionCheckType.atLeastOne;
          if (loginRequired === true && user === undefined) {
              result = jcs.modules.auth.enums.authorised.loginRequired;
          } else if ((loginRequired === true && user !== undefined) &&
              (requiredPermissions === undefined || requiredPermissions.length === 0)) {
              // Login is required but no specific permissions are specified.
              result = jcs.modules.auth.enums.authorised.authorised;
          } else if (requiredPermissions) {
              loweredPermissions = [];
              angular.forEach(user.permissions, function (permission) {
                  loweredPermissions.push(permission.toLowerCase());
              });
      
              for (i = 0; i < requiredPermissions.length; i += 1) {
                  permission = requiredPermissions[i].toLowerCase();
      
                  if (permissionCheckType === jcs.modules.auth.enums.permissionCheckType.combinationRequired) {
                      hasPermission = hasPermission && loweredPermissions.indexOf(permission) > -1;
                      // if all the permissions are required and hasPermission is false there is no point carrying on
                      if (hasPermission === false) {
                          break;
                      }
                  } else if (permissionCheckType === jcs.modules.auth.enums.permissionCheckType.atLeastOne) {
                      hasPermission = loweredPermissions.indexOf(permission) > -1;
                      // if we only need one of the permissions and we have it there is no point carrying on
                      if (hasPermission) {
                          break;
                      }
                  }
              }
      
              result = hasPermission ?
                       jcs.modules.auth.enums.authorised.authorised :
                       jcs.modules.auth.enums.authorised.notAuthorised;
          }
      
          return result;
      };
      

      现在的路线有你需要确定是否当路由变化已经开始,用户可以访问路线的方法的安全性。要做到这一点,我们来拦截路径改变请求,检查路由对象(与我们在其上新的访问对象),如果用户无法访问视图我们替换用另一个的路由。

      Now that a route has security you need a way of determining if a user can access the route when a route change has been started. To do this we be intercepting the route change request, examining the route object (with our new access object on it) and if the user cannot access the view we replace the route with another one.

      angular.module(jcs.modules.auth.name).run([  
          '$rootScope',
          '$location',
          jcs.modules.auth.services.authorization,
          function ($rootScope, $location, authorization) {
              $rootScope.$on('$routeChangeStart', function (event, next) {
                  var authorised;
                  if (next.access !== undefined) {
                      authorised = authorization.authorize(next.access.loginRequired,
                                                           next.access.permissions,
                                                           next.access.permissionCheckType);
                      if (authorised === jcs.modules.auth.enums.authorised.loginRequired) {
                          $location.path(jcs.modules.auth.routes.login);
                      } else if (authorised === jcs.modules.auth.enums.authorised.notAuthorised) {
                          $location.path(jcs.modules.auth.routes.notAuthorised).replace();
                      }
                  }
              });
          }]);
      

      这里的关键真的是'.replace()',因为这取代目前的路线与我们将其重定向到路由(他们没有得到权利看到一个)。该停止任何然后导航回未经授权的路线。

      The key here really is the '.replace()' as this replace the current route (the one they have not got rights to see) with the route we are redirecting them to. This stop any then navigating back to the unauthorised route.

      现在我们可以拦截路线,我们可以做不少很酷的事情,包括<一个href=\"http://jonsamwell.com/url-route-authorization-and-security-in-angular/#redirecting_after_login\">redirecting登录后如果用户登陆的路线上,他们需要被记录在。

      Now we can intercept routes we can do quite a few cool things including redirecting after a login if a user landed on a route that they needed to be logged in for.

      该解决方案的第二部分是能够根据有权利隐藏/显示UI元素给用户。这是通过一个简单的指令实现的。

      The second part of the solution is being able to hide/show UI element to the user depending on there rights. This is achieve via a simple directive.

      angular.module(jcs.modules.auth.name).directive('access', [  
              jcs.modules.auth.services.authorization,
              function (authorization) {
                  return {
                    restrict: 'A',
                    link: function (scope, element, attrs) {
                        var makeVisible = function () {
                                element.removeClass('hidden');
                            },
                            makeHidden = function () {
                                element.addClass('hidden');
                            },
                            determineVisibility = function (resetFirst) {
                                var result;
                                if (resetFirst) {
                                    makeVisible();
                                }
      
                                result = authorization.authorize(true, roles, attrs.accessPermissionType);
                                if (result === jcs.modules.auth.enums.authorised.authorised) {
                                    makeVisible();
                                } else {
                                    makeHidden();
                                }
                            },
                            roles = attrs.access.split(',');
      
      
                        if (roles.length > 0) {
                            determineVisibility(true);
                        }
                    }
                  };
              }]);
      

      您会那么肯定,像这样一个元素:

      You would then sure an element like so:

       <button type="button" access="CanEditUser, Admin" access-permission-type="AtLeastOne">Save User</button>
      

      阅读我充分的博客文章了解更详细的概述的办法

      Read my full blog post for a much more detailed overview to the approach.

      这篇关于AngularJS认证+ REST的API的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆