<?php
namespace app\middleware;

use Closure;

/**
 * CSRF校验
 */
class Csrf 
{
    public function handle($request, Closure $next)
    {
        $csrfToken = session('_token');
        if (empty($csrfToken)) {
            $csrfToken = randomStr(1, 32);
            session('_token', $csrfToken);
        }
        $paramToken = input('param._token', '');
        if (!empty($paramToken)) {
            if ($paramToken != $csrfToken) {
                return $this->csrfError($request);
            }
        } elseif($request->isPost() || $request->isAjax()) {
            if (empty($paramToken) || $paramToken != $csrfToken) {
                return $this->csrfError($request);
            }
            //HTTP_REFERER 认证
            $referer = $_SERVER['HTTP_REFERER'] ?? null;
            if(!empty($referer)) {
                $domain = $request->domain();
                $urlInfo = parse_url($referer);
                $scheme = $urlInfo['scheme'] ?? '';
                $requestSrc = '';
                if (!empty($scheme)) {
                    $requestSrc = $scheme.'://'.($urlInfo['host'] ?? '');
                }
                if($domain != $requestSrc) {
                    return $this->csrfError($request);
                }
            }
        }
        $request->csrfToken = $csrfToken;
        return $next($request);
    }

    protected function csrfError($request, $msg = '非法请求, 用户身份认证失败!')
    {
        if($request->isAjax()) {
            return json(['code'=>401, 'msg'=>$msg],200);
        } else {
            $referer = $_SERVER['HTTP_REFERER'] ?? null;
            if (empty($referer)) {
                $url = '/';
            } else {
                $domain = $request->domain();
                $urlInfo = parse_url($referer);
                $scheme = $urlInfo['scheme'] ?? '';
                $requestSrc = '';
                if (!empty($scheme)) {
                    $requestSrc = $scheme.'://'.($urlInfo['host'] ?? '');
                }
                if($domain != $requestSrc) {
                    $url = '/';
                } else {
                    $url = 'javascript:history.back(-1);';
                }
            }
            $errorData = [
                'code'=> 401,
                'msg' => $msg,
                'data' => [],
                'wait' => 5,
                'url' => $url
            ];
            return view('error/400', $errorData);
            // 返回401视图 response type has html、json、jsonp、xml、file、view、redirect
        }
    }
}