Spring MVC之拦截器的实现与非法请求拦截处理的实现

生活中,最使人疲惫的往往不是道路的遥远,而是心中的郁闷;最使人痛苦的往往不是生活的不幸,而是希望的破灭;最使人颓废的往往不是前途的坎坷,而是自信的丧失;最使人绝望的往往不是挫折的打击,而是心灵的死亡。所以我们要有自己的梦想,让梦想的星光指引着我们走出落漠,走出惆怅,带着我们走进自己的理想。

导读:本篇文章讲解 Spring MVC之拦截器的实现与非法请求拦截处理的实现,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

一、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

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!