java反向认证接口_java-http-json接口认证与防篡改机制非侵入式实现

一个好的代码,就是一次开发到处可用,开发者不用关注其细节,专心核心实现。奔着这个目标,有没有什么实现思路?那接下来,我不管你怎么想的,都听我的。

在本场 Chat 中,会讲到如下内容:

接口开发的固化与痛点

怎么解决接口提供方痛点

怎么解决接口调用方痛点

java-http-json 接口 sdk 使用指南

涉及技术:接口开发、装饰者模式 、自定义注解、反射、md5 加密、过滤器

我们的目标

接口提供方仅通过配置、写实现具体的签名规则方法和获取 appKey 的方法,即可实现。

接口调用方仅通过注解、使用工具类、写签名规则方法和签名的参数拼接方法,即可实现。

是不是感觉大大简化了接口的开发和接入。不懂可以参考笔者的默认实现,但不建议直接使用。

代码在 github 上,最后会 post 上地址,请大家多多支持和 star。

接口开发套路

当产品跟你说要开发接口提供给其他系统使用或者说你要通过接口方式接入某些系统时,肯定先会问需要怎么签名?数据要加密?需要什么方式传输?

接口提供方

一般写个工具类进行签名认证或者解密,验证通过后这些便进行实际的业务逻辑。签名验证等的非业务逻辑的参数看着“碍眼”,因为“用完即走”嘛。那还能怎么办?难道接口开发还能不要验证的接口参数?嗯....下文会填坑。

接口调用方

要对接新接口,如果是开发言语一致还好,就询问对方要接口验证的工具类,然后自己再加工下写个新的工具类实现调用咯。开发言语不一致?嗯...还真没有其他办法,只能按着签名逻辑,自己写工具类。无论如何,接口调用方最麻烦的就是按照接口约定的参数进行拼接签名,不同接口不一样,都要写一遍把需要参数传入。那好像没啥办法。不要担心,还有点办法。

接口开发的重复

接口提供方的接口方法可能还需要其他地方使用,但是又加上了一些接口验证的参数。老手当然业务代码抽出来作为新的方法同时给接口和其他地方使用。此时一位萌新使用了 ctrl+c 和 ctrl+v,并膜拜了下大神的代码。接口调用方对接同一系统的新接口,又要 get、set 的搬砖模式。

“用完即走”的契机

接口的开发流程基本固定,在那些环节可以“用完即走”?

我们先梳理下接口交互的全过程:接口调用>>>接口服务>>>认证通过>>>返回业务数据。

相信有经验的开发者,已经想到前文提到的问题产生的原因是接口认证过程和业务耦合了。要想解耦,我们再把 java-http-json 接口开发的关键技术摆出来:http、json、servlet、签名算法等。其中 servlet 技术还有 listener、filter。停...可以了。就是 filter 过滤器了,它可以承载接口的认证全过程,从过滤器再到实际的业务逻辑,对于开发者来说几乎是无感的,因为签名验证等的非业务逻辑的参数都可以不出现在业务方法中。

接口调用方要摆脱“约定的参数进行拼接签名”的 get、set 的搬砖模式,笔者能想到的是使用自定义注解的技术和解析注解的工具类实现。或许你有更好的办法,不妨联系笔者技术交流。

java-http-json 接口 sdk 开发

实现流程:java反向认证接口_java-http-json接口认证与防篡改机制非侵入式实现_第1张图片

接口提供方过滤器伪代码实现

重写过滤器初始化方法 init,实现接口时间戳超时与超前时间范围设置,笔者都默认 30 秒

重写过滤器过滤处理方法 doFilter,实现接口认证过程:(1)过滤掉非 post 请求(2)包装 post 请求,因为需要重复利用数据流,避免使用一次流就没了。(3)获取 post 请求中的公共参数对象 ApiRequestDTO(4)验证时间戳是否超时与超前(5)获取待验证的签名值和根据 appID 获取系统配置的 appKey(6)签名验证(7)去掉 post 请求中非业务逻辑所需的参数(8)转发到实际服务注意:包装 post 请求的具体实现请参考实际的 sdk 代码。

接口调用方伪代码实现

调用的接口的参数较少且不需要参与签名等,直接用 map 进行设置,否则创建参数 bean 设置。

自定义注解限定运行时触发且只注解到参数 bean 的属性上

