1、创建拦截器LoginInterceptor并实现HandlerInterceptor
@Component的作用
1、@component (把普通pojo实例化到spring容器中,相当于配置文件中的<bean id="" class=""/>) 2、@Component泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。
package com.sgcc.epri.basis.config;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Component
public class LoginInterceptor implements HandlerInterceptor {
/**
* 预处理回调方法,实现处理器的预处理
* 返回值:true表示继续流程;false表示流程中断,不会继续调用其他的拦截器或处理器
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
System.out.println("开始拦截.........");
//业务代码
return false;
}
/**
* 后处理回调方法,实现处理器(controller)的后处理,但在渲染视图之前
* 此时我们可以通过modelAndView对模型数据进行处理或对视图进行处理
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
// TODO Auto-generated method stub
}
/**
* 整个请求处理完毕回调方法,即在视图渲染完毕时回调,
* 如性能监控中我们可以在此记录结束时间并输出消耗时间,
* 还可以进行一些资源清理,类似于try-catch-finally中的finally,
* 但仅调用处理器执行链中
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
// TODO Auto-generated method stub
}
}
2、创建配置类,引入拦截器
@Configuration的作用
从Spring3.0,@Configuration用于定义配置类,可替换xml配置文件,被注解的类内部包含有一个或多个被@Bean注解的方法,这些方法将会被AnnotationConfigApplicationContext或AnnotationConfigWebApplicationContext类进行扫描,并用于构建bean定义,初始化Spring容器。
package com.sgcc.epri.basis.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
@Configuration
public class MvcInterceptorConfig extends WebMvcConfigurationSupport {
@Autowired
private LoginInterceptor loginInterceptor;
@Override
protected void addInterceptors(InterceptorRegistry registry) {
// 多个拦截器组成一个拦截器链
// addPathPatterns 用于添加拦截规则,/**表示拦截所有请求
// excludePathPatterns 用户排除拦截
registry.addInterceptor(loginInterceptor).addPathPatterns("/**")
.excludePathPatterns("/demo","/test");
super.addInterceptors(registry);
}
}
registry.addInterceptor(loginInterceptor).addPathPatterns("/**").excludePathPatterns("/demo","/test");
它的意思是拦截所有请求,但是放过/demo,/test两个请求
但是我们不会直接把放行的方法写到这里,每次修改代码的操作很冗余也不规范。
3、将不拦截方法写入到配置文件里
application.yml配置放行地址
# 权限校验url白名单,不用登录和授权也能访问的后端接口路径
# (多个使用逗号分隔) 换行请以“\”结尾
permitted-url: "/demo,\
/test"
在配置类里获取这个配置的内容
@Value("${permitted-url}")
private String permittedUrl;
注释之前代码改为一下内容
List<String> permittedUrls =new ArrayList<String>() ;
for(String permitted :permittedUrl.split(",") ) {
permittedUrls.add(permitted) ;
}
registry.addInterceptor(loginInterceptor).addPathPatterns("/**").excludePathPatterns(permittedUrls);
全代码如下
package com.sgcc.epri.basis.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import java.util.ArrayList;
import java.util.List;
@Configuration
public class MvcInterceptorConfig extends WebMvcConfigurationSupport {
@Autowired
private LoginInterceptor loginInterceptor;
@Value("${permitted-url}")
private String permittedUrl;
@Override
protected void addInterceptors(InterceptorRegistry registry) {
// 多个拦截器组成一个拦截器链
// addPathPatterns 用于添加拦截规则,/**表示拦截所有请求
// excludePathPatterns 用户排除拦截
/*registry.addInterceptor(loginInterceptor).addPathPatterns("/**")
.excludePathPatterns("/demo","/test");
super.addInterceptors(registry);*/
// 读取配置文件的放行方法
List<String> permittedUrls =new ArrayList<String>() ;
for(String permitted :permittedUrl.split(",") ) {
permittedUrls.add(permitted) ;
}
registry.addInterceptor(loginInterceptor).addPathPatterns("/**").excludePathPatterns(permittedUrls);
}
}
4、测试
测试一下,先随便访问一个需要拦截的方法
拦截住了,并且没有执行下面的方法,控制台输出了拦截日志
我们再访问一下放行的方法
访问成功,测试结束,但是直接放行的方法注定只是极小数,主要的还是拦截以后的验证
5、拦截器的自定义业务验证功能
在上面我们的LoginInterceptor类里只是写了个输出并且全部返回了false,这里面的代码就需要我们根据不同的需求自己定义,我的需求就是在拦截的方法中会带着手机号,我们拿手机号匹配用户信息,匹配到了就展示此用户的业务数据,如果没有或者没带手机号就展示示例数据,所以在我的需求里只会有放行,但是也可以设想为有匹配数据就是验证成功,如果没有就验证失败,返回错误信息,这个就看各自的业务需求。
/**
* 预处理回调方法,实现处理器的预处理
* 返回值:true表示继续流程;false表示流程中断,不会继续调用其他的拦截器或处理器
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
// 获取登陆手机号
String loginPhone = request.getParameter("loginPhone");
// 判断是否传递了手机号
if (loginPhone != null && !"".equals(loginPhone)){
String consId = demoService.getConsId();
request.getSession().setAttribute("consId",consId);
return true;
}else{
request.getSession().setAttribute("consId","0");
return true;
}
}
现在我们都设置了true再试试之前被拦截的方法是否能通过,到这里拦截器就配好了。
可能还有许多验证用户是否过期,没有过期就无需拦截,或者访问的时候自动更新活跃状态,这些可能还需要多验证一下session和缓存,看业务需求了,下面是我们之前的拦截请求,包含了pc和小程序的拦截,由于pc登陆时已经存储了session所以主要是给小程序做复核token使用,不完整的地方是未验证企业id是否存在,但是我们的需求企业id是平台给的,所以是获取的企业id是已经存在的所以直接返回true,如果是单独系统的话需要再验证一下的
response.setContentType("text/plain;charset=UTF-8");
response.setCharacterEncoding("utf-8");
JSONObject json = JSONObject.parseObject(String.valueOf(request.getSession().getAttribute("consInfo")));// 获取用户信息
if (json != null) {// 验证企业id是否存在
return true;
}else {
String token = request.getParameter("token");// 获取传递的token
System.err.println(token);
if (token!=null&&!"".equals(token)) {// 验证是否传递token
request.getSession().setAttribute("token", token);
System.err.println(request.getSession().getAttribute("token"));
ResponseParam responseParam = userInterface.login(request,response);
if ("200".equals(String.valueOf(responseParam.getStatus()))) {
return true;
}else {
JSONObject data = new JSONObject();
data.put("status", 500);
data.put("message", "用户失效");
data.put("sessionExpired", true);
response.getWriter().write(data.toString());
return false;
}
}
JSONObject data = new JSONObject();
data.put("status", 500);
data.put("message", "用户失效");
data.put("sessionExpired", true);
response.getWriter().write(data.toString());
return false;
}