kleijnweb / jwt-bundle
支持非对称密钥和外部加载机密的Symfony JWT身份验证
Requires
- php: ^7.0.0
- symfony/config: >=2.8.30
- symfony/dependency-injection: >=2.8.30
- symfony/event-dispatcher: >=2.8.30
- symfony/finder: >=2.8.30
- symfony/http-foundation: >=2.8.30
- symfony/http-kernel: >=2.8.30
- symfony/security: >=2.8.30
- symfony/security-bundle: >=2.8.30
- symfony/var-dumper: >=2.8.30
- symfony/yaml: >=2.8.30
Requires (Dev)
- mikey179/vfsstream: ^1.6
- phpunit/phpunit: ^6.5
- satooshi/php-coveralls: <1.0
- squizlabs/php_codesniffer: ^3.2
- symfony/browser-kit: >=2.8.30
- symfony/form: >=2.8.30
- symfony/framework-bundle: >=2.8.30
- symfony/monolog-bundle: ^3.1
README
集成JWT API令牌进行身份验证。
前往发布页面查找有关最新发布的详细信息。
示例请参见swagger-bundle-example。
注意:寻找PHP <7.0和Symfony <2.8.7支持?使用0.x版本。
安装
使用composer(composer require kleijnweb/jwt-bundle
)安装。您应该检查发布页面以确保您获得所需的内容,并可选地验证您的下载。
身份验证
使用标准(保留)JWT声明验证令牌
名称 | 类型 | 描述 |
---|---|---|
exp |
int [1] | 过期时间必须省略 [3] 或小于 time() + leeway [2]。 |
nbf |
int [1] | "Not before",令牌有效开始时间,必须省略 [3] 或大于或等于 time() - leeway [2]。 |
iat |
int [1] | 令牌签发时间,必须省略 [3] 或小于配置的 minIssueTime + leeway 。当配置了 minIssueTime 时是必需的。 |
iss |
string | 令牌的发行者,必须与配置的 issuer 匹配。当配置了 issuer 时是必需的。 |
aud |
string | JWT "audience",必须省略 [3] 或如果配置了则匹配配置的 audience 。当配置了 audience 时是必需的。 |
sub |
string | JWT "subject"。用作Symfony Security集成的username 。始终必需(或其别名),如果没有它,则"Resource Owner cannot be identified"。 |
prn |
string | JWT "principle"。对sub 的弃用别名,用于JWT RFC的旧版本。 |
jti |
string | JWT "ID"。不使用,将被忽略。 |
typ |
string | 不使用,将被忽略。 |
- [1] Unix时间
- [2]
leeway
允许令牌发行者和运行您的应用程序的服务器之间的秒数差异。保持一个很小的数字,默认为0。 - [3] 使用
require
配置选项标记任何必需的声明,包括自定义(非保留)声明。
忽略遇到的所有其他声明。JWT头检查kid
(见下文)和alg
,它们必须与密钥配置的type
值匹配。
密钥
验证器支持多个密钥,并允许为每个kid
(密钥ID,当配置了多个密钥时必须包含在JWT头中)配置所有选项
jwt: keys: keyOne: # Only one key, 'kid' is optional (but must match when provided) issuer: http://api.server.com/oauth2/token # OAuth2 example, but could be any string value audience: ~ # NULL, accept any minIssueTime: 1442132949 # Reject 'old' tokens, regardless of 'exp' require: [nbf, exp, my-claim] # Mark claims as required leeway: 5 # Allow 5 seconds of time de-synchronization (both ways) between this server and api.server.com
JwtBundle和发行者必须共享一个密钥,以便JwtBundle能够验证令牌。您可以选择使用预共享密钥(PSK)或非对称密钥。
jwt: keys: keyOne: # Must match 'kid' issuer: http://api.server1.com/oauth2/token secret: 'A Pre-Shared Key' # type: Defaults to HS256 (HMACSHA256). All options: HS256, HS512, RS256 and RS512 keyTwo: # Must match 'kid' issuer: http://api.server2.com/oauth2/token type: RS256 # RSA SHA256, needed for asymmetric keys secret: | -----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwND1VMVJ3BC/aM38tQRH 2GDHecXE8EsGoeAeBR5dFt3QC1/Eoub/F2kee3RBtI6I+kDBjrSDz5lsqh3Sm7N/ 47fTKZLvdBaHbCuYXVBQ2tZeEiUBESnsY2HUzXDlqSyDWohuiYeeL6gewxe1CnSE 0l8gYZ0Tx4ViPFYulva6siew0f4tBuSEwSPiKZQnGcssQYJ/VevTD6L4wGoDhkXV VvJ+qiNgmXXssgCl5vHs22y/RIgeOnDhkj81aB9Evx9iR7DOtyRBxnovrbN5gDwX m6IDw3fRhZQrVwZ816/eN+1sqpIMZF4oo4kRA4b64U04ex67A/6BwDDQ3LH0mD4d EwIDAQAB -----END PUBLIC KEY-----
要使用非对称密钥,type
必须设置为RS256
或RS512
。在这种情况下,密钥是发行者的公钥。
从外部源加载密钥
除了静态配置密钥外,还可以使用JWT令牌中可用的任何数据动态加载。示例配置
jwt: keys: keyThree: # Must match 'kid' issuer: http://api.server1.com/oauth2/token loader: 'my.loader.di.key'
加载器必须实现KleijnWeb\JwtBundle\Authenticator\SecretLoader
。一个简单的示例,从模糊的数据存储中加载密钥
use KleijnWeb\JwtBundle\Authenticator\JwtToken; use KleijnWeb\JwtBundle\Authenticator\SecretLoader; class SimpleSecretLoader implements SecretLoader { /** * @var DataStore */ private $store; /** * @param DataStore $store */ public function __construct(DataStore $store) { $this->store = $store; } /** * @param JwtToken $token * * @return string */ public function load(JwtToken $token) { return $this->store->loadSecretByUsername($token->getClaims()['sub']); } }
您可以使用令牌中可用的任何信息,例如kid
、alg
或任何自定义声明。您不能同时配置secret
和loader
。在适当的时候确保抛出AuthenticationException
(例如,缺少加载密钥所需的声明)。
集成到Symfony Security
摘要
security: firewalls: default: stateless: true jwt: header: X-Header-Name # Defaults to "Authorization", in which case encountered "Bearer" prefixes are stripped provider: jwt providers: jwt: id: jwt.user_provider
使用捆绑的用户提供者是可选的。这将仅从令牌数据中生成用户对象,并从aud
声明(无论是否设置了aud
)生成角色。
使用备用UserProvider将受众分配给用户角色
JwtBundle可以将JwtToken中的受众声明分配给User对象的用户角色属性。理想情况下,这是在UserProvider中完成的,这样组就无法修改。
如果这是可以接受的风险,您不想使用JwtUser/JwtUserProvider,但确实希望JwtBundle将aud
声明复制到用户角色,则可以将您的User类实现为KleijnWeb\JwtBundle\User\UnsafeGroupsUserInterface
接口,JwtBundle将在从提供者加载用户后添加角色。这种行为可能在未来的版本中被移除。
注意:此功能仅复制令牌中的角色。
颁发令牌
颁发令牌目前仅限于HS256
。要创建令牌字符串
$token = new JwtToken([ 'header' => [ 'alg' => 'HS256', 'typ' => 'JWT', 'kid' => 'Optional Key ID' ], 'claims' => [ /* Array of claims */ ], 'secret' => 'Your Secret' ]); $token->getTokenString();
许可
KleijnWeb\JwtBundle是在LGPL,版本3.0的条款下提供的。