vue axios 请求接口 session 每次都变化解决办法

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

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

1、 vuejs ajax跨域请求

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

?
1
npm install axios -S

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

?
1
2
import axios from 'axios' ;
axios.defaults.withCredentials= true ;

main.js全部配置如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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文件中具体使用如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
<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,如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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

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

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

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

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

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

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

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

?
1
response.setHeader( "Access-Control-Allow-Origin" , <a href= "http://127.0.0.1:8010" rel= "external nofollow" >http://127.0.0.1:8010</a>);

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

?
1
Cookie:JSESSIONID=node015f4w1j2kgjk61i7jyyim8lo3u0.node0;

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

发现一下内容:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
// `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中的这句话:

?
1
axios.defaults.withCredentials= true ;

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

3、代理配置

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

?
1
2
3
4
5
6
7
8
9
10
11
12
devServer: {
   host: '127.0.0.1' ,
   port: 8010,
   proxy: {
    '/api/' : {
     target: 'http://127.0.0.1:8080' ,
     changeOrigin: true ,
     pathRewrite:{
           '/api' : '/xxxxxx'
         }
    }
   }

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

?
1
2
3
4
5
6
7
8
9
10
11
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下也就是项目的根路径下使用,于是我把代理改成:

?
1
2
3
4
5
6
7
8
9
devServer: {
   host: '127.0.0.1' ,
   port: 8010,
   proxy: {
    '/xxxx/' : {
     target: 'http://127.0.0.1:8080' ,
     changeOrigin: true
    }
   }

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

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

原文地址 http://www.jb51.net/article/112341.htm
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值