java json接口加密解密

java json接口加密解密

对json接口进行加密解密, 这里实现的方式是 解密使用自定义过滤器

1、启动类加注解@ServletComponentScan

@SpringBootApplication
@ServletComponentScan
public class TestWebApplication {

	public static void main(String[] args) {
		SpringApplication.run(TestWebApplication.class, args);
	}

}

2、创建一个自定义Filter


/**
 * 解密过滤器
 */
@Order(1)
@WebFilter({"/*"})
public class DecodeFilter extends OncePerRequestFilter {

    private static final Logger logger = LoggerFactory.getLogger(DecodeFilter.class);

    protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain chain) throws ServletException, IOException {
        String contentType = req.getContentType();
        String url = req.getRequestURI();
        //判断是否是json形式请求
        if (StringUtils.isNotBlank(contentType) && contentType.contains("application/json")) {
            //获取request的请求数据
            BufferedReader streamReader = new BufferedReader(new InputStreamReader(req.getInputStream(), "UTF-8"));
            StringBuilder responseStrBuilder = new StringBuilder();
            String inputStr;
            while ((inputStr = streamReader.readLine()) != null)
                responseStrBuilder.append(inputStr);
            //请求json
            JSONObject jsonObject = JSONObject.parseObject(responseStrBuilder.toString());
            //是否加密, 是则进行解密
            if (jsonObject != null && StringUtils.isNotBlank(jsonObject.getString("isEnc"))
                    && jsonObject.getString("isEnc").equals("Y")) {

                //获取request的请求数据
                String bodyInfoEn = jsonObject.getString("content");
                //解密密钥
                String sKey = jsonObject.getString("sKey");

                if (StringUtils.isNotEmpty(bodyInfoEn)) {
                    logger.info("参数解密前: {}", bodyInfoEn);

                    //解密后字符串
                    String bodyInfoDe = AESOperator.getInstance().decrypt(bodyInfoEn, sKey);

                    logger.info("url: {}, 解密后: {}", req.getRequestURI(), bodyInfoDe);

                    if (StringUtils.isNotEmpty(bodyInfoDe)) {

                        //由于request请求没有修改参数的权限,使用篡改后的request代替原先的
                        BodyRequestWrapper requestWrapper = new BodyRequestWrapper(req, bodyInfoDe);

                        chain.doFilter(requestWrapper, res);
                        return;
                    }
                }
                //如果content不存在则返回错误信息
                res.setCharacterEncoding("UTF-8");
                res.setContentType("application/json; charset=utf-8");
                PrintWriter out = res.getWriter();
                try {
                    //加密返回
                    String encrypt = AESOperator.getInstance().encrypt(("缺少必要参数"), AESOperator.skey);
                    out.print(JSONObject.toJSONString(new ApiResult<>(encrypt)));
                    out.flush();
                    out.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            } else {
                //非加密 直接请求
                String param = jsonObject.toJSONString();
                BodyRequestWrapper requestWrapper = new BodyRequestWrapper(req, param);
                chain.doFilter(requestWrapper, res);
            }
        } else {
            //过滤请求
            chain.doFilter(req, res);
        }
    }
}

篡改request


public class BodyRequestWrapper extends HttpServletRequestWrapper {

    private byte[] body;

    public BodyRequestWrapper(HttpServletRequest request, String json) throws IOException {
        super(request);
        body = json.getBytes();
    }

    @Override
    public BufferedReader getReader() throws IOException {
        return new BufferedReader(new InputStreamReader(getInputStream()));
    }

    /**
     * 在使用@RequestBody注解的时候,其实框架是调用了getInputStream()方法,所以我们要重写这个方法
     *
     * @return
     * @throws IOException
     */
    @Override
    public ServletInputStream getInputStream() throws IOException {
        final ByteArrayInputStream bais = new ByteArrayInputStream(body);

        return new ServletInputStream() {
            @Override
            public boolean isFinished() {
                return false;
            }

            @Override
            public boolean isReady() {
                return false;
            }

            @Override
            public void setReadListener(ReadListener readListener) {

            }

            @Override
            public int read() throws IOException {
                return bais.read();
            }
        };
    }
}

使用AES 加密解密


/**
 * AES 是一种可逆加密算法,对用户的敏感信息加密处理 对原始数据进行AES加密后,在进行Base64编码转化;
 */

public class AESOperator {

    /*
     * 加密用的Key 可以用26个字母和数字组成 此处使用AES-128-CBC加密模式,key需要为16位。
     */
    public static final String skey = "smkldospdosldaaa";//key,可自行修改
    private String ivParameter = "1016449182158477";//偏移量,可自行修改
    private static AESOperator instance = null;

    private AESOperator() {

    }

    public static AESOperator getInstance() {
        if (instance == null)
            instance = new AESOperator();
        return instance;
    }

    public static String Encrypt(String encData, String secretKey, String vector) throws Exception {

        if (secretKey == null) {
            return null;
        }
        if (secretKey.length() != 16) {
            return null;
        }
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        byte[] raw = secretKey.getBytes();
        SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
        IvParameterSpec iv = new IvParameterSpec(vector.getBytes());// 使用CBC模式,需要一个向量iv,可增加加密算法的强度
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
        byte[] encrypted = cipher.doFinal(encData.getBytes("utf-8"));
        return new BASE64Encoder().encode(encrypted);// 此处使用BASE64做转码。
    }


    // 加密
    public String encrypt(String sSrc, String sKey) throws Exception {
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        byte[] raw = sKey.getBytes();
        SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
        IvParameterSpec iv = new IvParameterSpec(ivParameter.getBytes());// 使用CBC模式,需要一个向量iv,可增加加密算法的强度
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
        byte[] encrypted = cipher.doFinal(sSrc.getBytes("utf-8"));
        return replace(new BASE64Encoder().encode(encrypted));// 此处使用BASE64做转码。
    }

    // 解密
    public String decrypt(String sSrc, String sKey) {
        try {
            byte[] raw = sKey.getBytes("ASCII");
            SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            IvParameterSpec iv = new IvParameterSpec(ivParameter.getBytes());
            cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
            byte[] encrypted1 = new BASE64Decoder().decodeBuffer(sSrc);// 先用base64解密
            byte[] original = cipher.doFinal(encrypted1);
            String originalString = new String(original, "utf-8");
            return originalString;
        } catch (Exception ex) {
            return null;
        }
    }

    public String decrypt(String sSrc, String key, String ivs) throws Exception {
        try {
            byte[] raw = key.getBytes("ASCII");
            SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            IvParameterSpec iv = new IvParameterSpec(ivs.getBytes());
            cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
            byte[] encrypted1 = new BASE64Decoder().decodeBuffer(sSrc);// 先用base64解密
            byte[] original = cipher.doFinal(encrypted1);
            String originalString = new String(original, "utf-8");
            return originalString;
        } catch (Exception ex) {
            return null;
        }
    }

    public static String encodeBytes(byte[] bytes) {
        StringBuffer strBuf = new StringBuffer();

        for (int i = 0; i < bytes.length; i++) {
            strBuf.append((char) (((bytes[i] >> 4) & 0xF) + ((int) 'a')));
            strBuf.append((char) (((bytes[i]) & 0xF) + ((int) 'a')));
        }

        return strBuf.toString();
    }

    /**
     * 去除 换行符、制表符
     * @param str
     * @return
     */
    public String replace(String str) {
        if (!StringUtil.isEmpty(str)) {
            return str.replaceAll("\r|\n", "");
        }
        return str;
    }

    public static void main(String[] args) throws Exception {
        // 需要加密的字串
        String cSrc = "{\"loginName\":\"test\",\"secret\":\"123456\"}";

        // 加密
        String enString = AESOperator.getInstance().encrypt(cSrc, skey);
        System.out.println("加密后的字串是:" + enString);

        // 解密
        String DeString = AESOperator.getInstance().decrypt(enString, skey);
        System.out.println("解密后的字串是:" + DeString);
    }

3、这里加密返回用aop

		<!-- AOP -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-aop</artifactId>
		</dependency>

@Aspect // 表示该类是一个通知类
@Configuration //spring注解方式bean注入 交给spring管理
public class ResultAspect {

    private static Logger logger = LoggerFactory.getLogger(ResultAspect.class);

    // 定义切点Pointcut
    @Pointcut("execution(* com.test.controller.api..*(..))")
    public void excudeService() {
    }

    @Around("excudeService()")
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
        RequestAttributes ra = RequestContextHolder.getRequestAttributes();
        ServletRequestAttributes sra = (ServletRequestAttributes) ra;
        HttpServletRequest request = sra.getRequest();

        // result的值就是被拦截方法的返回值
        Object result = pjp.proceed();
        logger.info("请求结束,controller的返回值是 " + JSONObject.toJSONString(result));
        String contentType = request.getContentType();
        String url = request.getRequestURI();
        String sKey = AESOperator.skey;
        logger.info("加密返回:url = {} skey = {}", url, sKey);
        String encrypt = AESOperator.getInstance().encrypt(JSONObject.toJSONString(result), sKey);

        return new ApiResult<>(encrypt);
    }
}


测试请求:

	{ 
	    "isEnc": "Y",
	    "content": "n7XJKiXTxMOBBwaSIRLtbJPtLy6tZ4AsVPimyOctSzglYO4pmQng4lb9wVnjmihb",
	    "sKey": "smkldospdosldaaa"
	}
  • 5
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Java中使用JWT(JSON Web Token)进行加密解密是一种常见的身份验证和授权机制。JWT由三部分组成:头部(Header)、载荷(Payload)和签名(Signature)。 1. 头部(Header):包含了算法和令牌类型等信息,通常使用Base64编码表示。 2. 载荷(Payload):包含了要传输的数据,比如用户ID、角色等信息,同样使用Base64编码表示。 3. 签名(Signature):使用私钥对头部和载荷进行签名,以确保数据的完整性和真实性。 下面是使用Java进行JWT加密解密的步骤: 1. 导入相关依赖:在项目的pom.xml文件中添加以下依赖: ```xml <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt-api</artifactId> <version>0.11.2</version> </dependency> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt-impl</artifactId> <version>0.11.2</version> <scope>runtime</scope> </dependency> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt-jackson</artifactId> <version>0.11.2</version> <scope>runtime</scope> </dependency> ``` 2. 创建JWT生成器:使用`Jwts.builder()`创建一个JWT生成器对象。 ```java JwtBuilder builder = Jwts.builder(); ``` 3. 设置头部和载荷信息:使用`setHeader()`和`setClaims()`方法设置头部和载荷信息。 ```java builder.setHeader(headerMap); builder.setClaims(claimsMap); ``` 4. 设置签名:使用`signWith()`方法设置签名算法和私钥。 ```java builder.signWith(SignatureAlgorithm.HS256, secretKey); ``` 5. 生成JWT:使用`compact()`方法生成最终的JWT字符串。 ```java String jwt = builder.compact(); ``` 6. 解密JWT:使用`Jwts.parser()`创建一个JWT解析器对象,并使用`setSigningKey()`方法设置公钥或密钥。 ```java Claims claims = Jwts.parser().setSigningKey(secretKey).parseClaimsJws(jwt).getBody(); ``` 以上是使用Java进行JWT加密解密的基本步骤。需要注意的是,生成JWT时需要使用私钥进行签名,解密JWT时需要使用公钥或密钥进行验证。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值