常见PHP框架CSRF防范方案分析

本文详细探讨了PHP框架Laravel和Yii2中针对CSRF(跨站请求伪造)攻击的防御措施,包括中间件的工作原理、token的生成与验证。同时,还介绍了两种不依赖session的防护方案,一种利用强加密函数,另一种使用Md5,并讨论了它们的优缺点。文章适合了解PHP框架的安全实践。
摘要由CSDN通过智能技术生成

什么是CSRF

CSRF(跨站请求伪造)是一种恶意的攻击,它凭借已通过身份验证的用户身份来运行未经过授权的命令。网上有很多相关介绍了,具体攻击方式就不细说了,下面来说说LaravelYii2是如何来做CSRF攻击防范的。

Laravel CSRF防范

本次对Laravel CSRF防范源码的分析是基于5.4.36版本的,其他版本代码可能有所不同,但原理是相似的。

Laravel通过中间件app/Http/Middleware/VerifyCsrfToken.php来做CSRF防范,来看下源码。

<?php

namespace App\Http\Middleware;

use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as BaseVerifier;

class VerifyCsrfToken extends BaseVerifier
{
   
    /**
     * The URIs that should be excluded from CSRF verification.
     *
     * @var array
     */
    protected $except = [
        //
    ];
}

可以发现它是直接继承了Illuminate\Foundation\Http\Middleware\VerifyCsrfToken,只是提供了配置不进行CSRF验证的路由的功能(这里是因为某些场景下是不需要进行验证的,例如微信支付的回调)。

再来看下Illuminate\Foundation\Http\Middleware\VerifyCsrfToken主要源码。

    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     *
     * @throws \Illuminate\Session\TokenMismatchException
     */
    public function handle($request, Closure $next)
    {
   
        if (
            $this->isReading($request) ||
            $this->runningUnitTests() ||
            $this->inExceptArray($request) ||
            $this->tokensMatch($request)
        ) {
   
            return $this->addCookieToResponse($request, $next($request));
        }

        throw new TokenMismatchException;
    }

这里handle是所有路由经过都会执行的方法。可以看到中间件先判断是否是读请求,例如'HEAD', 'GET', 'OPTIONS',又或者是处于单元测试,又或者是不需要进行验证的路由,又或者token验证通过,那就会把这个token设置到cookie里去(可以使用 cookie 值来设置 X-XSRF-TOKEN 请求头,而一些 JavaScript 框架和库(如 AngularAxios)会自动将这个值添加到 X-XSRF-TOKEN 头中)。

我们再来看下是怎么验证token的。

    /**
     * Determine if the session and input CSRF tokens match.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return bool
     */
    protected function tokensMatch($request)
    {
   
        $token = $this->getTokenFromRequest($request);

        return is_string($request->session()->token()) &&
               is_string($token) &&
               hash_equals($request->session()->token(
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值