No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

FormTokenCheck.php 2.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | Yzncms [ 御宅男工作室 ]
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2018 http://yzncms.com All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
  8. // +----------------------------------------------------------------------
  9. // | Author: 御宅男 <530765310@qq.com>
  10. // +----------------------------------------------------------------------
  11. // +----------------------------------------------------------------------
  12. // | 防crsf全局
  13. // +----------------------------------------------------------------------
  14. namespace app\common\middleware;
  15. use think\exception\HttpResponseException;
  16. use think\facade\Session;
  17. class FormTokenCheck
  18. {
  19. /**
  20. * 表单令牌检测
  21. * @access public
  22. * @param Request $request
  23. * @param Closure $next
  24. * @param string $token 表单令牌Token名称
  25. * @return Response
  26. */
  27. public function handle($request, \Closure $next, string $token = null)
  28. {
  29. $check = $this->checkToken($request, $token ?: '__token__');
  30. $_token = $request->token();
  31. if (false === $check) {
  32. $result = [
  33. 'code' => -1,
  34. 'msg' => '令牌错误',
  35. 'data' => ['__token__' => $_token],
  36. 'url' => '',
  37. ];
  38. throw new HttpResponseException(json($result));
  39. }
  40. return $next($request);
  41. }
  42. /**
  43. * 检查请求令牌
  44. * @access public
  45. * @param string $token 令牌名称
  46. * @param array $data 表单数据
  47. * @return bool
  48. */
  49. public function checkToken($request, string $token = '__token__', array $data = [])
  50. {
  51. if (in_array($request->method(), ['GET', 'HEAD', 'OPTIONS'], true)) {
  52. return true;
  53. }
  54. if (!Session::has($token)) {
  55. // 令牌数据无效
  56. return false;
  57. }
  58. // Header验证
  59. if ($request->header('X-CSRF-TOKEN') && Session::get($token) === $request->header('X-CSRF-TOKEN')) {
  60. // 防止重复提交
  61. Session::delete($token); // 验证完成销毁session
  62. return true;
  63. }
  64. if (empty($data)) {
  65. $data = $request->post();
  66. }
  67. // 令牌验证
  68. if (isset($data[$token]) && Session::get($token) === $data[$token]) {
  69. // 防止重复提交
  70. Session::delete($token); // 验证完成销毁session
  71. return true;
  72. }
  73. // 开启TOKEN重置
  74. Session::delete($token);
  75. return false;
  76. }
  77. }