在网页中,某些界面一般需要经过登录后才能进行访问,未登录需要跳转到登录界面登录或注册后才能进行访问,因此,我们需要类似于javaweb中的过滤器一样的功能来解决这个问题。
在进入正式话题之前,请允许介绍一个我个人比较陌生的东西(本人小白)--Authorization:
这个东西其实就是在浏览器中用于验证身份的,和session的作用相同,但是也存在区别,区别在于当访问跨域请求的时候,session经常会失效 所以使用了token来验证用户身份,发送给后台的session会是一个新的session ,服务器没法通过session来验证你的身份,所以服务器的过滤器(或拦截器)会过滤掉你的请求,让你返回登陆界面重新登录,使用户体验变差,而Authorization里面存放的就是token,就相当于每次发送请求的时候,拦截器都会拦截一次你的请求,把你请求头部的Authorization拿出来,与当前存在服务器上的token做对比如果是同一个,则证明是同一用户,然后拦截器就为你当前的请求放行,继续执行你的请求,如果不是同一个,那么服务器会截断你的请求并发送错误码给前端,让前端验证身份重新登陆。
接下来,我们回归正题。
首先,我们需要创建一个Loginceptor类来实现HandlerInterceptor中的方法,然后从请求头里获取Authorization字段的值(接下来就直接看代码吧,代码中每一步都有注释)
public class Loginceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 从请求头里面获取Authorization字段的值
String authorization=request.getHeader("Authorization");
// 不要写成authorization.isEmpty() ,否则会报空指针错(500)
if(authorization == null){
// 设置响应字符编码
response.setCharacterEncoding("UTF-8");
// 设置响应内容为“json”
response.setContentType("application/json;charset= utf-8");
// 设置提示信息
response.getWriter().write("权限不足 ,请登录");
return false;
}
//从回话中获取Authorization字段对应的值
HttpSession session=request.getSession();
Object obj=session.getAttribute("Authorization");
if(ObjectUtils.isEmpty(obj)){
// 设置响应字符编码
response.setCharacterEncoding("UTF-8");
// 设置响应内容为“json”
response.setContentType("application/json;charset= utf-8");
response.getWriter().write("token已过期");
}
return true;
}
需要注意的是,判断Authorization是否为空,不能使用.isEmpty(),否则就会报空指针错误,如下。
然后,我们需要在配置类中进行配置我们刚刚写好的过滤器:(我的是直接在解析视图的配置器中进行配置的,读者也可以根据自己的代码进行修改,但是一定需要实现WebMvcConfigurer)
@Configuration
public class ViewConfig implements WebMvcConfigurer {
// 配置视图解析器
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/views/"); // 修改为以斜杠开头的相对路径
viewResolver.setSuffix(".jsp");
registry.viewResolver(viewResolver);
}
// 配置拦截器
@Override
public void addInterceptors(InterceptorRegistry registry){
InterceptorRegistration registration= registry.addInterceptor(new Loginceptor());
registration.addPathPatterns("/**").excludePathPatterns("/login", "/register");
}
}
配置好之后,就可以开始写控制器方法了。(这里我写了一个简单的登录模拟)
@RequestMapping(value = "/login", produces = "application/text;charset=utf-8")
@ResponseBody
public String test4(UserinfoOne userinfoOne, HttpSession httpSession, HttpServletRequest request) {
try {
if ("admin".equals(userinfoOne.getUsername()) && "123".equals(userinfoOne.getPassword())) {
UUID uuid = UUID.randomUUID();
httpSession.setAttribute("userinfo", uuid);
return uuid.toString();
}
} catch (Exception e) {
}
return "用户密码或用户名错误";
}
要注意的是produces = "application/text;charset=utf-8"是以Query Params返回的,若要用json返回,请使用produces = "application/json;charset=utf-8",前后端传输格式不一致也是会报错的哦。
结果:
正确输入相关信息:
用户名或密码错误:
当前进入界面不是登录或注册界面,但是需要先进行登录后才能进入:
以上是对该拦截器的结果显示