接口和抽象类的设计
class="java" name="code">
//身份解决者接口
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/b
logs/2395132