# api-wrap **Repository Path**: slacrey/api-wrap ## Basic Information - **Project Name**: api-wrap - **Description**: API签名验证工具,简单易用 https://github.com/slacrey/api-wrap - **Primary Language**: Java - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 57 - **Forks**: 19 - **Created**: 2020-10-30 - **Last Updated**: 2025-06-06 ## Categories & Tags **Categories**: api-gateway **Tags**: None ## README # 服务端安全签名验签 ## chang list - api-wrap-boot去除redis依赖 ## 引入jar包 ### gradle ``` compile 'com.seelyn:api-wrap-boot:{version}' ``` ### maven ``` com.seelyn api-wrap-boot {version} ``` ## 使用示例 - 使用EnableApiWrap注解,开启API Wrap功能 ```java @SpringBootApplication @EnableApiWrap public class WrapWebApplication { public static void main(String[] args) { SpringApplication.run(WrapWebApplication.class, args); } } ``` - 在controller类方法或类上添加@ApiWrap注解, 注解也可以自定义处理类,只有使用了注解的类和方法才能接收签名验签请求 ``` @ApiWrap @PostMapping(value = "/web") public WrapRequest web(@RequestBody WrapRequest request) { return request; } ``` - 自定义API签名验签处理类 ``` @ApiWrap(value=CustomWrapHandler.class) CustomWrapHandler类需要实现WrapHandler接口 ``` - WrapRequest 是统一的API验证请求类,其中泛型 DefaultWrapData类需要继承WrapData类 ```java public class WrapRequest { private String appKey; private String signature; private long timestamp; private int nonce; private T data; //setter getter省略.... } ``` ```java import com.seelyn.apiwrap.WrapData; import com.seelyn.apiwrap.annotation.SignIgnore; public class DefaultWrapData extends WrapData { // SignIgnore 注解标识标识忽略属性用于签名 @SignIgnore private String name; private String url; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } } ``` - 存储appKey和appSecret用于请求验证 ``` @Autoware private WrapStore wrapStore; // 存储密钥 wrapStore.putSecret(appKey, appSecret); ``` - 配置文件 ``` #===========api wrap=========== # app密钥,若用户没有自定义,则使用此 api.wrap.secret=testjjhdsa # 单位秒,请求时间和服务器时间不能超过300秒 api.wrap.legal-time=300 # 若没有redis配置,wrapStore为本地存储 # 若配置了redis,则wrapStore为redis存储 #===========api wrap redis============= spring.redis.host=localhost spring.redis.port=6379 spring.redis.database=0 ``` - 若没有redis配置,wrapStore为本地存储 - 若配置了redis,则wrapStore为redis存储 # 客户端辅助签名工具 ## 引入工具包 ### gradle ``` compile 'com.seelyn:api-wrap-client:{version}' ``` ### maven ``` com.seelyn api-wrap-client {version} ``` ## 使用说明 ``` DefaultWrapData WrapData = new DefaultWrapData(); WrapClient wrapClient = WrapClient.create(appKey, appSecret); WrapRequest request = wrapClient.wrap(WrapData) // request 为带签名信息的对象 ``` # 服务端扩展 ## 扩展WrapStore ```java @Service class CustomWrapStore extends RedisWrapStore { } ``` 这样继承RedisWrapStore类或者实现WrapStore接口,可自定义包裹存储接口。系统自动使用你自定义的WrapStore ## 扩展WrapHandler ### 自定义CustomWrapHandler ``` // 自定义WrapHandler, 使用@Component注入到spring中管理 @Component public class CustomWrapHandler implements WrapHandler { @Override public String getAppSecret(String appKey) { return null; } @Override public String getSignature(String appKey, WrapRequest request) { return null; } @Override public void isLegalTime(long timestamp) { } @Override public void isReplayAttack(String appKey, long timestamp, int nonce, String signature) { } } ``` ### 使用CustomWrapHandler ``` // ApiWrap中指定CustomWrapHandler.class类,则系统会根据此类型从Spring中获取对应的实例 @ApiWrap(value = CustomWrapHandler.class) @PostMapping(value = "/web") public WrapRequest custom(@RequestBody WrapRequest request) { return request; } ```