ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

thinkphp6: 给接口api做签名验证(php 8.1.1 / thinkphp v6.0.10LTS )

2022-01-22 13:02:17  阅读:317  来源: 互联网

标签:8.1 v6.0 code return 10LTS param sign php data


一,创建middelware和controller

liuhongdi@lhdpc:/data/php/admapi$ php think make:middleware CheckSign
Middleware:app\middleware\CheckSign created successfully.
liuhongdi@lhdpc:/data/php/admapi$ php think make:controller Pay
Controller:app\controller\Pay created successfully.

说明:刘宏缔的架构森林是一个专注架构的博客,地址:https://www.cnblogs.com/architectforest

         对应的源码可以访问这里获取: https://github.com/liuhongdi/
         或: https://gitee.com/liuhongdi

说明:作者:刘宏缔 邮箱: 371125307@qq.com

二,编写php代码:

1,middleware/CheckSign.php  
<?php
declare (strict_types = 1);
 
namespace app\middleware;
 
use app\result\Result;
use app\lib\util\sign;
 
class CheckSign
{
    //第三方对接口的访问不需要检查
    private $notCheck = ["/pay/alipayreturn","/pay/alipayrotify"];
    /**
     * 处理请求
     *
     * @param \think\Request $request
     * @param \Closure       $next
     * @return Response
     */
    public function handle($request, \Closure $next)
    {
        $uri = $request->server("REQUEST_URI");
        //如果是不需检查的uri
        if (in_array($uri ,$this->notCheck)) {
            return $next($request);
        } else {
            $sign = new sign();
            $param = $request->request();
            unset($param['s']);
            //检查参数的sign
            $res = $sign->verifySign($param);
            if ($res['code'] == 0){
                return $next($request);
            } else {
                return Result::Error(1,$res['msg']);
            }
        }
    }
}
2,lib/util/sign.php
<?php
namespace app\lib\util;
 
class sign {
    private $appId = "lc20220118";
    private $appKey = "u665698fzur5e2t85tyu142";
 
    //创建sign
    public function makeSign($data) {
        ksort($data);
        $string = $this->toUrlParams($data);
        $string = $string . "&key=" . $this->appKey;
        $string = md5($string);
        $result = strtolower($string);
        return $result;
    }
 
    //检验sign是否正确
    public function verifySign($data) {
        //check sign
       if (!isset($data['sign']) || !$data['sign']) {
          return ['code'=>1,'msg'=>'发送的数据签名不存在'];
       }
 
        //check sign
        if (!isset($data['appid']) || !$data['appid']) {
            return ['code'=>1,'msg'=>'发送的应用参数1不存在'];
        }
        if ($data['appid'] != $this->appId) {
            return ['code'=>1,'msg'=>'发送的应用参数1错误'];
        }
 
        //check sign
        if (!isset($data['nonce']) || !$data['nonce']) {
            return ['code'=>1,'msg'=>'发送的应用参数2不存在'];
        }
 
       //check timestamp
       if (!isset($data['timestamp']) || !$data['timestamp']) {
          return ['code'=>1,'msg'=>'发送的数据参数不合法'];
       }
 
       // 验证请求, 10分钟失效
       if (time() - $data['timestamp'] > 600) {
          return ['code'=>1,'msg'=>'验证超时, 请重新发送请求'];
       }
 
       $clientSign = $data['sign'];
        unset($data['sign']);
       $serverSign = $this->makeSign($data);
       if ($clientSign == $serverSign) {
         return ['code'=>0,'msg'=>'验证通过'];
       } else {
         return ['code'=>1,'msg'=>'请求不合法'];
       }
    }
 
    //生成url字符串
    private function toUrlParams($values){
        $buff = "";
        foreach ($values as $k => $v)
        {
            //&& $v != ""
            if($k != "sign" && !is_array($v)){
                $buff .= $k . "=" . $v . "&";
            }
        }
        $buff = trim($buff, "&");
        return $buff;
    }
}
3,controller/Pay.php
<?php
declare (strict_types = 1);
 
namespace app\controller;
 
use think\Request;
 
class Pay
{
    /**
     * return
     *
     * @return \think\Response
     */
    public function alipayReturn()
    {
        echo "alipayReturn";
        exit;
    }
 
    /**
     * notify
     *
     * @return \think\Response
     */
    public function alipayNotify()
    {
        echo "alipayNotify";
        exit;
    }
}

三,编写vue代码:

说明:vue代码仅供演示,因为js中无法安全保存appkey,            所以web/wap等不需要做验证:
<template>
  <div style="text-align: left;">
    id:{{article.id}}<br/>
    title:{{article.title}}<br/>
    content:{{article.content}}<br/>
  </div>
</template>
 
<script>
import {apiArticleOne} from "../api/api";
import {ElMessage} from "element-plus";
import {ref} from "vue";
import md5 from 'js-md5';
export default {
  name: "Article",
  setup() {
 
    const article = ref([]);
    //得到sign
    const getSign = (param,key) => {
      let str = "";
      for(var idx in param) {
         let one = idx+"="+param[idx];
         if (str == "") {
             str = one;
         } else {
             str = str+"&"+one;
         }
      }
      str = str+"&key="+key;
      //console.log("before md5:"+str);
      let md5str = md5(str);
      return md5str;
    }
 
    //得到参数对象
    const getParam = (id) => {
       let appid = "lc20220118";
       let appkey = "u665698fzur5e2t85tyu1421";
       let timestamp = parseInt((new Date()).getTime()/1000);
       let nonce = Math.floor(Math.random()*8999)+1000;
 
       let param = {
           appid:appid,
           id:id,
           nonce:nonce,
           timestamp:timestamp,
       }
      let sign = getSign(param,appkey);
      param.sign = sign;
      return param;
    }
 
    //查询得到一篇文章的内容:
    const getArticle = () => {
      var param = getParam(1);
      apiArticleOne(param).then(res => {
        //成功
        if (res.code == 0) {
          article.value = res.data;
        } else {
          ElMessage.error("获取表单令牌失败:"+res.msg);
        }
      }).catch((error) => {
        console.log(error)
      })
    }
    getArticle();
    return {
      article,
    }
  }
}
</script>
 
<style scoped>
</style>

四,测试效果:

1,成功返回数据时: 2,appkey不正确时: 3,直接访问接口时报错: 4,访问不做check的接口:

五,查看php和thinkphp的版本:

php:
liuhongdi@lhdpc:/data/php/admapi$ php --version
PHP 8.1.1 (cli) (built: Dec 20 2021 16:12:16) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.1.1, Copyright (c) Zend Technologies
    with Zend OPcache v8.1.1, Copyright (c), by Zend Technologies 
thinkphp:
liuhongdi@lhdpc:/var/www/html$ cd /data/php/admapi/
liuhongdi@lhdpc:/data/php/admapi$ php think version
v6.0.10LTS 

 

标签:8.1,v6.0,code,return,10LTS,param,sign,php,data
来源: https://www.cnblogs.com/architectforest/p/15832850.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有