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";

在这里插入图片描述

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CodeDevMaster

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值