有没有遇到这样子的接口,放到互联网上面去,谁都可以调用,谁都可以访问,完全就是公开的,这样子的接口,如果只是普通的数据,其实可以考虑,只是可以考虑,但是,一般情况下,我们是不允许这样子做的。
接口安全防什么
1、防止恶意调用攻击
2、防止篡改信息攻击
3、防拦截攻击,数据被截取后进行修改后重新放回去
4、防止数据泄漏攻击
什么是抓包
“抓包(packet capture)就是将网络传输发送与接收的数据包进行截获、重发、编辑、转存等操作,也用来检查网络安全。抓包也经常被用来进行数据截取等。
”
这是百度百科给我们的解释,当我们一些放到互联网上的数据,直接采用明文的话,就很容易被抓包,然后进行修改或者被恶意植入木马,这是比较恶心的行为,今天我们就来研究一下怎么样对接口进行数据加密。
POM文件
-
<!-- springboot核心web -->
-
<dependency>
-
<groupId>org.springframework.boot</groupId>
-
<artifactId>spring-boot-starter-web</artifactId>
-
</dependency>
-
-
<!-- 配置包,用于配置属性文件 -->
-
<dependency>
-
<groupId>org.springframework.boot</groupId>
-
<artifactId>spring-boot-autoconfigure</artifactId>
-
</dependency>
-
-
<!-- 统一API包 -->
-
<dependency>
-
<groupId>com.boots</groupId>
-
<artifactId>module-boots-api</artifactId>
-
<version>
2.0
.0.RELEASE</version>
-
</dependency>
编写加密解密工具类
-
/**
-
* All rights Reserved, Designed By 林溪
-
* Copyright: Copyright(C) 2016-2020
-
* Company 溪云阁 .
-
*/
-
-
package com.module.boots.api.de.utils;
-
-
import java.security.NoSuchAlgorithmException;
-
import java.security.SecureRandom;
-
-
import javax.crypto.Cipher;
-
import javax.crypto.KeyGenerator;
-
import javax.crypto.SecretKey;
-
import javax.crypto.spec.SecretKeySpec;
-
-
import org.apache.tomcat.util.codec.binary.Base64;
-
-
import com.module.boots.exception.CommonRuntimeException;
-
-
/**
-
* AES加密解密
-
* @author:溪云阁
-
* @date:2020年6月4日
-
*/
-
public class AesUtils {
-
-
private static final String KEY_ALGORITHM =
"AES";
-
-
private static final String DEFAULT_CIPHER_ALGORITHM =
"AES/ECB/PKCS5Padding";
// 默认的加密算法
-
-
/**
-
* AES 加密操作
-
* @author 溪云阁
-
* @param content 待加密内容
-
* @param password 加密密码
-
* @return String 返回Base64转码后的加密数据
-
*/
-
public static String encrypt(String content, String password) {
-
try {
-
// 创建密码器
-
final Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);
-
// 设置为UTF-8编码
-
final
byte[] byteContent = content.getBytes(
"utf-8");
-
// 初始化为加密模式的密码器
-
cipher.init(Cipher.ENCRYPT_MODE, getSecretKey(password));
-
// 加密
-
final
byte[] result = cipher.doFinal(byteContent);
-
// 通过Base64转码返回
-
return Base64.encodeBase64String(result);
-
-
}
-
catch (final Exception ex) {
-
throw
new CommonRuntimeException(ex.fillInStackTrace());
-
-
}
-
}
-
-
/**
-
* AES 解密操作
-
* @author 溪云阁
-
* @param content
-
* @param password
-
* @return String
-
*/
-
public static String decrypt(String content, String password) {
-
try {
-
// 实例化
-
final Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);
-
// 使用密钥初始化,设置为解密模式
-
cipher.init(Cipher.DECRYPT_MODE, getSecretKey(password));
-
// 执行操作
-
final
byte[] result = cipher.doFinal(Base64.decodeBase64(content));
-
// 采用UTF-8编码转化为字符串
-
return
new String(result,
"utf-8");
-
-
}
-
catch (final Exception ex) {
-
throw
new CommonRuntimeException(ex.fillInStackTrace());
-
}
-
-
}
-
-
/**
-
* 生成加密秘钥
-
* @author 溪云阁
-
* @param password 加密的密码
-
* @return SecretKeySpec
-
*/
-
private static SecretKeySpec getSecretKey(final String password) {
-
// 返回生成指定算法密钥生成器的 KeyGenerator 对象
-
KeyGenerator kg = null;
-
try {
-
kg = KeyGenerator.getInstance(KEY_ALGORITHM);
-
// AES 要求密钥长度为 128
-
kg.init(
128,
new SecureRandom(password.getBytes()));
-
// 生成一个密钥
-
final SecretKey secretKey = kg.generateKey();
-
// 转换为AES专用密钥
-
return
new SecretKeySpec(secretKey.getEncoded(), KEY_ALGORITHM);
-
}
-
catch (final NoSuchAlgorithmException ex) {
-
throw
new CommonRuntimeException(ex.fillInStackTrace());
-
}
-
}
-
-
public static void main(String[] args) {
-
final String str =
"V9JofCHn02eyXRiDb1VuseRSuOgEQftROwudMPWwMAO2Wk5K7aYZ4Vtm6xiTn5i5";
-
System.out.
println(decrypt(str,
"xy934yrn9342u0ry4br8cn-9u2"));
-
}
-
-
}
编写加密注解
-
/**
-
* All rights Reserved, Designed By 林溪
-
* Copyright: Copyright(C) 2016-2020
-
* Company 溪云阁 .
-
*/
-
-
package com.module.boots.api.de;
-
-
import java.lang.annotation.Documented;
-
import java.lang.annotation.ElementType;
-
import java.lang.annotation.Retention;
-
import java.lang.annotation.RetentionPolicy;
-
import java.lang.annotation.Target;
-
-
/**
-
* 返回对body加密,针对类跟方法
-
* @author:溪云阁
-
* @date:2020年6月4日
-
*/
-
@Target({ ElementType.METHOD, ElementType.TYPE })
-
@Retention(RetentionPolicy.RUNTIME)
-
@Documented
-
public @
interface ResponseEncrypt {
-
-
/**
-
* 返回对body加密,默认是true
-
* @author 溪云阁
-
* @return boolean
-
*/
-
boolean value()
default
true;
-
}
编写加密判断类
-
/**
-
* All rights Reserved, Designed By 林溪
-
* Copyright: Copyright(C) 2016-2020
-
* Company 溪云阁 .
-
*/
-
-
package com.module.boots.api.de;
-
-
import org.springframework.core.MethodParameter;
-
-
/**
-
* 是否需要加密解密
-
* @author:溪云阁
-
* @date:2020年6月4日
-
*/
-
public class NeedDe {
-
-
/**
-
* 判断是否需要加密
-
* @author 溪云阁
-
* @param returnType
-
* @return boolean
-
*/
-
public static boolean needEncrypt(MethodParameter returnType) {
-
boolean encrypt =
false;
-
// 获取类上的注解
-
final boolean classPresentAnno = returnType.getContainingClass().isAnnotationPresent(ResponseEncrypt.class);
-
// 获取方法上的注解
-
final boolean methodPresentAnno = returnType.getMethod().isAnnotationPresent(ResponseEncrypt.class);
-
if (classPresentAnno) {
-
// 类上标注的是否需要加密
-
encrypt = returnType.getContainingClass().getAnnotation(ResponseEncrypt.class).value();
-
// 类不加密,所有都不加密
-
if (!encrypt) {
-
return
false;
-
}
-
}
-
if (methodPresentAnno) {
-
// 方法上标注的是否需要加密
-
encrypt = returnType.getMethod().getAnnotation(ResponseEncrypt.class).value();
-
}
-
return encrypt;
-
}
-
-
}
编写加密拦截
-
/**
-
* All rights Reserved, Designed By 林溪
-
* Copyright: Copyright(C) 2016-2020
-
* Company 溪云阁 .
-
*/
-
-
package com.module.boots.api.de;
-
-
import org.springframework.beans.factory.annotation.Value;
-
import org.springframework.core.MethodParameter;
-
import org.springframework.http.MediaType;
-
import org.springframework.http.converter.HttpMessageConverter;
-
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 com.module.boots.api.de.utils.AesUtils;
-
import com.module.boots.api.message.ResponseMsg;
-
-
/**
-
* 对接口数据进行加密
-
* @author:溪云阁
-
* @date:2020年6月4日
-
*/
-
@ControllerAdvice
-
public class ResponseEncryptAdvice implements ResponseBodyAdvice<Object> {
-
-
@Value(
"${module.boots.response.aes.key}")
-
private String key;
-
-
@Override
-
public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
-
return
true;
-
}
-
-
/**
-
* 在写入之前更改body的值
-
* @author 溪云阁
-
* @param body
-
* @param returnType
-
* @param selectedContentType
-
* @param selectedConverterType
-
* @param request
-
* @param response
-
* @return
-
* @return
-
*/
-
@SuppressWarnings({
"unchecked",
"rawtypes" })
-
@Override
-
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType,
-
Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request,
-
ServerHttpResponse response) {
-
// 判断是否需要加密
-
final boolean encrypt = NeedDe.needEncrypt(returnType);
-
if (!encrypt) {
-
return body;
-
}
else {
-
// 如果body是属于ResponseMsg类型,只需要对data里面的数据进行加密即可
-
if (body instanceof ResponseMsg) {
-
final ResponseMsg responseMsg = (ResponseMsg) body;
-
final Object data = responseMsg.getData();
-
if (data == null) {
-
return body;
-
}
else {
-
responseMsg.setData(AesUtils.encrypt(data.toString(), key));
-
return responseMsg;
-
}
-
}
else {
-
return body;
-
}
-
}
-
}
-
-
}
加入密钥
-
# aes的密钥
-
module.boots.response.aes.key: xy934yrn9342u0ry4br8cn
-9u2
编写加密解密接口
-
/**
-
* All rights Reserved, Designed By 林溪
-
* Copyright: Copyright(C) 2016-2020
-
* Company 溪云阁 .
-
*/
-
-
package com.boots.api.de.view.de.view;
-
-
import org.springframework.beans.factory.annotation.Value;
-
import org.springframework.http.MediaType;
-
import org.springframework.web.bind.annotation.GetMapping;
-
import org.springframework.web.bind.annotation.RequestMapping;
-
import org.springframework.web.bind.annotation.RequestParam;
-
import org.springframework.web.bind.annotation.RestController;
-
-
import com.boots.api.de.view.de.vo.GetEncryptVO;
-
import com.module.boots.api.de.ResponseEncrypt;
-
import com.module.boots.api.de.utils.AesUtils;
-
import com.module.boots.api.message.ResponseMsg;
-
import com.module.boots.api.utils.MsgUtils;
-
import com.module.boots.exception.CommonRuntimeException;
-
-
import io.swagger.annotations.Api;
-
import io.swagger.annotations.ApiOperation;
-
import lombok.SneakyThrows;
-
-
/**
-
* 加密数据接口
-
* @author:溪云阁
-
* @date:2020年6月4日
-
*/
-
@SuppressWarnings(
"deprecation")
-
@Api(tags = {
"web服务:加密数据接口" })
-
@RestController
-
@RequestMapping(
"view/deView")
-
public class DeView {
-
-
@Value(
"${module.boots.response.aes.key}")
-
private String key;
-
-
/**
-
* 获取加密数据
-
* @author 溪云阁
-
* @return ResponseMsg<GetDeVO>
-
*/
-
@ApiOperation(value =
"获取加密数据")
-
@GetMapping(value =
"/getEncrypt", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
-
@SneakyThrows(CommonRuntimeException.class)
-
@ResponseEncrypt
-
public ResponseMsg<GetEncryptVO> getEncrypt() {
-
final GetEncryptVO vo =
new GetEncryptVO();
-
vo.setId(
"b037123c");
-
vo.setUserName(
"xnwqr98urx");
-
return MsgUtils.buildSuccessMsg(vo);
-
}
-
-
/**
-
* 获取解密数据
-
* @author 溪云阁
-
* @return ResponseMsg<GetDeVO>
-
*/
-
@ApiOperation(value =
"获取解密数据")
-
@GetMapping(value =
"/getDecrypt", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
-
@SneakyThrows(CommonRuntimeException.class)
-
public ResponseMsg<String> getDecrypt(@RequestParam(value =
"content") String content) {
-
final String str = AesUtils.decrypt(content, key);
-
return MsgUtils.buildSuccessMsg(str);
-
}
-
-
}
测试
从实验的结果上看,我们在获取数据的时候,直接对data里面的数据进行了加密,这种加密方式只有我们自己可以破解,放到网上去,即使只有密钥,也破解不了。
这里只做接口的数据的加密,生产中经常需要加入token,时间戳等进行验证,各位同学自行拓展即可。
好文章,我在看
好文章,我在看
转载:https://blog.csdn.net/weixin_46768610/article/details/109882496
查看评论