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实现的鼠标滑过按钮改变背景图片
Jul 15 Javascript
JavaScript 一道字符串分解的题目
Aug 03 Javascript
深入理解JSON数据源格式
Jan 10 Javascript
使用Jquery实现每日签到功能
Apr 03 Javascript
基于jQuery+JSON的省市二三级联动效果
Jun 05 Javascript
深入浅析search 搜索框的写法
Aug 02 Javascript
JS设置CSS样式的方式汇总
Jan 21 Javascript
Vue2.0用户权限控制解决方案
Nov 29 Javascript
vue axios登录请求拦截器
Apr 02 Javascript
浅谈关于iview表单验证的问题
Sep 29 Javascript
微信小程序CSS3动画下拉菜单效果
Nov 04 Javascript
Ant Design的Table组件去除
Oct 24 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
Windows下PHP5和Apache的安装与配置
2006/09/05 PHP
一个简单的自动发送邮件系统(二)
2006/10/09 PHP
php获取本地图片文件并生成xml文件输出具体思路
2013/04/27 PHP
php查询mysql数据库并将结果保存到数组的方法
2015/03/18 PHP
ThinkPHP5 框架引入 Go AOP,PHP AOP编程项目详解
2020/05/12 PHP
jQuery formValidator表单验证插件开源了 含API帮助、源码、示例
2008/08/14 Javascript
jquery中的$(document).ready()与window.onload的区别
2009/11/18 Javascript
js实现页面转发功能示例代码
2013/08/05 Javascript
js特殊字符过滤的示例代码
2014/03/05 Javascript
jquery 页眉单行信息滚动显示实现思路及代码
2014/06/26 Javascript
js实现类似jquery里animate动画效果的方法
2015/04/10 Javascript
学习JavaScript设计模式之模板方法模式
2016/01/20 Javascript
Javascript点击其他任意地方隐藏关闭DIV实例
2016/06/21 Javascript
JS实现的表头列头固定页面功能示例
2017/01/10 Javascript
ES6新特性之变量和字符串用法示例
2017/04/01 Javascript
JS 组件系列之Bootstrap Table的冻结列功能彻底解决高度问题
2017/06/30 Javascript
vue-cli实现多页面多路由的示例代码
2018/01/30 Javascript
JavaScript中利用Array filter() 方法压缩稀疏数组
2018/02/24 Javascript
微信JS-SDK实现微信会员卡功能(给用户微信卡包里发送会员卡)
2019/07/25 Javascript
解决使用layui的时候form表单中的select等不能渲染的问题
2019/09/18 Javascript
vue实现将数据存入vuex中以及从vuex中取出数据
2019/11/08 Javascript
[07:20]2014DOTA2西雅图国际邀请赛 选手讲解积分赛第二天
2014/07/11 DOTA
Python通过DOM和SAX方式解析XML的应用实例分享
2015/11/16 Python
详解python如何调用C/C++底层库与互相传值
2016/08/10 Python
Python反转序列的方法实例分析
2018/03/21 Python
python的pandas工具包,保存.csv文件时不要表头的实例
2018/06/14 Python
Python实现八皇后问题示例代码
2018/12/09 Python
python画图--输出指定像素点的颜色值方法
2019/07/03 Python
django之对FileField字段的upload_to的设定方法
2019/07/28 Python
Django之富文本(获取内容,设置内容方式)
2020/05/21 Python
amazeui页面校验功能的实现代码
2020/08/24 HTML / CSS
大学生职业生涯规划书模板
2014/01/18 职场文书
《晏子使楚》教学反思
2014/02/08 职场文书
2014领导干部四风问题查摆思想汇报
2014/09/13 职场文书
无工作证明怎么写
2015/06/15 职场文书
Golang数据类型和相互转换
2022/04/12 Golang