Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
73.33% |
11 / 15 |
|
33.33% |
1 / 3 |
CRAP | |
0.00% |
0 / 1 |
WebSecurity | |
73.33% |
11 / 15 |
|
33.33% |
1 / 3 |
10.54 | |
0.00% |
0 / 1 |
getCsrfKind | |
83.33% |
5 / 6 |
|
0.00% |
0 / 1 |
5.12 | |||
getCsrfTokenHash | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
generateCsrfToken | |
62.50% |
5 / 8 |
|
0.00% |
0 / 1 |
3.47 |
1 | <?php |
2 | |
3 | declare(strict_types=1); |
4 | |
5 | namespace PeServer\Core\Web; |
6 | |
7 | use PeServer\Core\Binary; |
8 | use PeServer\Core\Cryptography; |
9 | use PeServer\Core\MiddlewareArgument; |
10 | use PeServer\Core\Text; |
11 | use PeServer\Core\Throws\CryptoException; |
12 | use PeServer\Core\Throws\SessionException; |
13 | use PeServer\Core\Throws\Throws; |
14 | |
15 | class WebSecurity |
16 | { |
17 | #region define |
18 | |
19 | public const CSRF_KIND_SESSION_KEY = 1; |
20 | public const CSRF_KIND_REQUEST_ID = 2; |
21 | public const CSRF_KIND_REQUEST_NAME = 3; |
22 | public const CSRF_KIND_HEADER_NAME = 4; |
23 | |
24 | private const CSRF_SESSION_KEY = 'core__csrf'; |
25 | private const CSRF_REQUEST_ID = 'core__csrf_id'; |
26 | private const CSRF_REQUEST_NAME = 'core__csrf_name'; |
27 | private const CSRF_HEADER_NAME = 'X-CSRF-TOKEN'; |
28 | |
29 | private const CSRF_HASH_ALGORITHM = 'sha256'; |
30 | |
31 | #endregion |
32 | |
33 | #region function |
34 | |
35 | /** |
36 | * CSRFに関する項目名等々を取得。 |
37 | * |
38 | * HTTP/HTML上のキーに関するのものが対象となる。 |
39 | * |
40 | * @param int $kind |
41 | * @phpstan-param self::CSRF_KIND_* $kind |
42 | * @return non-empty-string |
43 | */ |
44 | public function getCsrfKind(int $kind): string |
45 | { |
46 | return match ($kind) { |
47 | self::CSRF_KIND_SESSION_KEY => self::CSRF_SESSION_KEY, |
48 | self::CSRF_KIND_REQUEST_ID => self::CSRF_REQUEST_ID, |
49 | self::CSRF_KIND_REQUEST_NAME => self::CSRF_REQUEST_NAME, |
50 | self::CSRF_KIND_HEADER_NAME => self::CSRF_HEADER_NAME, |
51 | }; |
52 | } |
53 | |
54 | /** |
55 | * CSRFトークンのハッシュアルゴリズム。 |
56 | * @return non-empty-string |
57 | */ |
58 | protected function getCsrfTokenHash(): string |
59 | { |
60 | return self::CSRF_HASH_ALGORITHM; |
61 | } |
62 | |
63 | /** |
64 | * CSRFトークンを取得。 |
65 | * |
66 | * @return non-empty-string |
67 | * @throws SessionException セッションID取得失敗。 |
68 | */ |
69 | public function generateCsrfToken(): string |
70 | { |
71 | $sessionId = session_id(); |
72 | if ($sessionId === false) { |
73 | throw new SessionException('セッションID取得失敗'); |
74 | } |
75 | |
76 | $algorithm = $this->getCsrfTokenHash(); |
77 | try { |
78 | $hash = Cryptography::generateHashString($algorithm, new Binary($sessionId)); |
79 | } catch (CryptoException $ex) { |
80 | Throws::reThrow(SessionException::class, $ex, 'CSRFトークン生成失敗'); |
81 | } |
82 | |
83 | return $hash; |
84 | } |
85 | |
86 | #endregion |
87 | } |