vue2 前后端分离项目ajax跨域session问题解决方法


Posted in Javascript onApril 27, 2017

最近学习使用vuejs前后端分离,重构一个已有的后台管理系统,遇到了下面这个问题:

实现跨域请求时,每次ajax请求都是新的session,导致无法获取登录信息,所有的请求都被判定为未登陆。

1、 vuejs ajax跨域请求

最开始使用的是vue-resource,结果发现vue2推荐的是axios,于是改成axios;安装axios

npm install axios -S

安装完成后在main.js中增加一下配置:

import axios from 'axios';
axios.defaults.withCredentials=true;

main.js全部配置如下:

import Vue from 'vue'
import App from './App.vue'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-default/index.css'
import router from './router';
import axios from 'axios';
import './assets/css/main.css'
import './assets/css/color-dark.css'

//开启debug模式
Vue.config.debug = true;
axios.defaults.withCredentials=true;
Vue.prototype.$axios = axios;
Vue.use(ElementUI);

new Vue(
  {
   router,
   el: '#app',
   render: h => h(App)
  }
).$mount('#app')

在XXX.vue文件中具体使用如下:

<template>

 <el-col :span="4" style="background-color: #eef1f6;height:100%;">
    <el-menu default-active="1" class="el-menu-vertical-demo" :unique-opened="uniqueOpened" router
     v-for="menu in menulist" :key="menu.fidStr">
      <template v-if="menu.isleaf === 1">
       <el-menu-item :index="menu.furl">{{menu.fname}}</el-menu-item>
      </template>
      <template v-else>
        <el-submenu :index="menu.fidStr">
         <template slot="title"><i class="el-icon-menu"></i>{{menu.fname}}</template>
         <template v-for="firstLevelChild in menu.children" >
          <template v-if="firstLevelChild.isleaf === 1" >
           <el-menu-item :index="firstLevelChild.furl">{{firstLevelChild.fname}}</el-menu-item>
          </template>
          <template v-else>
            <el-submenu :index="firstLevelChild.fidStr">
              <template slot="title"><i class="el-icon-menu"></i>{{firstLevelChild.fname}}</template>
              <el-menu-item v-for="secondLevelChild in firstLevelChild.children" :index="secondLevelChild.furl">
               {{secondLevelChild.fname}}
              </el-menu-item>
            </el-submenu>
         </template>
         </template>
        </el-submenu>
      </template>
    </el-menu>

  </el-col>

</template>

<script type="text/javascript">

export default {
   data() {
    return {
     uniqueOpened:true,
     menulist:[]
    }
   }   ,
   mounted: function() {
     let self = this;
     this.$axios.post('http://localhost:8080/test/xxx/xxxx', {}, {
       headers: {
        "Content-Type":"application/json;charset=utf-8"
       },
       withCredentials : true
     }).then(function(response) {
       // 这里是处理正确的回调
       let result = response.data.result;
       if (0 == result) {
        self.menulist = response.data.item.menulist;
       } else if (11 == result || 9 == result) {
        self.$router.push('/login');
       } else {
        console.log(response.data);
       }

     }).catch( function(response) {
       // 这里是处理错误的回调
       console.log(response)
     });
   }
 }

</script>

<style scoped>
  .sidebar{
    display: block;
    position: absolute;
    width: 200px;
    left: 0;
    top: 70px;
    bottom:0;
    background: #2E363F;
  }
  .sidebar > ul {
    height:100%;
  }
</style>

在后台项目中的登陆拦截器中设置了,接受跨域访问的header,如下:

public class LoginInterceptor extends HandlerInterceptorAdapter {

  @Override
  public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
      throws Exception {
    
    response.setHeader("Access-Control-Allow-Headers", "X-Requested-With, accept, content-type, xxxx");
    response.setHeader("Access-Control-Allow-Methods", "GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH");
    response.setHeader("Access-Control-Allow-Origin", "*"); 
    
    
    return true;
  }
}

现在可以就可以跨域访问了。

2、登陆session获取

因为是后台管理系统,肯定都需要需要登陆,才能用的, 因此我在登陆时保存了session

