【问题标题】:JWT Authentication in Angular - Multiple authentication levelsAngular 中的 JWT 身份验证 - 多个身份验证级别
【发布时间】:2015-04-16 14:27:11
【问题描述】:

我正在构建一个带有sails.js 后端的角度应用程序。我已将此 JWT 身份验证合并到应用程序中。
https://github.com/Foxandxss/sails-angular-jwt-example

我仍在探索身份验证的工作原理,目前正在尝试弄清楚如何添加多个授权级别。 它预先构建了 0 和 1,我想在此之上添加一个管理员级别。

它处理现有的授权级别如下: 每个路由都通过一个常量分配一个授权级别。所以所有用户路由都会在 state 中的 data 属性上获得这个访问属性:

    $stateProvider
          .state('user', {
            abstract: true,
            template: '<ui-view/>',
            data: {
              access: AccessLevels.user
            }
          })

AccessLevels.user 是从一个常量键值对中提取的:

angular.module('app')
  .constant('AccessLevels', {
      anon: 0,
      user: 1
  });

每当导航到某个路由时,它都会检查 data.access 属性以查看该特定路由的访问级别。如果它作为需要身份验证的路由返回,它会检查 localStorage 是否有令牌。如果有令牌,则路由继续,否则引导您。

这是在 stateChangeStart 上调用的函数:

authorize: function(access) { //<- 'access' will be whatever is in the data property for that state
        if (access === AccessLevels.user) {
          return this.isAuthenticated(); // <- this just grabs the token
        } else {
          return true;
        }
      }

那么添加额外图层的最简单方法是什么?
我显然需要将 auth_level 值放入用户模型中。但是然后呢?添加此功能并保持现有身份验证完整性的最佳方法是什么(我担心安全性)?

【问题讨论】:

    标签: angularjs sails.js jwt


    【解决方案1】:

    您可以使用private claims 来持有服务器授予的授权。私有声明让您可以在 JWT 中添加您想要的任何其他类型的数据。

    我从未使用过node-jsonwebtoken(这似乎是sails.js 用于JWT 的东西),但看起来您可以直接使用JWT 有效负载来访问您希望存在的值,所以你可以这样做:

    // Assign authorization on server after successful authentication of an admin
    token.auth = AccessLevels.admin;
    
    // Read authorization on client
    authorize: function(access) {
        if (access === AccessLevels.anon) {
            return true;
        }
        // Assumes the JWT token is returned by isAuthenticated()
        // (Sorry, not familiar with Sails.js or the JWT example)
        return this.isAuthenticated().auth === access;
    }
    

    身份验证后,任何后续请求也应验证用户的授权,可能通过在您提供的示例中添加类似于“tokenAuth”的附加策略,但验证提供的 JWT 上的 auth 声明与所需的授权匹配调用任何即将被调用的函数。

    【讨论】:

    • 所以我看到服务器端授权控制器在成功登录时发回用户对象和一个令牌键值对。令牌包含签名方法的值,有效负载为{sid: user.id}。你是说我可以把它改成{sid: user.id, auth_level: user.auth_level}
    • 是的。 JWT 的声明基本上是一个映射,JWT 定义了某些特定的键/值对(iss、sub、aud、exp、nbf、iat、jti),但也允许添加其他生产者/消费者定义的声明。大多数库也支持添加任意声明,并且使用 JavaScript,声明通常是一个映射,您可以开始添加和分配值。
    【解决方案2】:

    首先,Erik Gillespie 让我朝着正确的方向前进。谢谢!

    为了向我的 angular/sails 应用程序添加额外级别的身份验证,我必须执行以下操作:

    • 我必须在我的用户模型中添加一个“级别”字段。我正在使用的身份验证模块已经为匿名用户 (0) 和普通用户 (1) 设置了一些变量。所以现在我的用户模型存储你是 1 级还是 2 级。
    • 我必须更新 Angular 应用程序中的相关常数,该应用程序在执行某些身份验证时会被引用。我刚刚将admin: 2 添加到现有的用户类型列表中。
    • 我不得不在我的 JWT 中使用私有声明将用户级别存储在他们的会话令牌中。这对于确认用户在尝试做某事(通常是 CRUD)时确实拥有他们所说的权限是必要的。他们的权限级别将根据存储在其令牌中的权限级别进行检查。这导致我接下来要做的事情......
    • 我必须创建两个策略。 Sails 有一个简洁的配置结构,您可以在 API 中创建中间件(它称它们为策略)。您只需使用您可能需要的任何中间件填充策略文件夹。然后在sails config 文件夹中,有一个对应的policy.js 文件,您可以在其中为每个控制器的每个特定功能分配中间件。很酷。所以我创建了一个中间件来检查以确保用户是他们所说的权限级别,另一个以确保他们是管理员(如果他们试图做管理员的事情)。然后,我将适当的中间件添加到我想要限制的任何功能中。
    • 如果有人登录,我有两个单独的仪表板以及一些普通用户无法访问的页面。例如,Angular 需要检查您是管理员还是用户,然后将您引导至适当的仪表板。我没有弄乱我的导航,而是在 app.run 中创建了一个这样的函数:
          $rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams) {
                if (toState.url == '/dashboard') {
                  var dash = Auth.level(); // <- this is a service I made that checks the users level and returns the appropriate state to go to for that user
                  event.preventDefault();
                  $state.go(dash);
                }
      我添加了适合每种用户类型的任何路由,然后当他们点击该 url 时,它会将它们推送到正确的那个。我的路线也都有一个附加的数据对象,指定访问所需的级别。因此,它会检查用户级别,以确保他们甚至可以进入应用程序的该部分。该 get 使用类似的 stateChangeStart 函数进行处理。

    【讨论】:

      猜你喜欢
      • 2019-03-15
      • 1970-01-01
      • 2020-07-23
      • 2016-04-24
      • 2020-03-18
      • 2020-01-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多