首页 物流新闻 API接口的安全规划验证:ticket,签名,时刻戳

API接口的安全规划验证:ticket,签名,时刻戳

cnblogs.com/dslx/p/14116294.html 概述 与前端对接的API接口,假如被第三方抓包并进行歹意篡改参数,或许会导致数据走漏,乃至会被篡改数据,我首要环绕…


cnblogs.com/dslx/p/14116294.html

概述

与前端对接的API接口,假如被第三方抓包并进行歹意篡改参数,或许会导致数据走漏,乃至会被篡改数据,我首要环绕时刻戳,token,签名三个部分来确保API接口的安全性


1.用户成功登陆站点后,服务器会回来一个token,用户的任何操作都必须带了这个参数,能够将这个参数直接放到header里。

2.客户端用需求发送的参数和token生成一个签名sign,作为参数一同发送给服务端,服务端在用相同的办法生成sign进行查看是否被篡改。

3.但这仍然存在问题,或许会被进行歹意无约束拜访,这时咱们需求引进一个时刻戳参数,假如超时便是无效的。

4.服务端需求对token,签名,时刻戳进行验证,只需token有用,时刻戳未超时,签名有用才干被放行。


敞开接口

没有进行任何约束,简略粗犷的拜访办法,这样的接口办法一般在敞开的使用渠道,查气候,查快递,只需你输入正确对应的参数调用,即可获取到自己需求的信息,咱们能够恣意修正参数值。

      
      /*
 * Description: 敞开的接口
 *  huangweicheng
 *  2020/12/21
*/


("/token")
public class TokenSignController {

    
    private TokenSignService tokenSignService;

    (value = "openDemo",method = RequestMethod.GET)
    public ListPersonEntity openDemo(int personId){
        return tokenSignService.getPersonList(personId);
    }
}


Token认证获取

用户登录成功后,会获取一个ticket值,接下去任何接口的拜访都需求这个参数。咱们把它放置在redis内,有用期为10分钟,在ticket行将超时,无感知续命。延伸使用时刻,假如用户在一段时刻内没进行任何操作,就需求从头登录体系。扩展:记一次token安全认证的实践

      
      (value = "login",method = RequestMethod.POST)
    public JSONObject login(@NotNull String username, @NotNull String password){
        return tokenSignService.login(username,password);
    }

登录操作,查看是否有这个用户,用户名和暗码匹配即可成功登录。

      
      /** 
     * 
     * Description:验证登录,ticket成功后放置缓存中,
     * 
     *  huangweicheng
     *  2020/12/31   
    */
 
    public JSONObject login(String username,String password){
        JSONObject result = new JSONObject();
        PersonEntity personEntity = personDao.findByLoginName(username);
        if (personEntity == null || (personEntity != null  !personEntity.getPassword().equals(password))){
            result.put("success",false);
            result.put("ticket","");
            result.put("code","999");
            result.put("message","用户名和暗码不匹配");
            return result;
        }
        if (personEntity.getLoginName().equals(username)  personEntity.getPassword().equals(password)){
            String ticket = UUID.randomUUID().toString();
            ticket = ticket.replace("-","");
            redisTemplate.opsForValue().set(ticket,personEntity.getLoginName(),10L, TimeUnit.MINUTES);
            result.put("success",true);
            result.put("ticket",ticket);
            result.put("code",200);
            result.put("message","登录成功");
            return result;
        }
        result.put("success",false);
        result.put("ticket","");
        result.put("code","1000");
        result.put("message","不知道反常,请重试");
        return result;
    }


Sign签名

把一切的参数拼接一同,在参加体系秘钥,进行MD5核算生成一个sign签名,避免参数被人歹意篡改,后台按相同的办法生成秘钥,进行签名比照。

      
      /**
     *  request
     * 
     */

    public static Boolean checkSign(HttpServletRequest request,String sign){
        Boolean flag= false;
        //查看sigin是否过期
        Enumeration? pNames =  request.getParameterNames();
        MapString, String params = new HashMapString, String();
        while (pNames.hasMoreElements()) {
            String pName = (String) pNames.nextElement();
            if("sign".equals(pName)) continue;
            String pValue = (String)request.getParameter(pName);
            params.put(pName, pValue);
        }
        System.out.println("现在的sign--" + sign);
        System.out.println("验证的sign--" + getSign(params,secretKeyOfWxh));
        if(sign.equals(getSign(params, secretKeyOfWxh))){
            flag = true;
        }
        return flag;
    }


