一、什么是拦截器:
什么是拦截器:在AOP(Aspect-Oriented Programming)中用于在某个方法或字段被访问之前,进行拦截然后在之前或之后加入某些操作。拦截是AOP的一种实现策略
为什么需要拦截器:在做身份认证或者是进行日志的记录时,我们需要通过拦截器达到我们的目的。最常用的登录拦截、或是权限校验、或是防重复提交、或是根据业务像12306去校验购票时间,总之可以去做很多的事情
如何用拦截器:在spring中用拦截器需要实现HandlerInterceptor接口或者它的实现子类:HandlerInterceptorAdapter,同时在applicationContext.xml文件中配置拦截器
二、定义实现类
定义一个Interceptor 非常简单方式有:
1、类要实现Spring 的HandlerInterceptor 接口
2、类继承实现了HandlerInterceptor 接口的类,例如 已经提供的实现了HandlerInterceptor 接口的抽象类HandlerInterceptorAdapter
三、HandlerInterceptor方法
boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception;
void postHandle(
HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
throws Exception;
void afterCompletion(
HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception;
preHandle
:在业务处理器处理请求之前被调用。预处理,可以进行编码、安全控制、权限校验等处理;
postHandle
:在业务处理器处理请求执行完成后,生成视图之前执行。后处理(调用了Service并返回ModelAndView,但未进行页面渲染),有机会修改ModelAndView (这个博主就基本不怎么用了);
afterCompletion
:在DispatcherServlet完全处理完请求后被调用,可用于清理资源等。返回处理(已经渲染了页面);
四、实战演练
1.配置yml
spring:
application:
name: web
profiles:
active: dev
visit:
allowWebHost:
- 写一个拦截器 实现HandlerInterceptor 接口
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.net.URI;
import java.util.Arrays;
import java.util.UUID;
/**
* @author
* @version V1.0
* @Package
* @Description: 用于登录拦截
* @date
*/
@Component
@Slf4j
public class AuthorizeInterceptor implements HandlerInterceptor {
@Value("${spring.profiles.active}")
private String SPRING_PROFILES_ACTIVE;
// ip白名单,如果配置了白名单,则只有白名单可以访问,其他地址非法跨域
@Value("${visit.allowWebHost}")
private String allowWebHostStr;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
//CSRF 跨站攻击简单Referer验证
String referer = request.getHeader("referer");
if (StringUtils.isNotEmpty(referer)) {
URI refererUrl = new URI(referer);
String[] allowWebHostList = allowWebHostStr.split(",");
if (null != allowWebHostList && allowWebHostList.length > 1 && !Arrays.asList(allowWebHostList).contains(refererUrl.getHost())) {
log.error("非法跨站请求URL:" + refererUrl);
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
try (PrintWriter pw = response.getWriter()) {
pw.print(R.error(ResultCodeEnum.ILLEGAL_REQUEST.getMsg(), ResultCodeEnum.ILLEGAL_REQUEST.getCode()));
pw.flush();
}
return false;
}
}
//安全header添加
response.setHeader("XSS-Protection", "1; mode=block");
response.setHeader("X-Content-Type-Options", "nosniff");
response.setHeader("Content-Security-Policy", ""); // 不设置
response.setHeader("x-frame-options", "ALLOW-FROM");
response.setHeader("Access-Control-Allow-Credentials","true");
response.setHeader("Access-Control-Allow-Origin",request.getHeader("Origin"));
//从cookie获取自定义sessionID,不存在则放置
String sessinIdFromCookie = getSessionIdFromCookie(request, response);
//从redis 中获取usersession信息
UserSessionVo userSessionVo = JedisUtils.getBean(CacheKey.CRM_JDM_USER_SESSION_KEY + sessinIdFromCookie, UserSessionVo.class);
// 登录session 验证
if (userSessionVo == null) {
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
try (PrintWriter pw = response.getWriter()) {
pw.print(R.error(ResultCodeEnum.UNAUTHORIZED.getMsg(), ResultCodeEnum.UNAUTHORIZED.getCode()));
pw.flush();
}
return false;
} else {
return true;
}
}
/**
* 获取自定义sessionId
* @param request
* @return
*/
private String getSessionIdFromCookie(HttpServletRequest request, HttpServletResponse response){
String sessionId = null;
// 开发环境缓存注入方式登陆商家后台
String localLoginSession = JedisUtils.getString(CacheKey.CRM_JDM_LOCAL_LOGIN_SESSION);
if ("dev".equals(SPRING_PROFILES_ACTIVE) && !StringUtils.isEmpty(localLoginSession)) {
return localLoginSession;
}
Cookie[] cookies = request.getCookies();
if(null!=cookies){
for(Cookie cookie : cookies){
if(CacheKey.CRM_JDM_COOKIE_SESSION_ID.equals(cookie.getName())){
sessionId = cookie.getValue();
break;
}
}
}
if(StringUtils.isEmpty(sessionId)){
sessionId = UUID.randomUUID().toString();;
Cookie cookie = new Cookie(CacheKey.CRM_JDM_COOKIE_SESSION_ID, sessionId);
cookie.setHttpOnly(true);
cookie.setPath("/");
response.addCookie(cookie);
}
return sessionId;
}
}