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模板实现方法
Apr 27 Javascript
JavaScript 关键字屏蔽实现函数
Aug 02 Javascript
基于jquery的地址栏射击游戏代码
Mar 10 Javascript
果断收藏9个Javascript代码高亮脚本
Jan 06 Javascript
Bootstrap Table使用方法解析
Oct 19 Javascript
微信小程序实战之自定义模态弹窗(8)
Apr 18 Javascript
微信小程序使用checkbox显示多项选择框功能【附源码下载】
Dec 11 Javascript
JS简单实现查看文档创建日期、修改日期和文档大小的方法示例
Apr 08 Javascript
ES6基础之展开语法(Spread syntax)
Feb 21 Javascript
微信公众平台 客服接口发消息的实现代码(Java接口开发)
Apr 17 Javascript
JavaScrip数组去重操作实例小结
Jun 20 Javascript
解决VueCil代理本地proxytable无效报错404的问题
Nov 07 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 生成自动创建文件夹并上传文件的示例代码
2014/03/07 PHP
php实现删除指定目录下相关文件的方法
2014/10/20 PHP
jQuery操作CheckBox的方法介绍(选中,取消,取值)
2014/02/04 Javascript
详解JavaScript的AngularJS框架中的表达式与指令
2016/03/05 Javascript
JS实现重新加载当前页面
2016/11/29 Javascript
Bootstrap实现圆角、圆形头像和响应式图片
2016/12/14 Javascript
bootstrap警告框使用方法解析
2017/01/13 Javascript
windows下vue-cli及webpack搭建安装环境
2017/04/25 Javascript
详解webpack 入门总结和实践(按需异步加载,css单独打包,生成多个入口文件)
2017/06/20 Javascript
详解Vue2 SSR 缓存 Api 数据
2017/11/20 Javascript
javaScript字符串工具类StringUtils详解
2017/12/08 Javascript
jquery判断滚动条距离顶部的距离方法
2018/09/05 jQuery
详解jenkins自动化部署vue
2019/05/14 Javascript
vue父子模板传值问题解决方法案例分析
2020/02/26 Javascript
node.js +mongdb实现登录功能
2020/06/18 Javascript
Element Tooltip 文字提示的使用示例
2020/07/26 Javascript
python的tkinter布局之简单的聊天窗口实现方法
2014/09/03 Python
举例简单讲解Python中的数据存储模块shelve的用法
2016/03/03 Python
windows系统下Python环境搭建教程
2017/03/28 Python
Python生成数字图片代码分享
2017/10/31 Python
python将txt等文件中的数据读为numpy数组的方法
2018/12/22 Python
Python编程快速上手——Excel表格创建乘法表案例分析
2020/02/28 Python
python 实现分组求和与分组累加求和代码
2020/05/18 Python
Michael Kors香港官网:美国奢侈品品牌
2019/12/26 全球购物
PHP数据运算类型都有哪些
2013/11/05 面试题
实习生个人的自我评价
2013/12/08 职场文书
区域销售经理岗位职责
2013/12/10 职场文书
办理信用卡工作证明
2014/01/11 职场文书
前厅收银主管岗位职责
2014/02/04 职场文书
《千年梦圆在今朝》教学反思
2014/02/24 职场文书
中学生期中自我鉴定
2014/04/20 职场文书
会计个人实习计划书
2014/08/15 职场文书
法定代表人授权委托书范文
2014/09/22 职场文书
入党积极分子对十八届四中全会期盼的思想汇报
2014/10/17 职场文书
2014年设备管理工作总结
2014/11/26 职场文书
Java使用JMeter进行高并发测试
2021/11/23 Java/Android