玻璃行业做的非常有设计感的网站,怎么给搞笑网站做文案,企业如何进行网络营销,知名的深圳小程序开发公司需求 有个简单的需求#xff0c;对于第三方接口我们需要做个简单的鉴权机制#xff0c;这边使用的是非对称性加密的机制。我们提供三方公钥#xff0c;他们通过公钥对接口json报文使用加密后的报文请求#xff0c;我们通过对接收过来的请求某一个加密报文字段来进行RSA解密… 需求 有个简单的需求对于第三方接口我们需要做个简单的鉴权机制这边使用的是非对称性加密的机制。我们提供三方公钥他们通过公钥对接口json报文使用加密后的报文请求我们通过对接收过来的请求某一个加密报文字段来进行RSA解密校验
考虑到日后方便其他接口使用我这边使用了拦截自定义注解RequestBodyAdvice机制来处理。话不多说来实操一把 定义自定义注解类
Target({ElementType.METHOD})
Retention(RetentionPolicy.RUNTIME)
Documented
public interface AuthenticationThird{}
RAS工具类
pom文件引入依赖 dependencygroupIdcom.github.shalousun/groupIdartifactIdcommon-util/artifactIdversion1.9.2/version/dependency
import com.power.common.util.RSAUtil;import java.util.Map;public class RSATool {/*** 随机生成一对公私钥*/public static MapString, String generatorRsaPariKey() {return RSAUtil.createKeys(1024);}/*** 通过公钥来加密获取对应base64字符串** param sourceData* param publicKey* return*/public static String encryptStr(String sourceData, String publicKey) {return RSAUtil.encryptString(sourceData, publicKey);}/*** 通过RAS 公钥加密的字符串 使用私钥来解密** param encryptStr* param privateKey* return*/public static String decryptStr(String encryptStr, String privateKey) {return RSAUtil.decryptString(encryptStr, privateKey);}}私钥配置类
Configuration
Data
public class ThridApiInfoConfig {Value(${api.auth.privateKey})public String authenticationThirdPrivateKey;
} 第三方请求加密后封装报文类
Data
public class BaseEncryptReq {private String encryptBoyStr;private String reqSource;}
自定义异常类
Setter
Getter
public class NoPassException extends RuntimeException {private String message;public NoPassException(String message) {this.message message;}}RequestBodyAdvice这里类能干什么 对RequestBody进行增强处理比如所有请求的数据都加密之后放在 body 中在到达 controller 的方法之前需要先进行解密那么就可以通过 RequestBodyAdvice 来进行统一的解密处理无需在 controller 方法中去做这些通用的操作。
自定义的类需要实现 RequestBodyAdvice 接口但是这个接口有个默认的实现类 RequestBodyAdviceAdapter相当于一个适配器方法体都是空的所以我们自定义的类可以直接继承这个类更方便一些
继承RequestBodyAdviceAdapter类 Slf4j
ControllerAdvice
public class DecryptRequestBodyAdvice extends RequestBodyAdviceAdapter {Autowiredprivate ThridApiInfoConfig thridApiInfoConfig;Overridepublic boolean supports(MethodParameter methodParameter, Type targetType, Class? extends HttpMessageConverter? converterType) {return methodParameter.getMethod().isAnnotationPresent(AuthenticationThird.class);}Overridepublic HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class? extends HttpMessageConverter? converterType) {String encoding UTF-8;InputStream inputStream null;try {//step1 获取http请求中原始的bodyString body IOUtils.toString(inputMessage.getBody(), encoding);//step2 将对应字符串转为beanBaseEncryptReq baseEncryptReq JSON.parseObject(body, BaseEncryptReq.class);if (!StringUtil.isNotBlank(baseEncryptReq.getEncryptBoyStr())) {throw new NoPassException(接口加密报文不能为空);}if (!StringUtil.isNotBlank(baseEncryptReq.getReqSource())) {throw new NoPassException(接口请求来源参数不能为空);}//todo 判断来源if (StringUtil.isNotBlank(baseEncryptReq.getReqSource()) !xxx.equals(baseEncryptReq.getReqSource())) {throw new NoPassException(接口请求来源参数不合法);}//step3 解密baseEncryptReq.encryptBoyStr属性进行RSATool解密String decryptBody RSATool.decryptStr(baseEncryptReq.getEncryptBoyStr(), thridApiInfoConfig.getAuthenticationThirdPrivateKey());//step 4 将解密之后的body数据重新封装为HttpInputMessage作为当前方法的返回值inputStream IOUtils.toInputStream(decryptBody, encoding);} catch (NoPassException ex) {log.error(DecryptRequestBodyAdvice 处理解密异常);throw new NoPassException(ex.getMessage());} catch (Exception ex) {log.error(DecryptRequestBodyAdvice 处理解密异常);throw new NoPassException(接口解密异常);}InputStream finalInputStream inputStream;return new HttpInputMessage() {Overridepublic InputStream getBody() throws IOException {return finalInputStream;}Overridepublic HttpHeaders getHeaders() {return inputMessage.getHeaders();}};}} 定义测试controller类
Slf4j
RestController
RequestMapping(/testController)
public class TestController {AuthenticationThirdPostMapping(value/testAuth)public ResultDto testAuth(RequestBody String param){log.info(解密后的报文:{},param);return ResultDto.builder().success(true).message(测试鉴权).build();}
}
定义全局异常处理类
Slf4j
ControllerAdvice
public class GlobalExceptionHandler {/*** 处理 NoPassException 异常** param e* return*/ExceptionHandler(NoPassException.class)ResponseBodypublic ResultDto handleNoPassException(NoPassException e) {log.error(自定义NoPassException异常:{},{}, e.getMessage(), e);return ResultDto.builder().success(false).message(e.getMessage()).build();} 接口响应实体类 Data
public class ResultDto {private Boolean success;private String message;
}测试效果
我们先用之前的RSATool工具类对报文通过公钥来加密 控制台输出 修改下加密报文 至此就完成了一个简单通用的接口鉴权