最新公告
  • 欢迎您光临源码库,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入
  • 如何在 WordPress 中生成和验证 JWT(JSON Web Token)

    终于在 WPJAM Basic 中实现了 JWT 登录和认证功能,今天就整理一下,首先按照惯例做一些 JWT 的介绍。

    什么是 JWT

    JWT(JSON Web Token)是一种轻量级的、自包含的、通常用于身份验证和授权的令牌,它将用户信息(如用户ID、角色和权限等)编码到一个 JSON 对象中,然后对其进行数字签名,从而生成一个经过签名的令牌。

    如何在 WordPress 中生成和验证 JWT(JSON Web Token)-1

    由于 JWT 在客户端和服务器之间传输时是加密的,因此服务器可以轻松验证该令牌的有效性和真实性。JWT 常用于无状态的 RESTful API,作为访问受保护资源的凭据,可以在每次请求时附加在请求头中,下图是使用 JWT 的一个常见的交互流程:

    如何在 WordPress 中生成和验证 JWT(JSON Web Token)-2

    JWT 的结构

    JWT(JSON Web Token)由三部分组成,分别是:Header(头部)、Payload(负载)和 Signature(签名)。

    如何在 WordPress 中生成和验证 JWT(JSON Web Token)-3

    这三部分使用点(.)分隔,合并为一个字符,如下所示:

    
    
    header.payload.signature

    Header(头部)

    Header 是一个 JSON 对象,通常包含两个属性

    alg

     和 

    typ

    alg

     属性表示签名算法(如 HS256、RS256 等),

    typ

     属性表示令牌类型,通常为 “JWT”。Header 会被 Base64Url 编码,得到一个字符串。例如:

    
    
    {
      "alg": "HS256",
      "typ": "JWT"
    }

    Payload(负载):

    Payload 是一个 JSON 对象,包含一些“声明”(Claim),用于传递用户信息和其他业务数据,声明可以是预定义的(如 iss、exp、sub 等),也可以是自定义的,Payload 会被 Base64Url 编码,得到一个字符串。例如:

    
    
    {
      "sub": "1234567890",
      "name": "John Doe",
      "iat": 1516239022
    }

    下面这 7 个字段都是由官方所定义的,也就是预定义(Registered claims)的,但并不都是必需的,

    • iss (issuer):签发人
    • sub (subject):主题
    • aud (audience):受众
    • exp (expiration time):过期时间
    • nbf (Not Before):生效时间,在此之前是无效的
    • iat (Issued At):签发时间
    • jti (JWT ID):唯一身份标识,主要用来作为一次性 token,从而回避重放攻击

    另外声明名称只有三个字符,因为 JWT 意味着是紧凑的。

    Signature(签名):

    签名用于保证 JWT 的完整性和安全性,它是将 Header、Payload 和一个密钥(Secret)通过签名算法进行加密得到的,签名可以防止 JWT 被篡改和伪造,例如,使用 HMAC-SHA256 算法生成签名的方法如下:

    
    
    HMACSHA256(
      base64UrlEncode(header) + "." +
      base64UrlEncode(payload),
      secret
    )

    将 

    Header

    Payload

     和 

    Signature

     用点(.)连接起来,就得到了一个完整的 JWT,例如:

    
    
    eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

    WordPress 中实现 JWT

    通过上面 JWT 的介绍和 JWT 结构可知,生成 JWT,就是通过签名算法和一个用于生成签名的密钥(

    Secret

    )对 

    Payload

     生成签名:我们为了方便就只支持 SHA256 签名算法:

    
    
    <span class="token keyword">function</span> wpjam_generate_jwt<span class="token punctuation">(</span><span class="token variable">$payload</span><span class="token punctuation">,</span> <span class="token variable">$secret</span><span class="token operator">=</span><span class="token string">''</span><span class="token punctuation">,</span> <span class="token variable">$header</span><span class="token operator">=</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
        <span class="token comment" spellcheck="true">//无法生成没有设置过期时间的 JWT
    </span> <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token function">empty</span><span class="token punctuation">(</span><span class="token variable">$payload</span><span class="token punctuation">[</span><span class="token string">'exp'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
            <span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>

        <span class="token variable">$header</span> <span class="token operator">=</span> wp_parse_args<span class="token punctuation">(</span><span class="token variable">$header</span><span class="token punctuation">,</span> <span class="token punctuation">[</span>
            <span class="token string">'alg'</span> <span class="token operator">=&gt;</span> <span class="token string">'HS256'</span><span class="token punctuation">,</span>
            <span class="token string">'typ'</span> <span class="token operator">=&gt;</span> <span class="token string">'JWT'</span>
        <span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

        <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token variable">$header</span><span class="token punctuation">[</span><span class="token string">'alg'</span><span class="token punctuation">]</span> <span class="token operator">==</span> <span class="token string">'HS256'</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
            <span class="token variable">$header</span>     <span class="token operator">=</span> base64_urlencode<span class="token punctuation">(</span>wpjam_json_encode<span class="token punctuation">(</span><span class="token variable">$header</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token variable">$payload</span>    <span class="token operator">=</span> base64_urlencode<span class="token punctuation">(</span>wpjam_json_encode<span class="token punctuation">(</span><span class="token variable">$payload</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token variable">$jwt</span>        <span class="token operator">=</span> <span class="token variable">$header</span><span class="token punctuation">.</span><span class="token string">'.'</span><span class="token punctuation">.</span><span class="token variable">$payload</span><span class="token punctuation">;</span>
            <span class="token variable">$secret</span>     <span class="token operator">=</span> <span class="token variable">$secret</span> <span class="token operator">?</span><span class="token punctuation">:</span> wp_salt<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

            <span class="token keyword">return</span> <span class="token variable">$jwt</span><span class="token punctuation">.</span><span class="token string">'.'</span><span class="token punctuation">.</span>base64_urlencode<span class="token punctuation">(</span>hash_hmac<span class="token punctuation">(</span><span class="token string">'sha256'</span><span class="token punctuation">,</span> <span class="token variable">$jwt</span><span class="token punctuation">,</span> <span class="token variable">$secret</span><span class="token punctuation">,</span> <span class="token boolean">true</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>

    上面的代码首先对 

    Header

     和 

    Payload

     进行 JSON 编码和 URL 安全的 Base64 编码,生成签名的密钥(

    Secret

    )如果为空,则使用 WordPress 默认的盐值函数来生成,最后把 

    Header

     和 

    Payload

     和生成的签名通过点(.)连接起来得到了一个完整的 JWT 。

    那么怎么验证 JWT 呢,验证的过程就是生成的反过程:首先通过点(.)将 JWT 分割成 

    Header

    Payload

     和 

    Signature

     三段,然后对 

    Header

     和 

    Payload

     进行 URL 安全的 Base64 解码和JSON 解码,通过签名的密钥最后验证签名:

    
    
    <span class="token keyword">function</span> wpjam_verify_jwt<span class="token punctuation">(</span><span class="token variable">$token</span><span class="token punctuation">,</span> <span class="token variable">$secret</span><span class="token operator">=</span><span class="token string">''</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
        <span class="token variable">$tokens</span> <span class="token operator">=</span> <span class="token function">explode</span><span class="token punctuation">(</span><span class="token string">'.'</span><span class="token punctuation">,</span> <span class="token variable">$token</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

        <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token function">count</span><span class="token punctuation">(</span><span class="token variable">$tokens</span><span class="token punctuation">)</span> <span class="token operator">!</span><span class="token operator">=</span> <span class="token number">3</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
            <span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>

        list<span class="token punctuation">(</span><span class="token variable">$header</span><span class="token punctuation">,</span> <span class="token variable">$payload</span><span class="token punctuation">,</span> <span class="token variable">$sign</span><span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token variable">$tokens</span><span class="token punctuation">;</span>

        <span class="token variable">$jwt</span>        <span class="token operator">=</span> <span class="token variable">$header</span><span class="token punctuation">.</span><span class="token string">'.'</span><span class="token punctuation">.</span><span class="token variable">$payload</span><span class="token punctuation">;</span>
        <span class="token variable">$secret</span>     <span class="token operator">=</span> <span class="token variable">$secret</span> <span class="token operator">?</span><span class="token punctuation">:</span> wp_salt<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token variable">$header</span>     <span class="token operator">=</span> wpjam_json_decode<span class="token punctuation">(</span>base64_urldecode<span class="token punctuation">(</span><span class="token variable">$header</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token variable">$payload</span>    <span class="token operator">=</span> wpjam_json_decode<span class="token punctuation">(</span>base64_urldecode<span class="token punctuation">(</span><span class="token variable">$payload</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

        <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token function">empty</span><span class="token punctuation">(</span><span class="token variable">$header</span><span class="token punctuation">[</span><span class="token string">'alg'</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token operator">||</span> <span class="token variable">$header</span><span class="token punctuation">[</span><span class="token string">'alg'</span><span class="token punctuation">]</span> <span class="token operator">!</span><span class="token operator">=</span> <span class="token string">'HS256'</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
            <span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>

        <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token operator">!</span>hash_equals<span class="token punctuation">(</span>base64_urlencode<span class="token punctuation">(</span>hash_hmac<span class="token punctuation">(</span><span class="token string">'sha256'</span><span class="token punctuation">,</span> <span class="token variable">$jwt</span><span class="token punctuation">,</span> <span class="token variable">$secret</span><span class="token punctuation">,</span> <span class="token boolean">true</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token variable">$sign</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
            <span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>

        <span class="token comment" spellcheck="true">//签发时间大于当前服务器时间验证失败
    </span> <span class="token keyword">if</span><span class="token punctuation">(</span>isset<span class="token punctuation">(</span><span class="token variable">$payload</span><span class="token punctuation">[</span><span class="token string">'iat'</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token operator">&amp;&amp;</span> <span class="token variable">$payload</span><span class="token punctuation">[</span><span class="token string">'iat'</span><span class="token punctuation">]</span> <span class="token operator">&gt;</span> time<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
            <span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>

        <span class="token comment" spellcheck="true">//该nbf时间之前不接收处理该Token
    </span> <span class="token keyword">if</span><span class="token punctuation">(</span>isset<span class="token punctuation">(</span><span class="token variable">$payload</span><span class="token punctuation">[</span><span class="token string">'nbf'</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token operator">&amp;&amp;</span> <span class="token variable">$payload</span><span class="token punctuation">[</span><span class="token string">'nbf'</span><span class="token punctuation">]</span> <span class="token operator">&gt;</span> time<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
            <span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>

        <span class="token comment" spellcheck="true">//没有设置过期时间,或过期时间小于当前服务器时间验证失败
    </span> <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token function">empty</span><span class="token punctuation">(</span><span class="token variable">$payload</span><span class="token punctuation">[</span><span class="token string">'exp'</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token operator">||</span> <span class="token variable">$payload</span><span class="token punctuation">[</span><span class="token string">'exp'</span><span class="token punctuation">]</span> <span class="token operator">&lt;</span> time<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
            <span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>

        <span class="token keyword">return</span> <span class="token variable">$payload</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    我们这边生成和验证函数有点特殊处理,就是都要实现过期时间设置,意思就是不能设置没有过期时间的 JWT。

    wpjam_generate_jwt

     和 

    wpjam_verify_jwt

     这两个函数在 WPJAM Basic 中已经内置了,通过他们就可以在 WordPress 实现 JWT 的生成和验证了。

    特别提醒一下过程中用到的 URL 安全的 Base64 编码和解码函数 

    base64_urlencode

     和 

    base64_urldecode

     也是在 WPJAM Basic 中定义了。

    1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
    2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
    3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
    4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
    5. 如有链接无法下载、失效或广告,请联系管理员处理!
    6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需!

    源码资源库 » 如何在 WordPress 中生成和验证 JWT(JSON Web Token)
    • 3237会员总数(位)
    • 65685资源总数(个)
    • 12本周发布(个)
    • 12 今日发布(个)
    • 1340稳定运行(天)

    提供最优质的资源集合

    立即查看 了解详情