package org.xmx0632.deliciousfruit.api.v1.interceptor; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import net.sf.ehcache.Cache; import net.sf.ehcache.Element; import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import org.springside.modules.utils.Encodes; import org.xmx0632.deliciousfruit.api.v1.Constant; import org.xmx0632.deliciousfruit.entity.UserAccount; import org.xmx0632.deliciousfruit.erp.ErpService; import org.xmx0632.deliciousfruit.service.UserAccountService; public class RequestValidationInterceptor implements HandlerInterceptor { private static final String ERROR_MSG = "errorMsg"; private static Logger log = LoggerFactory .getLogger(RequestValidationInterceptor.class); @Autowired private UserAccountService userAccountService; @Autowired private ErpService erpService; @Autowired private Cache dynamicPasswordCache; public RequestValidationInterceptor() { } /** * 在业务处理器处理请求之前被调用 如果返回false 从当前的拦截器往回执行所有拦截器的afterCompletion(),再退出拦截器链 * * 如果返回true 执行下一个拦截器,直到所有的拦截器都执行完毕 再执行被拦截的Controller 然后进入拦截器链, * 从最后一个拦截器往回执行所有的postHandle() 接着再从最后一个拦截器往回执行所有的afterCompletion() * * @throws IOException * @throws ServletException * * @throws Exception */ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { HttpStatus status = isValidUser(request); if (HttpStatus.OK.equals(status)) { return true; } response.sendError(status.value()); return false; } private HttpStatus isValidUser(HttpServletRequest request) { String auth = request.getHeader(Constant.AUTH); log.debug("auth in head:{}", auth); try { if (auth == null) { log.debug("auth is null in header"); setErrorMessage(request, "auth is null in header"); return HttpStatus.UNAUTHORIZED; } byte[] decodeBase64 = Encodes.decodeBase64(auth); String usernameAndPassword = new String(decodeBase64, "utf-8"); log.debug("usernameAndPassword:{}", usernameAndPassword); String[] s = usernameAndPassword.split("\\:"); if (s == null || s.length != 2) { log.debug("invalid auth [{}] in header", usernameAndPassword); setErrorMessage(request, "invalid auth [" + usernameAndPassword + "] in header"); return HttpStatus.UNAUTHORIZED; } String username = s[0]; String password = s[1]; if (StringUtils.isBlank(password)) { log.info( "blank password with username:{},maybe attack request!", username); setErrorMessage(request, "blank password with username:" + username + ",maybe attack request!"); return HttpStatus.UNAUTHORIZED; } UserAccount userAccount = userAccountService .findByUsername(username); if (userAccount != null) { if (isValid(password, userAccount)) { if (userAccount.isNormal()) { request.setAttribute(Constant.CURRENT_USER, userAccount); return HttpStatus.OK; } else { log.debug("banned user:{} attempt login", username); setErrorMessage(request, "banned user:" + username + " attempt login"); return HttpStatus.FORBIDDEN; } } else { log.debug("user:{} password error.", username); setErrorMessage(request, "password error"); return HttpStatus.UNAUTHORIZED; } } // TODO 如果用户账号在平台不存在或者用户账号为ERP同步会员,则平台发起到ERP的会员信息同步请求, // 平台获取到ERP返回的会员信息后则检验用户的账号、密码是否正确 boolean syncSuccess = erpService.pullUserInfoByUsername(username); if (syncSuccess) { UserAccount userAccountFromErp = userAccountService .findByUsername(username); if (isValid(password, userAccountFromErp)) { request.setAttribute(Constant.CURRENT_USER, userAccountFromErp); return HttpStatus.OK; } } } catch (Exception e) { log.error("auth error for [" + auth + "]. " + e.getMessage(), e); setErrorMessage(request, "auth error for [" + auth + "]. " + e.getMessage()); return HttpStatus.UNAUTHORIZED; } log.debug("no user found with auth:{}", auth); setErrorMessage(request, "no user found"); return HttpStatus.UNAUTHORIZED; } private void setErrorMessage(HttpServletRequest request, String errorMessage) { request.setAttribute(ERROR_MSG, errorMessage); } private boolean isValid(String password, UserAccount userAccount) { String passwordMd5 = DigestUtils.md5Hex(password); log.debug("passwordMd5:{}", passwordMd5); Element element = dynamicPasswordCache.get(userAccount.getUsername()); if (element != null) { String dynamicPassword = (String) element.getObjectValue(); if (passwordMd5.equals(dynamicPassword)) { return true; } } return passwordMd5.equals(userAccount.getPassword()); // return password.equals(userAccountFromErp.getPassword()); } /** * 在业务处理器处理请求执行完成后,生成视图之前执行的动作 */ @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { } /** * 在DispatcherServlet完全处理完请求后被调用 * * 当有拦截器抛出异常时,会从当前拦截器往回执行所有的拦截器的afterCompletion() */ @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { } }