SecurityInterceptor

/*
 * Copyright (c) 2013 LIAONING SHIDAI_WANHENG CO.,LTD. All Rights Reserved.
 * This work contains SHIDAI_WANHENG CO.,LTD.'s unpublished
 * proprietary information which may constitute a trade secret
 * and/or be confidential. This work may be used only for the
 * purposes for which it was provided, and may not be copied
 * or disclosed to others. Copyright notice is precautionary
 * only, and does not imply publication.
 *
 */
package com.mtf.vega.interceptor;


import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Locale;


import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;


import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.util.WebUtils;


import com.mtf.vega.controller.user.UserController;
import com.mtf.vega.model.common.Json;
import com.mtf.vega.model.common.Message;
import com.mtf.vega.service.ISecurityService;
import com.mtf.vega.util.ConfigUtils;
import com.mtf.vega.util.Constants;
import com.mtf.vega.util.LogUtils;
import com.mtf.vega.util.SecurityUtils;
import com.mtf.vega.util.SessionInfo;
import com.mtf.vega.util.UUIDUtils;
import com.mtf.vega.util.Utils;


/**
 * 安全性检查拦截器
 *
 * @author Wade.Zhu
 * @version 1.0 2013-4-25 Wade.Zhu created.
 * @version <ver>
 */
public class SecurityInterceptor implements HandlerInterceptor {


private static final Log logger = LogFactory.getLog(SecurityInterceptor.class);
private List<String> noSessionUris;
private List<String> noSessionUrisPrefix;
private List<String> noSecurityUris;
private List<String> noSecurityUrisPrefix;
private List<String> operationNodes;
private List<Long> operationSpans;


@Autowired
private UserController userController;
@Autowired
private ISecurityService securityService;
@Autowired
private MessageSource messages;

private SimpleDateFormat dateFormatter = new SimpleDateFormat(ConfigUtils.getDateTimeFormat());


/**
* 设定无需登录即可使用的资源

* @param noSessionUris 资源列表
*/
public void setNoSessionUris(List<String> noSessionUris) {
this.noSessionUris = noSessionUris;
}

/**
* 设定无需登录即可使用的资源路径前缀

* @param noSessionUrisPrefix 资源列表
*/
public void setNoSessionUrisPrefix(List<String> noSessionUrisPrefix) {
this.noSessionUrisPrefix = noSessionUrisPrefix;
}

/**
* 设定无需权限即可使用的资源

* @param noSecurityUris 资源列表
*/
public void setNoSecurityUris(List<String> noSecurityUris) {
this.noSecurityUris = noSecurityUris;
}

/**
* 设定无需权限即可使用的资源路径前缀

* @param noSecurityUrisPrefix 资源列表
*/
public void setNoSecurityUrisPrefix(List<String> noSecurityUrisPrefix) {
this.noSecurityUrisPrefix = noSecurityUrisPrefix;
}

/**
* 设定需要验证时间的资源节点
* 例如: /workgroup/, /maintenance/, /admin/

* @param operationNodes 资源节点
*/
public void setOperationNodes(List<String> operationNodes) {
this.operationNodes = operationNodes;
}

/**
* 设定需要验证时间的资源时间
* 例如: 1000

* @param operationSpans 时间间隔(毫秒)
*/
public void setOperationSpans(List<Long> operationSpans) {
this.operationSpans = operationSpans;
}


@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object object, Exception exception) throws Exception {


}


@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object object, ModelAndView modelAndView) throws Exception {


}


