• API接口的安全设计验证:ticket,签名,时间戳


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

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

    3.但这依然存在问题,可能会被进行恶意无限制访问,这时我们需要引入一个时间戳参数,如果超时即是无效的。

    4.服务端需要对token,签名,时间戳进行验证,只有token有效,时间戳未超时,签名有效才能被放行。

     

    Token认证获取

    用户登录成功后,会获取一个ticket值,接下去任何接口的访问都需要这个参数。我们把它放置在redis内,有效期为10分钟,在ticket即将超时,无感知续命。延长使用时间,如果用户在一段时间内没进行任何操作,就需要重新登录系统。

     

    每次请求都带有这三个参数,我们都需要进行验证,只有在三个参数都满足我们的要求,才允许数据返回或被操作。

    public class LoginInterceptor implements HandlerInterceptor {

        @Autowired
        private RedisTemplate redisTemplate;

        @Override
        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;
        }
    }
  • 相关阅读:
    jQuery火箭图标返回顶部代码
    jQuery火箭图标返回顶部代码
    jQuery火箭图标返回顶部代码
    jQuery火箭图标返回顶部代码
    jQuery火箭图标返回顶部代码
    jQuery火箭图标返回顶部代码
    jQuery火箭图标返回顶部代码
    jQuery火箭图标返回顶部代码
    jQuery火箭图标返回顶部代码
    jQuery火箭图标返回顶部代码
  • 原文地址:https://www.cnblogs.com/KL2016/p/15936675.html
Copyright © 2020-2023  润新知