Skip to content

Commit cd05fb8

Browse files
committed
update
1 parent 1788e54 commit cd05fb8

3 files changed

Lines changed: 56 additions & 156 deletions

File tree

src/Config/Token.php

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,7 @@
55
namespace xiaodi\JWTAuth\Config;
66

77
use Lcobucci\JWT\Signer;
8-
use Lcobucci\JWT\Signer\Key;
98
use xiaodi\JWTAuth\Exception\JWTException;
10-
use think\App;
119

1210
class Token
1311
{
@@ -33,14 +31,13 @@ public function __construct(array $options)
3331
}
3432
}
3533

36-
public function makeSignerKey()
34+
public function getSigningKey()
3735
{
38-
$key = $this->signer_key;
39-
if (empty($key)) {
36+
if (empty($this->signer_key)) {
4037
throw new JWTException('config signer_key required.', 500);
4138
}
4239

43-
return new Key($key);
40+
return $this->signer_key;
4441
}
4542

4643
public function getIdKey(): string

src/Service/Jwt.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,11 @@ protected function getDefaultApp(): string
6262
* @param array $claims
6363
* @return JwtToken
6464
*/
65-
public function token(array $claims): JwtToken
65+
public function token($identifier, array $claims = []): JwtToken
6666
{
67-
$token = $this->app->get('jwt.token')->make($claims);
67+
$token = $this->app->get('jwt.token')->make($identifier, $claims);
6868

69-
$this->app->get('jwt.manager')->login($token);
69+
// $this->app->get('jwt.manager')->login($token);
7070

7171
return $token;
7272
}

src/Service/Token.php

Lines changed: 50 additions & 147 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,19 @@
44

55
namespace xiaodi\JWTAuth\Service;
66

7+
use DateTimeZone;
8+
use DateTimeImmutable;
79
use think\App;
8-
use Lcobucci\JWT\Builder;
9-
use Lcobucci\JWT\Token as JwtToken;
10-
use Lcobucci\JWT\ValidationData;
11-
use Lcobucci\JWT\Parser;
1210
use xiaodi\JWTAuth\Config\Token as Config;
13-
use xiaodi\JWTAuth\Exception\JWTException;
14-
use xiaodi\JWTAuth\Exception\JWTInvalidArgumentException;
15-
use xiaodi\JWTAuth\Exception\TokenAlreadyEexpired;
1611
use xiaodi\JWTAuth\Handle\RequestToken;
12+
use Lcobucci\JWT\Configuration;
13+
use Lcobucci\JWT\Token as JwtToken;
14+
use Lcobucci\JWT\Signer\Key\InMemory;
15+
use Lcobucci\JWT\Validation\Constraint\SignedWith;
16+
use Lcobucci\JWT\Validation\Constraint\ValidAt;
17+
use Lcobucci\Clock\SystemClock;
1718

1819
/**
19-
* Undocumented class
2020
*
2121
* @method JwtToken make()
2222
* @method bool verify()
@@ -41,6 +41,11 @@ class Token
4141
*/
4242
protected $token;
4343

44+
/**
45+
* @var Configuration
46+
*/
47+
private $jwtConfiguration;
48+
4449
public function __construct(App $app)
4550
{
4651
$this->app = $app;
@@ -49,107 +54,59 @@ public function __construct(App $app)
4954

5055
protected function init()
5156
{
52-
$options = $this->resolveConfig();
57+
$this->resolveConfig();
58+
$this->initJwtConfiguration();
59+
}
5360

54-
$this->config = new Config($options);
61+
protected function initJwtConfiguration()
62+
{
63+
$this->jwtConfiguration = Configuration::forSymmetricSigner(
64+
$this->config->getSigner(),
65+
InMemory::base64Encoded($this->config->getSigningKey())
66+
);
5567
}
5668

5769
protected function getStore()
5870
{
5971
return $this->app->get('jwt')->getStore();
6072
}
6173

62-
protected function resolveConfig(): array
74+
protected function resolveConfig()
6375
{
6476
$store = $this->getStore();
6577
$options = $this->app->config->get("jwt.stores.{$store}.token", []);
6678

6779
if (!empty($options)) {
68-
return $options;
69-
}
70-
71-
throw new JWTException($store . '应用 Token 配置未完整', 500);
72-
}
73-
74-
protected function makeId(array $claims)
75-
{
76-
$key = $this->config->getIdKey();
77-
if (!array_key_exists($key, $claims)) {
78-
throw new JWTException("claims {$key} requried", 500);
80+
$this->config = new Config($options);
81+
} else {
82+
throw new JWTException($store . '应用 Token 配置未完整', 500);
7983
}
80-
81-
return $claims[$key];
8284
}
8385

84-
public function make(array $claims): JwtToken
86+
public function make($identifier, array $claims = []): JwtToken
8587
{
86-
$unique_id = $this->makeId($claims);
87-
88-
$now = time();
89-
$expires = $now + $this->config->getExpires();
90-
$refreshAt = $expires + $this->config->getRefreshTTL();
91-
$notBefore = $this->config->getNotBefore();
92-
$iss = $this->config->getIss();
93-
$aud = $this->config->getAud();
94-
95-
$builder = new Builder();
96-
$builder->setIssuer($iss)
97-
->setAudience($aud)
98-
->setId($unique_id, true)
99-
->setIssuedAt($now)
100-
->setNotBefore($now + $notBefore)
101-
->setExpiration($expires)
102-
->set('refreshAt', $refreshAt);
103-
104-
$builder->set('store', $this->getStore());
105-
106-
foreach ($claims as $key => $claim) {
107-
$builder->set($key, $claim);
108-
}
109-
110-
$token = $builder->getToken($this->config->getSigner(), $this->config->makeSignerKey());
111-
112-
return $token;
88+
$now = new DateTimeImmutable();
89+
return $this->jwtConfiguration->builder()
90+
->permittedFor($this->config->getAud())
91+
->issuedBy($this->config->getIss())
92+
->identifiedBy((string)$identifier)
93+
->issuedAt($now)
94+
->canOnlyBeUsedAfter($now)
95+
->expiresAt($this->getExpiryDateTime($now))
96+
->relatedTo((string) $identifier)
97+
->withClaim('scopes', json_encode($claims))
98+
->getToken($this->jwtConfiguration->signer(), $this->jwtConfiguration->signingKey());
11399
}
114100

115-
/**
116-
* Token 自动续期
117-
*
118-
* @param Token $token
119-
* @param int|string $ttl 秒数
120-
* @return void
121-
*/
122-
protected function automaticRenewalToken(JwtToken $token)
101+
public function getExpiryDateTime($now): DateTimeImmutable
123102
{
124-
$claims = $token->getClaims();
125-
126-
unset($claims['iat']);
127-
unset($claims['jti']);
128-
unset($claims['nbf']);
129-
unset($claims['exp']);
130-
unset($claims['iss']);
131-
unset($claims['aud']);
132-
unset($claims['refreshAt']);
133-
134-
$token = $this->make($claims);
135-
$claims = $token->getClaims();
136-
$refreshAt = $claims['refreshAt'];
137-
138-
header('Access-Control-Expose-Headers:Automatic-Renewal-Token,Automatic-Renewal-Token-RefreshAt');
139-
header("Automatic-Renewal-Token:$token");
140-
header("Automatic-Renewal-Token-RefreshAt:$refreshAt");
141-
142-
return $token;
103+
$ttl = (string)$this->config->getExpires();
104+
return $now->modify("+{$ttl} sec");
143105
}
144106

145107
public function parseToken(string $token): JwtToken
146108
{
147-
try {
148-
$token = (new Parser())->parse($token);
149-
} catch (\InvalidArgumentException $e) {
150-
throw new JWTInvalidArgumentException('此 Token 解析失败', 500);
151-
}
152-
109+
$token = $this->jwtConfiguration->parser()->parse($token);
153110
return $token;
154111
}
155112

@@ -167,70 +124,21 @@ public function verify(string $token): ?bool
167124
{
168125
$this->token = $this->parseToken($token);
169126

170-
if (false === $this->token->verify($this->config->getSigner(), $this->config->makeSignerKey())) {
171-
throw new JWTException('此 Token 与 密钥不匹配', $this->config->getReloginCode());
172-
}
173-
174-
// Token 是否已可用
175-
$now = time();
176-
$exp = $this->token->getClaim('nbf');
177-
if ($now < $exp) {
178-
throw new JWTException('此 Token 暂未可用', 500);
179-
}
180-
181-
// 是否已过期
182-
if (true === $this->token->isExpired()) {
183-
if ($now <= $this->token->getClaim('refreshAt')) {
184-
// 是否开启自动续签
185-
if ($this->config->getAutomaticRenewal()) {
186-
$this->token = $this->automaticRenewalToken($this->token);
187-
} else {
188-
throw new TokenAlreadyEexpired('Token 已过期,请重新刷新', $this->config->getRefreshCode());
189-
}
190-
} else {
191-
throw new TokenAlreadyEexpired('Token 刷新时间已过,请重新登录', $this->config->getReloginCode());
192-
}
193-
} else {
194-
// 是否存在黑名单
195-
if (true === $this->app->get('jwt.manager')->wasBan($this->token)) {
196-
throw new TokenAlreadyEexpired('Token 已被禁用,请重新登录', $this->config->getReloginCode());
197-
}
198-
}
199-
200-
$data = new ValidationData();
127+
$this->jwtConfiguration->setValidationConstraints(
128+
new ValidAt(new SystemClock(new DateTimeZone(\date_default_timezone_get()))),
129+
new SignedWith($this->jwtConfiguration->signer(), $this->jwtConfiguration->signingKey())
130+
);
201131

202-
$jwt_id = $this->token->getHeader('jti');
203-
$data->setIssuer($this->config->getIss());
204-
$data->setAudience($this->config->getAud());
205-
$data->setId($jwt_id);
132+
$constraints = $this->jwtConfiguration->validationConstraints();
206133

207-
if (!$this->token->validate($data)) {
208-
throw new JWTException('此 Token 效验不通过', $this->config->getReloginCode());
134+
if (!$this->jwtConfiguration->validator()->validate($this->token, ...$constraints)) {
135+
throw new JWTException('效验失败', 401);
209136
}
210137

211138
return true;
212139
}
213140

214-
public function refresh(string $token = null): JwtToken
215-
{
216-
$token = $token ?: $this->getRequestToken();
217-
$token = $this->parseToken($token);
218-
219-
$claims = $token->getClaims();
220-
221-
unset($claims['iat']);
222-
unset($claims['jti']);
223-
unset($claims['nbf']);
224-
unset($claims['exp']);
225-
unset($claims['iss']);
226-
unset($claims['aud']);
227-
228-
$this->app->get('jwt.manager')->logout($token);
229-
230-
return $this->make($claims);
231-
}
232-
233-
public function logout(?string $token = null): void
141+
public function logout(?string $token): void
234142
{
235143
$token = $token ?: $this->getRequestToken();
236144
$token = $this->parseToken($token);
@@ -256,9 +164,4 @@ public function getType(): string
256164
{
257165
return $this->config->getTokenType();
258166
}
259-
260-
public function getRefreshTTL()
261-
{
262-
return $this->config->getRefreshTTL();
263-
}
264167
}

0 commit comments

Comments
 (0)