解决Axios跨域请求时session不一致

解决跨域Session不一致
本文深入探讨了跨域请求中Session不一致的问题,解析了会话保持的原理,详细阐述了前端与后端如何通过配置withCredentials属性来携带Cookie,实现跨域请求时的Session一致性。
1、原因

这个问题的产生关系到会话保持的原理:当浏览器第一次请求服务器时,服务器会为其创建一个session对象,每个session对象有一个自己的唯一id作为自己的标识。服务器为了判断下次请求的是不是同一个浏览器,会把这个sessionId放到cookie中,以cookie的形式返回给浏览器,并暂时存储在浏览器中。这样,只要浏览器不关闭,再去访问服务器时,就会自动带上这个sessionId,服务器再次接收请求时,就会去获取这个sessionId,并与服务器内存中存在的sessionId比对,验证通过就说明这个用户之前访问过,不用为其重新分配新的session对象,就达到了会话的保持。如果以上理解不了的请先自行查阅什么是session和cookie。

所以维持会话的一个关键点其实是携带了sessionId的这个cookie。出现了session不一致的问题,那多半就是跨域请求时没有携带cookie,或者服务器不允许你携带cookie~

根据线索去查阅资料后得知:XMLHttpRequest 存在一个名为withCredentials的属性,该属性默认值为false,在发送同源请求时该属性不起作用,但在作跨域请求时,它的作用就非常大了:
true:在跨域请求时,会携带用户凭证,也就是cookie;
false:在跨域请求时,不会携带用户凭证,并且返回的response里也会忽略cookie。

2.解决方法

锁定了问题的原因,问题自然也就迎刃而解了:

1.设置前端请求的withCredentials属性为true,让其请求时携带cookie;
在axios请求时携带该属性:

this.$axios.get('/api/test',{withCredentials : true}).then((res)=>{
        console.log(res)
      })

或者在main.js中作全局的配置,一劳永逸~

import Vue from 'vue';
import axios from 'axios';
//请求默认地址
axios.defaults.baseURL = "http://127.0.0.1:8081/";
//请求超时时间
axios.defaults.timeout = 10000;
//post请求头
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=utf-8';
//设置cross跨域 并设置访问权限 允许跨域携带cookie信息
axios.defaults.withCredentials=true;

2.设置后台的withCredentials属性为true,让其允许前端携带cookie请求,并在响应时也携带cookie。

在springboot构建的项目中,如果用的@CrossOrigin注解,为其加上allowCredentials参数,作局部的处理:@CrossOrigin(allowCredentials="true")(在@CrossOrigin源码中默认为false)。

或者使用拦截器或过滤器作全局的配置:

拦截器:

package com.example.pahms.Inteceptor;

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Component
public class CORSInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        response.setHeader("Access-Control-Expose-Headers", "token");// 服务器 headers 白名单,可以让客户端进行访问操作的属性
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
        return true;
    }

}

过滤器:

package com.example.pahms.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

@Configuration
public class GlobalCorsConfig {

