小言_互联网的博客

实现接口权限验证——验签

403人阅读  评论(0)

实现接口权限验证

开发用户接口实例之前,还需要设计一套严格的接口验证方法,保证 API 接口的安全
性。常见的接口验证一般包含以下几种

  • 请求时间:接口时效性验证。为了防止大 的重复请求, 可以设置每次请求的时效 小到以秒为单位, 大到可以是半个 小时
  • 验签:参数完整性验证。一般接口攻击, 都会截获请求,附带额外参数进行攻击,需要进行过滤验证。此时就需要客户端把所有的请求参 数根据一个特定的算法,生成一个签名字符串,并在请求时一并发送。服务器接收到这个 签名字符串后进行验证。
  • token:用户唯一Token 。用户每次登录都会生成唯 Token 信息,注销或者超时会话时 Token 会被注销,防止被非法获取

根据以上设计思路,本实例设计基于时效和参数 效验的权限验证方法。接口验证流程如图所示 下面以 ThinkP 框架为例,查看实现接口验 证父类的步骤与方法。

下面以 ThinkP 框架为例,查看实现接口验
证父类的步骤与方法。

实现权限验证基类

在application 目录下创建名为 api 应用模块 随后新建控制器 Api lp 作步骤如下。

(1 )定义返回值方法

api.php 控制器文件中 新增以下方法

/*
* 数据返回
* @param string $code HTTP CODE 
* @param string message 提示信息
* @param array $data 返回数据
*/ 
public function return_msg($code="200", $message="成功", $data= [)){
   
		header('Content-Type:application/json');//设置返回类型
		http_response_code($code);//设置返回头部
		$return['code'] = $code ; 
		$return['message'] =$message ; 
		if(!empty($data)){
    
			$return['data '] =$data; 
		}  
		exit(json_encode($return, JSON_UNESCAPED_UNICODE));
}

此方法用来定义返回信息操作,其中定义了 HTTP Header 类型和编码,代码如下:

header(‘Content-Type:application/json’);//设置返回类型
http_response_code($code);//设置返回头部

把传入的参数组装为数组,返回 JSON 格式数据,代码如下

$return['code'] = $code ; 
$return['message'] =$message ; 
if(!empty($data)){
    
	$return['data '] =$data; 
}  
exit(json_encode($return, JSON_UNESCAPED_UNICODE));

(2 )定义接口时效性验证方法

定义接口 验证方法,代码如下:

/** 
*检测接口 是否超时
* @pa ram $arr 
*/
public function check_time($arr) {
    
//设置返回类型
//设置返回头部
if(!isset($arr["time"])|| intval($arr["time"])<=1){
   
	$this_return_msg(400, '时间戳错误 !');
} 
if(time()-  intval($arr["time"]) >$this->timeout_second){
   
	$this_return_msg(400, ' 请求超时!');
} 
 
 

该方法中进行了两部分验证 时间参数(time )是否非空验证和是否超时验证。如果
任意一项无法匹配,方法都会返回错误信息。其 $this- timeout_second 属性,定义了接
口时效是多少秒,在类中定义为属性,代码如下 :

//默认接口的有效期为 60
protected $timeout_second = 60 ;

(3 )定义生成接口签名方法

为了防止请求中带有其他恶意的参数 需要根据原始数据,定义签名生成方法,代
如下:

/**
*构建请求签名
* @param pa ram 
* @return string 
*/
public function buildSign($param){
   
	unset($param["sign"]);//sign 字段不需要加入签名算法
	unset($param["time "]);//time 字段不需要加入签名算法
	ksort($param);//键值对的 key 按照升序排序
	$str=implode("",$param);//请求参数值拼接成字符串
	$sign =md5(md5($str).$this->sign_key);//执行加密
	return $sign ;
}   

buildSign()方法中,生成签名的算法主要有以下3步

  • 对请求参数 数组进行排序 使用 PHP 中的 ksort() 方法进行排序。
  • 把排序结果转换为字符串。
  • 使用 md5()方法和默认签名的 Key 进行签名生成的运算。
    其中 $this- sign_key 属性值在类中定义 代码如下。 签名 Key 可以是动态的,只要能和客户端在生成签名时保持一致即可。
//执行 key
private $sign_key = 'ThinkPHPS ';

(4)定义签名验证方法

该方法把请求接口的参数值,先进行排序和字符串转换,然后再进行生成签名处理。
返回值中所带的签名,如果和验证参数值生成的签名值保持 ,则通过验证,反之则
示错误信息。该方法定义如下

/** 
*验证请求签名是否正确
*@param $param 
*/
public function check_sign($param ){
   
	if(!issert($param["sign"])||!$param["sign"]){
   
		$this_return_msg(400, ' 签名不能为空!');
	}
	if( $param["sign"]!== $this->buildSign($param)){
   
		$this_return_msg(400, '签名错误!');
	}
}

(5)在初始化方法中调用验证

验证方法定义完成后 需要在控制器的初始化方法中调用,代码定义如下:

//初始化方法
public function _initialize(){
   
	parent::_initialize();
	//获取请求对象
	$this->request= Request::instance();
	//是否开启 API 权限验证(方便测试)
	if(confid("api_auth")){
   
			//验证时间戳是否超时
			$this->check_time($this->request->only(["time"]));
			//验证签名是否正确
			$this->check_sign($this->request->param());
	}
} 

需要注意的是,初始化方法中不仅获取了请求对象

 $this->request= Request::instance();

还使用了系统配置,来定义是否开启验证(方便开发者模式)

if(confid("api_auth"))

application api config.php 文件中,定义如下

<?php 
II API 块设计
return [ 
//应用命名空间
	'api_auth' => true 
]

访问地址 若效果如图,则说明 API 接口的全局验证成功

奇奇怪怪的只是又增加了呢

为了快速生成控制器类 在命令行下切换到应用根目 录下,执行 以下命令:

php think make:controller api/User 

系统会自动生成 User 资源控制器类,并创建对应资源操作的几个方法。为了在URL 中可以访问资源,则需要定义资源路由规则。在 application 目录下的 route,php 文件
中,追加以下内容:

Route::resource('users','api/User');

按资源路由的注册方法,定义 个名为 users 的路由, 其实内部会自动注册 个路由
规则,详细对应关系如表

请求表示 请求类型 路由规则 对应操作方法 描述
index GET users index 显示用户列表
create GET users/create create 新增用户页面
save POST users save 保存用户信息
read GET users/:id read 查看用户信息
edit GET users/:id/edit edit 编辑用户页面
update PUT users/:id update 更新用户信息
delete DELETE users/:id delete 删除用户

转载:https://blog.csdn.net/wangzhae/article/details/115019627
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场