Java 自定义注解实现简单的白名单 入参出参打印
自定义注解 MyAnnotation
注解具体干什么 MyAnnotationAop
配置白名单 application.yml
MyAnnotation
package com.example.annotation.demos.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @Author huicai
* @Date 2024/8/7 20:57
**/
@Retention(RetentionPolicy.RUNTIME) //注解在运行时有效
@Target(ElementType.METHOD) //注解在方法上有效
public @interface MyAnnotation {
/**
* 是否验证接口白名单(true:校验, false:不校验) 默认不校验
*/
boolean verify() default false;
/**
* RetentionPolicy.RUNTIME: 运行时注解,注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在;
* RetentionPolicy.CLASS:编译时注解,注解在class文件中存在;
* RetentionPolicy.SOURCE:源码中注解存在,编译后注解不存在;
*
* ElementType.TYPE:类、接口(包括注解类型)或枚举声明
* ElementType.FIELD:字段声明(包括枚举常量)
* ElementType.METHOD:方法声明
* ElementType.PARAMETER:参数声明
* ElementType.CONSTRUCTOR:构造函数声明
* ElementType.PACKAGE:针对包声
* ElementType.LOCAL_VARIABLE:针对注解
*
*/
}
MyAnnotationAop
package com.example.annotation.demos.annotation;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
/**
* @Author huicai
* @Date 2024/8/8 09:27
**/
@Slf4j
@Component
@Aspect //声明切面
public class MyAnnotationAop {
/**
* 配置获取白名单IP
*/
@Value("${white.list}")
private List<String> whiteList;
/**
* <p>
* 入参打印 + 特殊接口的白名单校验
*
* @param jp
* @param myAnnotation 这个方法会 在方法执行前 执行
*/
@Before(value = "@annotation(myAnnotation)")
public void whitelistCheck(JoinPoint jp, MyAnnotation myAnnotation) {
//可以获取request信息、session信息
ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if (servletRequestAttributes == null) {
throw new RuntimeException("非法请求");
}
HttpServletRequest request = servletRequestAttributes.getRequest();
//获取请求路径
String requestURI = request.getRequestURI();
log.info("——————————————————————————————————");
log.info("请求路径:{}", requestURI);
///annotation/select_user
/**
* 是否需要校验白名单
*/
if (myAnnotation.verify()) {
//获取请求ip 方法 1
//String ip = request.getRemoteAddr(); //也可以获取IP
//获取请求ip 方法 2 和调用者约定好 请求头里面带IP
String ip = request.getHeader("IP");
if (StringUtils.isEmpty(ip)) {
log.info("请求头没有带IP,无权访问");
throw new RuntimeException("无权访问");
}
//白名单校验
if (!whiteList.contains(ip)) {
log.error("[{}]无权访问", ip);
throw new RuntimeException("非法请求");
}
}
/**
* //获取用户有没有带token + 有没有调用这个接口的权限
String token = request.getHeader("token");
if (StringUtils.isEmpty(token)) {
log.info("请求头没有带token,无权访问");
throw new RuntimeException("无权访问");
}
//获取到token,可以去获取用户信息 + 用户的权限信息,判断用户有没有调用这个接口的权限
*/
//打印入参
log.info("入参打印:{}", jp.getArgs());
//User(id=111, name=null, age=null, mobilePhoneNumber=1233474637)
//其他补充
Object aThis = jp.getThis();
log.info("AOP代理对象:{}", aThis);
//com.example.annotation.demos.controller
Object target = jp.getTarget();
log.info("被代理对象:{}", target);
//com.example.annotation.demos.controller
Signature signature = jp.getSignature();
log.info("连接点的 返回类型 方法 入参:{}", signature.toString());
//List com.example.annotation.demos.controller
log.info("连接点的 访问类型 返回类型 方法 入参:{}", signature.toLongString());
//public java.util.List com.example.annotation.demos.controller.MyAnnotationController.selectUser(com.example.annotation.demos.vo.User)
log.info("连接点的 类 方法:{}", signature.toShortString());
//MyAnnotationController.selectUser(..)
log.info("被代理对象名称:{}", signature.getName());
//selectUser
log.info("被代理的类(具体路径) :{}", signature.getDeclaringTypeName());
//com.example.annotation.demos.controller
log.info("被代理的 类型 具体路径 :{}", signature.getDeclaringType().toString());
//class com.example.annotation.demos.controller
log.info("被代理的类(具体路径) :{}", signature.getDeclaringType().getName());
//com.example.annotation.demos.controller
log.info("连接点类型 :{}", jp.getKind());
//method-execution
//获取请求头其他信息
request.getHeader("");
/**
* 用户ip: 192.168.X.171 服务ip: 192.168.X.114
*/
log.info("完整路径 :{}", request.getRequestURL().toString());
//http://192.168.X.114:8080/annotation/userById
log.info("请求方式 :{}", request.getMethod());
//POST
log.info("获取远程地址(那个ip调用的你) :{}", request.getRemoteAddr());
//192.168.X.171
}
/**
* * @AfterReturning注解,在方法正常返回后执行
*
* @param jp
* @param myAnnotation
* @param jsonResult
*/
@AfterReturning(pointcut = "@annotation(myAnnotation)", returning = "jsonResult")
public void doAfterReturning(JoinPoint jp, MyAnnotation myAnnotation, Object jsonResult) {
//可以获取出参 做一些处理
log.info("出参打印:{}", jsonResult.toString());
//User(id=1, name=李四, age=99, mobilePhoneNumber=999999)
log.info("——————————————————————————————————");
}
}
MyAnnotationController
package com.example.annotation.demos.controller;
import com.example.annotation.demos.annotation.MyAnnotation;
import com.example.annotation.demos.vo.User;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
/**
* @Author huicai
* @Date 2024/3/13 10:01
**/
@RestController
@RequestMapping("annotation")
public class MyAnnotationController {
/**
* 测试
*
* @return
*/
@PostMapping("/test")
public String test() {
return "Hello Word !!!";
}
/**
* 通过用户的一些信息查询用户
*
* @param user
* @return
*/
@MyAnnotation(verify = true)
@PostMapping("/select_user")
public List<User> selectUser(@RequestBody User user) {
//逻辑处理 我这里简单处理一下
List<User> list = new ArrayList<>();
User user1 = new User();
user1.setId("111");
user1.setAge(24);
user1.setName("张三");
user1.setMobilePhoneNumber("1233474637");
list.add(user1);
return list;
}
/**
* 通过用户id 获取用户信息
*
* @param id
* @return
*/
@MyAnnotation
@PostMapping("/userById")
public User userById(@RequestParam("id") String id) {
//逻辑处理 我这里简单处理一下
User user1 = new User();
user1.setId(id);
user1.setAge(99);
user1.setName("李四");
user1.setMobilePhoneNumber("999999");
return user1;
}
}
User
package com.example.annotation.demos.vo;
import lombok.Data;
/**
* @Author huicai
* @Date 2024/8/8 09:58
**/
@Data
public class User {
/**
* ID
*/
private String id;
/**
* 姓名
*/
private String name;
/**
* 年龄
*/
private Integer age;
/**
* 手机号
*/
private String mobilePhoneNumber;
}
application.yml
spring:
application:
name: annotation
server:
port: 8080
# 白名单地址
white:
list: 192.168.X.114,192.168.X.111
pom 用的这个
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.6</version>
</dependency>
希望对大家有一些帮助吧。