AES256通过注解方式接口实现

AES256通过注解方式接口实现

上一篇通过方法的方式去实现接口aes的加密AES256加解密与异常处理,这一篇通过aop切面注解的方式去调用加密方法

方法实现

AesKeyConst密钥key64位

/**
 * Copyright (C), 2018-2020
 * FileName: AesKeyConst
 * Author:   Lee
 * Date:     2020/11/3 10:44
 * Description: aes256加密key
 * History:
 */
package com.yc.asset.consts;

import lombok.Getter;

/**
 * @author Lee
 * @create 2020/11/3
 * @since 1.0.0
 */
@Getter
public class AesKeyConst {

    public static final String KEY = "3a6e2b4d4823f7c7c390c01ecd81d28c3a6e2b4d4823f7c7c390c01ecd81d28c";
}

DecryptResponse注解

/**
 * Copyright (C), 2018-2020
 * FileName: DecryptResponse
 * Author:   Lee
 * Date:     2020/11/5 9:18
 * Description: aes256加解密
 * History:
 */
package com.yc.asset.framework.annotation;

import java.lang.annotation.*;

/**
 * @author Lee
 * @create 2020/11/5
 * @since 1.0.0
 */
@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DecryptResponse {

	//请求参是否需要加密,默认true
    boolean inDecode() default true;
	//出参是否需要加密,默认true
    boolean outEncode() default true;
}

DecryptRequestBodyAdvice解密

/**
 * Copyright (C), 2018-2020
 * FileName: DecryptRequestBodyAdvice
 * Author:   Lee
 * Date:     2020/11/5 9:19
 * Description:
 * History:
 */
package com.yc.asset.framework.advice;

import com.yc.asset.framework.annotation.DecryptResponse;
import com.yc.asset.utils.http.DecryptHttpInputMessage;
import org.springframework.core.MethodParameter;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdvice;

import java.io.IOException;
import java.lang.reflect.Type;
import java.nio.charset.StandardCharsets;

/**
 * @author Lee
 * @create 2020/11/5
 * @since 1.0.0
 */
@ControllerAdvice
public class DecryptRequestBodyAdvice implements RequestBodyAdvice {

	//获取接口是否包含DecryptResponse
    @Override
    public boolean supports(MethodParameter methodParameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
        return methodParameter.getMethod().isAnnotationPresent(DecryptResponse.class);
    }

    @Override
    public HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) throws IOException {
        if (needDecrypt(parameter)) {
            return new DecryptHttpInputMessage(inputMessage, StandardCharsets.UTF_8);
        }
        return inputMessage;
    }

    @Override
    public Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
        return body;
    }

    @Override
    public Object handleEmptyBody(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
        return body;
    }

	//判断当前接口请求是否需要解密
    public boolean needDecrypt(MethodParameter returnType) {
        boolean encrypt = false;
        boolean classPresentAnno  = returnType.getContainingClass().isAnnotationPresent(DecryptResponse.class);
        boolean methodPresentAnno = returnType.getMethod().isAnnotationPresent(DecryptResponse.class);

        if(classPresentAnno){
            //类上标注的是否需要加密
            encrypt = returnType.getContainingClass().getAnnotation(DecryptResponse.class).inDecode();
            //类不加密,所有都不加密
            if(!encrypt){
                return false;
            }
        }
        if(methodPresentAnno){
            //方法上标注的是否需要加密
            encrypt = returnType.getMethod().getAnnotation(DecryptResponse.class).inDecode();
        }
        return encrypt;
    }
}

DecryptHttpInputMessage

/**
 * Copyright (C), 2018-2020
 * FileName: DecryptHttpInputMessage
 * Author:   Lee
 * Date:     2020/11/5 9:33
 * Description:
 * History:
 */
package com.yc.asset.utils.http;

import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.HexUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.symmetric.AES;
import com.alibaba.fastjson.JSON;
import com.yc.asset.consts.AesKeyConst;
import com.yc.asset.orms.vo.MonitorReqVO;
import com.yc.asset.orms.vo.MonitorRestMapVO;
import lombok.AllArgsConstructor;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpInputMessage;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;

/**
 * @author Lee
 * @create 2020/11/5
 * @since 1.0.0
 */
@AllArgsConstructor
public class DecryptHttpInputMessage implements HttpInputMessage {

    private HttpInputMessage inputMessage;
    private Charset charset;

