当前位置: 首页 > 面试题库 >

AngularJS身份验证+ RESTful API

拓拔坚
2023-03-14
问题内容

几个不同的问题和一些不同的教程中都涉及到了这一点,但是我所遇到的所有以前的资源并没有完全解决问题。

简而言之,我需要

  • 通过POST从登录http://client.foohttp://api.foo/login
  • 为用户提供提供logout路由的“已登录” GUI /组件状态
  • 用户注销/注销时能够“更新” UI。 这是最令人沮丧的
  • 保护我的路由以检查身份验证状态(他们是否需要),并将用户相应地重定向到登录页面

我的问题是

  • 每次导航到另一个页面时,我都需要打电话以api.foo/status确定用户是否已登录。(ATM我使用Express进行路由)这会导致Angular确定诸如以下内容的问题ng-show="user.is_authenticated"
  • 成功登录/注销后,我需要刷新页面(我不想这样做)以填充诸如的内容{{user.first_name}},或者在注销的情况下清空该值。
    // 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使用post data和不使用query params。文档对此没有任何帮助。

为什么我觉得自己迷失了方向

  • 似乎每个教程都依赖于某些数据库(许多Mongo,Couch,PHP + MySQL,无限广告)解决方案,并且没有一个纯粹依赖于与RESTful API的通信来保持登录状态。登录后,还会通过发送其他POST / GET withCredentials:true,所以这不是问题
  • 我找不到任何使用Angular + REST + Auth,没有后端语言的示例/教程/仓库。

我不太骄傲

诚然,我是Angular的新手,如果我以一种荒谬的方式来处理它,也不会感到惊讶。如果有人提出其他选择,我会很高兴-即使是汤到坚果。

我使用的Express主要是因为我真的很喜欢JadeStylus-我没有结婚的Express“路由和会放弃它,如果我想要做的是唯一可能与角的路由。

在此先感谢您提供任何帮助。而且请不要问我Google,因为我有大约26页的紫色链接。;-)

1该解决方案依赖于Angular的$ httpBackend模拟,并且尚不清楚如何使其与真实服务器对话。

2这是最接近的,但是由于我已有需要使用的API进行身份验证,因此无法使用护照的’localStrategy’,并且编写OAUTH服务似乎是 疯狂的
……只有我打算使用。


问题答案:

这摘自我在此处有关url路由授权和元素安全性的博客文章,但我将简要总结要点:-)

前端Web应用程序中的安全性只是阻止Joe Public的开始措施,但是任何具有Web知识的用户都可以规避它,因此您也应该始终在服务器端拥有安全性。

角度安全性方面的主要关注点是路线安全性,幸运的是,在定义角度路线时,您要创建一个对象,该对象可以具有其他属性。我的方法的基础是在此路由对象中添加一个安全对象,该对象基本上定义了用户必须具有的角色才能访问特定路由。

     // 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'
            });

整个方法围绕授权服务进行,该服务基本上进行检查以查看用户是否具有所需的权限。该服务将关注点从该解决方案的其他部分中抽象出来,以解决用户及其在登录期间可能已从服务器检索到的实际许可。虽然代码很冗长,但我的博客文章中已对其进行了详细说明。但是,它基本上处理许可检查和两种授权模式。第一个是用户必须至少具有定义的权限中的一个,第二个是用户必须具有所有定义的权限。

    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;
    };

现在,路由已具有安全性,您需要一种确定路线更改开始后用户是否可以访问该路由的方法。为此,我们拦截了路由更改请求,检查了路由对象(上面有我们的新访问对象),如果用户无法访问视图,我们将其替换为另一个视图。

    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()’,因为它将当前路由(他们没有权限查看的路由)替换为我们将其重定向到的路由。这将停止任何操作,然后导航回未经授权的路线。

现在,我们可以拦截路由,我们可以做很多很酷的事情,包括如果用户登陆需要登录的路由,则在登录后进行重定向。

解决方案的第二部分是能够根据那里的权限向用户隐藏/显示UI元素。这可以通过一个简单的指令来实现。

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);
                  }
              }
            };
        }]);

然后,您将确定像这样的元素:

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

阅读我的完整博客文章,以详细了解该方法。



 类似资料:
  • 我尝试了angular.js,并从一个restful api的web-ui开始(使用超文本传输协议基本授权)。这真的很好,除了授权工作。 到目前为止,我使用的是设置密码,但大多数情况下浏览器会打开http basic auth的默认登录表单。另一个奇怪的行为是angular请求不包含授权头(选项和GET请求都不包含)。我还尝试使用header配置在每个请求上设置此header,但这也不起作用。 有

  • 问题内容: 因为在AngularJS中使用CORS和http身份验证可能会比较棘手,所以我编辑了问题以分享一个经验教训。首先,我要感谢igorzg。他的回答对我很有帮助。场景如下:您想使用AngularJS $ http服务将POST请求发送到另一个域。获取AngularJS和服务器设置时,需要注意一些棘手的事情。 第一:在您的应用程序配置中,您必须允许跨域调用 第二:您必须指定withCrede

  • 身份验证 PDF版下载 企业应用中的URL链接可以通过OAuth2.0验证接口来获取员工的身份信息。 通过此接口获取员工身份会有一定的时间开销。对于频繁获取员工身份的场景,建议采用如下方案: 企业应用中的URL链接直接填写企业自己的页面地址; 员工跳转到企业页面时,企业校验是否有代表员工身份的cookie,此cookie由企业生成; 如果没有获取到cookie,重定向到OAuth验证链接,获取员工

  • 问题内容: 我是AngularJS的新手,正在尝试为我的新Web应用程序对其进行评估。 需求: 我将有一个ASP.NET Web API,它将从Android,iPhone和Web应用程序(ASP.NET MVC)中使用。ASP.NET Identity将在Web API中实现。这三个应用程序都将调用Web API的login方法来获取auth令牌。 问题: 我的问题是当Angular进行调用以获

  • 问题内容: 我正在尝试在Node.js中使用Socket.IO,并试图允许服务器为每个Socket.IO客户端赋予一个身份。由于套接字代码不在http服务器代码的范围内,因此无法轻松访问已发送的请求信息,因此我假设在连接期间需要将其发送出去。什么是最好的方法 1)将有关谁通过Socket.IO连接到服务器的信息 2)验证他们说的是谁(如果正在使事情变得更容易,我目前正在使用Express) 问题答

  • 我试图使用swift代码在网站上找到这里,但响应是html代码与两个错误:“您必须输入密码!”和“您必须输入用户名!”我是NSURLSession的新手,试图更改用于身份验证的字符串,但无法更改响应。下面是我的代码: 这是控制台响应中的内容: