4228306 5 år sedan
förälder
incheckning
aeb30fd515

+ 17 - 0
src/main/java/com/yaoxiang/diagnosis/authority/AuthCheck.java

@@ -0,0 +1,17 @@
+package com.yaoxiang.diagnosis.authority;
+
+import java.lang.annotation.*;
+
+/**
+ * @author Created by yawn on 2017-11-24 15:44
+ */
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+public @interface AuthCheck {
+
+    String role() default "";
+
+    String authority() default "";
+
+}

+ 184 - 0
src/main/java/com/yaoxiang/diagnosis/authority/AuthCheckAspect.java

@@ -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();
+        }
+//        String clazzName = joinPoint.getTarget().getClass().getName();
+        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();
+        }
+//        String[] paramNames = new String[0];
+//        try {
+//            paramNames = getFieldsNames(joinPoint.getTarget().getClass(), clazzName, methodName);
+//        } catch (NotFoundException e) {
+//            e.printStackTrace();
+//        }
+//        for (int i = 0; i < paramNames.length; i++) {
+//            if (argName.equals(paramNames[i])) {
+//                return i;
+//            }
+//        }
+        throw new RuntimeException("未找到参数" + argName);
+    }
+//
+//    private static String[] getFieldsNames(Class cls, String clazzName, String methodName) throws NotFoundException {
+//        ClassPool pool = ClassPool.getDefault();
+//        ClassClassPath classPath = new ClassClassPath(cls);
+//        pool.insertClassPath(classPath);
+//
+//        CtClass cc = pool.page(clazzName);
+//        CtMethod cm = cc.getDeclaredMethod(methodName);
+//        MethodInfo methodInfo = cm.getMethodInfo();
+//        CodeAttribute codeAttribute = methodInfo.getCodeAttribute();
+//        LocalVariableAttribute attr = (LocalVariableAttribute) codeAttribute.getAttribute(LocalVariableAttribute.tag);
+//        if (attr == null) {
+//            // exception
+//        }
+//        String[] paramNames = new String[cm.getParameterTypes().length];
+//        int pos = Modifier.isStatic(cm.getModifiers()) ? 0 : 1;
+//        for (int i = 0; i < paramNames.length; i++) {
+//            paramNames[i] = attr.variableName(i + pos);
+//        }
+//        return paramNames;
+//    }
+
+}

+ 14 - 0
src/main/java/com/yaoxiang/diagnosis/authority/AuthCheckException.java

@@ -0,0 +1,14 @@
+package com.yaoxiang.diagnosis.authority;
+
+public class AuthCheckException extends RuntimeException{
+    public AuthCheckException() {
+    }
+
+    public AuthCheckException(String message) {
+        super(message);
+    }
+
+    public AuthCheckException(String message, Throwable cause) {
+        super(message, cause);
+    }
+}

+ 7 - 0
src/main/java/com/yaoxiang/diagnosis/authority/AuthService.java

@@ -0,0 +1,7 @@
+package com.yaoxiang.diagnosis.authority;
+
+public interface AuthService {
+
+    boolean check(String principal,String role, String authority);
+
+}

+ 49 - 0
src/main/java/com/yaoxiang/diagnosis/authority/AuthServiceImpl.java

@@ -0,0 +1,49 @@
+package com.yaoxiang.diagnosis.authority;
+
+import com.yaoxiang.diagnosis.entity.Role;
+import com.yaoxiang.diagnosis.entity.UserInfo;
+import com.yaoxiang.diagnosis.service.RoleService;
+import com.yaoxiang.diagnosis.service.UserService;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.stereotype.Service;
+import org.springframework.util.Assert;
+
+import javax.annotation.Resource;
+import java.util.List;
+
+@Service
+public class AuthServiceImpl implements AuthService {
+
+    @Resource
+    private UserService userService;
+    @Resource
+    private RoleService roleService;
+
+    @Override
+    public boolean check(String principal, String role, String authority) {
+        boolean hasRole = StringUtils.isNotBlank(role);
+        boolean hasAuthority = StringUtils.isNotBlank(authority);
+        if (hasAuthority) {
+            return checkAuthority(principal, authority);
+        }
+        if (hasRole) {
+            return checkRole(principal, role);
+        }
+        return true;
+    }
+
+    public boolean checkRole(String principal, String role) {
+        UserInfo info = userService.findByUsername(principal);
+        String roleIds = info.getRoleIds();
+        List<Role> roles = roleService.listRoles(roleIds);
+        return roles.stream().anyMatch(r -> role.equals(r.getName()));
+    }
+
+    public boolean checkAuthority(String principal, String authority) {
+        UserInfo info = userService.findByUsername(principal);
+        List<String> authorities = info.getAuthorities();
+        return authorities.contains(authority);
+    }
+
+
+}

+ 19 - 0
src/main/java/com/yaoxiang/diagnosis/authority/ResultHandler.java

@@ -0,0 +1,19 @@
+package com.yaoxiang.diagnosis.authority;
+
+import com.yaoxiang.diagnosis.model.Result;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.bind.annotation.ControllerAdvice;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+
+@ControllerAdvice
+public class ResultHandler {
+
+    private static final Logger logger = LoggerFactory.getLogger(ResultHandler.class);
+
+    @ExceptionHandler(value = Exception.class)
+    public Result exceptionHandler(Exception e) {
+        logger.error("发生业务异常!原因是:{}", e.getMessage());
+        return Result.fail(e.getMessage());
+    }
+}