周浩 9 роки тому
батько
коміт
c28b0ab1de

+ 75 - 0
hsweb-web-core/src/main/java/org/hsweb/web/authorize/AopAuthorizeValidator.java

@@ -0,0 +1,75 @@
+package org.hsweb.web.authorize;
+
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.reflect.MethodSignature;
+import org.hsweb.web.authorize.annotation.Authorize;
+import org.hsweb.web.authorize.validator.SimpleAuthorizeValidator;
+import org.hsweb.web.bean.po.user.User;
+import org.hsweb.web.exception.AuthorizeException;
+import org.hsweb.web.utils.WebUtil;
+import org.webbuilder.utils.common.ClassUtils;
+import org.webbuilder.utils.common.StringUtils;
+
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+/**
+ * Created by zhouhao on 16-4-28.
+ */
+public class AopAuthorizeValidator extends SimpleAuthorizeValidator {
+
+    protected ConcurrentMap<String, AuthorizeValidatorConfig> configCache = new ConcurrentHashMap<>();
+
+    protected AuthorizeValidatorConfig getConfig(ProceedingJoinPoint pjp) {
+        String cacheKey = StringUtils.concat(pjp.getTarget().getClass().getName(), ".", getMethodName(pjp));
+        AuthorizeValidatorConfig config = configCache.get(cacheKey);
+        if (config == null) {
+            config = this.createConfig();
+            MethodSignature signature = (MethodSignature) pjp.getSignature();
+            Authorize methodAuth = ClassUtils.getAnnotation(signature.getMethod(), Authorize.class);
+            Authorize classAuth = ClassUtils.getAnnotation(pjp.getTarget().getClass(), Authorize.class);
+            if (methodAuth == null && classAuth == null) {
+                return null;
+            }
+            Set<Authorize> authorizes = new LinkedHashSet<>();
+            if (classAuth != null)
+                authorizes.add(classAuth);
+            if (methodAuth != null)
+                authorizes.add(methodAuth);
+
+            config.addAnnotation(authorizes);
+            configCache.put(cacheKey, config);
+        }
+        return config;
+    }
+
+    public boolean validate(ProceedingJoinPoint pjp) {
+        AuthorizeValidatorConfig config = getConfig(pjp);
+        if (config == null) return true;
+        User user = WebUtil.getLoginUser();
+        if (user == null) throw new AuthorizeException("未登录", 401);
+        Map<String, Object> param = new LinkedHashMap<>();
+        MethodSignature signature = (MethodSignature) pjp.getSignature();
+        String[] names = signature.getParameterNames();
+        for (int i = 0; i < names.length; i++) {
+            param.put(names[i], pjp.getArgs()[i]);
+        }
+        return validate(user, param, config);
+    }
+
+    protected String getMethodName(ProceedingJoinPoint pjp) {
+        StringBuilder methodName = new StringBuilder(pjp.getSignature().getName()).append("(");
+        MethodSignature signature = (MethodSignature) pjp.getSignature();
+        String[] names = signature.getParameterNames();
+        Class[] args = signature.getParameterTypes();
+        for (int i = 0, len = args.length; i < len; i++) {
+            if (i != 0) methodName.append(",");
+            methodName.append(args[i].getSimpleName()).append(" ").append(names[i]);
+        }
+        return methodName.append(")").toString();
+    }
+}

+ 15 - 0
hsweb-web-core/src/main/java/org/hsweb/web/authorize/AuthorizeValidator.java

@@ -0,0 +1,15 @@
+package org.hsweb.web.authorize;
+
+import org.hsweb.web.bean.po.user.User;
+
+import java.util.Map;
+
+/**
+ * 权限验证器
+ * Created by zhouhao on 16-4-28.
+ */
+public interface AuthorizeValidator {
+    boolean validate(User user, Map<String, Object> param, AuthorizeValidatorConfig config);
+
+    AuthorizeValidatorConfig createConfig();
+}

+ 36 - 0
hsweb-web-core/src/main/java/org/hsweb/web/authorize/AuthorizeValidatorConfig.java

@@ -0,0 +1,36 @@
+package org.hsweb.web.authorize;
+
+import org.hsweb.web.authorize.annotation.Authorize;
+
+import java.util.*;
+
+/**
+ * Created by zhouhao on 16-4-28.
+ */
+public interface AuthorizeValidatorConfig {
+    AuthorizeValidatorConfig setModules(Set<String> modules);
+
+    AuthorizeValidatorConfig setRoles(Set<String> roles);
+
+    AuthorizeValidatorConfig setActions(Set<String> actions);
+
+    AuthorizeValidatorConfig setMod(Authorize.MOD mod);
+
+    AuthorizeValidatorConfig addExpression(String expression, String language);
+
+    default AuthorizeValidatorConfig addAnnotation(Set<Authorize> authorizes) {
+        Set<String> modules = new LinkedHashSet<>();
+        Set<String> roles = new LinkedHashSet<>();
+        Set<String> actions = new LinkedHashSet<>();
+        authorizes.forEach(tmp -> {
+            modules.addAll(Arrays.asList(tmp.module()));
+            roles.addAll(Arrays.asList(tmp.role()));
+            actions.addAll(Arrays.asList(tmp.action()));
+            setMod(tmp.mod());
+            addExpression(tmp.expression(), tmp.expressionLanguage());
+        });
+        setActions(actions).setModules(modules).setRoles(roles);
+        return this;
+    }
+
+}

+ 8 - 0
hsweb-web-core/src/main/java/org/hsweb/web/authorize/ExpressionScopeBean.java

@@ -0,0 +1,8 @@
+package org.hsweb.web.authorize;
+
+/**
+ * 表达式作用域bean。实现该接口。可在权限注解的表达式中调用
+ * Created by zhouhao on 16-4-28.
+ */
+public interface ExpressionScopeBean {
+}

+ 89 - 0
hsweb-web-core/src/main/java/org/hsweb/web/authorize/validator/SimpleAuthorizeValidator.java

@@ -0,0 +1,89 @@
+package org.hsweb.web.authorize.validator;
+
+import org.hsweb.web.authorize.AuthorizeValidator;
+import org.hsweb.web.authorize.AuthorizeValidatorConfig;
+import org.hsweb.web.authorize.ExpressionScopeBean;
+import org.hsweb.web.authorize.annotation.Authorize;
+import org.hsweb.web.bean.po.user.User;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
+import org.webbuilder.utils.common.StringUtils;
+import org.webbuilder.utils.script.engine.DynamicScriptEngine;
+import org.webbuilder.utils.script.engine.DynamicScriptEngineFactory;
+
+import javax.annotation.PostConstruct;
+import java.util.*;
+
+/**
+ * 权限验证器
+ * Created by zhouhao on 16-4-28.
+ */
+public class SimpleAuthorizeValidator implements AuthorizeValidator {
+
+    @Autowired
+    private ApplicationContext context;
+
+    private Map<String, ExpressionScopeBean> expressionScopeBeanMap;
+
+    @Override
+    public boolean validate(User user, Map<String, Object> param, AuthorizeValidatorConfig config) {
+        SimpleAuthorizeValidatorConfig validatorConfig = ((SimpleAuthorizeValidatorConfig) config);
+        Set<String> modules = validatorConfig.getModules();
+        Set<String> roles = validatorConfig.getRoles();
+        Set<String> actions = validatorConfig.getActions();
+        Set<SimpleAuthorizeValidatorConfig.Expression> expressions = validatorConfig.getExpressions();
+        Authorize.MOD mod = validatorConfig.getMod();
+        boolean access = false;
+        //验证模块
+        if (!modules.isEmpty()) {
+            if (mod == Authorize.MOD.AND)
+                access = modules.stream().allMatch(module ->
+                        user.hasAccessModuleAction(module, actions.toArray(new String[actions.size()])));
+            else access = modules.stream().anyMatch(module ->
+                    user.hasAccessModuleAction(module, actions.toArray(new String[actions.size()])));
+        }
+        //验证角色
+        if (!roles.isEmpty()) {
+            if (mod == Authorize.MOD.AND)
+                access = roles.stream().allMatch(role -> user.hasAccessRole(role));
+            else
+                access = roles.stream().anyMatch(role -> user.hasAccessRole(role));
+        }
+        //验证表达式
+        if (!expressions.isEmpty()) {
+            if (mod == Authorize.MOD.AND)
+                access = expressions.stream().allMatch(expression -> {
+                    DynamicScriptEngine engine = DynamicScriptEngineFactory.getEngine(expression.getLanguage());
+                    Map<String, Object> var = getExpressionRoot(user);
+                    var.putAll(param);
+                    return StringUtils.isTrue(engine.execute(expression.getId(), var).getResult());
+                });
+            else
+                access = expressions.stream().anyMatch(expression -> {
+                    DynamicScriptEngine engine = DynamicScriptEngineFactory.getEngine(expression.getLanguage());
+                    Map<String, Object> var = getExpressionRoot(user);
+                    var.putAll(param);
+                    return StringUtils.isTrue(engine.execute(expression.getId(), var).getResult());
+                });
+        }
+        return access;
+    }
+
+
+    public Map<String, Object> getExpressionRoot(User user) {
+        Map<String, Object> root = new HashMap<>();
+        root.putAll(expressionScopeBeanMap);
+        root.put("user", user);
+        return root;
+    }
+
+    @Override
+    public AuthorizeValidatorConfig createConfig() {
+        return new SimpleAuthorizeValidatorConfig();
+    }
+
+    @PostConstruct
+    public void init() {
+        expressionScopeBeanMap = context.getBeansOfType(ExpressionScopeBean.class);
+    }
+}

