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 相关文章推荐
jQuery 学习入门篇附实例代码
Mar 16 Javascript
jQuery实现的超酷苹果风格图标滑出菜单效果代码
Sep 16 Javascript
JavaScrip调试技巧之断点调试
Oct 22 Javascript
深入php面向对象、模式与实践
Feb 16 Javascript
分析js闭包引起的事件注册问题
Mar 29 Javascript
JavaScript中函数声明与函数表达式的区别详解
Aug 18 Javascript
jQuery实现动态文字搜索功能
Jan 05 Javascript
Angular2监听页面大小变化的解决方法
Oct 09 Javascript
从零开始最小实现react服务器渲染详解
Jan 26 Javascript
利用SpringMVC过滤器解决vue跨域请求的问题
Feb 10 Javascript
10分钟上手vue-cli 3.0 入门介绍
Apr 04 Javascript
详解Vue webapp项目通过HBulider打包原生APP(vue+webpack+HBulider)
Feb 02 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
Uchome1.2 1.5 代码学习 common.php
2009/04/24 PHP
php读取EXCEL文件 php excelreader读取excel文件
2012/12/06 PHP
php 不使用js实现页面跳转
2014/02/11 PHP
ThinkPHP模板之变量输出、自定义函数与判断语句用法
2014/11/01 PHP
php+jQuery实现的三级导航栏下拉菜单显示效果
2017/08/10 PHP
postman的安装与使用方法(模拟Get和Post请求)
2018/08/06 PHP
PHP中rename()函数的妙用讲解
2019/02/28 PHP
用js实现层随着内容大小动态渐变改变 推荐
2009/12/19 Javascript
基于jquery的一个浮动框(扩展性比较好 )
2010/08/27 Javascript
javascript学习笔记(二十) 获得和设置元素的特性(属性)
2012/06/20 Javascript
使用Math.floor与Math.random取随机整数的方法详解
2013/05/07 Javascript
jQuery选择器中含有空格的使用示例及注意事项
2013/08/25 Javascript
javascript实现颜色渐变的方法
2013/10/30 Javascript
JS判断对象是否存在的10种方法总结
2013/12/23 Javascript
JQuery对表单元素的基本操作使用总结
2014/07/18 Javascript
javascript实现保留两位小数的多种方法
2015/12/18 Javascript
深入浅析JS的数组遍历方法(推荐)
2016/06/15 Javascript
关于react-router的几种配置方式详解
2017/07/24 Javascript
Layui table 组件的使用之初始化加载数据、数据刷新表格、传参数
2017/09/11 Javascript
js推箱子小游戏步骤代码解析
2018/01/10 Javascript
JavaScript设计模式之享元模式实例详解
2019/01/17 Javascript
为什么要使用Vuex的介绍
2019/01/19 Javascript
js 计数排序的实现示例(升级版)
2020/01/12 Javascript
基于python分析你的上网行为 看看你平时上网都在干嘛
2019/08/13 Python
在jupyter notebook中调用.ipynb文件方式
2020/04/14 Python
CSS3中的clip-path使用攻略
2015/08/03 HTML / CSS
Canvas实现放大镜效果完整案例分析(附代码)
2020/11/26 HTML / CSS
英国信箱在线鲜花速递公司:Bloom & Wild
2019/03/10 全球购物
什么是JNDI的上下文?如何初始化JNDI上下文
2012/03/10 面试题
外贸公司实习自我鉴定
2013/09/24 职场文书
教师党的群众路线教育实践活动剖析材料
2014/10/09 职场文书
入党积极分子对十八届四中全会期盼的思想汇报
2014/10/17 职场文书
销售会议开幕词
2015/01/28 职场文书
最感人的道歉情书
2015/05/12 职场文书
运动会通讯稿600字
2015/07/20 职场文书
Python中 range | np.arange | np.linspace三者的区别
2022/03/22 Python