    @Bean
    public CorsFilter corsFilter() {
        CorsConfiguration config = new CorsConfiguration();
        config.addAllowedOrigin("*");
        config.setAllowCredentials(true);
        config.addAllowedMethod("*");
        config.addAllowedHeader("*");
        UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource();
        configSource.registerCorsConfiguration("/**", config);
        return new CorsFilter(configSource);
    }

}
<think>我们正在讨论如何使用axios设置请求头来传递session信息。根据引用[1]中的示例,设置请求头的方式是: Axios.defaults.headers.common["User-Id"] = store.state.user.id; 但是,用户现在想要设置的是请求头中的session。根据引用[2]和[3],我们知道在请求,如果涉及到session,还需要注意携带cookie(因为session通常依赖于cookie中的session id)。过,用户的问题明确要求设置请求头中的session,所以我们首先考虑如何设置一个名为"session"的请求头。 需要注意的是,通常情况下,session信息并是通过自定义请求头传递的,而是通过cookie自动携带的。但是,如果后端要求将session id放在一个自定义的请求头中(例如某些API的设计),那么我们可以按照以下方式设置: 方法1:全局设置 Axios.defaults.headers.common['session'] = '你的session值'; 方法2:针对某个实例设置(推荐,避免全局污染) 先创建一个axios实例,然后设置该实例的默认请求头。 方法3:在单个请求中设置 在具体的请求配置中添加headers。 另外,引用[2]和[3]提到session变化的问题,这可能与是否携带cookie有关。如果后端需要验证cookie中的session,那么前端需要设置`withCredentials: true`,这样才会在请求携带cookie。但是,注意设置自定义请求头可能会触发预检请求(OPTIONS),如引用[1]所述。 因此,如果用户需要设置一个名为"session"的请求头,同又要确保请求能够携带cookie(如果后端需要),那么需要做两件事: 1. 设置自定义请求头。 2. 配置axios以携带凭证(cookie)。 步骤: (1)在创建axios实例(或者全局配置)设置`withCredentials: true`。 (2)设置请求头的session字段。 示例代码: 方式一:全局设置(推荐,除非整个应用都需要) ```javascript axios.defaults.withCredentials = true; // 携带cookie axios.defaults.headers.common['session'] = 'your_session_value_here'; ``` 方式二:创建实例(推荐) ```javascript const instance = axios.create({ withCredentials: true, headers: { 'session': 'your_session_value_here' } }); // 然后使用instance发起请求 ``` 方式三:在单个请求中设置 ```javascript axios.get('/api/endpoint', { withCredentials: true, headers: { 'session': 'your_session_value_here' } }); ``` 注意:如果自定义请求头(如'session')是后端要求添加的,那么后端在配置中必须允许这个请求头。否则,预检请求(OPTIONS)会因为请求在允许范围内而失败。 另外,引用[3]中提到了使用`createAxios`来创建一个配置了`withCredentials: true`的实例,这与上述方式二类似。 总结:用户想要设置请求头中的session,可以使用以上三种方式之一。同,如果需要携带cookie,务必设置`withCredentials: true`。 生成相关问题: 1. 如何在axios中全局设置请求头? 2. 请求如何携带cookie? 3. 如何避免每次请求都设置相同的请求头? 4. 为什么设置自定义请求头会导致两次请求(预检请求)? 注意:在回答中,我们引用了提供的引用[1]、[2]、[3],并在引用处添加了引用标识。 </think>### 如何使用 Axios 设置请求SessionAxios 中设置请求头传递 Session 信息,主要有以下三种方式(根据您的引用[1][2][3]整理): #### 1️⃣ **全局设置(推荐)** ```javascript // 设置所有请求的公共请求axios.defaults.headers.common['Session'] = 'your_session_id_here'; ``` - ✅ 优点:一次设置,所有请求自动生效 - ⚠️ 注意:需确保后端 CORS 配置允许 `Session` 头部(引用[1]) #### 2️⃣ **创建独立实例** ```javascript // 创建带凭证的独立实例(引用[3]) const sessionHttp = axios.create({ withCredentials: true, // 携带凭证(如cookie) headers: {'Session': 'your_session_id_here'} }); // 使用实例发送请求 sessionHttp.get('/api/data'); ``` - ✅ 优点:隔离同 API 的会话配置 - 💡 适用场景:需要同维护多种会话状态 #### 3️⃣ **单次请求设置** ```javascript axios.get('/api/data', { headers: { 'Session': 'your_session_id_here' }, withCredentials: true // 携带凭证(引用[2]) }); ``` - ✅ 优点:灵活控制特定请求 --- ### 🌐 注意事项(引用[1][2]) 1. 后端必须配置 CORS 允许 `Session` 头部 2. 首次会发送 `OPTIONS` 预检请求(无 Session) 3. 第二次才是携带 Session 的实际请求 4. 必须设置 `withCredentials: true` 保持会话一致性 ### 📝 完整示例 ```javascript // 从Vuex获取会话ID(引用[1]) const sessionId = store.state.session.id; // 创建Axios实例 const api = axios.create({ baseURL: 'https://your-api.com', headers: {'Session': sessionId}, withCredentials: true }); // 发送请求 api.post('/user', {data}) .then(response => console.log(response)); ``` 🔔 **重要提示** 若遇到 Session 一致问题(引用[2]),请检查: 1. 后端是否正确配置 `Access-Control-Allow-Credentials: true` 2. 前端是否每个请求都设置了 `withCredentials: true`
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值