// Identity resolver interface public interface IdentityResolver { public boolean isLoggedIn(HttpServletRequest req); } // License resolver interface public interface PermissionResolver { / / Determine whether the license resolver and the licensed object match public boolean match(String permissionStr); //Returning Boolean or integer here may be able to support more complex permission logic, such as one-vote veto, weighted permission, I lack business experience in this regard. Not yet public boolean hasPermission(HttpServletRequest req); } //License solver abstract class, the implementation here is to use a string similar to xxxx.yyyy.zzzz to represent hierarchical authorization, and the wildcard * represents all permissions of a certain layer 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(); } }
Permission tool class
public class Security { private final List<IdentityResolver> identityResolverList = new ArrayList<>(); private final List<PermissionResolver> permissionResolverList = new ArrayList<>(); //cache private final Map<String, List<PermissionResolver>> permissionResolverMap = new ConcurrentHashMap<>(); private boolean skip = false;//Whether to close the authorization system, the configuration file should be read here, not written in the code 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<>(); //Add the permission resolver implementation that matches the authorization object to the queue. Here we use a simple list. Whether to use the chain of responsibility or other design patterns is worth considering for (PermissionResolver pr : permissionResolverList) { if (pr.match(permissionStr)) { prs.add(pr); } } //Cache, balance of time and space permissionResolverMap.put(permissionStr, prs); } for (PermissionResolver pr : permissionResolverMap.get(permissionStr)) { if (pr.hasPermission(req)) { return true; } } return false; } }
Calling code in business logic: In the
servlet context listener
Security security = new Security(); //The specific implementation of identity resolver and permission resolver should be packaged separately for different services IdentityResolver identityResolver = new IdentityResolverImpl(); PermissionResolver allPR =new AllPR(); ... //Add identity resolver to queue security.addIdentityResolver(identityResolver); ... //Add permission resolver to queue security.addPermissionResolver(allPR); ...
Example of business logic invocation
//messages is the message object public static boolean isLoggedIn(Security security, HttpServletRequest req, Messages messages) { if (!security.isLoggedIn(req)) { String msg = "Please log in to perform this operation"; 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 = "You are not authorized to perform this operation"; messages.add(Message.Severity.WARN, msg, msg); return false; } return true; }
Related reading:
My java web architecture solution http://afadgaeg.iteye.com/admin/blogs/2395132