|
@@ -1,22 +1,46 @@
|
|
package com.diagbot.aop;
|
|
package com.diagbot.aop;
|
|
|
|
|
|
import com.diagbot.annotation.TokenAuth;
|
|
import com.diagbot.annotation.TokenAuth;
|
|
|
|
+import com.diagbot.dto.PermissionDTO;
|
|
import com.diagbot.exception.CommonErrorCode;
|
|
import com.diagbot.exception.CommonErrorCode;
|
|
import com.diagbot.exception.CommonException;
|
|
import com.diagbot.exception.CommonException;
|
|
|
|
+import com.diagbot.facade.HospitalInfoFacade;
|
|
|
|
+import com.diagbot.facade.TokenHospitalFacade;
|
|
|
|
+import com.diagbot.facade.TokenPermissionFacade;
|
|
|
|
+import com.diagbot.util.ListUtil;
|
|
import com.diagbot.util.StringUtil;
|
|
import com.diagbot.util.StringUtil;
|
|
|
|
+import com.diagbot.util.SysJwtUtil;
|
|
|
|
+import com.diagbot.vo.HospitalCheckVO;
|
|
|
|
+import com.diagbot.vo.TokenPermissionVO;
|
|
|
|
+import com.google.common.collect.Lists;
|
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
import org.aspectj.lang.JoinPoint;
|
|
import org.aspectj.lang.JoinPoint;
|
|
import org.aspectj.lang.annotation.Aspect;
|
|
import org.aspectj.lang.annotation.Aspect;
|
|
import org.aspectj.lang.annotation.Before;
|
|
import org.aspectj.lang.annotation.Before;
|
|
import org.aspectj.lang.annotation.Pointcut;
|
|
import org.aspectj.lang.annotation.Pointcut;
|
|
import org.aspectj.lang.reflect.MethodSignature;
|
|
import org.aspectj.lang.reflect.MethodSignature;
|
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
|
|
|
+import org.springframework.core.DefaultParameterNameDiscoverer;
|
|
|
|
+import org.springframework.core.ParameterNameDiscoverer;
|
|
|
|
+import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
|
import org.springframework.stereotype.Component;
|
|
import org.springframework.stereotype.Component;
|
|
import org.springframework.web.context.request.RequestAttributes;
|
|
import org.springframework.web.context.request.RequestAttributes;
|
|
import org.springframework.web.context.request.RequestContextHolder;
|
|
import org.springframework.web.context.request.RequestContextHolder;
|
|
import org.springframework.web.context.request.ServletRequestAttributes;
|
|
import org.springframework.web.context.request.ServletRequestAttributes;
|
|
|
|
|
|
import javax.servlet.http.HttpServletRequest;
|
|
import javax.servlet.http.HttpServletRequest;
|
|
|
|
+import java.lang.reflect.Field;
|
|
|
|
+import java.lang.reflect.InvocationTargetException;
|
|
import java.lang.reflect.Method;
|
|
import java.lang.reflect.Method;
|
|
|
|
+import java.util.ArrayList;
|
|
|
|
+import java.util.Arrays;
|
|
|
|
+import java.util.HashMap;
|
|
|
|
+import java.util.HashSet;
|
|
|
|
+import java.util.Iterator;
|
|
|
|
+import java.util.List;
|
|
|
|
+import java.util.Map;
|
|
|
|
+import java.util.Set;
|
|
|
|
|
|
/**
|
|
/**
|
|
* @Description:
|
|
* @Description:
|
|
@@ -26,8 +50,20 @@ import java.lang.reflect.Method;
|
|
@Aspect
|
|
@Aspect
|
|
@Component
|
|
@Component
|
|
@ConditionalOnProperty(prefix = "tokenAuth", value = { "enable" }, havingValue = "true")
|
|
@ConditionalOnProperty(prefix = "tokenAuth", value = { "enable" }, havingValue = "true")
|
|
|
|
+@Slf4j
|
|
public class TokenAuthAspect {
|
|
public class TokenAuthAspect {
|
|
|
|
|
|
|
|
+ private static HospitalInfoFacade hospitalInfoFacade;
|
|
|
|
+ private static TokenHospitalFacade tokenHospitalFacade;
|
|
|
|
+ private static TokenPermissionFacade tokenPermissionFacade;
|
|
|
|
+
|
|
|
|
+ @Autowired
|
|
|
|
+ public void TokenAuthAspect(HospitalInfoFacade hospitalInfoFacade,TokenHospitalFacade tokenHospitalFacade,TokenPermissionFacade tokenPermissionFacade) {
|
|
|
|
+ TokenAuthAspect.hospitalInfoFacade = hospitalInfoFacade;
|
|
|
|
+ TokenAuthAspect.tokenHospitalFacade = tokenHospitalFacade;
|
|
|
|
+ TokenAuthAspect.tokenPermissionFacade = tokenPermissionFacade;
|
|
|
|
+ }
|
|
|
|
+
|
|
//切所有Controller
|
|
//切所有Controller
|
|
@Pointcut("execution(* com.diagbot.web..*.*(..))")
|
|
@Pointcut("execution(* com.diagbot.web..*.*(..))")
|
|
public void pointcutController() {
|
|
public void pointcutController() {
|
|
@@ -53,7 +89,210 @@ public class TokenAuthAspect {
|
|
throw new CommonException(CommonErrorCode.PARAM_IS_NULL, "请传入token!");
|
|
throw new CommonException(CommonErrorCode.PARAM_IS_NULL, "请传入token!");
|
|
}
|
|
}
|
|
//todo 期限和医院有效性验证
|
|
//todo 期限和医院有效性验证
|
|
|
|
+ long hospitalId = Long.parseLong(SysJwtUtil.getHospId(token));
|
|
|
|
+ HospitalCheckVO hospitalCheckVO = new HospitalCheckVO();
|
|
|
|
+ hospitalCheckVO.setHospitalId(hospitalId);
|
|
|
|
+ if (!hospitalInfoFacade.checkHospital(hospitalCheckVO)){
|
|
|
|
+ throw new CommonException(CommonErrorCode.NOT_EXISTS, "该医院不存在!");
|
|
|
|
+ }
|
|
|
|
+ if(!tokenHospitalFacade.checkTokenHospitals(token)){
|
|
|
|
+ throw new CommonException(CommonErrorCode.NOT_EXISTS, "已超过有效期");
|
|
|
|
+ }
|
|
//todo 权限拦截
|
|
//todo 权限拦截
|
|
|
|
+ //todo 远程获取权限验证权限
|
|
|
|
+ //验证权限
|
|
|
|
+ String uri = request.getRequestURI();
|
|
|
|
+ log.info(uri);
|
|
|
|
+ TokenPermissionVO permissionVO = new TokenPermissionVO();
|
|
|
|
+ permissionVO.setTokenId(1L);//TODO
|
|
|
|
+ PermissionDTO permissionDTO = tokenPermissionFacade.getPermission(permissionVO);
|
|
|
|
+ Map<String, List<Map<String, Set<String>>>> hasParamMap = new HashMap<>();
|
|
|
|
+ Map<String, List<Map<String, Set<String>>>> noParamMap = new HashMap<>();
|
|
|
|
+ if (permissionDTO.getPermissionMap() != null) {
|
|
|
|
+ hasParamMap = permissionDTO.getPermissionMap().get("hasParam");
|
|
|
|
+ noParamMap = permissionDTO.getPermissionMap().get("noParam");
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ //todo 验证是否在无参数的Map
|
|
|
|
+ Boolean noParam = false;
|
|
|
|
+ if (noParamMap != null) {
|
|
|
|
+ if (noParamMap.containsKey(uri)) {
|
|
|
|
+ noParam = true;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ //todo 验证是否在有参数的Map
|
|
|
|
+ Boolean hasParam = false;
|
|
|
|
+ List<Map<String, Set<String>>> perParamList = Lists.newLinkedList();
|
|
|
|
+ if (hasParamMap != null) {
|
|
|
|
+ if (hasParamMap.containsKey(uri)) {
|
|
|
|
+ hasParam = true;
|
|
|
|
+ perParamList = hasParamMap.get(uri);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (!noParam && !hasParam) {
|
|
|
|
+ throw new CommonException(CommonErrorCode.NO_PERMISSION);
|
|
|
|
+ }
|
|
|
|
+ //todo 验证参数
|
|
|
|
+ Object[] args = joinPoint.getArgs();
|
|
|
|
+ if (args == null) {
|
|
|
|
+ throw new CommonException(CommonErrorCode.NO_PERMISSION);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ Map<String, Object> paramMap = new HashMap<>();
|
|
|
|
+ paramMap = getFieldsName(joinPoint);
|
|
|
|
+ //todo 利用paramMap获取结果
|
|
|
|
+ try {
|
|
|
|
+ if (!noParam && hasParam && ListUtil.isNotEmpty(perParamList)) {
|
|
|
|
+
|
|
|
|
+ for (Map.Entry<String, Object> entry : paramMap.entrySet()) {
|
|
|
|
+ if (entry.getValue() == null) {
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ Field[] fields = getAllFields(entry.getValue());
|
|
|
|
+ Boolean hasPermission = true;
|
|
|
|
+ for (Map<String, Set<String>> perParamMap : perParamList) {
|
|
|
|
+ if (perParamMap == null || perParamMap.size() == 0) {
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ //验证单条paramKey是否所有参数都满足,包含关系
|
|
|
|
+ for (Map.Entry<String, Set<String>> paramEntry : perParamMap.entrySet()) {
|
|
|
|
+ for (int i = 0; i < fields.length; i++) {
|
|
|
|
+ String fieldName = fields[i].getName();
|
|
|
|
+ if (!paramEntry.getKey().equals(fieldName)) {
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ Set<String> paramValueSet = paramEntry.getValue();
|
|
|
|
+ if (paramValueSet == null || paramValueSet.size() == 0) {
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ String getter = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
|
|
|
|
+ String type = fields[i].getGenericType().toString();
|
|
|
|
+ Class clazz = entry.getValue().getClass();
|
|
|
|
+ Method methods = clazz.getMethod(getter, new Class[]{});
|
|
|
|
+ Object obj = methods.invoke(entry.getValue(), new Object[]{});
|
|
|
|
+ if (type.equals("class java.lang.String")
|
|
|
|
+ || type.equals("class java.lang.Integer")
|
|
|
|
+ || type.equals("class java.lang.Long")) {
|
|
|
|
+ String value = obj.toString();
|
|
|
|
+ String[] valueArr = value.split(",|,");
|
|
|
|
+ Set<String> valueSet = new HashSet<>(Arrays.asList(valueArr));
|
|
|
|
+ if (paramValueSet.containsAll(valueSet)) {
|
|
|
|
+ hasPermission = true;
|
|
|
|
+ break;
|
|
|
|
+ } else {
|
|
|
|
+ hasPermission = false;
|
|
|
|
+ }
|
|
|
|
+ } else if (type.equals("class java.lang.Boolean")) {
|
|
|
|
+ Boolean value = (Boolean) obj;
|
|
|
|
+ Iterator<String> it = paramEntry.getValue().iterator();
|
|
|
|
+ while (it.hasNext()) {
|
|
|
|
+ it.next().toLowerCase();
|
|
|
|
+ }
|
|
|
|
+ if (paramEntry.getValue().contains(value.toString().toLowerCase())) {
|
|
|
|
+ hasPermission = true;
|
|
|
|
+ } else {
|
|
|
|
+ hasPermission = false;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if (!hasPermission) {
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ //当前组合中有一个参数不满足,则整条都不满足
|
|
|
|
+ if (!hasPermission) {
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ //有一条完整的参数验证通过,则结束循环
|
|
|
|
+ if (hasPermission) {
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ //遍历所有参数组合之后,没有一条满足,则说明没有权限
|
|
|
|
+ if (!hasPermission) {
|
|
|
|
+ throw new CommonException(CommonErrorCode.NO_PERMISSION);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
|
|
|
|
+ throw new CommonException(CommonErrorCode.FAIL, e.getMessage());
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+ public static Field[] getAllFields(Object object) {
|
|
|
|
+ Class clazz = object.getClass();
|
|
|
|
+ List<Field> fieldList = new ArrayList<>();
|
|
|
|
+ while (clazz != null) {
|
|
|
|
+ fieldList.addAll(new ArrayList<>(Arrays.asList(clazz.getDeclaredFields())));
|
|
|
|
+ clazz = clazz.getSuperclass();
|
|
|
|
+ }
|
|
|
|
+ Field[] fields = new Field[fieldList.size()];
|
|
|
|
+ fieldList.toArray(fields);
|
|
|
|
+ return fields;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private static Map getFieldsName(JoinPoint joinPoint) {
|
|
|
|
+ try {
|
|
|
|
+ String classType = joinPoint.getTarget().getClass().getName();
|
|
|
|
+ String methodName = joinPoint.getSignature().getName();
|
|
|
|
+ // 参数值
|
|
|
|
+ Object[] args = joinPoint.getArgs();
|
|
|
|
+ Class<?>[] classes = new Class[args.length];
|
|
|
|
+ for (int k = 0; k < args.length; k++) {
|
|
|
|
+ if (!args[k].getClass().isPrimitive()) {
|
|
|
|
+ // 获取的是封装类型而不是基础类型
|
|
|
|
+ String result = args[k].getClass().getName();
|
|
|
|
+ Class s = map.get(result);
|
|
|
|
+ classes[k] = s == null ? args[k].getClass() : s;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ ParameterNameDiscoverer pnd = new DefaultParameterNameDiscoverer();
|
|
|
|
+ // 获取指定的方法,第二个参数可以不传,但是为了防止有重载的现象,还是需要传入参数的类型
|
|
|
|
+ Method method = Class.forName(classType).getMethod(methodName, classes);
|
|
|
|
+ // 参数名
|
|
|
|
+ String[] parameterNames = pnd.getParameterNames(method);
|
|
|
|
+ // 通过map封装参数和参数值
|
|
|
|
+ HashMap<String, Object> paramMap = new HashMap();
|
|
|
|
+ for (int i = 0; i < parameterNames.length; i++) {
|
|
|
|
+ paramMap.put(parameterNames[i], args[i]);
|
|
|
|
+ }
|
|
|
|
+ return paramMap;
|
|
|
|
+ } catch (ClassNotFoundException e) {
|
|
|
|
+ return null;
|
|
|
|
+ } catch (NoSuchMethodException e) {
|
|
|
|
+ return null;
|
|
|
|
+ }
|
|
|
|
|
|
}
|
|
}
|
|
|
|
+ private static HashMap<String, Class> map = new HashMap<String, Class>() {
|
|
|
|
+ {
|
|
|
|
+ put("java.lang.Integer", int.class);
|
|
|
|
+ put("java.lang.Double", double.class);
|
|
|
|
+ put("java.lang.Float", float.class);
|
|
|
|
+ put("java.lang.Long", long.class);
|
|
|
|
+ put("java.lang.Short", short.class);
|
|
|
|
+ put("java.lang.Boolean", boolean.class);
|
|
|
|
+ put("java.lang.Char", char.class);
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ private static Boolean matchPermitAllUrl(HttpServletRequest request, List<String> ignoreUrl) {
|
|
|
|
+ if (ListUtil.isNotEmpty(ignoreUrl)) {
|
|
|
|
+ for (String url : ignoreUrl) {
|
|
|
|
+ if (matchers(url, request)) {
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private static Boolean matchers(String url, HttpServletRequest request) {
|
|
|
|
+ AntPathRequestMatcher matcher = new AntPathRequestMatcher(url);
|
|
|
|
+ if (matcher.matches(request)) {
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
}
|
|
}
|