项目登录流程如下

用户进入前端登录界面,输入账号密码等,输入完成之后前端发送请求到后端(拦截器不会拦截登录请求),后端验证账号密码等成功之后生成Token并存储到数据库,数据库中包含该Token过期时间,然后返回生成的Token到前端。

前端收到Token,表示登录成功,把这个Token存储到浏览器Cookie中。然后跳转到用户中心页面,用户中心页面从浏览器Cookie中扣出Token,跟随请求用户数据接口一起带到后端。

后端通过拦截器拦截到这个请求,去判断这个Token是否有效,有效就放过去做他该做的事情,无效就抛出异常。

跨域配置

先说一下这个前后分离的项目,已经配置过跨域这些问题。我这里后端配置的方式如下:

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("POST", "GET", "PUT", "OPTIONS", "DELETE")
.maxAge(3600)
.allowCredentials(true);
}
}

前端每次发送请求也都有在ajax里面设置xhrFields:{withCredentials: true}属性。

拦截器代码

@Component
public class LoginInterceptor extends HandlerInterceptorAdapter { @Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { //从header中获取token
String token = request.getHeader("token");
//token为空
if(StringUtils.isBlank(token)){
throw new XjxccException("登录信息不存在,请重新登录", 601);
} //查询token信息
TbUserToken tbToken = tokenService.queryByToken(token);
if(tbToken == null || tbToken.getExpireTime().getTime() < System.currentTimeMillis()){
throw new XjxccException("登录信息已失效,请重新登录", 602);
} return true;
}
}

问题

现在的情况是,如果Token正常就没问题,如果Token失效了,前端发送的请求就会提示跨域问题,可是该项目已经配置过跨域问题了。既然又提示跨域问题,那我们修改代码如下:

@Component
public class LoginInterceptor extends HandlerInterceptorAdapter { @Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { //从header中获取token
String token = request.getHeader("token");
//token为空
if(StringUtils.isBlank(token)){
setCorsMappings(request, response);
throw new XjxccException("登录信息不存在,请重新登录", 601);
} //查询token信息
TbUserToken tbToken = tokenService.queryByToken(token);
if(tbToken == null || tbToken.getExpireTime().getTime() < System.currentTimeMillis()){
setCorsMappings(request, response);
throw new XjxccException("登录信息已失效,请重新登录", 602);
} return true;
} private void setCorsMappings(HttpServletRequest request, HttpServletResponse response){
String origin = request.getHeader("Origin");
response.setHeader("Access-Control-Allow-Origin", origin);
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "x-requested-with,Authorization");
response.setHeader("Access-Control-Allow-Credentials", "true");
}
}

这样修改之后,如果Token无效,前端发送的请求就不会提示跨域问题。而且也可以在ajax的success方法中根据错误码(601/602)做不同的判断,代码如下:

$.ajax({
type: "POST",
url: "请求用户信息接口",
xhrFields:{withCredentials: true},
headers: {token: vm.token},
contentType: 'application/json',
success: function(result){
//如果是token无效
if(result.code == 601 || result.code == 602){
layer.msg(result.msg + "<br>稍后为您自动跳转到登录页面");
window.setInterval(function (){
window.location.href = "user-login.html";
},1500);
}else if(判断用户信息接口返回的code){
...
}
},error: function(){
layer.msg("系统异常");
}
});

下面附上上面代码中的XjxccException类:

/**
* <p>Title: XjxccException.java</p>
* <p>Description: 自定义异常</p>
* <p>Copyright: Copyright (c) 2018</p>
*
* @email lgqxjxcc@163.com
* @author liguoqing
* @date 2018年10月21日
* @version 1.0
*/
public class XjxccException extends RuntimeException {
private static final long serialVersionUID = 1L; private String msg;
private int code = 500; public XjxccException(String msg) {
super(msg);
this.msg = msg;
}
public XjxccException(String msg, Throwable e) {
super(msg, e);
this.msg = msg;
}
public XjxccException(String msg, int code) {
super(msg);
this.msg = msg;
this.code = code;
}
public XjxccException(String msg, int code, Throwable e) {
super(msg, e);
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
}

Springboot前后端分离中,后端拦截器拦截后,前端没有对应的返回码可以判断的更多相关文章

  1. 前后端分离中的无痛刷新token机制

    今天我们来说一说前后端分离中的无痛刷新token机制 博主先来分享一波福利,最近挖到的宝藏,刚开始学Java的同学看 https://www.bilibili.com/video/BV1Rx41187 ...

  2. nodejs--JWT 在前后端分离中的应用与实践

    nodejs--JWT 在前后端分离中的应用与实践 http://www.cnblogs.com/lidongyue/p/5269695.html

