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 继承实现方法
Aug 26 Javascript
js实现点击切换TAB标签实例
Aug 21 Javascript
jQuery div拖拽用法实例
Jan 14 Javascript
简单讲解jQuery中的子元素过滤选择器
Apr 18 Javascript
jQuery中选择器的基础使用教程
May 23 Javascript
浅谈JavaScript for循环 闭包
Jun 22 Javascript
bootstrap flask登录页面编写实例
Nov 01 Javascript
jquery Ajax 全局调用封装实例详解
Jan 16 Javascript
BootStrap的双日历时间控件使用
Jul 25 Javascript
简单实现js进度条加载效果
Mar 25 Javascript
Vue CLI3 开启gzip压缩文件的方式
Sep 30 Javascript
node.js 基于cheerio的爬虫工具的实现(需要登录权限的爬虫工具)
Apr 10 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下网站防IP攻击代码,超级实用
2010/10/24 PHP
PHP中去掉字符串首尾空格的方法
2012/05/19 PHP
php字符串截取函数mb_substr用法实例分析
2019/06/25 PHP
提高网站性能之 如何对待JavaScript
2009/10/31 Javascript
10个实用的脚本代码工具
2010/05/04 Javascript
jquery ui dialog ie8出现滚动条的解决方法
2010/12/06 Javascript
javascript-简单的计算器实现步骤分解(附图)
2013/05/30 Javascript
js如何获取兄弟、父类等节点
2014/01/06 Javascript
JavaScript每天定时更换皮肤样式的方法
2015/07/01 Javascript
jQuery常用知识点总结以及平时封装常用函数
2016/02/23 Javascript
window.close(); 关闭浏览器窗口js代码的总结介绍
2016/07/14 Javascript
js中用cssText设置css样式的简单方法
2016/09/19 Javascript
微信 java 实现js-sdk 图片上传下载完整流程
2016/10/21 Javascript
vue router路由嵌套不显示问题的解决方法
2017/06/17 Javascript
详解JavaScript修改注册表的方法
2020/01/05 Javascript
js实现简单音乐播放器
2020/06/30 Javascript
jQuery 添加元素和删除元素的方法
2020/07/15 jQuery
Echarts.js无法引入问题解决方案
2020/10/30 Javascript
JS中循环遍历数组的四种方式总结
2021/01/23 Javascript
Python随机生成彩票号码的方法
2015/03/05 Python
在Windows系统上搭建Nginx+Python+MySQL环境的教程
2015/12/25 Python
python中学习K-Means和图片压缩
2017/11/20 Python
Python实现的插入排序算法原理与用法实例分析
2017/11/22 Python
python实现音乐下载的统计
2018/06/20 Python
Python用字典构建多级菜单功能
2019/07/11 Python
python threading和multiprocessing模块基本用法实例分析
2019/07/25 Python
详解使用Python下载文件的几种方法
2019/10/13 Python
Django 用户登陆访问限制实例 @login_required
2020/05/13 Python
Python Selenium异常处理的实例分析
2021/02/28 Python
《金孔雀轻轻跳》教学反思
2014/04/20 职场文书
公司法定代表人授权委托书
2014/09/29 职场文书
公安机关党的群众路线教育实践活动剖析材料
2014/10/10 职场文书
2014年综合治理工作总结
2014/11/20 职场文书
开会通知
2015/04/20 职场文书
Go 在 MongoDB 中常用查询与修改的操作
2021/05/07 Golang
Mysql 一主多从的部署
2022/05/20 MySQL