Design of User Group Rights Management Module

Design of interfaces and abstract classes

// 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

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326223926&siteId=291194637