+ 123 - 0
hsweb-web-core/src/main/java/org/hsweb/web/authorize/validator/SimpleAuthorizeValidatorConfig.java

@@ -0,0 +1,123 @@
+package org.hsweb.web.authorize.validator;
+
+import org.hsweb.web.authorize.AuthorizeValidatorConfig;
+import org.hsweb.web.authorize.annotation.Authorize;
+import org.hsweb.web.exception.AuthorizeException;
+import org.webbuilder.utils.common.StringUtils;
+import org.webbuilder.utils.script.engine.DynamicScriptEngine;
+import org.webbuilder.utils.script.engine.DynamicScriptEngineFactory;
+
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+/**
+ * Created by zhouhao on 16-4-28.
+ */
+public class SimpleAuthorizeValidatorConfig implements AuthorizeValidatorConfig {
+    protected Set<String> modules;
+    protected Set<String> roles;
+    protected Set<String> actions;
+    protected Set<Expression> expressions = new LinkedHashSet<>();
+    protected Authorize.MOD mod;
+
+    @Override
+    public AuthorizeValidatorConfig setModules(Set<String> modules) {
+        this.modules = modules;
+        return this;
+    }
+
+    @Override
+    public AuthorizeValidatorConfig setRoles(Set<String> roles) {
+        this.roles = roles;
+        return this;
+    }
+
+    @Override
+    public AuthorizeValidatorConfig setActions(Set<String> actions) {
+        this.actions = actions;
+        return this;
+    }
+
+    @Override
+    public AuthorizeValidatorConfig setMod(Authorize.MOD mod) {
+        this.mod = mod;
+        return this;
+    }
+
+    @Override
+    public AuthorizeValidatorConfig addExpression(String expression, String language) {
+        if (StringUtils.isNullOrEmpty(expression)) return this;
+        DynamicScriptEngine engine = DynamicScriptEngineFactory.getEngine(language);
+        try {
+            String id = "authorize.validator." + expression.hashCode();
+            engine.compile(id, expression);
+            expressions.add(new Expression(id, language));
+        } catch (Exception e) {
+            throw new AuthorizeException("compile expression error", e, 403);
+        }
+        return this;
+    }
+
+    @Override
+    public int hashCode() {
+        return super.hashCode();
+    }
+
+    public Set<String> getModules() {
+        if (modules == null) modules = new LinkedHashSet<>();
+        return modules;
+    }
+
+    public Set<String> getRoles() {
+        if (roles == null) roles = new LinkedHashSet<>();
+        return roles;
+    }
+
+    public Set<String> getActions() {
+        if (actions == null) actions = new LinkedHashSet<>();
+        return actions;
+    }
+
+    public Set<Expression> getExpressions() {
+        if (expressions == null) expressions = new LinkedHashSet<>();
+        return expressions;
+    }
+
+    public void setExpressions(Set<Expression> expressions) {
+        this.expressions = expressions;
+    }
+
+    public Authorize.MOD getMod() {
+        return mod;
+    }
+
+    public static class Expression {
+        private String id;
+        private String language;
+
+        public Expression() {
+        }
+
+        public Expression(String id, String language) {
+            this.id = id;
+            this.language = language;
+        }
+
+        public String getId() {
+            return id;
+        }
+
+        public void setId(String id) {
+            this.id = id;
+        }
+
+        public String getLanguage() {
+            return language;
+        }
+
+        public void setLanguage(String language) {
+            this.language = language;
+        }
+    }
+
+}