zoukankan      html  css  js  c++  java
  • PHP开发api接口安全验证 -- 逻辑严谨性判断

    注意判断:
    数据验证
    传输数据安全加密
    唯一性验证
    为空
    false
    添加修改-----用户名重复怎么办
    如果传递值为空判断
    传递值与接收值是否相等
    字符串长度
    格式判断
    账户密码不能为空
    身份证号必须符合具体格式规定
    转账流程必须具有原子性,A账户扣钱、B账户存钱、A账户扣除手续费、通知户主四项操作必须要么都做,要么都不做”,都是完整性约束

    无非就是前台根据时间戳跟定义好的token加一个随机数,生成一个签名

    然后后台拿着token,与前台传过来的时间戳,加上随机数,再生成一次来比对而已

    接口的安全性主要围绕Token、Timestamp和Sign三个机制展开设计,保证接口的数据不会被篡改和重复调用,下面具体来看:

    方法一:用户登陆后生成token存到redis

    实现方法很多,用户登陆后,可以生成一个token(可以用uuid),存到redis中去,加入过期规则,用户在请求接口时,读取redis token吧token传过来,接收方,拿着这个token与redis中比对,如果redis Token不存在,说明请求无效,

    时间戳超时机制:(签名机制保证了数据不会被篡改)用户每次请求都带上当前时间的时间戳timestamp,服务端接收到timestamp后跟当前时间进行比对,如果时间差大于一定时间(比如5分钟),则认为该请求失效。时间戳超时机制是防御DOS攻击的有效手段。

    )签名机制:将 Token 和 时间戳 加上其他请求参数再用MD5或SHA-1算法(可根据情况加点盐)加密,加密后的数据就是本次请求的签名sign,服务端接收到请求后以同样的算法得到签名,并跟当前的签名进行比对,如果不一样,说明参数被更改过,直接返回错误标识。

    方法二:直接定义好token
    在实际工作中,使用PHP写api接口是经常做的,PHP写好接口后,前台就可以通过链接获取接口提供的数据,而返回的数据一般分为两种情况,xml和json,在这个过程中,服务器并不知道,请求的来源是什么,有可能是别人非法调用我们的接口,获取数据,因此就要使用安全验证。

    url 拦截规则,验证

      1. 用户登陆,验证成功后,生成token,缓存(username->token)并返回给客户端

      2. 客户端每个接口请求(除登陆接口)时,传必要的参数timestamp,token,username, sign,没传直接返回报错

      3. timestamp作用:是否在有效期内,有效期可以设置10,20分钟,根据需求设定

        比如说 过期时间设置为10分 服务接受到请求的当前时间戳是30,传过来的timestamp时间戳是10,30-10>10, 说明这个请求过期

      4. token作用:直接与redis中的username键值 对比,如果不相等,则过期,或如果redis缓存时间过期了,也过期

      5. sign作用:根据规则传过来的参数,生成sign,与传过来的sign对比。如果不相等,报错

    原理
    从图中可以看得很清楚,前台想要调用接口,需要使用几个参数生成签名。

    时间戳:当前时间
    随机数:随机生成的随机数
    口令:前后台开发时,一个双方都知道的标识,相当于暗号
    算法规则:商定好的运算规则,上面三个参数可以利用算法规则生成一个签名。
    前台生成一个签名,当需要访问接口的时候,把时间戳,随机数,签名通过URL传递到后台。后台拿到时间戳,随机数后,通过一样的算法规则计算出签名,然后和传递过来的签名进行对比,
    一样的话,返回数据。

      

    siginapi.php

    <?php
    namespace wstmartcommonmodel;
    /**
    
     * 插件类
     */
    class Siginapi extends Base{
       
        const TOKEN = 'API';
        //模拟前台请求服务器api接口
        //前台生成时间戳,随机数,请求别的接口,接收方:拿到这两个参数再跟定义好的token验证一边
        public function getDataFromServer(){
            //时间戳
            $timeStamp = time();
            //随机数
            $randomStr = $this -> createNonceStr();
            //生成签名
            $signature = $this -> arithmetic($timeStamp,$randomStr);
            //url地址
            $url = "http://www.apitest.com/Server/Server/respond/t/{$timeStamp}/r/{$randomStr}/s/{$signature}";
            $result = $this -> httpGet($url);
            dump($result);
        }
    
        //curl模拟get请求。
        private function httpGet($url){
            $curl = curl_init();
    
            //需要请求的是哪个地址
            curl_setopt($curl,CURLOPT_URL,$url);
            //表示把请求的数据已文件流的方式输出到变量中
            curl_setopt($curl,CURLOPT_RETURNTRANSFER,1);
    
            $result = curl_exec($curl);
            curl_close($curl);
            return $result;
        }
    
        //随机生成字符串
        private function createNonceStr($length = 8) {
            $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
            $str = "";
            for ($i = 0; $i < $length; $i++) {
                $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
            }
            return "z".$str;
        }
    
        /**
         * @param $timeStamp 时间戳
         * @param $randomStr 随机字符串
         * @return string 返回签名
         */
        private function arithmetic($timeStamp,$randomStr){
            $arr['timeStamp'] = $timeStamp;
            $arr['randomStr'] = $randomStr;
            $arr['token'] = self::TOKEN;
            //按照首字母大小写顺序排序
            sort($arr,SORT_STRING);
            //拼接成字符串
            $str = implode($arr);
            //进行加密
            $signature = sha1($str);
            $signature = md5($signature);
            //转换成大写
            $signature = strtoupper($signature);
            return $signature;
        }
    
    }

    signadmin.php

    <?php
    namespace wstmartcommonmodel;
    /**
    
     * 插件类
     */
    class Siginadmin extends Base{
       
        const TOKEN = 'API';
        //响应前台的请求
        /**
         * token授权机制:(Token是客户端访问服务端的凭证)--用户使用用户名密码登录后服务器给客户端返回一个Token(通常是UUID),并将Token-UserId以键值对的形式存放在缓存服务器中。服务端接收到请求后进行Token验证,如果Token不存在,说明请求无效。
         * 
         */
        public function respond(){
            //验证身份
            //时间戳超时机制:(签名机制保证了数据不会被篡改)用户每次请求都带上当前时间的时间戳timestamp,服务端接收到timestamp后跟当前时间进行比对,如果时间差大于一定时间(比如5分钟),则认为该请求失效。时间戳超时机制是防御DOS攻击的有效手段。
            $timeStamp = $_GET['t'];
            $randomStr = $_GET['r'];
            $signature = $_GET['s'];
            $str = $this -> arithmetic($timeStamp,$randomStr);
            if($str != $signature){
                echo "-1";
                exit;
            }
            //模拟数据
            $arr['name'] = 'api';
            $arr['age'] = 15;
            $arr['address'] = 'zz';
            $arr['ip'] = "192.168.0.1";
            echo json_encode($arr);
        }
    
        /**
         * @param $timeStamp 时间戳
         * @param $randomStr 随机字符串
         * @return string 返回签名
         */
        public function arithmetic($timeStamp,$randomStr){
            $arr['timeStamp'] = $timeStamp;
            $arr['randomStr'] = $randomStr;
            $arr['token'] = self::TOKEN;
            //按照首字母大小写顺序排序
            sort($arr,SORT_STRING);
            //拼接成字符串
            $str = implode($arr);
            //进行加密
            $signature = sha1($str);
            $signature = md5($signature);
            //转换成大写
            $signature = strtoupper($signature);
            return $signature;
        }
    
    }

     

  • 相关阅读:
    使用jsonp跨域调用百度js实现搜索框智能提示(转)
    jsonp 跨域
    Aixs2发布webservice服务
    java web service 上传下载文件
    java 网页 保存上传文件
    flash、js 函数 互相调用
    java web工程启动socket服务
    mysql 在Windows下自动备份
    Servlet中几个常用方法的推衍
    Tomcat常用设置 <持续更新>
  • 原文地址:https://www.cnblogs.com/yszr/p/14687872.html
Copyright © 2011-2022 走看看