/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/VerifyCsrfToken.php

https://github.com/immortalChensm/laravel-work · PHP · 180 lines · 83 code · 23 blank · 74 comment · 7 complexity · a407c3a5d6970902e1af833eb2b28223 MD5 · raw file

  1. <?php
  2. namespace Illuminate\Foundation\Http\Middleware;
  3. use Closure;
  4. use Illuminate\Foundation\Application;
  5. use Illuminate\Support\InteractsWithTime;
  6. use Symfony\Component\HttpFoundation\Cookie;
  7. use Illuminate\Contracts\Encryption\Encrypter;
  8. use Illuminate\Session\TokenMismatchException;
  9. use Illuminate\Cookie\Middleware\EncryptCookies;
  10. class VerifyCsrfToken
  11. {
  12. use InteractsWithTime;
  13. /**
  14. * The application instance.
  15. *
  16. * @var \Illuminate\Foundation\Application
  17. */
  18. protected $app;
  19. /**
  20. * The encrypter implementation.
  21. *
  22. * @var \Illuminate\Contracts\Encryption\Encrypter
  23. */
  24. protected $encrypter;
  25. /**
  26. * The URIs that should be excluded from CSRF verification.
  27. *
  28. * @var array
  29. */
  30. protected $except = [];
  31. /**
  32. * Create a new middleware instance.
  33. *
  34. * @param \Illuminate\Foundation\Application $app
  35. * @param \Illuminate\Contracts\Encryption\Encrypter $encrypter
  36. * @return void
  37. */
  38. public function __construct(Application $app, Encrypter $encrypter)
  39. {
  40. $this->app = $app;
  41. $this->encrypter = $encrypter;
  42. }
  43. /**
  44. * Handle an incoming request.
  45. *
  46. * @param \Illuminate\Http\Request $request
  47. * @param \Closure $next
  48. * @return mixed
  49. *
  50. * @throws \Illuminate\Session\TokenMismatchException
  51. */
  52. public function handle($request, Closure $next)
  53. {
  54. if (
  55. $this->isReading($request) ||
  56. $this->runningUnitTests() ||
  57. $this->inExceptArray($request) ||
  58. $this->tokensMatch($request)
  59. ) {
  60. return $this->addCookieToResponse($request, $next($request));
  61. }
  62. throw new TokenMismatchException;
  63. }
  64. /**
  65. * Determine if the HTTP request uses a ‘read’ verb.
  66. *
  67. * @param \Illuminate\Http\Request $request
  68. * @return bool
  69. */
  70. protected function isReading($request)
  71. {
  72. return in_array($request->method(), ['HEAD', 'GET', 'OPTIONS']);
  73. }
  74. /**
  75. * Determine if the application is running unit tests.
  76. *
  77. * @return bool
  78. */
  79. protected function runningUnitTests()
  80. {
  81. return $this->app->runningInConsole() && $this->app->runningUnitTests();
  82. }
  83. /**
  84. * Determine if the request has a URI that should pass through CSRF verification.
  85. *验证当前的请求是我当前设置的csrf应该要跳过的地址
  86. * @param \Illuminate\Http\Request $request
  87. * @return bool
  88. */
  89. protected function inExceptArray($request)
  90. {
  91. foreach ($this->except as $except) {
  92. if ($except !== '/') {
  93. $except = trim($except, '/');
  94. }
  95. if ($request->fullUrlIs($except) || $request->is($except)) {
  96. return true;
  97. }
  98. }
  99. return false;
  100. }
  101. /**
  102. * Determine if the session and input CSRF tokens match.
  103. *
  104. * @param \Illuminate\Http\Request $request
  105. * @return bool
  106. */
  107. protected function tokensMatch($request)
  108. {
  109. //会完成对请求的数据验签和openssl验证
  110. //得 到openssl解密的数据
  111. $token = $this->getTokenFromRequest($request);
  112. return is_string($request->session()->token()) &&
  113. is_string($token) &&
  114. hash_equals($request->session()->token(), $token);
  115. }
  116. /**
  117. * Get the CSRF token from the request.
  118. *
  119. * @param \Illuminate\Http\Request $request
  120. * @return string
  121. */
  122. protected function getTokenFromRequest($request)
  123. {
  124. $token = $request->input('_token') ?: $request->header('X-CSRF-TOKEN');
  125. if (! $token && $header = $request->header('X-XSRF-TOKEN')) {
  126. $token = $this->encrypter->decrypt($header, static::serialized());
  127. }
  128. return $token;
  129. }
  130. /**
  131. * Add the CSRF token to the response cookies.
  132. *
  133. * @param \Illuminate\Http\Request $request
  134. * @param \Symfony\Component\HttpFoundation\Response $response
  135. * @return \Symfony\Component\HttpFoundation\Response
  136. */
  137. protected function addCookieToResponse($request, $response)
  138. {
  139. $config = config('session');
  140. $response->headers->setCookie(
  141. new Cookie(
  142. 'XSRF-TOKEN', $request->session()->token(), $this->availableAt(60 * $config['lifetime']),
  143. $config['path'], $config['domain'], $config['secure'], false, false, $config['same_site'] ?? null
  144. )
  145. );
  146. return $response;
  147. }
  148. /**
  149. * Determine if the cookie contents should be serialized.
  150. *
  151. * @return bool
  152. */
  153. public static function serialized()
  154. {
  155. return EncryptCookies::serialized('XSRF-TOKEN');
  156. }
  157. }