欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

使用Spring AOP拦截器注解方法实现数据隐私保护(脱敏)

最编程 2024-07-22 12:17:53
...

pom.xml 文件

 

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>1.5.19.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.example</groupId>
	<artifactId>tuomin</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>tuomin</name>
	<description>Demo project for Spring Boot</description>

	<properties>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.mybatis.spring.boot</groupId>
			<artifactId>mybatis-spring-boot-starter</artifactId>
			<version>1.3.3</version>
		</dependency>

		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<!--工具-->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.4</version>
        </dependency>
        <dependency>
            <groupId>commons-beanutils</groupId>
            <artifactId>commons-beanutils</artifactId>
            <version>1.9.3</version>
        </dependency>
		<dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.7</version>
        </dependency>
        <!-- JSONObject对象依赖的jar包 开始-->
		<dependency>
			<groupId>commons-beanutils</groupId>
			<artifactId>commons-beanutils</artifactId>
			<version>1.9.3</version>
		</dependency>
		<dependency>
			<groupId>commons-collections</groupId>
			<artifactId>commons-collections</artifactId>
			<version>3.2.1</version>
		</dependency>
		<dependency>
			<groupId>commons-lang</groupId>
			<artifactId>commons-lang</artifactId>
			<version>2.6</version>
		</dependency>
		<dependency>
			<groupId>commons-logging</groupId>
			<artifactId>commons-logging</artifactId>
			<version>1.1.1</version>
		</dependency>
		<dependency>
			<groupId>net.sf.ezmorph</groupId>
			<artifactId>ezmorph</artifactId>
			<version>1.0.6</version>
		</dependency>
		<dependency>
			<groupId>net.sf.json-lib</groupId>
			<artifactId>json-lib</artifactId>
			<version>2.2.3</version>
			<classifier>jdk15</classifier><!-- jdk版本 -->
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-aop</artifactId>
		</dependency>
		<dependency>
        	<groupId>org.springframework.boot</groupId>
        	<artifactId>spring-boot-devtools</artifactId>
        	<optional>true</optional>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

application.properties文件

#访问的根路径
server.context-path=/springboot
#端口号
server.port=8081
#session失效时间
server.session-timeout=30
#编码
server.tomcat.uri-encoding=utf-8

test.name=kelly
test.password=admin123
#读取数据库信息
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8

脱敏注解类

package com.example.tuomin.annotations;

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;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface TuominAnn {
	String value() default "";
}

aop 拦截器实现脱敏 

package com.example.tuomin.interator;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.mvc.method.annotation.ServletRequestMethodArgumentResolver;

import com.example.tuomin.entity.Desensitization;
import com.example.tuomin.entity.Rules;
import com.example.tuomin.entity.User;


/**
 * 请求拦截器 切面编程
 * @author sanch
 *
 */
@Aspect // 表示该类是一个通知类
@Component //spring注解方式bean注入 交给spring管理
public class RequestInterceptor {
	private  final static Logger logger = Logger.getLogger(RequestInterceptor.class);
	
	//定义一个空方法 借用其注解抽取切点表达式 
	@Pointcut("execution (* com.example.tuomin.control.*.*(..)) && @annotation(com.example.tuomin.annotations.TuominAnn) ")
	public void point() {}
		
	@Before("point()")
	public void before(JoinPoint joinPoint) throws Exception{
			System.out.println("进入aop-----------------------");
	}
	 
	 
	 @Around("point()")
	 public Object around(ProceedingJoinPoint pjp) throws Throwable{
			System.out.println("beginning----"); 
			//获取方法的返回类型,让缓存可以返回正确的类型
	        Class returnType=((MethodSignature)pjp.getSignature()).getReturnType();
	        System.out.println(returnType);
			System.out.println(pjp.getTarget().getClass());
			Object object = pjp.proceed();    //运行doSth(),返回值用一个Object类型来接收
			//object = "Mission Two111";   //改变返回值
			if(returnType.isInstance(object)) {
				 returnType.cast(object);
			}
			User u = (User)object;
			//url的获取方式
			ServletRequestAttributes attributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
			HttpServletRequest request = attributes.getRequest();
			String requesturl = request.getRequestURL().toString().replace("http://localhost:8081", "");
			String name = init().getFiled();
			Field[] fields = User.class.getDeclaredFields();
			for(Field field : fields) {
				String name2 = field.getName();
				System.out.println("attribute name:"+name2);
				
				if(name2.equals(name)) {
					name2 = name2.substring(0,1).toUpperCase()+name2.substring(1); //将属性的首字符大写,方便构造get,set方法
					String rule = initrule().getRule();//获取脱敏规则
					Method m = returnType.getMethod("set"+name2, new Class[] {String.class});//获取到setter方法
					Method m2 = returnType.getMethod("get"+name2);//获取到getter方法
					String value = (String) m2.invoke(object); //执行getter方法
					setNewField(rule,object,m,value);
					
				}
			}
		    System.out.println("ending----"+requesturl);
			return u;    
		}
	 
	 /**
	  * 根据脱敏规则执行不同方法
	 * @throws InvocationTargetException 
	 * @throws IllegalArgumentException 
	 * @throws IllegalAccessException 
	  */
	 public void setNewField(String rule,Object u,Method m,String value) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		 switch (rule) {
		case "ACCOUNT":
			m.invoke(u,new Object[] {new String(StringUtils.left(value, 1)+"**")});
			break;
		case "PASSWORD":
			m.invoke(u,new Object[] {new String(StringUtils.left(value, 3)+"**")});
			break;
		default:
			break;
		}
	 }
	 
	 /**
	  * 脱敏接口url-字段
	  * 后期放数据库不需要该步骤
	  * @return
	  */
	 public Desensitization init() { 
		 Desensitization model = new Desensitization();
		 model.setFiled("account");
		 model.setRequestUrl("/springboot/user/");
		 
		 return model;
	 }
	 
	 /**
	  * 脱敏字段-规则 
	  * 后期放数据库不需要该步骤
	  * @return
	  */
	 public Rules initrule() { 
		 Rules rules = new Rules();
		 rules.setField("password");
		 rules.setRule("PASSWORD");
		 return rules;
	 }

	 @After("point()")
	 public void after(JoinPoint joinPoint){
			for (int i = 0; i < joinPoint.getArgs().length; i++) {  
	            System.out.println(joinPoint.getArgs()[i]);  
	        }  
	        System.out.println(joinPoint.getSignature().getName());  
	          
	        System.out.println("=====checkSecurity====");  

	 }
	 
	 @AfterReturning(returning="rvt", pointcut="@annotation(com.example.tuomin.annotations.TuominAnn)")
	 public void AfterExec(JoinPoint joinPoint,Object rvt){
		 System.out.println(rvt);

	 }

}

main 主函数启动类

package com.example.tuomin;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;

@SpringBootApplication
@ComponentScan("com.example.tuomin")
public class TuominApplication {

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

}

controller 层代码

package com.example.tuomin.control;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.example.tuomin.annotations.TuominAnn;
import com.example.tuomin.entity.User;

@RestController
@RequestMapping("/user")
public class UserController {
	
	@TuominAnn(value="abc")
	@RequestMapping("/")
	public User index() {
		User user = new User();
		user.setAccount("account账号");
		user.setIdCardNo("12345678099");
		user.setMobileNo("135890867809");
		user.setPassword("jiayou123wqy");
		user.setRealName("朴树");
		return user;
	}

}

最终效果图

推荐阅读