All Downloads are FREE. Search and download functionalities are using the official Maven repository.

myaction.extend.BaseServiceAction Maven / Gradle / Ivy

The newest version!
package myaction.extend;

import java.util.Date;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;

import myaction.utils.DateUtil;
import myaction.utils.MD5Util;
import myaction.utils.SortUtil;
import net.sf.jsqlx.DB;
import net.sf.jsqlx.JSQLException;
import net_io.core.StatNIO;
import net_io.myaction.BaseMyAction;
import net_io.myaction.CheckException;
import net_io.utils.EncodeUtils;
import net_io.utils.MixedUtils;
import net_io.utils.NetLog;

abstract public class BaseServiceAction extends BaseMyAction {
	//签名过期时间:10分钟
	private static final long SIGN_EXPIRE_TIME = 600 * StatNIO.ONE_THOUSAND_LONG;
	private static AtomicLong sRunCount = new AtomicLong(0);
	private static AtomicLong sRunUsTime = new AtomicLong(0);
	private String glbVisitId = EncodeUtils.createTimeRandId(); //创建唯一的日志ID
	
	/** 获取运行次数 **/
	public static long getTotalRunCount() { return sRunCount.get(); }
	/** 获取运行时间(单位:毫秒) **/
	public static long getTotalRunTime() { return sRunUsTime.get() / StatNIO.ONE_THOUSAND_LONG; }
	/** 获取运行时间 **/
	public String getPageVisitId() { return glbVisitId; }
	
	public BaseServiceAction() {
		sRunCount.incrementAndGet(); //运行次数总计
	}

	/**
	 * 获取参与签名的字段名(参与签名字段不允许为空)
	 * @return 返回null或空数组,则按默认校验签名
	 */
	protected String[] getSignFieldNames() {
		return null;
	}
	/** Action执行前过滤器(支持异常,并中断进程) **/
	protected void filterStart() throws Exception {}
	/** Action执行后过滤器(若有异常,不影响主进程) **/
	protected void filterEnd() {}
	

	/**
	 * 权限验证
	 * 参数:
	 *   g_platform 调用中间件的平台。系统配置
	 *   g_uid 用户ID。可为空,默认为0
	 *   g_accout 帐号名,默认为空
	 *   g_agent 浏览器ID(agent_id),不为空
	 *   g_ip 客户端IP地址,可为空
	 *   g_time 接口调用时间戳,北京时间,单位 秒。请求时间必须在前后10分钟内
	 *   g_sign 签名。默认签名:g_platform + g_agent + g_time + {secret_key}
	 */
	@Override
	protected void beforeExecute() throws Exception {
		filterStart(); //执行前过滤器
	}
	
	@Override
	final public void defaultExecute(String methodName) throws Exception {
		service(methodName);
	}

	@Override
	protected void afterExecute() throws Exception {
		//MessageLogFileBean.updateWriter(); //更新消息系统消息记录文件地址
		try {
			filterEnd(); //执行后过滤器
		} catch(Exception e) {
			NetLog.logError(e);
		} finally {
			super.afterExecute();
			Exception lastE = this.getLastActionException();
			if(lastE != null) {
				if(lastE instanceof JSQLException) {
					String lastSQL = ((JSQLException)lastE).getRunSQL();
					System.err.println(DateUtil.getDateTime()+" - Exception SQL: "+lastSQL);
				}
			}
			//回收连接资源
			DB.forceReleaseCurrentInstance();
			long costNsTime = System.nanoTime() - request.getStartNanoTime();
			sRunUsTime.addAndGet(costNsTime / StatNIO.ONE_THOUSAND_LONG); //运行时间总计
		}
	}

	
	
	abstract public void service(String methodName) throws Exception;
	
	protected void throwNotFoundException(String methodName) throws CheckException {
		throw new CheckException(404, "Not Found Method: "+methodName);
	}
	
	/**
	 * 检查API请求的签名
	 * 		必要字段:g_appid, g_time, g_sign
	 * @param params
	 */
	protected void checkApiSign(Map params, String appKey) throws CheckException {
		String appID = params.get("g_appid");
		String sTime = params.get("g_time");
		String sign = params.get("g_sign");
		boolean checkOldSign = false;
		if(MixedUtils.isEmpty(appID)) {
			appID = params.get("g_platform"); //兼容旧版(20180910)
			checkOldSign = true;
		}
		if(MixedUtils.isEmpty(appID)) {
			throw new CheckException(621, "The parameter of 'g_appid' is empty.");
		}
		if(MixedUtils.isEmpty(sTime)) {
			throw new CheckException(622, "The parameter of 'g_time' is empty.");
		}
		if(MixedUtils.isEmpty(sign)) {
			throw new CheckException(623, "The parameter of 'g_sign' is empty.");
		}
		long glbClientTime = MixedUtils.parseLong(sTime) * StatNIO.ONE_THOUSAND_LONG;
		//当前时间
		long curTime = new Date().getTime();
		if(curTime-glbClientTime > SIGN_EXPIRE_TIME || glbClientTime-curTime > SIGN_EXPIRE_TIME) {
			throw new CheckException(624, "The sign had been expire.");
		}
		//验证签名
		String[] signNames = getSignFieldNames();
		if (signNames != null && signNames.length > 0) {
			for (String name : signNames) {
				if (MixedUtils.isEmpty(params.get(name))) {
					throw new CheckException(625, "The parameter of '" + name + "' is empty.");
				}
			}
		} else {
			signNames = new String[params.size()];
			int index = 0;
			for (String name : params.keySet()) {
				signNames[index++] = name;
			}
			signNames = SortUtil.sort(signNames, SortUtil.ASC);
		}
		StringBuilder build = new StringBuilder();
		for(String name : signNames) {
			if("g_sign".equals(name)) {
				continue;
			}
			build.append(params.get(name));
		}
		build.append(appKey);			
		String rightSign = EncodeUtils.md5(build.toString());
		if(sign.equals(rightSign) == false) {
			if(checkOldSign) {
				String agentID = params.get("g_agent");
				if(MixedUtils.isEmpty(agentID)) {
					throw new CheckException(625, "The parameter of 'g_agent' is empty.");
				}
				build = new StringBuilder();
				build.append(appID);
				build.append(agentID);
				build.append(sTime);
				if(params.containsKey("g_args")) {
					build.append(params.get("g_args"));			
				}
				build.append(appKey);
				String rightOldSign = MD5Util.md5(build.toString());
				if(sign.equals(rightOldSign) == false) {
					if(params.containsKey("args")) {
						build.append(params.get("args"));
						rightOldSign = MD5Util.md5(build.toString());
						if(sign.equals(rightOldSign) == false) {
							throw new CheckException(626, "The sign not match.");
						}
					} else {
						throw new CheckException(627, "The sign not match.");						
					}
				}
			} else {
				throw new CheckException(628, "The sign not match.");
			}
		}
	
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy