用户分组权限管理模块的设计

接口和抽象类的设计

//身份解决者接口
public interface IdentityResolver  {
    public boolean isLoggedIn(HttpServletRequest req);
}
//许可解决者接口
public interface PermissionResolver {
    //判断许可解决者和被许可对象是否匹配
    public boolean match(String permissionStr);
    //这里返回Boolean或者整数可能能够支持更复杂的许可逻辑,比如一票否决,带权重许可,这方面我缺乏业务经验。暂且不表
    public boolean hasPermission(HttpServletRequest req);
}

//许可解决者抽象类,这里的实现是使用类似于 xxxx.yyyy.zzzz 的字符串来代表分层的授权,通配符*代表某层的所有权限
public abstract class PermissionResolverAbstract implements PermissionResolver {
    protected abstract String getMatch();
    protected Pattern pattern;
    @Override
    public boolean match(String permissionStr){
        if(pattern==null){
            String regEx = getMatch().replaceAll("\\*+", "\\\\S*").replaceAll("\\-", "\\\\-").replaceAll("\\.", "\\\\.");
            regEx = new StringBuilder("^").append(regEx).append("$").toString();
            pattern = Pattern.compile(regEx);
        }
        return pattern.matcher(permissionStr).matches();
    }
}



权限工具类
public class Security {

    private final List<IdentityResolver> identityResolverList = new ArrayList<>();
    private final List<PermissionResolver> permissionResolverList = new ArrayList<>();
    //缓存
    private final Map<String, List<PermissionResolver>> permissionResolverMap = new ConcurrentHashMap<>();
    private boolean skip = false;//是否关闭授权系统,这里应该读取配置文件,不是写死在代码中

    public Security() {
    }

    public void addIdentityResolver(IdentityResolver identityResolver) {
        identityResolverList.add(identityResolver);
    }

    public void addPermissionResolver(PermissionResolver permissionResolver) {
        permissionResolverList.add(permissionResolver);
    }
    
    public boolean isLoggedIn(HttpServletRequest req) {
        if (skip) {
            return true;
        }
        return _isLoggedIn(req);
    }
    
    public boolean hasPermission(String permissionStr,boolean checkLoggedIn, HttpServletRequest req) {
        if (skip) {
            return true;
        }
        if (checkLoggedIn && !_isLoggedIn(req)) {
            return false;
        }
        return _hasPermission(permissionStr, req);
    }

    public boolean hasPermission(String permissionStr, HttpServletRequest req) {
        return hasPermission(permissionStr,false, req);
    }

    private boolean _isLoggedIn(HttpServletRequest req) {
        for(IdentityResolver identityResolver :identityResolverList){
            if(identityResolver.isLoggedIn(req)){
                return true;
            }
        }
        return false;
    }

    private boolean _hasPermission(String permissionStr, HttpServletRequest req) {
        if (!permissionResolverMap.containsKey(permissionStr)) {
            List<PermissionResolver> prs = new ArrayList<>();
            //将与授权对象匹配的权限解决者实现添加进队列,这里用简单list,是否使用责任链或者其他设计模式,值得斟酌
            for (PermissionResolver pr : permissionResolverList) {
                if (pr.match(permissionStr)) {
                    prs.add(pr);
                }
            }
            //缓存,时间和空间的平衡
            permissionResolverMap.put(permissionStr, prs);
        }
        for (PermissionResolver pr : permissionResolverMap.get(permissionStr)) {
            if (pr.hasPermission(req)) {
                return true;
            }
        }
        return false;
    }

}


业务逻辑中的调用代码:

servlet上下文监听器中
Security security = new Security();

//身份解决者 和 许可解决者 的具体实现应该单独打包封装对应不同的业务
IdentityResolver identityResolver = new IdentityResolverImpl();
PermissionResolver allPR =new AllPR();
...

//添加身份解决者进入队列
security.addIdentityResolver(identityResolver);
...
//添加许可解决者进入队列
security.addPermissionResolver(allPR);
...


业务逻辑调用示例
//messages 为消息对象
public static boolean isLoggedIn(Security security, HttpServletRequest req, Messages messages) {
        if (!security.isLoggedIn(req)) {
            String msg = "请登录执行本操作";
            messages.add(Message.Severity.WARN, msg, msg);
            return false;
        }
        return true;
    }

    public static boolean hasPermission(String p, Security security, HttpServletRequest req, Messages messages) {
        if (!isLoggedIn(security, req, messages)) {
            return false;
        } else if (!security.hasPermission(p, req)) {
            String msg = "你无权执行本操作";
            messages.add(Message.Severity.WARN, msg, msg);
            return false;
        }
        return true;
    }


相关阅读:
我的java web架构方案 http://afadgaeg.iteye.com/admin/blogs/2395132

猜你喜欢

转载自afadgaeg.iteye.com/blog/2395507