编写自定义注解解析工具类:(1)编写解析注解对象的方法 getTamperResistantMap,利用反射获取被注解属性信息,得到属性名-属性值 map;(2)编写获取请求已签名 json 的方法 getRequestJsonWithSign,使用自定义签名接口对象作为方法参数,限定开发者调用前必须实现签名和参数拼接。

编写签名工具类注意:工具类的具体实现请参考实际的 sdk 代码。

java-http-json 接口 sdk 使用指南

上述进行了伪代码实现,主要为了更好地理解 sdk 的主要实现。sdk 的 github 地址:[email protected]:smooth-mirror/http-json.git环境要求:JDK1.8+、servlet3.1+使用前记得 clone 到本地然后 install 到本地 maven 仓库。

接口提供方使用方式

首先引入 maven 依赖或者引入 jar 包,参考 DefaultApiRequestAuthFilter 继承 BaseApiRequestAuthFilter 自定义 filter 过滤器,接口提供方提供了两种接入方式。

web.xml 配置过滤器接入

注意这里的 DefaultApiRequestAuthFilter,都应该换掉使用自定义过滤器,这里只是演示用

DefaultApiRequestAuthFilter cn.windflute.http.filter.DefaultApiRequestAuthFilter maxLeadingTimeSecond 30 maxTimeoutSecond 30 DefaultApiRequestAuthFilter URL1 DefaultApiRequestAuthFilter URL2

整合 spring 注解接入方式(spring4.3.8+)

修改继承 BaseApiRequestAuthFilter 自定义 filter 过滤器,添加注解配置并重写 init 方法,使 springbean 的注解生效。

@WebFilter(urlPatterns = "修改成需要拦截的接口地址", initParams = {//最大超前时间,默认 30 秒 @WebInitParam(name = "maxLeadingTimeSecond", value = "30"),// 最大超时时间,默认 30 秒 @WebInitParam(name = "maxTimeoutSecond", value = "30"),})public class TestFilter extends BaseApiRequestAuthFilter{//添加需要用到的 springbean,这里需要自己写服务,仅供参考 @Autowired IAppKeyService appKeyService; @Override public void init(FilterConfig filterConfig) throws ServletException { super.init(filterConfig); WebApplicationContextUtils .getWebApplicationContext(filterConfig.getServletContext()) .getAutowireCapableBeanFactory().autowireBean(this); }//使用 springbean 获取 AppKey 的方法,仅供参考 @Override public String getAppKey(PostParameterRequestWrapper request, String appId) { return appKeyService.getAppKey(request,appId); }}

接口代码的写法(spring4.3.8+)

接口方法使用@ResponseBody、@PostMapping 等注解,如果方法的参数是对象则需要增加@RequestBody 注解。例如:

@ResponseBody @PostMapping(value = "find.json") public Result find(@RequestBody ApiFindDTO findDTO) { // todo }

接口调用方使用方式

引入 maven 依赖或者引入 jar 包

使用 map 传入接口的业务参数或者使用 bean 对象作为传入接口的业务参数

如果使用 bean 对象作为传入接口的业务参数,可以在对应的属性上添加防篡改的注解@TamperResistantAnnotation(isTransJson=false),isTransJson 可以设置这个字段是否转成 json 字符串,来兼容集合等非基本类型字段

参考无 SignWithTamperResistant 参数的 TamperResistantHandler.getRequestJsonWithSign 方法,创建匿名 SignWithTamperResistant 接口对象实现使用签名方法 sign 和签名的参数 map 拼接方法 concatForSign

传入创建匿名 SignWithTamperResistant 接口对象调用有 SignWithTamperResistant 参数的 TamperResistantHandler.getRequestJsonWithSign 方法

步骤 3 的返回值转成 jsonstring,使用 OkHttpClientUtil.postJson 调用 http-json 接口即可。这一步的调用方式仅供可参考,也可以用其他的 http 工具类实现。

结束语

笔者开发的 java-http-json 接口 sdk,本意是为了可以非侵入、快速改造历史的 http-json 接口问题以及后续接口的高效开发,因为历史的 http-json 接口存在很多安全问题,欠下的技术债务是要还的。

本文首发于 GitChat,未经授权不得转载,转载需与 GitChat 联系。

阅读全文: http://gitbook.cn/gitchat/activity/5d655a990fe1fb2495bfa504

您还可以下载 CSDN 旗下精品原创内容社区 GitChat App ,阅读更多 GitChat 专享技术内容哦。

java反向认证接口_java-http-json接口认证与防篡改机制非侵入式实现_第2张图片

你可能感兴趣的:(java反向认证接口)