//身份解决者接口 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