这两个注解可以放在类和方法上,遵循一样的逻辑,即:类上的注解&&方法上的注解,一方没有即为true,都为false为false。逻辑主要在NeedCrypto中。
/**
* 判断是否需要加解密
* @author xiongshiyan at 2018/8/30 , contact me with email yanshixiong@126.com or phone 15208384257
*/
class NeedCrypto {
private NeedCrypto(){}
/**
* 是否需要对结果加密
* 1.类上标注或者方法上标注,并且都为true
* 2.有一个标注为false就不需要加密
*/
static boolean needEncrypt(MethodParameter returnType) {
boolean encrypt = false;
boolean classPresentAnno = returnType.getContainingClass().isAnnotationPresent(EncryptResponse.class);
boolean methodPresentAnno = returnType.getMethod().isAnnotationPresent(EncryptResponse.class);
if(classPresentAnno){
//类上标注的是否需要加密
encrypt = returnType.getContainingClass().getAnnotation(EncryptResponse.class).value();
//类不加密,所有都不加密
if(!encrypt){
return false;
}
}
if(methodPresentAnno){
//方法上标注的是否需要加密
encrypt = returnType.getMethod().getAnnotation(EncryptResponse.class).value();
}
return encrypt;
}
/**
* 是否需要参数解密
* 1.类上标注或者方法上标注,并且都为true
* 2.有一个标注为false就不需要解密
*/
static boolean needDecrypt(MethodParameter parameter) {
boolean encrypt = false;
boolean classPresentAnno = parameter.getContainingClass().isAnnotationPresent(DecryptRequest.class);
boolean methodPresentAnno = parameter.getMethod().isAnnotationPresent(DecryptRequest.class);
if(classPresentAnno){
//类上标注的是否需要解密
encrypt = parameter.getContainingClass().getAnnotation(DecryptRequest.class).value();
//类不加密,所有都不加密
if(!encrypt){
return false;
}
}
if(methodPresentAnno){
//方法上标注的是否需要解密
encrypt = parameter.getMethod().getAnnotation(DecryptRequest.class).value();
}
return encrypt;
}
}
对于返回值加密,定义EncryptResponseBodyAdvice,实现ResponseBodyAdvice。
/**
* 请求响应处理类
*
* 对加了@Encrypt的方法的数据进行加密操作
*
* @author 熊诗言
*
*/
@ControllerAdvice
@ConditionalOnProperty(prefix = 'spring.crypto.response.encrypt', name = 'enabled' , havingValue = 'true', matchIfMissing = true)
public class EncryptResponseBodyAdvice implements ResponseBodyAdvice
将接口参数的加密解密和返回信息的加密解密分开,分别定义注解,利用Controller的ControllerAdvice来拦截所有的请求,在其中判断是否需要加密解密,即可达到要求。
使用方法:使用 DecryptRequest 和 EncryptResponse 注解即可,可以放在Controller的类和方法上,其中一个为false就不执行了。像这样:
@RestController
@RequestMapping('/test')
//@DecryptRequest
@EncryptResponse
public class TestController {
@Autowired
@Qualifier('rrCrypto')
private Crypto crypto;
@DecryptRequest(false)
@EncryptResponse(false)
@RequestMapping(value = '/enc' , method = RequestMethod.POST)
public String enc(@RequestBody String body){
return crypto.encrypt(body);
}
}
标上注解ConditionalOnProperty表示只有条件为true的时候才开启解密功能,一个配置即可打开或者关闭解密功能。真正的解密逻辑留给DecryptHttpInputMessage,它又委托给Crypto。
/**
*
* @author xiongshiyan
*/
public class DecryptHttpInputMessage implements HttpInputMessage {
private HttpInputMessage inputMessage;
private String charset;
private Crypto crypto;
public DecryptHttpInputMessage(HttpInputMessage inputMessage, String charset , Crypto crypto) {
this.inputMessage = inputMessage;
this.charset = charset;
this.crypto = crypto;
}
@Override
public InputStream getBody() throws IOException {
String content = IoUtil.read(inputMessage.getBody() , charset);
String decryptBody = crypto.decrypt(content, charset);
return new ByteArrayInputStream(decryptBody.getBytes(charset));
}
@Override
public HttpHeaders getHeaders() {
return inputMessage.getHeaders();
}
}
加了此注解的接口(true)将进行数据加密操作 * 可以放在类上,可以放在方法上
* @author 熊诗言 */ @Target({ElementType.METHOD , ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface EncryptResponse { /** * 是否对结果加密 */ boolean value() default true; }至此,一个完美的对接口的加密解密就实现了。
定义返回信息加密的注解,EncryptResponse。
/**
* 加密注解
*
* 加了此注解的接口(true)将进行数据解密操作(post的body) 可
* 以放在类上,可以放在方法上
* @author xiongshiyan
*/
@Target({ElementType.METHOD , ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DecryptRequest {
/**
* 是否对body进行解密
*/
boolean value() default true;
}
然后定义ControllerAdvice,对于请求解密的,定义DecryptRequestBodyAdvice,实现RequestBodyAdvice。
/**
* 请求数据接收处理类
*
* 对加了@Decrypt的方法的数据进行解密操作
*
* 只对 @RequestBody 参数有效
* @author xiongshiyan
*/
@ControllerAdvice
@ConditionalOnProperty(prefix = 'spring.crypto.request.decrypt', name = 'enabled' , havingValue = 'true', matchIfMissing = true)
public class DecryptRequestBodyAdvice implements RequestBodyAdvice {
@Value('${spring.crypto.request.decrypt.charset:UTF-8}')
private String charset = 'UTF-8';
@Autowired
@Qualifier('rrCrypto')
private Crypto crypto;
@Override
public boolean supports(MethodParameter methodParameter, Type targetType,
Class extends HttpMessageConverter>> converterType) {
return true;
}
@Override
public Object handleEmptyBody(Object body, HttpInputMessage inputMessage, MethodParameter parameter,
Type targetType, Class extends HttpMessageConverter>> converterType) {
return body;
}
@Override
public HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter, Type targetType,
Class extends HttpMessageConverter>> converterType) throws IOException {
if( NeedCrypto.needDecrypt(parameter) ){
return new DecryptHttpInputMessage(inputMessage , charset , crypto);
}
return inputMessage;
}
@Override
public Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType,
Class extends HttpMessageConverter>> converterType) {
return body;
}
}
定义参数解密的注解,DecryptRequest。
/**
* 解密注解
*
*
文章为作者独立观点,不代表股票交易接口观点