//登陆成功
session.setAttribute("user", obj);

我希望其它请求进来时,在拦截器中判断是否登陆了,是否有权限访问这个请求路径

//拦截器中增加,获取session代码
    HttpSession session =request.getSession();
    System.out.println("拦截器中的session的id是====" + session.getId());
    Object obj = session.getAttribute("user");

结果发现,每次ajax跨域访问都是新的session ,每次的sessionID都不一样

在segmentfault上提了一个问题,有人提示需要让ajax请求携带cookie,也就是认证信息,于是在拦截器中,增加了一个需要认证信息的header:

response.setHeader("Access-Control-Allow-Credentials", "true");

然后再次在浏览器中测试,发现浏览器提示,当Access-Control-Allow-Credentials设为true的时候,Access-Control-Allow-Origin不能设为星号,既然不让我设为星号,我就改成前端项目的配置

response.setHeader("Access-Control-Allow-Origin", http://127.0.0.1:8010);

发现每次ajax请求,还是不同的session,打开chrome的network,发现每次请求的请求头中并没有,和我想象的一样携带cookie信息,也就是下面这个header:

Cookie:JSESSIONID=node015f4w1j2kgjk61i7jyyim8lo3u0.node0;

因为我用的axios,所以找到axios的文档链接描述

发现一下内容:

// `timeout` specifies the number of milliseconds before the request times out.
 // If the request takes longer than `timeout`, the request will be aborted.
 timeout: 1000,

 // `withCredentials` indicates whether or not cross-site Access-Control requests
 // should be made using credentials
 withCredentials: false, // default

 // `adapter` allows custom handling of requests which makes testing easier.
 // Return a promise and supply a valid response (see lib/adapters/README.md).
 adapter: function (config) {
  /* ... */
 },

withCredentials默认是false,意思就是不携带cookie信息,那就让它为true,我是全局性配置的,就是main.js中的这句话:

axios.defaults.withCredentials=true;

然后再测试,发现每次ajax请求都是同样的session了(不包含浏览器的options请求)。

3、代理配置

因为不想每个页面里的请求都写http://127.0.0.1:8080,并且我用的是element ui的webpack项目模板,所以就想使用代理(不知道叫这个合适不合适):

devServer: {
  host: '127.0.0.1',
  port: 8010,
  proxy: {
   '/api/': {
    target: 'http://127.0.0.1:8080',
    changeOrigin: true,
    pathRewrite:{
          '/api':'/xxxxxx'
        }
   }
  }

把ajax请求改成下面这个样子:

this.$axios.post('/api/xx/xxx', {}, {
      headers: {
        "Content-Type": "application/json;charset=utf-8"
      }     
    }).then(function(response) {
      // 这里是处理正确的回调     

    }).catch(function(response) {
      // 这里是处理错误的回调
      console.log(response)
    });

网上说都是配置为proxyTable, 用的是http-proxy-middleware这个插件,我装上插件,改成这个,webpack总是报错,说proxyTable是非法的配置,无法识别。

无奈改成了模板自带的proxy,可以使用,为什么可以用,我还不请求,proxyTabel为什么不能用,也没搞明白。有知道的,可以指点一下。

虽然代理配置好了,也能正常请求,结果发现请求的session又不一样了,感觉心好累啊!!!

没办法,只能再看请求头是不是有问题,发现返回header中有session限制的,如下:

set-cookie:JSESSIONID=node0v5dmueoc119rb42b59k5qf3w0.node0;Path=/xxxx

要求cookie只能再/xxxx下也就是项目的根路径下使用,于是我把代理改成:

devServer: {
  host: '127.0.0.1',
  port: 8010,
  proxy: {
   '/xxxx/': {
    target: 'http://127.0.0.1:8080',
    changeOrigin: true
   }
  }

session又恢复正常了,可以用了;不知道为什么配成api映射的形式为什么不能用。

这就是解决这个跨域session问题的过程,希望对大家有点帮助!也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
js parentElement和offsetParent之间的区别
Mar 23 Javascript
select多选 multiple的使用示例
Jun 16 Javascript
js验证真实姓名与身份证号是否匹配
Oct 13 Javascript
浅析JavaScript 调试方法和技巧
Oct 22 Javascript
浅析jQuery Mobile的初始化事件
Dec 03 Javascript
Bootstrap编写导航栏和登陆框
May 30 Javascript
JavaScript中匿名函数的用法及优缺点详解
Jun 01 Javascript
js删除Array数组中指定元素的两种方法
Aug 03 Javascript
JavaScript设计模式之策略模式详解
Jun 09 Javascript
Node.JS在命令行中检查Chrome浏览器是否安装并打开指定网址
May 21 Javascript
javascript设计模式 ? 职责链模式原理与用法实例分析
Apr 16 Javascript
返回上一个url并刷新界面的js代码
Sep 12 Javascript
Webpack中css-loader和less-loader的使用教程
Apr 27 #Javascript
jQuery使用正则验证15/18身份证的方法示例
Apr 27 #jQuery
Vue.js 2.0 移动端拍照压缩图片预览及上传实例
Apr 27 #Javascript
微信小程序 实现动态显示和隐藏某个控件
Apr 27 #Javascript
JS ES6中setTimeout函数的执行上下文示例
Apr 27 #Javascript
Vue实现购物车功能
Apr 27 #Javascript
js轮播图透明度切换(带上下页和底部圆点切换)
Apr 27 #Javascript
You might like
PHP+jQuery实现自动补全功能源码
2013/05/15 PHP
PHP 中使用explode()函数切割字符串为数组的示例
2017/05/06 PHP
javascript 自定义事件初探
2009/08/21 Javascript
node.js中的events.emitter.removeAllListeners方法使用说明
2014/12/10 Javascript
javascript实现表格排序 编辑 拖拽 缩放
2015/01/02 Javascript
js实现下拉框选择要显示图片的方法
2015/02/16 Javascript
JS实现仿雅虎首页快捷登录入口及导航模块效果
2015/09/19 Javascript
JavaScript操作select元素和option的实例代码
2016/01/29 Javascript
node.js中使用Export和Import的方法
2017/09/18 Javascript
禁止弹窗中蒙层底部页面跟随滚动的几种方法
2017/12/07 Javascript
vue 系列——vue2-webpack2框架搭建踩坑之路
2017/12/22 Javascript
详解mpvue小程序中怎么引入iconfont字体图标
2018/10/01 Javascript
jQuery的ztree仿windows文件新建和拖拽功能的实现代码
2018/12/05 jQuery
微信小程序学习笔记之函数定义、页面渲染图文详解
2019/03/28 Javascript
通过实践编写优雅的JavaScript代码
2019/05/30 Javascript
vue中使用 pako.js 解密 gzip加密字符串的方法
2019/06/10 Javascript
es6数组之扩展运算符操作实例分析
2020/04/25 Javascript
Vue结合路由配置递归实现菜单栏功能
2020/06/16 Javascript
Python可变参数用法实例分析
2017/04/02 Python
Python爬虫将爬取的图片写入world文档的方法
2018/11/07 Python
pycharm实现在子类中添加一个父类没有的属性
2020/03/12 Python
详解Python3中的 input() 函数
2020/03/18 Python
完美解决pycharm 不显示代码提示问题
2020/06/02 Python
CHARLES & KEITH台湾官网:新加坡时尚品牌
2019/07/30 全球购物
简述DNS进行域名解析的过程
2013/12/02 面试题
C#实现对任一张表的数据进行增,删,改,查要求,运用Webservice,体现出三层架构
2014/07/11 面试题
工商管理专业实习生自我鉴定
2013/09/29 职场文书
竞职演讲稿范文
2014/01/11 职场文书
初三政治教学反思
2014/01/30 职场文书
优秀党务工作者事迹材料
2014/05/07 职场文书
社区科普工作方案
2014/06/03 职场文书
商务考察邀请函模板
2015/02/02 职场文书
小孩不笨观后感
2015/06/03 职场文书
运动会广播稿50字
2015/08/19 职场文书
五年级语文教学反思
2016/03/03 职场文书
HTML中的表单Form实现居中效果
2021/05/25 HTML / CSS