Spring基于注解的自动解密

创建一个注解 RSAdecrypt

import java.lang.annotation.*;
@Target(ElementType.PARAMETER)//声明此注解只能在方法参数上生效
@Retention(RetentionPolicy.RUNTIME)//声明此注解生命周期  使用runtime可以在运行时动态获得注解信息
@Documented
public @interface RSAdecrypt {
    String[] value() default "";//设置注解需要传递字符串数组的参数  (方便之后给pojo对象的成员变量解密)
}

实现方法参数解析类(也就是前端传到后端并解析的实现类,前端的键名对应后端的参数名)

public class RSAdecryptResolver implements HandlerMethodArgumentResolver {
	private String key = "xxxxx";//这里是你生成的密钥
	
	@Override
    public boolean supportsParameter(MethodParameter parameter) {
        return parameter.hasParameterAnnotation(RSAdecrypt.class);
        //此方法判断在什么条件下才执行此解析器
        //也就是前端控制器  Controller类里的具体方法中的参数前加了此注解才会返回true执行以下方法
    }

	@Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
		//MethodParameter 对象指的是进入此解析的参数对象  也就是加了注解的参数对象
		String methodparametername = parameter.getParameterName();//获取controller层我们定义的参数名
		HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);//将nativerequest对象转换成HttpServletRequest对象
		String agument = request.getParameter(methodparametername);//调用此方法获得请求体的实际行参的参数值, 也就是被前端加密的字符串  所以说一定要 方法参数名  和  前端的键 保持一致
		return decrypt(agument,key);//返回解密后的字符串
	}


//这是RSA解密 有兴趣的同学可以看相关文档 本章不讨论此问题
   private String decrypt(String str, String privateKey) throws Exception {
        //64位解码加密后的字符串
        byte[] inputByte = Base64.getDecoder().decode(str);
        //base64编码的私钥
        byte[] decoded = Base64.getDecoder().decode(privateKey);
        RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decoded));
        //RSA解密
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE, priKey);
        String outStr = new String(cipher.doFinal(inputByte));
        return outStr;
    }
}

在springboot配置类中添加个参数解析器就ok啦

@Configuration
public class CommonRegister implements WebMvcConfigurer {
	 @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
        resolvers.add(new RSAdecryptResolver());
    }

}

就可以使用注解自动解密啦 代码清爽多了


    @RequestMapping("/loginmg")
    @ResponseBody
    public String login(@RSAdecrypt String param){
        return param;
     }

还有个pojo对象针对成员变量解密稍后更新

针对pojo对象的解密

public class RSAdecryptResolver implements HandlerMethodArgumentResolver {

    private String key;

    public RSAdecryptResolver(String key) {
        this.key = key;
    }

    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return parameter.hasParameterAnnotation(RSAdecrypt.class);
    }

    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
    	//获取注解
        RSAdecrypt annotation = parameter.getParameterAnnotation(RSAdecrypt.class);
        HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
        //获取被注解标记的参数字节码文件
        Class c = parameter.getParameterType();
   		//字符串就走传统方法,非走下面的反射方法
        if (c !=String.class){
        	//获取注解的value值(需要解密的对象成员变量名,必须是string,不然就没意义啦)
        	List m  = Arrays.asList(annotation.value());
        	//通过反射执行构造器生成此pojo对象(必须有个无参构造器)
            Object o = c.newInstance();
            //通过反射遍历每个成员变量  使用Declaredfield才能获取private成员变量
            for (Field field : c.getDeclaredFields()) {
            	//获取成员变量的type类型
                Class g = field.getType();
                //获取成员变量名
                String s = field.getName();
                //通过成员变量名获取它的set方法  upper方法作用就是将成名变量名的首字母大写  getMethod(参数一:方法名,参数二:此方法如果需要传递参数给他个传参类型,,当然是成员变量的类型咯,,此成员变量的set方法传参类型肯定是他本身的类型,,如果是多参就多加几个,动态参数无所谓的)
                Method set = c.getMethod("set"+upper(s),g);  
                Object p = request.getParameter(s);//通过成员变量名来获取传过来的键名(也就是常说的pojo对象属性名一定要和传过来的键名对应)
                //如果你的注解的value 也就是需要解密的字段集合  包含通过反射获得的成员变量名
                if (m.contains(s)){
                    set.invoke(o,decrypt((String) p,key));//则set方法执行,invoke(参数一:哪个对象需要执行set方法当然是前面生成的newinsatnce,参数二:传入参数的具体对象,如果要解密必须是string类型的)
                    continue;//封装好了跳过此循环,next成员变量
                }
                set.invoke(o,p); //这边就是除了你注解value传入需要解密的属性名以外的都走这个普通pojo赋值  再说明一下p是根据field成员变量名获得前端键所对应的值
            }
            //每个成员变量都处理完了返回pojo
            return o;
        }
        return decrypt(request.getParameter(parameter.getParameterName()),key);//他是String类型的就走传统方法解密咯
    }
    //简单的首字母大写
    private String upper(String attr){
      return attr.substring(0,1).toUpperCase()+attr.substring(1);
    }

pojo对象注解解密就是这个样子的

    @RequestMapping(value = "/addsalesman",method = RequestMethod.POST)
    @ResponseBody                      //传入需要解密的属性名就ok了
    public Map addsalesman(@RSAdecrypt({"password","phone","email"}) Salesman salesman){
    }
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Spring Data MongoDB 中,可以通过自定义 Converter 或使用 Spring Security 的加解密功能实现自动化的加解密。下面分别介绍这两种方式: 1. 自定义 Converter: 通过自定义 Converter,可以在保存到 MongoDB 之前对数据进行加密,在读取数据时进行解密。你可以创建一个实现了 org.springframework.core.convert.converter.Converter 接口的加解密类,然后在 Spring 配置文件中注册该 Converter。 例如,你可以创建一个加解密类,如下所示: ```java public class EncryptionConverter implements Converter<String, String> { @Override public String convert(String source) { // 在这里进行加解密操作 // 返回加解密后的结果 } } ``` 然后,在 Spring 配置文件中注册 Converter: ```xml <bean id="encryptionConverter" class="com.example.EncryptionConverter" /> <bean class="org.springframework.data.mongodb.core.convert.CustomConversions"> <constructor-arg> <list> <ref bean="encryptionConverter" /> </list> </constructor-arg> </bean> ``` 2. 使用 Spring Security 的加解密功能: Spring Security 提供了一套强大的加解密功能,可以用于保护敏感数据。你可以使用 Spring Security 的加解密功能对存储在 MongoDB 中的数据进行自动化的加解密。 首先,需要配置 Spring Security 加解密的相关设置。可以参考 Spring Security 的文档来了解如何配置加解密算法、密钥管理等内容。 然后,在 Spring Data MongoDB 的配置文件中,将 Spring Security 的加解密功能集成到 MongoDB 的操作中。可以使用 Spring Security 的 CryptoModule 来对数据进行加解密。 例如,使用 CryptoModule 对字段进行加解密: ```java @Document(collection = "users") public class User { @Id private String id; @Field(targetType = FieldType.STRING) @Encrypt private String username; // 其他字段... // getter 和 setter 方法... } ``` 在上面的示例中,使用了 @Encrypt 注解来标记需要加密的字段。在读取和保存数据时,Spring Data MongoDB 将自动对该字段进行加解密操作。 需要注意的是,无论是使用自定义 Converter 还是使用 Spring Security 的加解密功能,都需要谨慎处理密钥的管理和保护。确保密钥的安全性非常重要,以免导致数据泄露或其他安全问题。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值