Spring MVC之拦截器的实现与非法请求拦截处理的实现
一、Spring MVC拦截器
Spring MVC 的拦截器类似于 Servlet 开发中的过滤器 Filter,用于对处理器进行预处理和后处理。
将拦截器按一定的顺序联结成一条链,这条链称为拦截器链(InterceptorChain)。在访问被拦截的方法时,拦截器链中的拦截器就会按其之前定义的顺序被调用。
两种定义方式
1.实现接口:org.springframework.web.servlet.HandlerInterceptor
2.继承适配器:org.springframework.web.servlet.handler.HandlerInterceptorAdapter
拦截器interceptor和filter的区别
区别角度 | 过滤器 | 拦截器 |
---|---|---|
从使用范围看 | 是 servlet 规范中的一部分,任何 java web 工程都可以使用 | 是 SpringMVC 框架自身的,只有使用了 SpringMVC 框架的工程才能用。 |
从拦截范围看 | 在 url-pattern 中配置了/*之后,可以对所有要访问的资源拦截 | 只会拦截要访问的控制器方法,如果访问的是 jsp,html,css,image 或者 js 是不会进行拦截 |
二、拦截器的配置
1.实现HandlerInterceptor 接口
1.HandlerInterceptor接口方法
public interface HandlerInterceptor {
/**
* preHandle方法是controller方法执行前拦截的方法
*
* 1. 可以使用request或者response跳转到指定的页面
* 2. return true放行,执行下一个拦截器,如果没有拦截器,执行controller中的方法。
* 3. return false不放行,不会执行controller中的方法。
*/
default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
return true;
}
/**
*
* postHandle是controller方法执行后执行的方法,在JSP视图执行前。
*
* 1. 可以使用request或者response跳转到指定的页面
* 2. 如果指定了跳转的页面,那么controller方法跳转的页面将不会显示。
*/
default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
}
/**
* afterCompletion方法在JSP执行后执行
*
* 1. request或者response不能再跳转页面了。
*/
default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
}
}
2.自定义拦截器实现HandlerInterceptor 接口
public class PermissionInterceptor implements HandlerInterceptor {
private final static Log log= LogFactory.getLog(PermissionInterceptor.class);
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
log.info("preHandle");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
log.info("postHandle");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
log.info("afterCompletion");
}
}
3.配置spring mvc文件
path配置:
/** 所有路径及里面的子路径
/* 当前路径下的所有路径,不含子文件
/ 项目根目录的请求
SpringMvc框架支持多个拦截器配置,从而构成拦截器链,对客户端请求进行多次拦截操作
<mvc:interceptors>
<!-- 拦截所有 -->
<mvc:interceptor>
<!-- 拦截指定的请求url -->
<mvc:mapping path="/user/**"/>
<!-- 哪些方法不进行拦截
<mvc:exclude-mapping path=""/>
-->
<!--放行用户登录请求-->
<mvc:exclude-mapping path="/user/userLogin"/>
<!-- 注册拦截器对象 -->
<bean class="cn.ybzy.common.interceptor.Permissioninterceptor"/>
<!--配置第二个拦截器-->
</mvc:interceptor>
<mvc:interceptor>
<!--要拦截的具体的方法-->
<mvc:mapping path="user/**"/>
<!-- 哪些方法不进行拦截
<mvc:exclude-mapping path=""/>
-->
<!--配置拦截器对象-->
<bean class="cn.ybzy.common.interceptor.Permissioninterceptor2" />
</mvc:interceptor>
</mvc:interceptors>
4.编写登录方法
@RequestMapping(value = "login",method = RequestMethod.GET)
@ResponseBody
public String login(String name,String pwd){
System.out.println("name:"+name+"------"+"pwd:"+pwd);
return "Hello World!";
}
5.断点验证
preHandle在请求之前调用
执行控制器方法
postHandle在请求后调用
afterCompletion在请求结束调用
2.继承HandlerInterceptorAdapter
public class MyInterceptor extends HandlerInterceptorAdapter {
/**
* 重写preHandle 请求执行前执行
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
System.out.println("handler方法之前执行...");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
System.out.println("handler方法之后,生成视图之前执行...");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
System.out.println("handler方法执行完毕,生成视图后执行...");
}
}
配置方式一:
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/test/*" />
<bean class="cn.ybzy.common.interceptor.MyInterceptor" />
</mvc:interceptor>
</mvc:interceptors>
配置方式二:
<mvc:interceptors>
<!-- 使用bean定义一个Interceptor,直接定义在mvc:interceptors根下面的Interceptor将拦截所有的请求 -->
<bean class="cn.ybzy.common.interceptor.MyInterceptor" />
</mvc:interceptors>
三、非法请求拦截处理实现
1.用户登录过程实现
@RequestMapping(value = "login",method = RequestMethod.GET)
@ResponseBody
public String login(String username, String password, HttpSession session, ServletResponse response){
//向浏览器写入cookies
Cookie ck = new Cookie("sso-cookies",session.getId());
ck.setDomain("localhost");
ck.setPath("/");
ck.setHttpOnly(true);
ck.setMaxAge(60 * 30);
HttpServletResponse resp=(HttpServletResponse)response;
resp.addCookie(ck);
//构造一个成功登录的用户信息
JSONObject object = new JSONObject();
object.put("name",username);
object.put("pwd",password);
//向redis写入数据
Jedis jedis = new Jedis("localhost");
jedis.setex(session.getId(),60*30,object.toJSONString());
return "Hello World!";
}
2.拦截业务实现
@Slf4j
public class PermissionInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
log.info("preHandle");
//请求Controller中的方法名
HandlerMethod handlerMethod = (HandlerMethod)handler;
//请求的方法名
String methodName = handlerMethod.getMethod().getName();
//请求方法所在类的类名
String className = handlerMethod.getBean().getClass().getSimpleName();
//解析请求参数
HashMap<Object, Object> hashMap = new HashMap<>();
Map paramMap = request.getParameterMap();
Iterator it = paramMap.entrySet().iterator();
while (it.hasNext()){
Map.Entry entry = (Map.Entry)it.next();
String mapKey = (String)entry.getKey();
String mapValue = StringUtils.EMPTY;
// entry.getValue()里面的value返回的是一个String[]
Object obj = entry.getValue();
if(obj instanceof String[]){
String[] strs = (String[])obj;
mapValue = Arrays.toString(strs);
}
hashMap.put(mapKey,mapValue);
}
log.info("request parameters : {}",hashMap);
if(StringUtils.equals(className,"UserController") && StringUtils.equals(methodName,"login")){
log.info("权限拦截器拦截到请求,className:{},methodName:{}",className,methodName);
return true;
}
log.info("权限拦截器拦截到请求,className:{},methodName:{},param:{}",className,methodName, hashMap.toString());
User user = null;
//获取登录时写入的cookies
String loginToken=null;
Cookie[] cookies = request.getCookies();
if(cookies != null){
for(Cookie cookie : cookies){
if(StringUtils.equals(cookie.getName(),"sso-cookies")){
loginToken= cookie.getValue();
}
}
}
//从redis中取登录的用户信息
if(StringUtils.isNotEmpty(loginToken)){
Jedis jedis = new Jedis("localhost");
String userJson = jedis.get(loginToken);
user =JSONObject.parseObject(userJson,User.class);
}
//假设该登录用户的角色 admin
String userRole="admin";
if(user == null || (!StringUtils.equals(userRole, "admin"))){
// 设置编码/返回值类型
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json;charset=UTF-8");
PrintWriter out = response.getWriter();
if(user == null){
out.print("拦截器拦截,未登录!");
}else{
out.print("拦截器拦截,无权限!");
}
out.flush();
out.close();
//返回false.不执行controller里的方法
return false;
}
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
log.info("postHandle");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
log.info("afterCompletion");
}
}
3.访问登录方法
1.request参数的map,里面的value返回的是一个String[]
2.cookies写入浏览器
3.用户信息存入redis
4.获取登录用户信息
@RequestMapping(value = "getUserInfo",method = RequestMethod.GET)
@ResponseBody
public String getUserInfo(String username, String password, HttpServletRequest request){
//获取cookie
String loginToken=null;
Cookie[] cookies = request.getCookies();
if(cookies != null){
for(Cookie cookie : cookies){
if(StringUtils.equals(cookie.getName(),"sso-cookies")){
loginToken= cookie.getValue();
}
}
}
//redis中取用户信息
if(StringUtils.isNotEmpty(loginToken)){
Jedis jedis = new Jedis("localhost");
String userJson = jedis.get(loginToken);
return JSONObject.parseObject(userJson).toJSONString();
}
return null;
}
1.已登录且String userRole="admin";
2.未登录
3.已登录且String userRole="product";
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/137152.html