重复拜访

引进一个时刻戳参数,确保接口仅在一分钟内有用,需求和客户端时刻保持一致。

      
      public static long getTimestamp(){
        long timestampLong = System.currentTimeMillis();

        long timestampsStr = timestampLong / 1000;

        return timestampsStr;
    }

需求跟当时服务器时刻进行比照,假如超越一分钟,就回绝本次恳求,节约服务器查询数据的耗费


拦截器

每次恳求都带有这三个参数,咱们都需求进行验证,只需在三个参数都满意咱们的要求,才答应数据回来或被操作。

      
      public class LoginInterceptor implements HandlerInterceptor {

    
    private RedisTemplate redisTemplate;

    
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response,Object handler) throws IOException {
        JSONObject jsonObject = new JSONObject();
        String ticket = request.getParameter("ticket");
        String sign = request.getParameter("sign");
        String ts = request.getParameter("ts");
        if (StringUtils.isEmpty(ticket) || StringUtils.isEmpty(sign) || StringUtils.isEmpty(ts)){
            jsonObject.put("success",false);
            jsonObject.put("message","args is isEmpty");
            jsonObject.put("code","1001");
            PrintWriter printWriter = response.getWriter();
            printWriter.write(jsonObject.toJSONString());
            return false;
        }
        //假如redis存在ticket就认为是合法的恳求
        if (redisTemplate.hasKey(ticket)){
            System.out.println(redisTemplate.opsForValue().getOperations().getExpire(ticket));
            String values = (String) redisTemplate.opsForValue().get(ticket);
            //判别ticket是否行将过期,进行续命操作
            if (redisTemplate.opsForValue().getOperations().getExpire(ticket) != -2  redisTemplate.opsForValue().getOperations().getExpire(ticket)  20){
                redisTemplate.opsForValue().set(ticket,values,10L, TimeUnit.MINUTES);
            }
            System.out.println(SignUtils.getTimestamp());
            //判别是否重复拜访,存在重放进犯的时刻窗口期
            if (SignUtils.getTimestamp() - Long.valueOf(ts)  600){
                jsonObject.put("success",false);
                jsonObject.put("message","Overtime to connect to server");
                jsonObject.put("code","1002");
                PrintWriter printWriter = response.getWriter();
                printWriter.write(jsonObject.toJSONString());
                return false;
            }
            //验证签名
            if (!SignUtils.checkSign(request,sign)){
                jsonObject.put("success",false);
                jsonObject.put("message","sign is invalid");
                jsonObject.put("code","1003");
                PrintWriter printWriter = response.getWriter();
                printWriter.write(jsonObject.toJSONString());
                return false;
            }
            return true;
        }else {
            jsonObject.put("success",false);
            jsonObject.put("message","ticket is invalid,Relogin.");
            jsonObject.put("code","1004");
            PrintWriter printWriter = response.getWriter();
            printWriter.write(jsonObject.toJSONString());
        }
        return false;
    }
}


拜访

先登录体系,获取合法的ticket


生成一个合法的sign验证,获取测验ts,拜访openDemo,即可正常拜访。还能够将参数加密,将http换成https,就不一 一展开了。


demo代码

https://github.com/hwc4110/spring-demo1221


    

或许你还想看

  1. 围观几款程序员专用小众的浏览器,你用过哪几个呢?
  2. 小姐姐,我这么写代码怎么了?你不要轻视我啊!
  3. 狗哥引荐:分布式业务精品资源,月薪5万必需要翻越的一座山!
  4. 引荐一个终年霸榜的爬虫结构,你用过么?
  5. 一堆你没有见过的黑科技东西!
  6. 作为程序员的你,常用的东西软件有哪些?
  7. 最让你震动的网站有哪些?
  8. B站精华资源,搜藏渐渐看!
  9. 核算机专业必读哪些经典书本?
  10. 10分钟建立一个博客!
  11. 一招破解迅雷下载约束!
  12. 引荐几个高清看片网站!!!!
  13. 这款插件不火,天理难容!!
  14. 10个可谓经典的电脑小技巧,让你工作事半功倍!
本文来自网络,不代表快递资讯网立场。转载请注明出处: http://www.llaiot.com/logistics-news/2647.html
上一篇
下一篇

为您推荐

返回顶部