首页

通过责任链设计模式定义ProcessorChain责任链、Processor处理器及上下文接口类在请求登录过程中安全控制及逻辑单元解耦扩展实现请求源码说明

标签:责任链设计模式,rocessorChain责任链,Processor处理器接口,安全控制,逻辑单元解耦扩展,过滤器设计,系统设计     发布时间:2018-10-06   

一、前言

通过javax.servlet.Filter过滤器自定义LoginFilter登录授权过滤器类,并通过定义Processor处理上下文接口、AbstractProcessor抽象类、处理接口返回类型ProcessorResult枚举类,实现用户登录过程中的XSS攻击安全过滤、访问控制限制处理、登录字段验证类、session会话刷新、超时验证等逻辑处理单元等。

二、代码示例

1. Processor接口、AbstractProcessor抽象类、ProcessorContext上下类

public interface Processor {@b@@b@	ProcessorResult process(ProcessorContext context);@b@	@b@}
public abstract class AbstractProcessor implements Processor {@b@@b@	@Override@b@	public ProcessorResult process(ProcessorContext context) {@b@		ProcessorResult result = ProcessorResult.CONTINUE;@b@		@b@		try{@b@			ProcessorResult tempResult = this.doProcess(context);@b@			result = (tempResult == null ? result : tempResult);@b@		} catch(Exception e) {@b@			result = ProcessorResult.REJECT;@b@		}@b@		@b@		return result;@b@	}@b@	@b@	public abstract ProcessorResult doProcess(ProcessorContext context);@b@@b@}
public enum ProcessorResult {@b@@b@	REJECT("reject"), COMPLETE("complete"), CONTINUE("continue");@b@	@b@	private String message;@b@	@b@	private ProcessorResult(String message){@b@		this.message = message;@b@	}@b@@b@	public String getMessage() {@b@		return message;@b@	}@b@}
import java.util.Map;@b@import java.util.concurrent.ConcurrentHashMap;@b@@b@public class ProcessorContext {@b@@b@	private Map<String, Object> context = new ConcurrentHashMap<String, Object>();@b@@b@	public void put(String key, Object value) {@b@		if (key != null && value != null) {@b@			this.context.put(key, value);@b@		}@b@	}@b@@b@	public Object get(String key) {@b@		return this.context.get(key);@b@	}@b@@b@	@SuppressWarnings("unchecked")@b@	public <T> T getValue(String key) {@b@		Object obj = this.context.get(key);@b@		if (obj == null) {@b@			return null;@b@		}@b@		return (T) obj;@b@	}@b@@b@	public boolean getBooleanValue(String key) {@b@		Boolean value = getValue(key);@b@		if (value == null) {@b@			return false;@b@		}@b@		return value;@b@	}@b@@b@	public Object remove(String key) {@b@		return this.context.remove(key);@b@	}@b@@b@	@SuppressWarnings("unchecked")@b@	public <T> T removeValue(String key) {@b@		Object obj = this.context.remove(key);@b@		if (obj == null) {@b@			return null;@b@		}@b@		return (T) obj;@b@	}@b@	@b@	public void clear() {@b@		this.context.clear();@b@	}@b@@b@	public boolean isValid() {@b@		if (this.context != null && !this.context.isEmpty()) {@b@			return true;@b@		} else {@b@			return false;@b@		}@b@	}@b@	@b@	public boolean contains(String key){@b@		return context.containsKey(key);@b@	}@b@}

2. ProcessorChain实现类

