一、前言
最近在做一个前后端分离的自动化平台,由于环境部分还没搭建所以在本地启动前后端服务,开始接口联调,发现一个很有意思的问题,问了三个前端开发也没有解决;最后问题竟然出在一个小细节手中,还是要记录一下

前端地址:http://localhost:8080
后端地址:http://localhost:9090

二、后端基本代码配置

  1. 后端拦截器部分,不用多说做开发都应该知道
public class CorsInterceptor extends HandlerInterceptorAdapter {

    @Value("${service.corsOrigin}")  //跨域自定义配置application.yml自己配置
    private String corsOrigin;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String origin = request.getHeader("Origin");
        //后端响应基本配置项
        if (!StringUtils.isEmpty(origin) && corsOrigin.contains(origin)) {
            response.setHeader("Access-Control-Allow-Origin", origin);
            response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
            response.setHeader("Access-Control-Allow-Methods", "POST, GET");
            response.setHeader("Access-Control-Allow-Credentials", "true");
        }
        //设备默认值
        response.setContentType("application/json;charset=UTF-8");
        return true;
    }
}

1.简要说明setHeader设置的必要性
"Access-Control-Allow-Origin"需要指定前端指定域名,不能用*号,否则无法实现跨域
“Access-Control-Allow-Credentials” 设置成true是告知前端可以请求头携带cookie请求,否则前端将无法进行请求
2.另外前端每次都会发两次请求,其中首次是options请求,该请求为试探性请求可以被拦截器捕获,然后给与前端上述响应的内容,告知对它开放的一些权限及要求

2.拦截器最后要实现WebMvcConfigurer开启拦截器配置,否则上面的代码无法生效,springMVC机制

@Configuration
public class BaseInterceptor implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(getCorsInterceptor());
    }

    @Bean
    public CorsInterceptor getCorsInterceptor() {
        return new CorsInterceptor();
    }
}

3.前端调用后端登录接口,肯定要设置cookie到响应header中,cookie形式本文采用jwt技术

//设置cookie的工具类方法
public static void addCookie(HttpServletResponse response, String name, String value, String domain, int maxAge) {
    try {
        Cookie cookie = new Cookie(name, URLEncoder.encode(value, "utf-8"));
        cookie.setPath("/");
        cookie.setDomain(domain);
        cookie.setMaxAge(maxAge);
        cookie.setHttpOnly(true);
        response.addCookie(cookie);
    } catch (Exception var6) {
        throw new RuntimeException(var6.getMessage());
    }
}

在这里插入图片描述

图中截图登录接口service层处理cookie的调用方法,在service层设置响应cookie

4.自此后端基本配置完毕,开始前端部分

前端安装 axios、mockjs ,不用多说一个用来进行跨域请求,一个用来开发前的mock数据

5.前端点击登录触发的方法如下

//domain 为后端域名;login为接口
this.$axios.post(baseUrl.domain + baseInterface.login, {
          username: this.loginForm.username,
          password: this.loginForm.password
        })
          .then(res => {
            if (res.data.code === '20000') {
              console.log(res.data.data.token)
              //登录成功跳转进入首页
              this.$router.push({ path: '/dashboard' })
            } else {
              var errorInfo = res.data.message
              this.openError(errorInfo)
              this.loading = false
            }
          })
      } else {
        Message.close()
        this.loading = false
        this.openError()
      }
      

前端的mainjs文件要写入axios全局配置,允许后端写入cookie到浏览器中
axios.defaults.withCredentials = true

在这里插入图片描述
6.此时有意思的来了,由于我启动的是开发环境,所以mockjs配置还在只是登录的时候我把,mockjs中的登录mock数据注释掉了,如下
在这里插入图片描述

7.然后登录请求后端接口能够成功,并且有真实数据返回,同样后端响应的set-cookie也获取到了
在这里插入图片描述
在这里插入图片描述

8.理论上后端响应set-cookie后,浏览器能够自动保存cookie到application中,但是很神奇浏览器并没有进行保存
在这里插入图片描述

9.然后网上找了很多种说法,说什么前后端不能同域否则不能设置cookie,后端拦截器响"Access-Control-Allow-Origin"不能用*号,“Access-Control-Allow-Credentials” 要设置true这些我都没有问题配置了,然后找了三个前端开发都没有定位到问题

为什么我找前端不找后端,因为后端是没有问题的,我新搭建了一个vue项目然后通过发请求,浏览器能够正常获取到cookie,但是此vue项目就不行,所以后端肯定没问题,就一直在找前端的原因

10.后面有意思的就来了,我控制台突然发现接口请求竟然走的是mockjs
在这里插入图片描述

1.当时mockjs登录接口我是注释了的,竟然请求的发出还是走的mock,应该是是被mock拦截了然后由mock转发出去,同样能够请求到后端
2.同样登录cookie无法设置到浏览器后面的接口请求头就无法自动携带cookie请求

11.然后我把mockjs文件全部清空或注释掉,让mockjs无法生效,请求自动变成xhr正常请求,后面的接口也正常
在这里插入图片描述
12.或者你在mockjs文件中配置Mock.XHR.prototype.withCredentials = true同样后面的接口也能携带cookie进行请求,但是还是由mock进行转发的
在这里插入图片描述
13.所以自此这个问题也就解决了,希望大家不要遇到跟我一样的问题;因为网上没有资料针对我这种情况的,然后下面遇到一个很有趣的问题给大家分享一下

三、有趣的问题发现
1.前后端必须要同等域名下,application才能存入cookie(如果是ng做转发应该就不存在这种必要条件吧)
2.前后端不同域下进行请求,application不能存入cookie,但是不应该后面的接口进行请求

出现这种问题是由于浏览器同源策略导致,也就是说前端是www.baidu.com,请求后端域名也要为www.baidu.com否则application不能存入cookie,浏览器同源策略、浏览器同源策略、浏览器同源策略;重要事情说三遍

前提配置:
前端:http://127.0.0.1:8080
后端:http://localhost:9090

在这里插入图片描述

后端要设置前端IP跨域,否则会出现跨域报错
在这里插入图片描述

在这里插入图片描述

Logo

基于 Vue 的企业级 UI 组件库和中后台系统解决方案,为数万开发者服务。

更多推荐