接口校验思路:

在对外提供接口时,我们一定要注意到数据的安全问题。如果可以建议使用HTTPS,但是在接口安全方面,还是建议大家对接口数据进行数据签名,防止中途数据被串改。签名的主要思想如下:

1、首先要定义如下三个字段:

当前时间戳:防止接口一直被刷 签名字段:主要是服务端用来进行对比数据是否一致 签名秘钥: 必须将当前时间戳和签名秘钥参数追加到传递进来的参数中。

2、对所有参数按照键进行升序排列

3、将第二步排列好的参数按照key=value&key=value进行拼接

4、将第三步拼接好的参数与时间戳、秘钥拼接

5、将第四步的字符串进行md5进行加密后转大写,生成对应的签名字符串

6、将第五步的签名数据追加到传递进来的参数中

7、将第六步的数据进行签名对比

实例:

  1. <?php
  2. namespace App\Http\Middleware;
  3. use App\Http\Constants\ApiStatus;
  4. use App\Http\Controllers\Controller;
  5. use Closure;
  6. use Illuminate\Http\Request;
  7. use Illuminate\Support\Facades\Log;
  8. /**
  9. * 接口签名校验
  10. * Class SignMiddleware
  11. * @package App\Http\Middleware
  12. */
  13. class SignMiddleware
  14. {
  15. /**
  16. * Handle an incoming request.
  17. *
  18. * @param Request $request
  19. * @param Closure $next
  20. * @return mixed
  21. */
  22. public function handle($request, Closure $next)
  23. {
  24. try {
  25. $miyuSign = $request->header("miyu-sign");
  26. $time = $request->header("miyu-time");
  27. if (empty($sign) || empty($time)) {
  28. return Controller::responseError(ApiStatus::ILLEGAL_REQUEST);
  29. }
  30. # 时间有效性校验
  31. $currentTime = time();
  32. if ($currentTime - $time >= 300 || $currentTime - $time < -300) {
  33. return Controller::responseError(ApiStatus::TIME_EXCEPT);
  34. }
  35. if ($request->method() == "POST") {
  36. $data = $request->post();
  37. } elseif ($request->method() == "GET") {
  38. $data = $request->all();
  39. }
  40. ksort($data);
  41. $sign = md5(urldecode(http_build_query($data)) . "&time=" . $time . '&token=111111111');
  42. if ($sign !== $miyuSign) {
  43. return Controller::responseError(ApiStatus::ILLEGAL_REQUEST);
  44. }
  45. } catch (\Exception $e) {
  46. Log::debug($e->getMessage());
  47. return Controller::responseError(ApiStatus::ILLEGAL_REQUEST);
  48. }
  49. return $next($request);
  50. }
  51. }

注意事项

1、假如是客户端请求接口,就需要多想一步了。假如把 秘钥 硬编码到客户端,会有反编译的风险,特别是 android 。可以在客户端登陆验证成功后,返回给客户端的信息中带上 秘钥(当然,返回的数据也可能被拦截,真是防不胜防啊。。。)。特别说明一下,在 android 开发中,假如硬要把 秘钥 硬编码,建议把 appsecret 放到 NDK 中编译成 so 文件, app 启动后去读取。