vue+springboot前后端分离实现单点登录跨域问题解决方法


Posted in Javascript onJanuary 30, 2018

最近在做一个后台管理系统,前端是用时下火热的vue.js,后台是基于springboot的。因为后台系统没有登录功能,但是公司要求统一登录,登录认证统一使用.net项目组的认证系统。那就意味着做单点登录咯,至于不知道什么是单点登录的同学,建议去找一下万能的度娘。

刚接到这个需求的时候,老夫心里便不屑的认为:区区登录何足挂齿,但是,开发的过程狠狠的打了我一巴掌(火辣辣的一巴掌)。。。,所以这次必须得好好记录一下这次教训,以免以后再踩这样的坑。

我面临的第一个问题是跨域,浏览器控制台直接报CORS,以我多年开发经验,我果断在后台配置了跨域配置,代码如下:

@Configuration
public class CorsConfiguration {
 @Bean
 public WebMvcConfigurer corsConfigurer() {
  return new WebMvcConfigurerAdapter() {
   @Override
   public void addCorsMappings(CorsRegistry registry) {
    registry.addMapping("/**")
      .allowedHeaders("*")
      .allowedMethods("*")
      .allowedOrigins("*");
   }
  };
 }
}

这个配置就是允许所有mapping,所有请求头,所有请求方法,所有源。改好配置之后我果断重启项目,看效果,结果发现根本没法重定向跳转到单点登录页面,看浏览器报错是跨域导致的,我先上我登录拦截器的代码

public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
 //用户已经登录
 if (request.getSession().getAttribute("user") != null) {
  return true;
 }
 //从单点登录返回之后的状态,本系统还不处于登录状态
 //根据code值去获取access_token,然后再根据access_token去获取用户信息,并将用户信息存到session中
 String state = request.getParameter("state");
 String uri = getUri(request);
 if (isLoginFromSSO(state)) {
  String code = request.getParameter("code");
  Object cacheUrl = request.getSession().getAttribute(state);
  if (cacheUrl == null) {
   response.sendRedirect(uri);
   return false;
  }
  HttpUtil client = new HttpUtil();
  StringBuffer sb = new StringBuffer();
  sb.append("code=").append(code)
    .append("&grant_type=").append("authorization_code")
    .append("&client_id=").append(SSOAuth.ClientID)
    .append("&client_secret=").append(SSOAuth.ClientSecret)
    .append("&redirect_uri=").append(URLEncoder.encode((String) cacheUrl));
  String resp = client.post(SSOAuth.AccessTokenUrl, sb.toString());
  Map<String, String> map = new Gson().fromJson(resp, Map.class);
  //根据access_token去获取用户信息
  String accessToken = map.get("access_token");
  HttpUtil http = new HttpUtil();
  http.addHeader("Authorization", "Bearer " + accessToken);
  String encrypt = http.get(SSOAuth.UserUrl);
  String userinfo = decryptUserInfo(encrypt);
  //封装成user对象
  User user = new Gson().fromJson(userinfo, User.class);
  request.getSession().setAttribute("user", user);
  return true;
 }
 //跳转到单点登录界面
 state = Const._SSO_LOGIN + Const.UNDERLINE + RandomUtil.getUUID();
 request.getSession().setAttribute(state, uri);
 String redirectUrl = buildAuthCodeUrl(uri, state);
 response.sendRedirect(redirectUrl);
 return false;
}

后面把前端vue请求后台的登录接口方式直接用

window.location.href=this.$api.config.baseUrl+"/system/user/login"

之后前端访问系统,可以直接跳转到单点登录页面。但是当我输完账号和密码点击登录后回跳到系统,发现所有的请求数据接口都无法正常访问,debug发现所有的请求都没带用户信息,被拦截器识别为未登录,所有请求无法通过。

为什么我明明登录了呀,拦截器也设置了用户信息到session啊,怎么cookies那就没了呢?再次发起请求,发现每次请求的JsessionId都不一样,查了很多资料,发现是需要在前端加一个允许带认证信息的配置

axios.defaults.withCredentials=true;

后台也需要做一个相应的配置allowCredentials(true);

@Bean
public WebMvcConfigurer corsConfigurer() {
 return new WebMvcConfigurerAdapter() {
  @Override
  public void addCorsMappings(CorsRegistry registry) {
   registry.addMapping("/**")
     .allowedHeaders("*")
     .allowedMethods("*")
     .allowedOrigins("*").allowCredentials(true);
  }
 };
}

加完这个配置之后,重新执行一遍操作流程,发现登录之后能正常跳转到系统,页面数据也展示正常。

正当我以为大功告成的时候,突然点到一个页面又无法正常显示数据,好纳闷啊,赶紧F12,发现一个之前没见过的请求方式,OPTIONS请求,原来这个请求方式明明是POST呀,怎么就变成了OPTIONS了呢?于是我有点了其他几个POST的请求,发现都变成了OPTIONS请求,一脸懵逼的我赶紧查了一下OPTIONS请求的资料,网上说OPTIONS请求叫做“预检查请求”,就是在你的正式请求执行之前,浏览器会先发起预检查请求,预检查请求通过了,才能执行正式请求。看完恍然大悟,原来OPTIONS被拦截了,所以没法再执行我的POST的请求啊,那我直接让预检查请求通过就好了。只要在拦截器中加一个这个判断就好了

