【问题标题】:Redirecting in AngularJS using UI router and a token使用 UI 路由器和令牌在 AngularJS 中重定向
【发布时间】:2016-01-25 06:54:13
【问题描述】:

我正在为Angular SPA(单页应用程序)编写代码。

  • 在后端,它连接到用Java 编写的引擎,该引擎完成大部分处理(我不关心)。

  • 我正在使用UI Router 进行路由。

问题

但是有一个棘手的情况我无法完成。

  • 登录时,我进行了 API 调用,该调用返回 JSON 格式的响应。

  • 如果我的调用成功(即登录凭据匹配),我会在返回的 JSON 中获得一个令牌,它基本上只是一个由符号、字母和数字组合而成的字符串。

  • 我将其保存在我的rootscope 中,然后以 $rootScope.myToken 的形式访问它。

  • 然后我在随后的 API 调用中使用相同的令牌。

现在我想在AngularJS 中做的是如果用户未登录并尝试通过在地址栏中输入直接访问某个 URL 来将用户重定向到登录页面。

我在这里找到了一个相当简单的方法 Redirect on all routes to login if not authenticated 。但是我无法用我的令牌来实现这一点。

问题

我应该怎么做才能使用令牌进行这项工作?除了这个答案之外的任何其他建议也是受欢迎的。

PS:我在 stackoverflow 上尝试了多种方法,但我发现它们要么不能在我的上下文中工作,要么过于复杂。

更新:我可以在我的代码中成功实现 Simon H 的答案。但是我面临的问题是,这只会在我登录和退出我的应用程序至少一个之后重定向。如果我尝试通过 URL 直接访问页面而无需登录和退出至少一次,此方法将失败,我仍然可以访问该页面。有小费吗?

【问题讨论】:

    标签: javascript angularjs angular-routing


    【解决方案1】:

    网上有很多关于 angular 和 jwt 的教程

    我用这些来开发你想要的东西。它们的关键部分代码在配置中

    $httpProvider.interceptors.push(function($q, $location, $localStorage, $injector) {
        return {
            'request': function (config) {
                config.headers = config.headers || {};
                if ($localStorage.token) {
                    config.headers.Authorization = 'Bearer ' + $localStorage.token;
                }
                return config;
            },
            'responseError': function(response) {
                /* 401, unauthorised:
                    - bad username / password
                    - token expired
                   403, forbidden - notAdmin
                */ 
                // if(response.status === 401 || response.status === 403) {
                if(response.status === 401) {
                    console.log("app.js: httpInterceptor caught 40x:", response);
                    $injector.get('$state').go('login');
                }
                // Replace reponse with rejected promise to prevent rest of execution
                return $q.reject(response);
            }
        };
    

    【讨论】:

    • 我是Web开发的初学者,从我的阅读来看,JWT相当复杂。就我而言, Token 只不过是我在问题中提到的随机生成的字符串。也许它甚至不是一个适当的令牌,我们只是称它为一个令牌。这还能用吗?
    • 另外,我有点困惑这段代码应该在哪里?在包含我的路由代码的app.js 文件中,我应该将它放在路由配置中吗?还是在外面?
    • 更新: 我可以在我的代码中成功实现这一点。但是我面临的问题是,这只会在我登录和退出我的应用程序至少一个之后重定向。如果我尝试通过 URL 直接访问页面而无需登录和退出至少一次,此方法将失败,我仍然可以访问该页面。有什么建议吗?
    【解决方案2】:

    可能真的很晚了(因为 Angular2 已经出来了,但是我仍然在回答是否有人仍在使用 1.x)但我已经在自己的时间里使用 Node 发送 JWT 和 Angular 使用它,我使用 UI 路由器完成了它. Simon 的解决方案会起作用,但是我尽量不要碰 rootScope。

    我实现了 3 个东西来让它工作。授权服务、ngStorage 模块和 Ui 路由器的状态解析属性。

    ngStorage

    这是一个暴露 $localStorage 和 $sessionStorage 的模块。您可以向其中添加任何对象,它会在浏览器中设置它,直到您清除它为止。

    UI 路由器状态的解析

    1.x 的官方文档指出,resolve 是一个映射到函数的属性,并且会在状态初始化之前触发。因此,这是一个你可以进行状态所依赖的微配置的地方,而且它对 Promise 也有好处。

    授权工厂

    这是一家有 3 项服务的工厂。登录、注销和 isAuthenticated。登录服务在成功时将令牌设置在 $localStorage 中。在它的依赖注入中,我将它与 ngStorage 的 $localStorage 服务以及 $http 和其他服务一起注入。


    现在我解释一下我是怎么做的。

    我总是将我的默认状态指向我的家庭状态而不是登录状态。

    我没有使用 rootscope,而是将授权工厂的登录服务发布到服务器的登录端点(该端点会给我一个新的令牌)。收到令牌后,我将其设置为 $localStorage 作为我的令牌。

    然后,在解决我的家庭状态时,我调用授权工厂的 isAuthenticated 服务,该服务仅检查令牌是否设置在 $localStorage 中。如果不是,则返回 false。如果返回 false,我可以通过 $state.go('login'); 将主状态重定向转换为我的登录状态;

    我得到的是,在每个 $http 调用应用程序范围内,我可以在控制器中注入授权的 isAuthenticated 服务并让它检查令牌(哪个登录服务得到了,哪个 isAuthenticated 也可以访问,因为它们是在同一家工厂)。如果存在令牌,我会提取该令牌并将其与我的数据一起发送到服务器。然后,我的服务器可以进行额外的令牌验证,例如检查它的到期时间和内容,并以 401 或 200 响应。

    现在这听起来可能令人气愤,而且看起来还不是 DRY。但我想说的是,我在一个根父状态中执行所有这些操作,并将所有其他状态附加为子状态。父级是抽象的,因此可以进行解析,无需初始化状态。 home 可以是默认的非抽象状态。

    我尽量远离 rootScopes 和 $watches 之类的东西,我总是把它们作为最后的手段。干杯!

    【讨论】:

      猜你喜欢
      • 2015-01-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多