欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2024-03-20 17:32:58
...

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源码中默认为)。

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

拦截器:

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);
    }

}
相关标签: Vue学习记录