Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.alogic.ac.AbstractACMAccessController Maven / Gradle / Ivy
package com.alogic.ac;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantLock;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import com.alogic.metrics.Dimensions;
import com.alogic.metrics.Fragment;
import com.alogic.metrics.Measures;
import com.alogic.metrics.Fragment.Method;
import com.alogic.metrics.impl.DefaultFragment;
import com.alogic.metrics.stream.MetricsCollector;
import com.anysoft.util.JsonTools;
import com.anysoft.util.Properties;
import com.anysoft.util.PropertiesConstants;
import com.anysoft.util.XmlElementProperties;
import com.anysoft.util.XmlTools;
import com.logicbus.backend.AccessController;
import com.logicbus.backend.Context;
import com.logicbus.models.catalog.Path;
import com.logicbus.models.servant.ServiceDescription;
/**
* 基于ACM访问控制器的虚基类
*
* @author yyduan
*
* @since 1.6.10.6
*
* @version 1.6.10.7 [20171115 duanyy]
* - AccessStat中增加被Denied的统计信息
*
* @version 1.6.10.12 [20171211 duanyy]
* - 兼容混合模式
*
* @version 1.6.12.29 [20190409]
* - 优化指标输出模型,对接Prometheus;
* - 优化访问控制算法
*
* @version 1.6.12.34 [20190507]
* - 统计数据支持按周期重置
*/
public abstract class AbstractACMAccessController implements AccessController {
/**
* a logger of slf4j
*/
protected static final Logger LOG = LoggerFactory.getLogger(AbstractACMAccessController.class);
/**
* 访问统计
*/
protected Map statsData = null;
/**
* 统计周期
*/
protected long statsCycle = 0;
/**
* 统计周期长度,毫秒
*/
protected long statsCycleLength = 24 * 60 * 60 * 1000L;
/**
* 锁
*/
protected ReentrantLock lock = new ReentrantLock();
/**
* 指标ID
*/
protected String metricsId = "acm.stat";
public AbstractACMAccessController(){
}
protected Map getStats(long now){
long cycle = (now / statsCycleLength)*statsCycleLength;
if (cycle != statsCycle || statsData == null){
//新的周期开始
statsData = new ConcurrentHashMap();
statsCycle = cycle;
}
return statsData;
}
@Override
public void configure(Element e, Properties props) {
XmlElementProperties p = new XmlElementProperties(e,props);
configure(p);
}
@Override
public void configure(Properties props) {
metricsId = PropertiesConstants.getString(props, "acm.metrics.id", metricsId);
statsCycleLength = PropertiesConstants.getLong(props, "acm.stat.cycleLength", statsCycleLength);
statsCycleLength = statsCycleLength <= 0? 24 * 60 * 60 * 1000L : statsCycleLength;
}
@Override
public String [] getGroupList(){
return new String[]{"default"};
}
@Override
public AccessController getGroup(String id){
return this;
}
/**
* 根据绘画获取ACM控制对象id
* @param sessionId 会话id
* @param serviceId 本次会话调用的服务
* @param servant 服务定义
* @param ctx 上下文
* @return 对象id
*/
protected String getACMObject(String sessionId,Path serviceId, ServiceDescription servant,
Context ctx){
return sessionId;
}
/**
* 根据会话获取ACM模型
* @param sessionId 会话id
* @param serviceId 本次会话调用的服务
* @param servant 服务定义
* @param ctx 上下文
* @return ACM模型
*/
abstract protected AccessControlModel getACM(String sessionId,Path serviceId, ServiceDescription servant,
Context ctx);
/**
* 获取当前调用者的ip
* @param ctx 上下文
* @return 调用者ip
*/
protected String getClientIp(Context ctx){
return ctx.getClientIp();
}
@Override
public int accessStart(String sessionId,Path serviceId, ServiceDescription servant,
Context ctx) {
AccessControlModel acm = getACM(sessionId,serviceId,servant,ctx);
if (acm == null){
return -2;
}
lock.lock();
try{
long timestamp = System.currentTimeMillis();
Map stats = this.getStats(timestamp);
String acmObject = getACMObject(sessionId,serviceId,servant,ctx);
AccessStat current = stats.get(acmObject);
if (current == null){
current = new AccessStat();
stats.put(acmObject, current);
}
current.timesTotal ++;
current.thread ++;
current.waitCnt = lock.getQueueLength();
timestamp = (timestamp / 60000)*60000;
if (timestamp != current.timestamp){
//新的周期
current.timesOneMin = 1;
current.deniedOneMin = 0;
current.thread = 1;
current.timestamp = timestamp;
}else{
current.timesOneMin ++;
}
int priority = acm.getPriority(getClientIp(ctx), serviceId.getPath(), current);
if (priority < 0){
current.deniedTotal ++;
current.deniedOneMin ++;
}
return priority;
}finally{
lock.unlock();
}
}
@Override
public int accessEnd(String sessionId,Path serviceId, ServiceDescription servant, Context ctx) {
lock.lock();
try{
Map stats = this.getStats(System.currentTimeMillis());
String acmObject = getACMObject(sessionId,serviceId,servant,ctx);
AccessStat current = stats.get(acmObject);
if (current != null){
current.thread --;
}
}finally{
lock.unlock();
}
return 0;
}
@Override
public void report(Element root) {
if (root != null){
XmlTools.setLong(root, "cycle", this.statsCycle);
XmlTools.setLong(root, "cycleLength", this.statsCycleLength);
Map stats = this.getStats(System.currentTimeMillis());
int offset = XmlTools.getInt(root, "offset", 0);
int limit = XmlTools.getInt(root,"limit",30);
String keyword = XmlTools.getString(root, "keyword", "");
Document doc = root.getOwnerDocument();
Iterator iter = stats.keySet().iterator();
int current = 0;
while (iter.hasNext()){
String key = iter.next();
boolean match = StringUtils.isEmpty(keyword) || key.contains(keyword);
if (match){
if (current >= offset && current < offset + limit){
AccessStat value = stats.get(key);
Element eAcl = doc.createElement("acl");
eAcl.setAttribute("session", key);
eAcl.setAttribute("currentThread", String.valueOf(value.thread));
eAcl.setAttribute("timesTotal", String.valueOf(value.timesTotal));
eAcl.setAttribute("timesOneMin",String.valueOf(value.timesOneMin));
eAcl.setAttribute("waitCnt", String.valueOf(value.waitCnt));
eAcl.setAttribute("deniedTotal", String.valueOf(value.deniedTotal));
eAcl.setAttribute("deniedOneMin", String.valueOf(value.deniedOneMin));
root.appendChild(eAcl);
}
current ++;
}
}
XmlTools.setInt(root, "total", current);
XmlTools.setInt(root, "all", stats.size());
XmlTools.setString(root,"module",getClass().getName());
}
}
@Override
public void report(Map json) {
if (json != null){
JsonTools.setLong(json, "cycle", this.statsCycle);
JsonTools.setLong(json, "cycleLength", this.statsCycleLength);
Map stats = this.getStats(System.currentTimeMillis());
int offset = JsonTools.getInt(json, "offset", 0);
int limit = JsonTools.getInt(json, "limit", 30);
String keyword = JsonTools.getString(json,"keyword","");
List acls = new ArrayList();
Iterator iter = stats.keySet().iterator();
int current = 0;
while (iter.hasNext()){
String key = iter.next();
boolean match = StringUtils.isEmpty(keyword) || key.contains(keyword);
if (match){
if (current >= offset && current < offset + limit){
AccessStat value = stats.get(key);
Map mAcl = new HashMap();
mAcl.put("session", key);
mAcl.put("currentThread", String.valueOf(value.thread));
mAcl.put("timesTotal", String.valueOf(value.timesTotal));
mAcl.put("timesOneMin",String.valueOf(value.timesOneMin));
mAcl.put("waitCnt", String.valueOf(value.waitCnt));
mAcl.put("deniedTotal", String.valueOf(value.deniedTotal));
mAcl.put("deniedOneMin", String.valueOf(value.deniedOneMin));
acls.add(mAcl);
}
current ++;
}
}
JsonTools.setInt(json, "total", current);
JsonTools.setInt(json,"all",stats.size());
JsonTools.setString(json, "module", getClass().getName());
json.put("acl", acls);
}
}
@Override
public void report(MetricsCollector collector,Properties p) {
if (collector != null){
Map stats = this.getStats(System.currentTimeMillis());
Iterator iter = stats.keySet().iterator();
while (iter.hasNext()){
String key = iter.next();
AccessStat value = stats.get(key);
Fragment f = new DefaultFragment(metricsId);
Dimensions dims = f.getDimensions();
if (dims != null){
dims.set("session", key, true);
}
Measures meas = f.getMeasures();
if (meas != null){
meas.set("thread", value.thread, Method.lst);
meas.set("timesTotal", value.timesTotal,Method.lst);
meas.set("timesOneMin", value.timesOneMin,Method.lst);
meas.set("waitCnt", value.waitCnt,Method.lst);
meas.set("deniedTotal", value.deniedTotal,Method.lst);
meas.set("deniedOneMin", value.deniedOneMin,Method.lst);
}
collector.metricsIncr(f);
}
}
}
}