//option预检查,直接通过请求
if ("OPTIONS".equals(request.getMethod())){
 return true;
}

这样拦截器发现请求是预检查请求就直接通过,就可以执行接下来的POST的请求了。

总结

以上所述是小编给大家介绍的vue+springboot前后端分离实现单点登录跨域问题解决方法,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
JavaScript性能陷阱小结(附实例说明)
Dec 28 Javascript
Dom 结点创建 基础知识
Oct 01 Javascript
Jquery实现鼠标移上弹出提示框、移出消失思路及代码
May 19 Javascript
jQuery 3.0中存在问题及解决办法
Jul 15 Javascript
JQuery实现DIV其他动画效果的简单实例
Sep 18 Javascript
微信开发 js实现tabs选项卡效果
Oct 28 Javascript
jQuery Validate表单验证插件的基本使用方法及功能拓展
Jan 04 Javascript
浅谈在vue中使用mint-ui swipe遇到的问题
Sep 27 Javascript
JavaScript数据结构与算法之二叉树实现查找最小值、最大值、给定值算法示例
Mar 01 Javascript
小程序识别身份证,银行卡,营业执照,驾照的实现
Nov 05 Javascript
js中调用微信的扫描二维码功能的实现代码
Apr 11 Javascript
webpack+express实现文件精确缓存的示例代码
Jun 11 Javascript
vue scroller返回页面记住滚动位置的实例代码
Jan 29 #Javascript
浅析vue深复制
Jan 29 #Javascript
浅析从vue源码看观察者模式
Jan 29 #Javascript
实例学习JavaScript读取和写入cookie
Jan 29 #Javascript
微信小程序之多文件下载的简单封装示例
Jan 29 #Javascript
JS中Object对象的原型概念基础
Jan 29 #Javascript
vue.js实现只弹一次弹框
Jan 29 #Javascript
You might like
《PHP编程最快明白》第三讲:php数组
2010/11/01 PHP
解决Laravel 使用insert插入数据,字段created_at为0000的问题
2019/10/11 PHP
浅谈Laravel中的三种中间件的作用
2019/10/13 PHP
jQuery toggle()设置CSS样式
2009/11/05 Javascript
AJAX使用了UpdatePanel后无法使用alert弹出脚本
2010/04/02 Javascript
javascript 事件处理程序介绍
2012/06/27 Javascript
javascript 图片裁剪技巧解读
2012/11/15 Javascript
JavaScript在XHTML中的用法详解
2013/04/11 Javascript
js判断IE浏览器版本过低示例代码
2013/11/22 Javascript
教你如何使用node.js制作代理服务器
2014/11/26 Javascript
跟我学习javascript解决异步编程异常方案
2015/11/23 Javascript
jQuery使用$.ajax进行异步刷新的方法(附demo下载)
2015/12/04 Javascript
JavaScript随机打乱数组顺序之随机洗牌算法
2016/08/02 Javascript
AngularJS  自定义指令详解及实例代码
2016/09/14 Javascript
深入理解vue-class-component源码阅读
2019/02/18 Javascript
vue+elementui 对话框取消 表单验证重置示例
2019/10/29 Javascript
Jquery Datatables的使用详解
2020/01/30 jQuery
在vue中使用Echarts利用watch做动态数据渲染操作
2020/07/20 Javascript
[01:52]2020年DOTA2 TI10夏季活动预告片
2020/07/15 DOTA
Python+Pika+RabbitMQ环境部署及实现工作队列的实例教程
2016/06/29 Python
Python通过future处理并发问题
2017/10/17 Python
pytorch + visdom 处理简单分类问题的示例
2018/06/04 Python
Python之list对应元素求和的方法
2018/06/28 Python
Python代码太长换行的实现
2019/07/05 Python
Html5上传图片 移动端、PC端通用代码
2016/06/08 HTML / CSS
非洲NO.1网上商店:Jumia肯尼亚
2016/08/18 全球购物
英国最大的奢侈珠宝和手表网站:C W Sellors
2017/02/10 全球购物
LG西班牙网上商店:Tienda LG Online Es
2019/07/30 全球购物
关爱留守儿童标语
2014/06/18 职场文书
农村党建工作汇报材料
2014/10/27 职场文书
小学教师学习党的群众路线教育实践活动心得体会
2014/10/31 职场文书
优秀教师个人总结
2015/02/11 职场文书
2015年高校就业工作总结
2015/05/04 职场文书
MYSQL主从数据库同步备份配置的方法
2021/05/26 MySQL
浅谈Python数学建模之线性规划
2021/06/23 Python
Pyqt5将多个类组合在一个界面显示的完整示例
2021/09/04 Python