使用UI路由器和令牌

时间:2016-01-25 06:54:13

标签: javascript angularjs angular-routing

我正在为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访问页面而不登录和注销至少一次,则此方法失败,我仍然可以访问该页面。有小费吗?

2 个答案:

答案 0 :(得分: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);
        }
    };

答案 1 :(得分:0)

可能真的很晚(因为Angular2已经出来但是如果有人还在使用1.x我还在回答)但是我已经按照自己的时间使用Node发送JWT和Angular使用它而我用UI路由器做了。 然而,Simon的解决方案仍然有效,我尽量不要触摸rootScope。

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

<强> ngStorage

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

UI路由器状态的解决方案

1.x的官方文档声明,resolve是一个映射到函数的属性,在状态甚至初始化之前将触发。因此,这是一个你可以做一个国家依赖的微配置的地方,它也可以兑现承诺。

授权工厂

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

现在我解释一下我是如何做到的。

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

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

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

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

现在这可能听起来令人气愤,似乎并不是干涩的。但是我想说我在一个根父状态中做了所有这些,并将所有其他状态作为子状态附加。父是抽象的,因此可以做出决定,并且不需要初始化状态。家庭可以是默认的非抽象状态。

我试图远离rootScopes和$ watch和东西,我总是将它们作为最后的手段。干杯!