AngularJS SPA 应用中集成 JWT 的实践

前言

在现代 Web 开发中,无论是传统后端渲染的应用,还是新型的单页面应用(SPA),都需要用到身份验证和授权。JSON Web Token(JWT)是一种用于描述安全令牌的 JSON 格式规范,广泛应用于 RESTful API 和 SPA 架构的身份验证中。AngularJS 是一个优秀的 SPA 框架,它提供了许多方便的工具和设施来集成 JWT,使开发人员能够更轻松地进行身份验证和授权。

本文将介绍如何在 AngularJS 单页应用中集成 JWT,包括身份验证、授权、刷新令牌等方面,以及一些最佳实践和值得关注的注意事项。代码示例将基于 AngularJS 1.7.9 版本和 AngularJS 的官方 JWT 模块。

身份验证和授权

身份验证是指确认用户身份的过程,通常依靠用户名和密码进行。在 SPA 应用中,一般采用表单方式输入用户名和密码,通过 AJAX 请求服务器端 API 进行认证。如果认证成功,服务器会返回 JWT 令牌,包含了用户信息和过期时间等等。之后,客户端会保存这个令牌,以备将来使用。

授权是指对已经登录的用户进行访问权限的控制,例如允许用户编辑自己的数据,但是不允许用户查看其他用户数据。在 SPA 应用中,通常采用 JWT 来实现授权,服务端返回一个有限的包含用户角色与权限的 JWT 令牌,客户端进行访问时需要将这个令牌带到请求头中,服务端会根据令牌中的内容来处理请求。

AngularJS 的 JWT 模块

AngularJS 官方提供了一个非常方便的 jwt 模块,用于集成 JWT 到 AngularJS 程序中。我们可以在 index.html 中加载这个模块:

--------- -----
----- ---------------
------
    ----- ----------------
    ---------------- --- ------------
    ------- --------------------------------------------------------------------------------
    ------- --------------------------------------------------------------------------------------
    ------- ----------------------
-------

----- -------------------------
    -- -------- ----------------------------
    -- -------- ------------------------------
    ---- -----------------------
        ------ -- ------------- ---
    ------
-------

-------

这段代码中,我们加载了 AngularJS 核心模块和 AngularJS 官方的 jwt 模块,并在 app.js 中定义了控制器 AuthCtrl。这个控制器管理用户登录状态和用户信息,并暴露了 login(),logout() 和 isLoggedIn() 方法。

----------------------- ----------------
    ----------------------- -------- -------- ------ -------- ---------- -
        ----------- - ---
        ---------- - ---
        
        ------------ - -------- -- -
            ----------------------- ------------
                -------------- ---------- -
                    ---------- - --------------------
                    ----------------------------------- ------------
                ---
        --
        
        ------------- - -------- -- -
            ---------------------------------------
            ---------- - ---
        --
        
        ----------------- - -------- -- -
            --- ----- - ------------------------------------
            ------ ----- -- ---------------------------------
        --
    ---

这个控制器中,我们通过 $http 服务进行与服务器交互,将用户的登录数据 $scope.user 发送到服务器端的 /api/auth 地址,服务器会返回一个 JWT 令牌作为响应。客户端使用 $window.localStorage 将这个令牌保存起来,使用 jwtHelper 的 isTokenExpired() 方法来检测令牌是否已过期,从而判断用户是否已经登录。

JWT 的保护和刷新

JWT 令牌保存在客户端,可能会面临盗用和窃听的风险。为了减少风险,我们需要在客户端保护令牌,使用 https 协议来保护通信安全,设置短期过期时间和定期更新令牌。

我们可以使用 $http 的拦截器来访问令牌,并在请求头中添加 Authorization 字段,将令牌发送给服务器。

-----------------------
    --------------------------- -------- ------------ --- -------- -
        ------ -
            -------- -------- -------- -
                -------------- - -------------- -- ---
                -- ------------------------------------- -
                    ---------------------------- - ------- - -
                        ------------------------------------
                -
                ------ -------
            --
            -------------- -------- ---------- -
                -- ---------------- --- ---- -
                    --------------------------------------
                -
                ------ --------------------
            -
        --
    --
    ---------------- --------------- -
        ---------------------------------------------------
    ---

这里我们定义了一个名为 authInterceptor 的 factory,它将从本地存储中获取 JWT 令牌,并将其加入到请求头 Authorization 字段中。

同样,我们应该定期更新令牌以提高安全性。如果我们设定 JWT 令牌的过期时间为 30 分钟,那么我们可以在变成后 25 分钟左右向服务器发送请求,让服务器为我们生成一个新的、更新过的 JWT 令牌。

-----------------------
    ---------------------- -------- ------- ---------- -------- ---------- -
        -------- -------------- -
            --- ----- - ------------------------------------
            -- ------ -- --------------------------------- -
                ------------------------------- - ------ ----- --
                    -------------- ---------- -
                        ----------------------------------- ---------------------
                    ---
            -
        -

        ----------------------- -- - -- - ------
    ---

这里我们定义了 jwtRefresh,它会在每个周期(25 分钟)内请求服务器来更新令牌,并且将更新后的令牌保存到本地存储当中。

最佳实践和注意事项

在集成 JWT 时,我们需要注意以下几个最佳实践和注意事项:

  1. 下载 AngularJS 官方提供的 jwt 模块,避免重复造轮子。
  2. JWT 令牌保存在本地存储中,尽量减少数据量和敏感信息。
  3. 使用拦截器来保护 JWT 令牌,避免被攻击者盗用。
  4. 设定较短的 JWT 过期时间,可以增加安全性。
  5. 尽量使用 https 协议,保护 JWT 的传输过程。
  6. 根据需要定期更新 JWT 令牌,增强安全性。
  7. 在服务端对 JWT 进行签名,避免伪造和篡改。
  8. 不要在 JWT 中包含敏感信息,例如密码和秘钥。

结论

在 AngularJS SPA 应用中集成 JWT 可以帮助我们轻松地进行身份验证和授权,并提高应用的安全性。通过模块化编程、定义拦截器和定时更新令牌等最佳实践,我们可以最大化发挥 JWT 的优势,保护我们的应用不受攻击者的伤害。该实践内容详细,并包含示例代码,希望可以帮助到前端开发人员进行学习并指导实践。

来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/6731d10e0bc820c5823a9392