|
@@ -0,0 +1,184 @@
|
|
|
+package com.yaoxiang.diagnosis.authority;
|
|
|
+
|
|
|
+import com.yaoxiang.diagnosis.model.Result;
|
|
|
+import com.yaoxiang.diagnosis.util.CommonUtil;
|
|
|
+import org.apache.commons.lang3.StringUtils;
|
|
|
+import org.aspectj.lang.JoinPoint;
|
|
|
+import org.aspectj.lang.ProceedingJoinPoint;
|
|
|
+import org.aspectj.lang.annotation.Around;
|
|
|
+import org.aspectj.lang.annotation.Aspect;
|
|
|
+import org.aspectj.lang.annotation.Pointcut;
|
|
|
+import org.slf4j.Logger;
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
|
|
|
+import org.springframework.security.core.Authentication;
|
|
|
+import org.springframework.security.core.context.SecurityContextHolder;
|
|
|
+import org.springframework.security.core.userdetails.UserDetails;
|
|
|
+import org.springframework.security.crypto.password.PasswordEncoder;
|
|
|
+import org.springframework.stereotype.Component;
|
|
|
+import org.springframework.util.Assert;
|
|
|
+
|
|
|
+import javax.annotation.Resource;
|
|
|
+import java.lang.reflect.Method;
|
|
|
+import java.util.Map;
|
|
|
+
|
|
|
+
|
|
|
+ * @author Created by yawn on 2017-11-24 15:46
|
|
|
+ */
|
|
|
+@Aspect
|
|
|
+@Component
|
|
|
+public class AuthCheckAspect {
|
|
|
+
|
|
|
+ private static final String ATTRIBUTE_SEPARATOR = ".";
|
|
|
+
|
|
|
+ private static final Logger logger = LoggerFactory.getLogger(AuthCheckAspect.class);
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private AuthService authService;
|
|
|
+
|
|
|
+ @Pointcut("@annotation(com.yaoxiang.diagnosis.authority.AuthCheck) && @annotation(authCheck)")
|
|
|
+ public void pointcut(AuthCheck authCheck) {
|
|
|
+ }
|
|
|
+
|
|
|
+ @Around(value = "pointcut(authCheck)", argNames = "joinPoint,authCheck")
|
|
|
+ public Object around(ProceedingJoinPoint joinPoint, AuthCheck authCheck) throws Throwable {
|
|
|
+ String principal = getPrincipal();
|
|
|
+ String role = authCheck.role();
|
|
|
+ String authority = authCheck.authority();
|
|
|
+ boolean access = authService.check(principal, role, authority);
|
|
|
+ logger.info("check auth for principal={},role={},authority={}", principal, role, authority);
|
|
|
+ Object result = null;
|
|
|
+ try {
|
|
|
+ if (access) {
|
|
|
+ result = joinPoint.proceed();
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ logger.error("Something wrong with Server. ", e);
|
|
|
+ }
|
|
|
+ return access ? result : "Auth check fail";
|
|
|
+ }
|
|
|
+
|
|
|
+ private String getPrincipal() {
|
|
|
+ String principal = "";
|
|
|
+ Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
|
|
+ if (authentication != null && authentication.getPrincipal() != null) {
|
|
|
+ Object principalObj = authentication.getPrincipal();
|
|
|
+ if (principalObj instanceof UserDetails) {
|
|
|
+ principal = ((UserDetails) principalObj).getUsername();
|
|
|
+ } else {
|
|
|
+ principal = principalObj.toString();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return principal;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * 根据value表达式解析出resource
|
|
|
+ *
|
|
|
+ * @param value 表达式,仅支持类似door.id或id的方式
|
|
|
+ * @return 解析后的客体(resource)
|
|
|
+ */
|
|
|
+ private String resolve(JoinPoint joinPoint, String value) {
|
|
|
+
|
|
|
+ String argName;
|
|
|
+ String attrName = null;
|
|
|
+ if (value.contains(ATTRIBUTE_SEPARATOR)) {
|
|
|
+ String[] strs = value.split("\\" + ATTRIBUTE_SEPARATOR);
|
|
|
+ argName = strs[0];
|
|
|
+ attrName = strs[1];
|
|
|
+ } else {
|
|
|
+ argName = value;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ Object[] args = joinPoint.getArgs();
|
|
|
+
|
|
|
+ int argIndex = getArgIndex(joinPoint, argName);
|
|
|
+ Object arg = args[argIndex];
|
|
|
+ if (arg == null) {
|
|
|
+ throw new RuntimeException("参数" + argName + "的值不能为null");
|
|
|
+ }
|
|
|
+
|
|
|
+ return argToResource(arg, attrName);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * 把参数转为客体resource
|
|
|
+ *
|
|
|
+ * @param arg 参数(Object类型)
|
|
|
+ * @param attrName 参数的属性名
|
|
|
+ * @return 客体的主键resource
|
|
|
+ */
|
|
|
+ private String argToResource(Object arg, String attrName) {
|
|
|
+ if (attrName == null) {
|
|
|
+ return (String) arg;
|
|
|
+ }
|
|
|
+ Map<String, Object> map = CommonUtil.beanToMap(arg);
|
|
|
+ return (String) map.get(attrName);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * 取得参数value的参数索引
|
|
|
+ *
|
|
|
+ * @param argName 参数名
|
|
|
+ * @return 索引
|
|
|
+ */
|
|
|
+ private int getArgIndex(JoinPoint joinPoint, String argName) {
|
|
|
+ String methodName = joinPoint.getSignature().getName();
|
|
|
+ Class<?> clazz = joinPoint.getTarget().getClass();
|
|
|
+ Object[] args = joinPoint.getArgs();
|
|
|
+ Class[] classes = new Class[args.length];
|
|
|
+ for (int i = 0; i < args.length; i++) {
|
|
|
+ classes[i] = args[i].getClass();
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ Method method = clazz.getDeclaredMethod(methodName, classes);
|
|
|
+ LocalVariableTableParameterNameDiscoverer discoverer = new LocalVariableTableParameterNameDiscoverer();
|
|
|
+ String[] names = discoverer.getParameterNames(method);
|
|
|
+ assert names != null;
|
|
|
+ for (int i = 0; i < names.length; i++) {
|
|
|
+ if (argName.equals(names[i])) {
|
|
|
+ return i;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (NoSuchMethodException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ throw new RuntimeException("未找到参数" + argName);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+}
|