@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object object) throws Exception {
String requestUri = request.getRequestURI();
String contextPath = request.getContextPath();
String uri = requestUri.indexOf(".do") > 0 ? requestUri.substring(contextPath.length(), requestUri.indexOf(".do") + 3) : requestUri.substring(contextPath.length());
String queryString = request.getQueryString();
String fromUri = java.net.URLEncoder.encode(requestUri.replace(contextPath, "") + (queryString == null ? "" : ('?' + queryString)), "UTF-8");

logger.debug("Request uri: " + uri);


// 检查当前在线用户数量
// int onlineCount = SessionContext.getInstance().getOnlineUsers().size();
// if (onlineCount >= ConfigUtils.getOnlineMax()) {
// logger.debug("The current number of online users has reached the upper limit of the system");
// response.setStatus(509);
// request.setAttribute("com.mtf.vega.exception", new Exception("The current number of online users has reached the upper limit of the system"));
// request.getRequestDispatcher("/WEB-INF/jsp/error/509.jsp").forward(request, response);
// return false;
// }

// 不需要验证的请求
if (this.noSessionUris != null && this.noSessionUris.contains(uri)) {
logger.debug("No need check session, skip!");
return true;
}
// 需要验证的请求
else {
// step 1 : 验证session
HttpSession session = SecurityUtils.getSession(request);
if (session == null) {
logger.debug("No session, refused!");
request.setAttribute("fromUri", fromUri);
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
request.setAttribute("exception", new Exception(this.messages.getMessage("error.security.needlogin", null, Locale.getDefault())));
request.getRequestDispatcher("/WEB-INF/jsp/error/nosession.jsp").forward(request, response);
return false;
}
// step 2 : 验证登录
SessionInfo sessionInfo = (SessionInfo) session.getAttribute(Constants.SESSION_INFO);
if (sessionInfo == null) {
String token = String.valueOf(request.getParameter("token"));
if (!UUIDUtils.isValidUUID(token)) {
Cookie cookie = WebUtils.getCookie(request, "token");
if (cookie != null) token = cookie.getValue();
}
if (UUIDUtils.isValidUUID(token)) {
// 如果有Token,那么自动使用尝试Token登录
String lng = String.valueOf(request.getParameter("lng"));
String client = String.valueOf(request.getParameter("client"));
String ver = String.valueOf(request.getParameter("ver"));
Json json = this.userController.doTokenLogin(token, lng, client, ver);
if (json.isSuccess()) {
logger.debug("Token login successed!");
// token login success
} else {
logger.debug("Token login failed!");
// token login failed
}
}
}
sessionInfo = (SessionInfo) session.getAttribute(Constants.SESSION_INFO);
if (sessionInfo == null) {
logger.debug("Session invalid, refused!");
request.setAttribute("fromUri", fromUri);
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
request.setAttribute("exception", new Exception(this.messages.getMessage("error.security.needlogin", null, Locale.getDefault())));
request.getRequestDispatcher("/WEB-INF/jsp/error/nosession.jsp").forward(request, response);
return false;
}

// step 3 :检查重复提交
if (StringUtils.equalsIgnoreCase(requestUri, sessionInfo.getLastOperationUri()) && System.currentTimeMillis() - sessionInfo.getLastOperationTime() < 10) {
logger.warn("Duplicate request risk triggered by " + sessionInfo.getDisplayName() + " at " + requestUri);
}

// step 4 : 验证超级用户角色
if (sessionInfo.getSuperUser() == 1) {
logger.debug("Super user, skip!");
return true;
}

// step 5 : 验证服务器状态
Message vegaStatus = (Message) session.getServletContext().getAttribute(Constants.VEGA_STATUS);
if (vegaStatus != null && vegaStatus.getCode() != 0) {
logger.debug("Vega Status false");
response.setStatus(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
request.setAttribute("exception", new Exception(vegaStatus.getMsg()));
request.getRequestDispatcher("/WEB-INF/jsp/error/503.jsp").forward(request, response);
//response.sendError(503, vegaStatus.getMsg());
return false;
}

// step 6 : 无需权限
if (this.noSecurityUrisPrefix != null && !this.noSecurityUrisPrefix.isEmpty()) {
for (String s : this.noSecurityUrisPrefix) {
if (s != null && uri.startsWith(s)) {
logger.debug("Do NOT need check security, skip!");
return true;
}
}
} else if (this.noSecurityUris != null && this.noSecurityUris.contains(uri)) {
logger.debug("Do NOT need check security, skip!");
return true;
}

// step 7 : 检查操作时间
if (uri.indexOf("/do") > 0 && this.operationNodes != null && this.operationNodes.size() > 0) {
long nowTime = System.currentTimeMillis();
long lastOperationTime = sessionInfo.getLastOperationTime();
long span = nowTime - lastOperationTime;
int count = this.operationNodes.size();
for (int i = 0; i < count; i ++) {
if (uri.indexOf(this.operationNodes.get(i)) != -1) {
long min = this.operationSpans.get(i);
if (span < min) { // 请求频率过快
sessionInfo.addAbqCount();
if (sessionInfo.getAbqCount() > 9) {//连续10次请求
LogUtils.log("request", sessionInfo);// write log
logger.debug("Abnormal request frequency, span=" + span + ", min=" + min);
response.setStatus(429);
request.setAttribute("exception", new Exception(this.messages.getMessage("error.security.frequency", null, Utils.getLocale(sessionInfo.getLanguage()))));
request.getRequestDispatcher("/WEB-INF/jsp/error/429.jsp").forward(request, response);
return false;
}
} else {
sessionInfo.resetAbqCount();
}
break;
}
}
sessionInfo.setLastOperationTime(nowTime);
sessionInfo.setLastOperationUri(requestUri);
}

// step 8 : 验证操作
int passCode = this.securityService.getPassCode(uri, sessionInfo);
//passCode = 0;
logger.debug("Security check return code with : " + passCode);
if (passCode == 0) {
logger.debug("Security check passed, continue!");
return true;
} else {
String errorMsg = null;
String errorPage = "500.jsp";
switch (passCode) {
case 1:
errorMsg = this.messages.getMessage("error.security.undefinedresource", null, Utils.getLocale(sessionInfo.getLanguage()));
response.setStatus(HttpServletResponse.SC_NOT_IMPLEMENTED);
errorPage = "501.jsp";
break;
case 2:
errorMsg = this.messages.getMessage("error.security.accessdenied", null, Utils.getLocale(sessionInfo.getLanguage()));
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
errorPage = "403.jsp";
break;
case 3:
errorMsg = this.messages.getMessage("error.security.unauthorized", null, Utils.getLocale(sessionInfo.getLanguage()));
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
errorPage = "401.jsp";
break;
default:
errorMsg = this.messages.getMessage("error.security.syserror", null, Utils.getLocale(sessionInfo.getLanguage()));
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
errorPage = "500.jsp";
break;
}


request.setAttribute("uri", uri);
request.setAttribute("errorCode", passCode);
request.setAttribute("errorMsg", errorMsg);
request.setAttribute("datetime", dateFormatter.format(new Date()));
request.setAttribute("exception", new Exception(errorMsg));
request.getRequestDispatcher("/WEB-INF/jsp/error/" + errorPage).forward(request, response);
return false;
}
}
}
}
阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/yueyue____1/article/details/80690889
个人分类: Java_EE
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