diff --git a/java/spring/aop/aop模板/权限校验/SSM权限校验.md b/java/spring/aop/aop模板/权限校验/SSM权限校验.md
new file mode 100644
index 0000000..aab36a9
--- /dev/null
+++ b/java/spring/aop/aop模板/权限校验/SSM权限校验.md
@@ -0,0 +1,285 @@
+# SSM注解+AOP实现鉴权(功能鉴权+数据鉴权)
+
+## 开启配置
+
+```xml
+##设定扫描路径确定能够扫描到后续我们自定义AOP类
+
+##开启自动代理 不开启这个的话后续注解在家接口上也是不会生效的
+
+```
+
+## 自定义权限注解
+
+### 属性介绍
+
+- **perm(功能权限)**
+
+ 可以看到我这里功能权限的字段用的是int类型的数组,这是因为我当前系统下权限是存在一个长字符串中的 这个字符串的每一个位置代表一个权限,比如新增订单在这个字符串的第二位那么给新增订单添加数据权限perm就应该等于2,代表着是去找这个用户的权限字符串中的第二位是否是1,是1的话代表拥有这个权限,我这里用数组是可以使一个接口在拥有多个权限下的情况才能调用,此处如果不需要可以直接改成int,不过通常用户权限列表不会使用一个长字符串来保存,而是一个字符串类型的集合,每一个权限是一个字符串,一般可以直接用接口的path作为权限名,或者另取别名作为权限名;数据校验的时候就是通过AOP校验传入的权限字符串在他本身权限列表中是否存在,如果不存在就代表他没有权限,需要给他拦截掉不能完成当前的请求
+
+- **dataPerm(数据权限)**
+
+ `dataPerm`是数据权限,用于校验当前数据是否可以进行修改,比如一个列表,查看一个列表是一个功能权限,删除列表中的一个数据也是一个功能权限,但是有些数据是指定人才可以删除,`dataPerm`就是针对这些特殊数据设定的权限
+
+- **shopNoParam**
+
+ 配合`dataPerm`实现数据权限控制,上面的`dataPerm`用于判断是否开启了数据权限,如果开启了数据权限,那么我们就要验证操作的数据是否可以被当前用户所操控,`shopNoParam`就是用于获取当前操作数据,此字段指定到方法的某个参数为目标,从这个目标上获取到门店号或者门店ID
+
+- **shopNoParamHandler**
+
+ 通过`shopNoParam`获取到了目标对象,但是这个对象还不是我们想要的值,我们想要的值在这个对象里面,这个时候我们需要指定一个处理器,这个处理器用来解析这个对象中的值
+
+```java
+@Target({ElementType.METHOD, ElementType.TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+public @interface AuthorityVerify {
+
+ //功能权限
+ int[] perm() default {};
+
+ //数据权限
+ int dataPerm() default -1;
+
+ /**
+ * 门店类数据权限校验 如果不为空则代表开启门店权限校验 会验证当前操作店铺是否拥有操作权限 此权限只有在dataPerm开启时才会生效
+ * @return 获取验证门店的字段
+ */
+ String shopNoParam() default "";
+
+ /**
+ * ApiParamHandler为抽象模板 不可以直接作为参数处理器使用 应选择其子类作为处理类
+ */
+ ParamHandlerEnum shopNoParamHandler() default ParamHandlerEnum.OBJECT;
+
+}
+```
+
+
+
+### 解析处理类
+
+```java
+/**
+ * 解析处理类枚举,注册了两个不同的处理对象,可以直接试用这个枚举进行调用
+ * @author dss
+ * @since 2022/3/9
+ */
+public enum ParamHandlerEnum{
+
+
+ OBJECT(1,"",new ObjectParamHandler())
+ ,GET_TARGET_PARAM(2,"",new GetTargetParamHandler())
+
+ ;
+
+ private final Integer code;
+ private final String name;
+ private final ApiParamHandler> handler;
+
+
+ public Integer getCode() {
+ return code;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public ApiParamHandler> getHandler() {
+ return handler;
+ }
+
+ ParamHandlerEnum(Integer code, String name, ApiParamHandler> handler) {
+ this.code = code;
+ this.name = name;
+ this.handler = handler;
+ }
+}
+
+/**
+ * 处理器抽象模板
+ * @author dss
+ * @since 2022/8/1
+ */
+public abstract class ApiParamHandler{
+
+ protected T pathParam = null;
+ protected T param = null;
+
+ //获取目标参数对象
+ protected void getParam(String tarParamName, String[] paramsSerial,Object[] argsSerial){
+
+ for (int i = 0; i < paramsSerial.length; i++) {
+ if (argsSerial[i]!=null){
+ PathVariable pathAnno = argsSerial[i].getClass().getAnnotation(PathVariable.class);
+ if (pathAnno!=null&&tarParamName.equals(pathAnno.value())){
+ pathParam= (T) argsSerial[i];
+ }
+ if (tarParamName.equals(paramsSerial[i])){
+ param= (T) argsSerial[i];
+ }
+ }
+ }
+ }
+
+ // 将目标对象转换为String类型
+ protected abstract String targetToString(String tarParamName, String[] paramsSerial,Object[] argsSerial);
+
+ // 清空参数
+ protected void clearParam(){
+ pathParam=null;
+ param=null;
+ }
+
+ public synchronized String getTargetStr(String tarParamName, String[] paramsSerial,Object[] argsSerial){
+ getParam(tarParamName, paramsSerial,argsSerial);
+ String s = targetToString(tarParamName, paramsSerial, argsSerial);
+ clearParam();
+ return s;
+ }
+}
+
+/**
+ * 简单的处理对象,直接将对象toString,适用于传的参数本身就是要取的值,比如一个接口传入的直接就是门店号,我就不需要再去解析他了
+ * @author dss
+ * @since 2022/8/1
+ * Object 类型参数处理器
+ */
+public class ObjectParamHandler extends ApiParamHandler