  3. Springboot通过拦截器拦截请求信息收集到日志

    1.需求 最近在工作中遇到的一个需求,将请求中的客户端类型.操作系统类型.ip.port.请求方式.URI以及请求参数值收集到日志中,网上找资料说用拦截器拦截所有请求然后收集信息,于是就开始了操作: ...

  4. Struts2 拦截器—拦截action

    对于拦截器的基本使用这里我就懒得打字了,我这里就讲下如何用 Struts2 拦截器 拦截action.这是我个人的想法,如果有什么不对的,或者你们有什么更好的方法.请多多留言! 拦截器的默认拦截的方法 ...

  5. 防止SpringMVC拦截器拦截js等静态资源文件

    SpringMVC提供<mvc:resources>来设置静态资源,但是增加该设置如果采用通配符的方式增加拦截器的话仍然会被拦截器拦截,可采用如下方案进行解决: 方案一.拦截器中增加针对静 ...

  6. 使用 paramsPrepareParamsStack 拦截器栈后的运行流程

    2. 使用 paramsPrepareParamsStack 拦截器栈后的运行流程 1). paramsPrepareParamsStack 和 defaultStack 一样都是拦截器栈. 而 st ...

  7. Vue+SpringBoot前后端分离中的跨域问题

    在前后端分离开发中,需要前端调用后端api并进行内容显示,如果前后端开发都在一台主机上,则会由于浏览器的同源策略限制,出现跨域问题(协议.域名.端口号不同等),导致不能正常调用api接口,给开发带来不 ...

  8. SpringBoot + Vue前后端分离图片上传到本地并前端访问图片

    同理应该可用于其他文件 图片上传 application.yml 配置相关常量 prop: upload-folder: E:/test/ # 配置SpringMVC文件上传限制,默认1M.注意MB要 ...

  9. 前后端分离中,Gulp实现头尾等公共页面的复用

    前言 通常我们所做的一些页面,我们可以从设计图里面看出有一些地方是相同的.例如:头部,底部,侧边栏等等.如果前后端分离时,制作静态页面的同学,对于这些重复的部分只能够通过复制粘贴到新的页面来,如果页面 ...

随机推荐

  1. XV6源代码阅读-中断与系统调用

    Exercise1 源代码阅读 1.启动部分: bootasm.S bootmain.c 和xv6初始化模块:main.c bootasm.S 由16位和32位汇编混合编写成的XV6引导加载器.boo ...

  2. 程序员如何 10 分钟用 Python 画出蒙娜丽莎?

    之前看到过很多头条,说哪国某人坚持了多少年自学使用excel画画,效果十分惊艳.对于他们的耐心我十分敬佩. 但是作为一个程序员,自然也得挑战一下自己. 这种需求,我们十分钟就可以完成! 基本思路   ...

  3. redis3.2.2 集群

    http://blog.csdn.net/imxiangzi/article/details/52431729 http://www.2cto.com/kf/201701/586689.html me ...

  4. R apply()函数

    创建一个列表变量,它的第一个元素包含所有从0到9的平方数,第二个元素为10到19之内的所有平方数,依此类推,最后一个元素为90到99之内的平方数.没有平方数的元素也应该被包含在内! 学习网友的解题思路 ...

  5. [洛谷Luogu]P1141 01迷宫[联通块 并查集]

    题目链接 大致题意 相邻格子不同为连通,计算每个点所在的连通块大小. 想法 我采用了并查集的做法. 开一个辅助数组记录连通块大小,每次合并的时候更新父亲节点的大小即可. 一个点先与它上面的点判定,若判 ...

  6. NASA的10条编码规则

    关于NASA的10条编程规则,他们曾表示:这些规则的作用就像汽车上的安全带:最初,它们可能有点不舒服,但过了一会儿,它们的使用就变成了第二天性,而没有使用它们就变得不可想象. Gerard J. Ho ...

  7. PHP笔记02

    PHP数组 能够在一个变量存储多个值 取值用下标,下标从0开始计算 好处:在处理物品清单等大量相同属性的变量内容时可以集中存取 <?php $arr=array("like" ...

  8. 吴裕雄--天生自然C++语言学习笔记:C++ 日期 & 时间

    C++ 标准库没有提供所谓的日期类型.C++ 继承了 C 语言用于日期和时间操作的结构和函数.为了使用日期和时间相关的函数和结构,需要在 C++ 程序中引用 <ctime> 头文件. 有四 ...

  9. 利用标签导出Word文档

    1 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; us ...

  10. ROS2学习日志:QoS学习日志

    QoS学习日志 参考:ROS2API 及 https://index.ros.org/doc/ros2/Concepts/About-Quality-of-Service-Settings 1.概述 ...