暴露在前端的接口被刷是件很头疼的事,这件事情无解,根据我观察,目前主流有三种方法:
1. 通过Js注入Cookie数据,此Cookie数据会在后端进行校检,此种方式必须采用渲染Js来进行破解,提高了刷接口成本。
2. 在前端对请求参数进行加密,加密方法采用代码混淆技术,这种成本比较低,效果还不错。
3. 每次请求生成一个唯一字符串,把该字符串注入Cookie中,此串只能用一次,当访问接口时会校检该串是否有效或是否被用过,无效串直接403。
出于成本考虑我采用1和2两种方法的结合,具体流程如下:
1. 生成一个与时间戳有关系的字符串K,该字符串可采用Rc4加密算法生成,保证加密串可以被还原成时间戳。
2. 将K注入Cookie中
3. 前端拿到K,根据请求参数算出Sign
4. 前端把Sign和请求参数传递到后端,后端首先提取出K计算是否有效、是否过期了一定时间间隔,然后计算Sign是否有效
/**
* 获取与时间戳有关的加密串
* @Return String
*/
Public Static Function Getencryptionkey() {
$Timestamp = Strval(Time());
$Rc4ret = Self::Rc4(Self::Common_secret_key, $Timestamp);
Return Base64_encode($Rc4ret);
}
/**
* 从加密串中解出时间戳
* @Param $Key
* @Return String
*/
Public Static Function Decodeencryptionkey($Key) {
Return Self::Rc4(Self::Common_secret_key, Base64_decode($Key));
}
/**
* 验证加密串是否有效,考虑时间戳的失效时间。
* @Param $Key
* @Return Bool
*/
Public Static Function Checkencryptionkey($Key) {
$Nowtimestamp = Intval(Time());
If (!Empty($Key)) {
$Encyptiontimestamp = Intval(Self::Decodeencryptionkey($Key));
Return (($Encyptiontimestamp + Self::Max_valid_time_interval) >= $Nowtimestamp);
}
Return False;
}