PHP CSRF的防御

2016/03/31
博文都是原创  复制请谨慎
学习记录下 毕竟这个功能还是挺有用的

生成csrf token

<?php
session_start();

class CSRF {
	protected static $originCheck = true; //来源控制
	
	//根据token   生成session token
	public static function _set_Token( $key=null ) {
		if (empty($key)) 
			throw new Exception("key为NULL");
		
		$extra = self::$originCheck ? sha1( $_SERVER['REMOTE_ADDR'] . $_SERVER['HTTP_USER_AGENT'] ) : ''; //判断是否启用来源验证
        
        $token = base64_encode( time() . $extra . self::_getString( 32 ) ); //一起加密
        
        $_SESSION[ 'csrf_' . $key ] = $token; //放入session
        
		return $token;
    }
	
	//生成字符串
	protected static function _getString( $length ) {
        $text = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijqlmnopqrtsuvwxyz0123456789';
        $max = strlen( $text ) - 1;
		
        $string = '';
        for ( $i = 0; $i < $length; ++$i )
            $string .= $text{intval( mt_rand( 0.0, $max ) )};
		
        return $string;
    }
	
	//放入隐藏域 
	public static function _set_Input_Token( $key ) {
		echo "<input type='hidden' name='token' value='".$_SESSION[ 'csrf_' . $key ]."'>";
	}
	
	//生成token过期时间
	
	protected static function _set_Time() {
		$_SESSION['token_time'] = time();
	}
	
	//init初始化
	public function _init( $token ) {
		CSRF::_set_Token($token);
		CSRF::_set_Input_Token($token);
		CSRF::_set_Time();
	}
}

	

html获取token

<!doctype html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Document</title>
</head>
<body>
	<form action="verifyCsrf.class.php" method="post" >
	<?php
		require_once 'getCSRF.php';
		$c = new CSRF();
		$c->_init('token');
	?>
	用户名:<input type="text" name="username">
	<input type="submit" value="提交">
	</form>
</body>
</html>

csrf 验证token

<?php
session_start();

class verifyCsrf{
	
	protected static $originCheck = true; //来源控制
	public $token;
	public $time_token;
	
	public static function _checkToken( $key, $origin ){
		if ( !isset( $_SESSION[ 'csrf_' . $key ] ) )
            return false;
		
		if ( !isset( $origin[ $key ] ) )
            return false;
			
		$hash = $_SESSION[ 'csrf_' . $key ]; //获取存在session中的token
		
		//验证来源  根据加密验证
		if( self::$originCheck && sha1( $_SERVER['REMOTE_ADDR'] . $_SERVER['HTTP_USER_AGENT'] ) != substr( base64_decode( $hash ), 10, 40 ) ) 
			return false;
		
		//验证token
		if ( $origin[ $key ] != $hash )
            return false;
		
		//验证时间
		$expired_time = time() - $_SESSION['token_time'];
		if ($expired_time >= 300)
			return false;
		
        return true;
	}

	
	//跳转
	public static function _jump() {
		header("Location: " . $_SERVER['HTTP_REFERER']);
	}
	
}

$post['token'] = $_POST['token'];

$vc = verifyCsrf::_checkToken('token',$post);

if ($vc === true) {
	//
	print_r('success');
} else {
	verifyCsrf::_jump();
}

个人随笔

安静的等待,你若盛开,蝴蝶自来

承接高质量 网站开发 app开发 如有需要请点击About联系

作者 @承鹏辉