1. 一个网站,有些页面是不需要登录就可以访问的(比如说登录页面),有些页面是需要登录(有jwt即有用户信息)才可以访问的(比如说会员系统页面)
,需要登录后才可以访问的页面有很多,在访问这些页面前,我们可以统一做一些处理,比如判断是否有jwt,没有此退出到登录页面,有jwt后查询出用户信息,去数据库查是否存在这个用户信息,没有也不能访问等等。
拦截器涉及到2个类:WebMvcConfigurer(springboot 2.0 取代了WebMvcConfigurerAdapter )
HandlerInterceptor
下面代码在 jwt (一)简单demo基础上进行修改:
接着上篇jwt (一)简单demo
下面案例要取得的结果,进入登陆功能不需要拦截,进入会员系统要进行拦截,jwt 符合则进入会员系统页面
代码很少,都是截图。
在controller 里面添加
//会员系统首页 @RequestMapping("/memberCenter") public String memberCenter(){ return "这里是会员系统首页"; } //会员系统里面的修改密码页面 @RequestMapping("/password") public String password(){ return "这里是会员系统里面的修改密码页面"; }
添加拦截器
import com.example.jwteasydemo.utils.JwtUtil; import io.jsonwebtoken.Claims; import io.jsonwebtoken.ExpiredJwtException; import org.springframework.util.StringUtils; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class MyHandlerInterceptor implements HandlerInterceptor { //在controller调用前执行,这个方法比较常用,返回true则程序继续往下执行。 @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String jwt = request.getHeader("token"); //1.没有token,则没有登录不能访问会员系统 if(StringUtils.isEmpty(jwt)){ response.sendError(401,"没有token,不能访问会员系统,请先登录"); return false; } try { //数据库不存在的用户信息,则不能访问。这里假设数据库会员系统里面只有一个用户,用户名是"abc" Claims claims = JwtUtil.parseTocken(jwt); String username = claims.get("username", String.class); if(!"abc".equals(username)){ response.sendError(402,"此用会员系统里面不存在,不能访问会员系统"); return false; } } catch (ExpiredJwtException e) { response.sendError(403,"jwt 已过期,请重新登录"); return false; } return true; } //在controller 调用后执行 @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { } //在渲染视图后执行 @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { } }
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import java.util.ArrayList; @Configuration public class MyWebMvcConfigurer implements WebMvcConfigurer { @Bean public MyHandlerInterceptor myHandlerInterceptor(){ return new MyHandlerInterceptor(); } //把要拦截的链接加进入来 @Override public void addInterceptors(InterceptorRegistry registry) { ArrayList interceptList = new ArrayList(); interceptList.add("/memberCenter");//1.拦截会员中心 interceptList.add("/password");//1.拦截会员中心修改密码 registry.addInterceptor(myHandlerInterceptor()).addPathPatterns(interceptList); } }
测试:
用postman模拟请求(我测试项目的端口改为8081,默认是8080)
1)直接进入 会员中心 和修改秘密 页面(预期结果:无token 被拦截)
http://localhost:8081/memberCenter
2)用户登录后取得jwt(期望结果:没有被拦截,取得jwt)
3)用取得的token 值,去访问会员系统和修改密码的页面(期望结果: 被拦截但是可以访问)
在header 里面放入token的值
拦截器起到了’切面‘的作用,这里访问会员系统和修改密码页面,我们可以进行统一的逻辑处理,对jwt进行的判断,也可以做一些其他判断。起到复用的效果。
但是实际上,我们在真实的项目里面不会直接用这个拦截器,而是用别人封装好的权限框架来控制访问,下篇整合shiro