import java.util.ArrayList;@b@import java.util.List; @b@import org.apache.commons.lang.Validate;@b@import org.apache.commons.lang.builder.ToStringBuilder;@b@import org.apache.commons.lang.builder.ToStringStyle;@b@import org.apache.log4j.Logger; @b@import com.xwood.mobilegw.util.LoggerUtil;@b@ @b@public class ProcessorChain implements Processor {@b@	@b@	private static final Logger logger = Logger@b@			.getLogger(ProcessorChain.class);@b@	@b@	private List<Processor> processorList = new ArrayList<Processor>();@b@@b@	@Override@b@	public ProcessorResult process(ProcessorContext context) {@b@		ProcessorResult result = ProcessorResult.COMPLETE;@b@		@b@		for (Processor processor : processorList){@b@			result = processor.process(context);@b@			//printLog(processor, context, result);@b@			@b@			if (!result.equals(ProcessorResult.CONTINUE)){@b@				return result;@b@			}@b@		}@b@		@b@		return result;@b@	}@b@	@b@	public void add(Processor processor){@b@		Validate.notNull(processor, "processor can not be null!");@b@		this.processorList.add(processor);@b@	}@b@	@b@	public void add(Processor... processors){@b@		Validate.notNull(processors, "processors can not be null!");@b@		for(Processor processor : processors){@b@			this.processorList.add(processor);@b@		}@b@	}@b@@b@	public List<Processor> getProcessorList() {@b@		return processorList;@b@	}@b@@b@	public void setProcessorList(List<Processor> processorList) {@b@		this.processorList = processorList;@b@	}@b@	@b@	private void printLog(Processor processor, ProcessorContext context, ProcessorResult result){@b@		String className = processor.getClass().getSimpleName();@b@		String parameters = ToStringBuilder.reflectionToString(context, ToStringStyle.SIMPLE_STYLE);@b@		@b@		StringBuilder builder = new StringBuilder();@b@		builder.append("处理的节点为: ");@b@		builder.append(className);@b@		@b@		builder.append(";\t");@b@		builder.append("参数为: ");@b@		builder.append(parameters);@b@		@b@		builder.append(";\t");@b@		builder.append("结果为: ");@b@		builder.append(result.name());@b@		@b@		LoggerUtil.info(logger, builder.toString());@b@	}@b@	@b@}
import javax.servlet.http.HttpServletRequest; @b@import com.xwood.mobilegw.bo.CustomerBO;@b@import com.xwood.mobilegw.bo.CustomerDynamicBO;@b@import com.xwood.mobilegw.util.customer.LoginUtil;@b@import com.xwood.mobilegw.util.processorchain.AbstractProcessor;@b@import com.xwood.mobilegw.util.processorchain.ProcessorConst;@b@import com.xwood.mobilegw.util.processorchain.ProcessorContext;@b@import com.xwood.mobilegw.util.processorchain.ProcessorResult;@b@@b@ @b@public class SessionRefreshProcessor extends AbstractProcessor{@b@	@b@	@Override@b@	public ProcessorResult doProcess(ProcessorContext context) {		@b@		@b@		HttpServletRequest httpRequest = context.getValue(ProcessorConst.HTTPREQUEST);@b@		CustomerBO customerBO = context.getValue(ProcessorConst.CUSTOMERBO);@b@		CustomerDynamicBO dynamicBO = context.getValue(ProcessorConst.DYNAMICBO);@b@		@b@		LoginUtil.putCustomerInfoToSession(httpRequest, customerBO, dynamicBO);@b@		@b@		return ProcessorResult.COMPLETE;@b@	}@b@}

3. LoginFilter处理规则主类

package com.xwood.mobilegw.web.filter;@b@@b@import java.io.IOException;@b@import javax.servlet.Filter;@b@import javax.servlet.FilterChain;@b@import javax.servlet.FilterConfig;@b@import javax.servlet.ServletException;@b@import javax.servlet.ServletRequest;@b@import javax.servlet.ServletResponse;@b@import javax.servlet.http.HttpServletRequest;@b@import javax.servlet.http.HttpServletResponse;@b@import org.apache.commons.lang.StringUtils;@b@import org.apache.log4j.Logger;@b@import com.alibaba.fastjson.JSON;@b@import com.alibaba.fastjson.JSONArray;@b@import com.alibaba.fastjson.JSONObject;@b@import com.xwood.mobilegw.adapterservice.ResultEnum;@b@import com.xwood.mobilegw.biz.login.processorchain.AccessLimitProcessor;@b@import com.xwood.mobilegw.biz.login.processorchain.AnyDoorTicketRefreshProcessor;@b@import com.xwood.mobilegw.biz.login.processorchain.DynamicInfoUpdateProcessor;@b@import com.xwood.mobilegw.biz.login.processorchain.LoginValidationProcessor;@b@import com.xwood.mobilegw.biz.login.processorchain.ReLoginProcessor;@b@import com.xwood.mobilegw.biz.login.processorchain.ServiceConfigValidator;@b@import com.xwood.mobilegw.biz.login.processorchain.SessionRefreshProcessor;@b@import com.xwood.mobilegw.biz.login.processorchain.SessionValidationProcessor;@b@import com.xwood.mobilegw.biz.login.processorchain.TimeoutValidationProcessor;@b@import com.xwood.mobilegw.biz.login.processorchain.XssAttackProcessor;@b@import com.xwood.mobilegw.bo.CustomerBO;@b@import com.xwood.mobilegw.bo.CustomerDynamicBO;@b@import com.xwood.mobilegw.core.model.GatewayResponse;@b@import com.xwood.mobilegw.core.service.util.ResponseUtil;@b@import com.xwood.mobilegw.util.LoggerUtil;@b@import com.xwood.mobilegw.util.customer.CustomerUtil;@b@import com.xwood.mobilegw.util.processorchain.Processor;@b@import com.xwood.mobilegw.util.processorchain.ProcessorChain;@b@import com.xwood.mobilegw.util.processorchain.ProcessorConst;@b@import com.xwood.mobilegw.util.processorchain.ProcessorContext;@b@import com.xwood.mobilegw.util.processorchain.ProcessorResult;@b@import com.xwood.mobilegw.util.processorchain.ProcessorUtil;@b@@b@public class LoginFilter implements Filter {@b@@b@	private static final Logger logger = Logger.getLogger(LoginFilter.class);@b@@b@	private ProcessorChain loginChain = new ProcessorChain();@b@@b@	@Override@b@	public void init(FilterConfig filterConfig) throws ServletException {@b@		loginChain.add(new XssAttackProcessor()); *//** 防止XSS处理的过滤器*//*@b@		loginChain.add(new ServiceConfigValidator());@b@		loginChain.add(new AccessLimitProcessor());@b@		loginChain.add(new LoginValidationProcessor());@b@		loginChain.add(new SessionValidationProcessor());@b@		loginChain.add(new TimeoutValidationProcessor());@b@		loginChain.add(new ReLoginProcessor());@b@		loginChain.add(new DynamicInfoUpdateProcessor());@b@		loginChain.add(new SessionRefreshProcessor());@b@	}@b@@b@	@Override@b@	public void doFilter(ServletRequest request, ServletResponse response,@b@			FilterChain filterChain) throws IOException, ServletException {@b@		ProcessorContext context = initProcessorContext(request, response);@b@		if (!context.isValid()) {@b@			LoggerUtil.info(logger, "LoginFilter初始化参数失败");@b@			return;@b@		}@b@@b@//		ProcessorResult result = loginChain.process(context);@b@		@b@		/**api debug switcher*/@b@		ProcessorResult result=ProcessorResult.COMPLETE;@b@		@b@		@b@		switch (result) {@b@		case REJECT:@b@			return;@b@@b@		case COMPLETE:@b@			filterChain.doFilter(request, response);@b@			break;@b@@b@		default:@b@			LoggerUtil.error(logger, null, "LoginFilter处理异常");@b@			break;@b@		}@b@	}@b@@b@	@Override@b@	public void destroy() {@b@@b@	}@b@@b@	private ProcessorContext initProcessorContext(ServletRequest request,@b@			ServletResponse response) {@b@@b@		ProcessorContext context = new ProcessorContext();@b@@b@		HttpServletRequest httpRequest = (HttpServletRequest) request;@b@		HttpServletResponse httpResponse = (HttpServletResponse) response;@b@		String operationType = null;@b@		String requestData = null;@b@@b@		try {@b@			operationType = (String) httpRequest.getParameter("operationType");@b@			requestData = (String) httpRequest.getParameter("requestData");@b@@b@			JSONArray dataArray = JSON.parseArray(requestData);@b@			JSONObject dynamicInfo = dataArray.getJSONObject(0);@b@@b@			CustomerDynamicBO dynamicBO = CustomerUtil.wrapCustomerDynamicBo(@b@					dynamicInfo, httpRequest);@b@			CustomerBO customerBO = null;@b@@b@			if (StringUtils.isNotEmpty(dynamicBO.getSessionId())) {@b@				customerBO = CustomerUtil.getCustomerBoBySession(dynamicBO@b@						.getSessionId());@b@			}@b@@b@			context.put(ProcessorConst.REQUESTDATA, requestData);@b@			context.put(ProcessorConst.CUSTOMERBO, customerBO);@b@			context.put(ProcessorConst.DYNAMICBO, dynamicBO);@b@			context.put(ProcessorConst.HTTPREQUEST, httpRequest);@b@			context.put(ProcessorConst.HTTPRESPONSE, httpResponse);@b@		} catch (Exception e) {@b@			LoggerUtil.error(logger, e, "参数验证不合法, operationType = ",@b@					operationType, ", requestData = ", requestData);@b@			GatewayResponse gatewayResponse = ResponseUtil.buildErrorResponse(ResultEnum.ValueInvalid);@b@			ProcessorUtil.buildAPPResponse(gatewayResponse, httpRequest, httpResponse);@b@			context.clear();@b@		}@b@@b@		return context;@b@	}@b@}