使用 Web-Token 功能
对于 v2.19,此扩展包支持 Web-Token 框架,以简化加密令牌和密钥轮换的使用。
注意
此功能仅在 PHP 8.1+ 和 Symfony 6.1+ 中可用。
依赖安装
要启用此功能,您必须安装以下依赖项
1
composer require web-token/jwt-bundle
关于算法
有两种类型的签名算法:对称和非对称。
对称算法以速度快而闻名。它们主要在发行者和接收者互相信任时使用。原因是密钥是对称的,即它既用于签名又用于验证令牌。
非对称算法速度较慢,但由于密钥是非对称的,您可以允许接收者验证令牌,而无需允许他们伪造新令牌。这通常在令牌旨在由第三方处理时使用。
迁移配置
自动迁移
当在启用调试模式(开发环境)下工作时,迁移命令可用。
1
bin/console lexik:jwt:migrate-config
运行此命令时,当前配置将被更新。新旧配置之间应该没有问题。请运行所有测试以验证在此迁移之后一切运行良好。
运行迁移工具后,您的签名密钥集将包含与您使用的密钥完全相同的密钥,但格式为 JWK (Json Wek Key)。此外,还添加了两个随机密钥。这些密钥未使用,将在轮换密钥集时删除。
手动迁移
如果您想手动迁移配置,可以按照以下步骤操作。
签名密钥和密钥集
签名私钥和签名公钥集是使用 Web-Token 库的必要条件。您可以使用以下命令生成它们。请使用与您的算法对应的命令。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
# We first need to convert the private key to a JWK.
# If the private key is encrypted, you must provide the passphrase.
# We take the opportunity to generate a random ID for the key and set the algorithm and the usage.
# This is not mandatory, but it is a good practice.
./jose.phar key:load:key --random_id --use=sig --alg=RS256 --secret="testing" config/jwt/private.pem > config/jwt/signature.jwk
# Next, we generate a random public keyset containing 3 private key.
# Please use the same algorithm as the one used for the private key.
./jose.phar keyset:generate:rsa --random_id --use=sig --alg=RS256 --size 3 4096 > config/jwt/signature.jwkset
./jose.phar keyset:generate:oct --random_id --use=sig --alg=HS256 3 256 > config/jwt/signature.jwkset
./jose.phar keyset:generate:ec --random_id --use=sig --alg=ES256 3 P-256 > config/jwt/signature.jwkset
./jose.phar keyset:generate:okp --random_id --use=sig --alg=ED256 3 Ed25519 > config/jwt/signature.jwkset
# Then, we rotate the keyset to add signautre private key to the keyset.
./jose.phar keyset:rotate `cat config/jwt/signature.jwkset` `cat config/jwt/signature.jwk` > config/jwt/signature.jwkset
扩展包配置
扩展包配置与扩展包先前版本使用的配置非常相似。您只需将 lexik_jwt_authentication.encoder.***
编码器替换为 lexik_jwt_authentication.encoder.web_token
编码器。然后,您必须设置访问令牌颁发和验证参数。
1 2 3 4 5 6 7 8 9 10 11 12 13
lexik_jwt_authentication:
encoder:
service: lexik_jwt_authentication.encoder.web_token # We use the Web-Token encoder
access_token_issuance:
enabled: true
signature:
algorithm: 'RS256'
key: 'env(file:SIGNATURE_KEY)'
access_token_verification:
enabled: true
signature:
allowed_algorithms: ['RS256']
keyset: 'env(file:SIGNATURE_KEYSET)'
在该示例中,我们使用环境变量来检索签名密钥和密钥集。
1 2 3 4
# config/services.yaml
parameters:
env(SIGNATURE_KEY): '%kernel.project_dir%/config/jwt/signature.jwk'
env(SIGNATURE_KEYSET): '%kernel.project_dir%/config/jwt/signature.jwkset'
注意
我们建议使用环境变量来存储签名密钥和密钥集,而不是文件。
加密支持
使用 WebTokenBundle,您可以加密令牌。令牌将仅能被拥有私钥来解密它们的应用程序读取。除非访问令牌包含敏感信息,否则不建议使用加密支持。
与签名一样,加密需要私钥(用于加密)和公钥集(用于解密)。
当在启用调试模式(开发环境)下工作时,辅助命令可用。此命令将询问要使用的算法并创建相应的密钥和密钥集。输出将是扩展包的更新配置。
1
bin/console lexik:jwt:enable-encryption
密钥轮换
在 Web-Token 库提供的所有功能中,您肯定希望定期轮换密钥。密钥轮换是防止攻击者猜测您的密钥并伪造具有提升权限的令牌的良好做法。
为了简化密钥操作,您应该考虑安装 [JWT App](https://github.com/web-token/jwt-app)。您只需从 [发布页面](https://github.com/web-token/jwt-app/releases) 下载最新的稳定版本,并将 PHAR 文件设置为可执行文件。
1
chmod +x jose.phar
在以下示例中,我们将考虑: 签名私钥存储在 config/jwt/signature.jwk
文件中, 签名公钥集存储在 config/jwt/signature.jwkset
文件中。
目标是通过添加新密钥并删除最旧的密钥来轮换密钥集。新的私钥将存储在 config/jwt/signature.jwk
文件中,新的公钥集将被更新。
签名私钥
新的签名私钥应与配置中声明的算法兼容。例如,如果您使用 RS256
算法,则必须生成 RSA 私钥。以下是一些 RSA (RS***
/PS***
)、OCT (HS***
)、EC (ES***
) 和 OKP (ED***
) 和私钥生成的示例
1 2 3 4
./jose.phar key:generate:rsa --random_id --use=sig --alg=RS256 --size 4096 > config/jwt/signature.jwk
./jose.phar key:generate:oct --random_id --use=sig --alg=HS256 256 > config/jwt/signature.jwk
./jose.phar key:generate:ec --random_id --use=sig --alg=ES256 P-256 > config/jwt/signature.jwk
./jose.phar key:generate:okp --random_id --use=sig --alg=ED256 Ed25519 > config/jwt/signature.jwk
签名公钥集
现在您有了新的私钥,您可以轮换公钥集。轮换是通过将新密钥添加到密钥集开头并删除最旧的(最后一个)密钥来完成的。
1
./jose.phar keyset:rotate `cat config/jwt/signature.jwkset` `cat config/jwt/signature.jwk` > config/jwt/signature.jwkset
加密密钥和密钥集
加密密钥的管理方式与签名密钥相同。不同之处如下: 您必须为私钥和公钥使用不同的文件(例如 encryption.jwk
和 encryption.jwkset
), 您必须使用 enc
密钥用途, * 您必须为密钥类型(RSA、OCT、EC、OKP)使用正确的算法。