拦截器:是一种动态拦截方法调用的机制,类似于过滤器。但在过滤器之后执行。拦截器是属于springmvc的,在Spring中动态拦截控制器中方法的执行。
作用:在指定的控制器中方法调用前后执行预先设定的代码,完成功能的增强。
拦截器的使用步骤大致可以分为
第一步:定义拦截器
定义一个拦截器类实现HandlerInterceptor接口实现其中方法并通过**@Component**注解注册成组件,确保可以被Spring扫描到。经常使用的是preHandle()方法,在请求到达控制器之前进行验证,可用于权限验证,登录验证等等
在preHandle()方法中return true代表放行,false代表不放行
@Component
public class RegisterInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("请求到达控制器器之前执行");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("控制器处理请求之后执行");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("在视图渲染之后执行");
}
}
第二步:注册拦截器
定义一个配置类实现WebMvcConfigurer接口,并重写addInterceptors()方法
@Configuration
public class WebDemoConfig implements WebMvcConfigurer {
@Autowired
private RegisterInterceptor registerInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(registerInterceptor)//注册拦截器这里面需要一个拦截器对象
.excludePathPatterns()//这个方法用来写不拦截的请求路径
.addPathPatterns();//这个方法里面写需要拦截的请求路径
}
excludePathPatterns()和addPathPatterns()这两个方法里面的参数可以是不定长字符串还可以是List集合对象,如下面这样:
//不定长字符串
excludePathPatterns("/user/login","/user/register")
//List<String>集合
List<String> partterns=new ArrayList<>();
partterns.add("/user/login");
partterns.add("/user/register");
addPathPatterns(partterns);
这两种都是可以的,我们可以按住ctrl点击excludePathPatterns()或addPathPatterns()去看看参数都可以怎么写?
另一个方法可以传递的参数与这个一致。
请求路径:
这样就完成了一个拦截器的简单注册和使用
接下来是拦截器用于登录验证:
第一步:先根据上面完成拦截器的注册和使用。
第二步:JWT令牌的使用:
1.先导入依赖坐标
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>4.4.0</version>
</dependency>
第二步token的生成和解析
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import java.util.Date;
import java.util.Map;
import static com.auth0.jwt.algorithms.Algorithm.HMAC256;
public class JWTUtil {
private static final String KEY="demo";//密钥
public static String getToken(Map<String,Object> map){
// 生成jwt
return JWT.create()
.withClaim("claim",map)//添加载荷
.withExpiresAt(new Date(System.currentTimeMillis()+1000*60*60*12))//添加过期时间
.sign(Algorithm.HMAC256(KEY));//生成时使用算法
}
// 解析JWT令牌
public static Map<String,Object> parseToken(String token){
return JWT.require(HMAC256(KEY))//解析时使用算法
.build()
.verify(token)
.getClaim("claim")
.asMap();
}
}
注意:在解析token和生成token的时候使用的算法和密钥必须一致,失效时间是按毫秒算的。
第三步:登录时生成token,拦截器里验证token
当用户登录成功的时候添加token,并将token发送到前端
Map<String,Object> claims = new HashMap<>();
claims.put("sno",user2.getSno());
String token = JWTUtil.getToken(claims);
return new Result(Code.LOGIN_OK,token,"登录成功");
在拦截器里面在请求发送到控制器前进行token的验证,如token在前端被存到请求头的Authorization,看能否从toke里面获取到需要的数据,获取到则放行,否则不放行
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 令牌验证
String token=request.getHeader("Authorization");
try {
Map<String, Object> map = JWTUtil.parseToken(token);
String sno = (String) map.get("sno");
System.out.println(sno);
return true;
// 成功放行
}catch (Exception e){
response.setStatus(401);
return false;
}
}
下一篇:记录一下过滤器的简单使用