    @Override
    public InputStream getBody() throws IOException {
        String content  = IoUtil.read(inputMessage.getBody(), charset);
        //这个地方根据实际需要自定义类型进行处理,博主因只对json体内的body值进行加解密所以对出入参进行封装。
        MonitorRestMapVO vo = JSON.parseObject(content, MonitorRestMapVO.class);
        MonitorReqVO body = JSON.parseObject(vo.getBody().toString(), MonitorReqVO.class);
        SecretKey secretKey = new SecretKeySpec(HexUtil.decodeHex(AesKeyConst.KEY), "AES");
        AES aes = SecureUtil.aes(secretKey.getEncoded());
        String decryptStr = aes.decryptStr(body.getVo());
        body.setVo(decryptStr);
        vo.setBody(body);
        return new ByteArrayInputStream(JSON.toJSONString(vo).getBytes());
    }

    @Override
    public HttpHeaders getHeaders() {
        return inputMessage.getHeaders();
    }
}

EncryptResponeBodyAdvice加密

/**
 * Copyright (C), 2018-2020
 * FileName: EncryptResponeBodyAdvice
 * Author:   Lee
 * Date:     2020/11/5 16:07
 * Description: 出参加密
 * History:
 */
package com.yc.asset.framework.advice;

import cn.hutool.core.util.HexUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.symmetric.AES;
import com.yc.asset.consts.AesKeyConst;
import com.yc.asset.framework.annotation.DecryptResponse;
import com.yc.asset.orms.vo.ResultVersionTwoVO;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

/**
 * @author Lee
 * @create 2020/11/5
 * @since 1.0.0
 */
@ControllerAdvice
public class EncryptResponeBodyAdvice implements ResponseBodyAdvice {

    @Override
    public boolean supports(MethodParameter returnType, Class converterType) {
        return returnType.getMethod().isAnnotationPresent(DecryptResponse.class);
    }

    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        if (null != body) {
            DecryptResponse methodAnnotation = returnType.getMethodAnnotation(DecryptResponse.class);
            if (methodAnnotation.outEncode()){
                SecretKey secretKey = new SecretKeySpec(HexUtil.decodeHex(AesKeyConst.KEY), "AES");
                AES aes = SecureUtil.aes(secretKey.getEncoded());
                ResultVersionTwoVO vo = (ResultVersionTwoVO) body;
                Object data = vo.getBody().getData();
                String hex = aes.encryptHex(String.valueOf(data));
                vo.getBody().setData(hex);
                return vo;
            }
        }
        return body;
    }
}

MonitorRestMapVO

package com.yc.asset.orms.vo;

import com.yc.asset.framework.annotation.PreHeaderSignCheck;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * 可以在POST METHOD中使用 {@link PreHeaderSignCheck} 进行header签名参数校验
 *
 * @author Lee
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class MonitorRestMapVO<T> {

    private RequestHeaderSignVO header;

    private T body;

}

RequestHeaderSignVO

package com.yc.asset.orms.vo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @author Lee
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class RequestHeaderSignVO {

    private String timestamp;

    private String username;

    private String signmode;

    private String type;

    private String sign;

    private String sync;

}

MonitorReqVO

/**
 * Copyright (C), 2018-2020
 * FileName: MonitorReqVO
 * Author:   Lee
 * Date:     2020/11/11 18:02
 * Description:
 * History:
 */
package com.yc.asset.orms.vo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @author Lee
 * @create 2020/11/11
 * @since 1.0.0
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class MonitorReqVO {

    private String vo;
}

ResultVersionTwoVO

package com.yc.asset.orms.vo;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @author : Lee
 * @version : 1.0
 * @since : 2020/11/11 19:36
 */
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class ResultVersionTwoVO<H, B> {
    // 返回头部
    private H header;
    // 返回数据体
    private BodyVO<B> body;
}

BodyVO

package com.yc.asset.orms.vo;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @author : Lee
 * @version : 1.0
 * @since : 2020/11/11 19:36
 */
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class BodyVO<T> {
    // 返回CODE
    private String code;
    // 返回错误信息
    private String message;
    // 返回数据
    private T data;
}

接口示例

@PostMapping(value = "/getDemo", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
//@DecryptResponse(inDecode = false, outEncode = false)
@DecryptResponse
public ResultVersionTwoVO<HeaderVO, MonitorListVO<List<MonitorIdListPO>>> getDemo(@RequestBody MonitorRestMapVO<MonitorReqVO> request) {
    RequestHeaderSignVO header = request.getHeader();
    MonitorRestDataIdListVO body = JSON.parseObject(request.getBody().getVo(), MonitorRestDataIdListVO.class);
  	//具体实现逻辑
    return new ResultVersionTwoVO<>(new HeaderVO(header.getType()), new BodyVO<>("1", "成功", new MonitorListVO<>(resultList)));
}

注意

因我们实现的是RequestBodyAdvice,所以请求在拦截时只会对接口中@RequestBody的参数进行处理

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值