ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

实现接口加密

2021-10-31 20:00:38  阅读:154  来源: 互联网

标签:拦截器 加密 请求 实现 接口 签名 注解 数据包


1 产生需求的原因

如图,假如这个地址暴露了,那么谁拿到地址都可以直接发送请求,但是前端发送请求一定是通过http实现的,也因此这个地址一定会曝光,有心人也一定能拿到这个地址,因此需要加一个sign签名,生成签名的方式别人不知道,这样就能保证别人拿到这个地址也没办法使用

image

2 加密原理

当客户端向服务端发送数据包时,会基于该数据包生成签名A并带上一起发送过去,当服务端收到数据包时,也会基于数据包生成签名B,并且对比签名A和B,两者相同则认为数据包确实是由客户端合法发送过来的,服务端才会响应请求,如果签名不一致,则表示数据包的数据被临时篡改了

image

整个过程中最重要的就是基于数据包实现加密的方式,因此sign签名不是随便什么字段来充当的,而是基于一定的加密规则实现的,这个加密规则不管是客户端还是服务端都是重点保密的数据

3 签名时效性

sign签名应当具备时效性,否则别人拦截了单次请求后,把这个请求向服务端发送100次,那么就出乱子了,比如用户本想发送一个付费道具,结果被人拦截请求并反复发送请求,就变成了让客户端发送100次礼物,那用户的钱不就没了吗。

实现时效性有两种方式:

  1. 在用户登录后由服务器下发该用户所属token,每个用户都不一样,签名的生成规则中以该token为加密秘钥,由于token具有有效期,就能令生成的签名也具备时效性,但是这样就得做两层加密,登录返回的token得加密,不能明文返回,然后才是正常的对数据包进行加密

  2. 令请求携带时间戳,要求请求响应时间与时间戳不能超过XX秒,这就等于为签名设置了过期时间,假设这个过期时间设置为2秒,那么请求刚被拦截下来,还没完成打包再发送呢,签名就过期了,这就实现了时效性

如果遇到恶意请求攻击,那就需要使用动态过滤器,那就是另外一套解决方案了,不是签名时效性能解决的,都不是一码事

4 选择性加密(动态验签)

并不是所有接口都需要加密,比如拉取房间人数,拉取礼物数据,这些就没必要加密了,只有很重要的功能,比如支付、充值需要加密

要实现加密,就是在请求到达controller之前生成签名并完成比对,所以就需要设置拦截器

5 实现方式

5.1 创建简单的拦截器

将拦截器写在公共模块下

首先创建一个拦截器

image

然后在spring配置类中配置拦截器

@Configuration
public class DefaultConfig implements WebMvcConfigurer {

    Logger logger = LoggerFactory.getLogger(DefaultConfig.class);
    @Resource
    private AuthInterceptor authInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(authInterceptor).addPathPatterns("/**")
        .excludePathPatterns("/login/**");
    }
}

5.2 理清拦截器能拦截的数据

现在,直接由前端请求接口,就会被拦截器拦截

image

拦截器可以识别请求要访问的接口以及具体的方法,也可以看到这个方法上是否有注解,有哪些注解,那么我们只需要自定义一个注解,然后放在需要加密的方法上,当过滤器发现前端请求要访问的是有这个注解的方法时,就进行拦截,这样就可以实现动态验签,只对重要的方法进行验证

image

5.3 自定义注解

在公共模块自定义一个注解,设置生命周期、注解类型以及一个布尔变量

@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Auth {
    boolean isCheck() default true;
}

如图,把这个注解放在需要加密的方法上,就实现了定点拦截的目的

image

5.4 完成过滤器的编写

5.4.1 获取方法的注解

过滤器基于如图所示方法就可以获取到被请求的方法的注解

image

5.4.2 自定义加密方式

  • 拓展:TreeMap实现排序

    代码如图

image

    效果如图

image

加密方式只要够复杂,别人很难获取和破解就行了,没有什么固定的说法

比如我们设置一种加密方式,首先把数据包中的属性按照A-Z或者Z-A排序,然后转为字符串,使用TreeMap就能实现A-Z或者Z-A排序

image

然后把排好序的属性挨个取出,拼成字符串,类似下图的效果,图中C为数组,因此有多个值,值与值之间就用逗号间隔

image

代码如下,在把属性拼接完毕后,最后拼接一个用户登录后服务器下发给用户的token,这样在发现签名不匹配时就可以记录这个token,反向追踪到发送了假数据的用户,然后可以封了用户或者报警让网警处理

image

最后对这个字符串sb进行加密,然后与前端发送过来的数据包里的签名进行比对,如果比对正确则放行

image

5.4.3 过滤器代码

整体代码如下

@Component
public class AuthInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //获取被请求的方法上的注解
        Auth methodAnnotation = ((HandlerMethod) handler).getMethodAnnotation(Auth.class);
        //如果能获取到@Auth注解并且注解的isCheck是true则进行拦截和验证
        if(methodAnnotation != null && methodAnnotation.isCheck()){
            //验证
            Map<String, String[]> parameterMap = request.getParameterMap();
            TreeMap<String, String[]> treeMap = new TreeMap<>(parameterMap);
            StringBuilder sb = new StringBuilder();
            treeMap.forEach((s, strings) -> {
                if(!s.equals("sign")){
                    sb.append(s);
                    sb.append("=");
                    sb.append(strings);
                    sb.append("&");
                }
            });
            sb.append("token="+"asdasdasdasdasdas");
            //这步操作:借助hutool工具类 实现MD5加密 得到服务端的签名A
            //获取前端传递的签名B
            String sign = request.getParameter("sign");
            //这步操作:比较前端和服务端的签名 两者一致才放行请求
        }
        return false;
    }
}

标签:拦截器,加密,请求,实现,接口,签名,注解,数据包
来源: https://www.cnblogs.com/BRSblackshoot/p/15490585.html

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

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

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

ICode9版权所有