springboot+vue2.x 解决session跨域失效问题

2022-10-14,,,,

服务端springboot2.x   :localhost:8082

前端vue2.x                 :localhost:81

前后端的端口号不同,为跨域,导致前端访问后端时,每次访问都新生产一个sessionid。解决如下:

 

后端:

1.添加过滤器:

package com.nsoft.gkzp.syscore.config.filter;

import org.apache.logging.log4j.logmanager;
import org.apache.logging.log4j.logger;
import org.springframework.web.bind.annotation.requestmethod;

import javax.servlet.*;
import javax.servlet.annotation.webfilter;
import javax.servlet.http.httpservletrequest;
import javax.servlet.http.httpservletresponse;
import java.io.ioexception;

@webfilter(urlpatterns = "/*", filtername = "corsfilter")
public class corsfilter implements filter {

    final private static logger logger = logmanager.getlogger(corsfilter.class);
    @override
    public void destroy() {
    }
    /**
     * 此过滤器只是处理跨域问题
     * @param servletrequest
     * @param servletresponse
     * @param chain
     * @throws servletexception
     * @throws ioexception
     */
    @override
    public void dofilter(servletrequest servletrequest, servletresponse servletresponse, filterchain chain) throws servletexception, ioexception {
        httpservletrequest request = (httpservletrequest) servletrequest;
        httpservletresponse response = (httpservletresponse) servletresponse;
        string origin = request.getheader("origin");
        if(origin == null) {
            origin = request.getheader("referer");
        }
        response.setheader("access-control-allow-origin", origin);// 允许指定域访问跨域资源(这里不能写*,*代表接受所有域名访问,如写*则下面一行代码无效。谨记)
        response.setheader("access-control-allow-credentials", "true");//true代表允许客户端携带cookie(此时origin值不能为“*”,只能为指定单一域名)
        response.setheader("access-control-allow-methods", "get, head, post, put, delete, trace, options, patch"); /// 允许浏览器在预检请求成功之后发送的实际请求方法名
        response.setheader("access-control-allow-headers", "authorization,origin, x-requested-with, content-type, accept,access-token");// 允许浏览器发送的请求消息头
        //response.setheader("access-control-max-age", "86400");            // 浏览器缓存预检请求结果时间,单位:秒

        chain.dofilter(request,response);
    }
    @override
    public void init(filterconfig filterconfig) throws servletexception {
    }


}

2. springboot2.配置过滤器时,启动类必须加上@servletcomponentscan才会加载过滤器

package com.nsoft.gkzp;

import org.mybatis.spring.annotation.mapperscan;
import org.springframework.boot.springapplication;
import org.springframework.boot.autoconfigure.springbootapplication;
import org.springframework.boot.web.server.configurablewebserverfactory;
import org.springframework.boot.web.server.errorpage;
import org.springframework.boot.web.server.webserverfactorycustomizer;
import org.springframework.boot.web.servlet.servletcomponentscan;
import org.springframework.context.annotation.bean;
import org.springframework.http.httpstatus;
import org.springframework.web.servlet.config.annotation.corsregistry;
import org.springframework.web.servlet.config.annotation.webmvcconfigurer;
import org.springframework.web.servlet.config.annotation.webmvcconfigureradapter;

/**
 * springboot入口
 * mapperscan("com.nsoft.gkzp.**.dao")为扫描mapper, 所以dao下面的类就不需要添加@mapper注解了
 * servletcomponentscan  添加了过滤器,故这里要添加@servletcomponentscan注解,spring才会扫描到过滤器(eg:com.nsoft.gkzp.syscore.config.filter.corsfilter)
 */
@springbootapplication
@servletcomponentscan
@mapperscan("com.nsoft.gkzp.**.dao")
public class gzygkzpapplication {

    public static void main(string[] args) {
        springapplication.run(gzygkzpapplication.class, args);
    }


    /**
     * 在springboot整合vue前端时,vue使用url跳转时报404错误,此处代码解决此问题
     * 参照https://blog.csdn.net/mr_evanchen/article/details/83625082
     */
    @bean
    public webserverfactorycustomizer<configurablewebserverfactory> webserverfactorycustomizer(){
        return factory -> {
            errorpage error404page = new errorpage(httpstatus.not_found, "/index.html");
            factory.adderrorpages(error404page);
        };
    }

}

3. spring-session 2.x 中 cookie里面了samesite ,他默认值是 lax 

samesite cookie 是用来防止csrf攻击,它有两个值:strict、lax
samesite = strict:意为严格模式,表明这个cookie在任何情况下都不可能作为第三方cookie;
samesite = lax  :意为宽松模式,在get请求是可以作为第三方cookie,但是不能携带cookie进行跨域post访问(这就很蛋疼了,我们那个校验接口就是post请求)

package com.nsoft.gkzp.syscore.config;

import org.springframework.context.annotation.bean;
import org.springframework.context.annotation.configuration;
import org.springframework.session.web.http.cookieserializer;
import org.springframework.session.web.http.defaultcookieserializer;

/**
* https://www.cnblogs.com/hujinshui/p/11025848.html
* spring-session 2.x 中 cookie里面引入了samesite他默认值是 lax,
* samesite cookie 是用来防止csrf攻击,它有两个值:strict、lax
* samesite = strict:意为严格模式,表明这个cookie在任何情况下都不可能作为第三方cookie;
* samesite = lax:意为宽松模式,在get请求是可以作为第三方cookie,但是不能携带cookie进行跨域post访问
* 总结:前端请求到后台,每次session都不一样,每次都是新的会话,导致获取不到用户信息
*/
@configuration public class springsessionconfig { public springsessionconfig() { } @bean public cookieserializer httpsessionidresolver() { defaultcookieserializer cookieserializer = new defaultcookieserializer(); // 取消仅限同一站点设置 cookieserializer.setsamesite(null); return cookieserializer; } }

 

前端:

1.在 main.js (前端用axios)

import axios from 'axios';
axios.defaults.withcredentials=true;//让ajax携带cookie

 

用了1天半时间,改了很多次依然不行,后来发现是前端用了 proxy 代理,它本身也是已经处理了跨域问题,网上找的时候发现有的文章也用到这个了。但我这里就是不行。

我原来的代码:

1)写的注册页面:

 

 2)全局配置如下:

main.js

// xenv 标记当前环境 true:开发环境   false:生产环境
const xenv = true;
// 注册全局变量
vue.prototype.$global = {
   //contentpath 标记根路径,主要用于axios请求后端数据的url
   contentpath: xenv ? '/api/' : router.options.base  
};

(xenv设为true;所以 根路径contentpath的值必为‘/api/’   ,而‘/api/’ 在vue.config.js里配置为代理,如下。)

vue.config.js

  devserver: {
    open: true,
    host: '0.0.0.0',
    port: 80,
    https: false,
    hotonly: false,
    before: app => {
    },
    proxy: {
      // 配置跨域
      '/api': {
        target: 'http://127.0.0.1:8082/',
        ws: true,
        changorigin: true,
        pathrewrite: {
          '^/api': '/'
        }
      }
    }
  },

 

2.不使用proxy代理,把根目录写死为'http://127.0.0.1:8082/',就成功了,修改如下:

main.js:

// xenv 标记当前环境 true:开发环境   false:生产环境
const xenv = true;
// 注册全局变量
vue.prototype.$global = {
  // contentpath 标记根路径,主要用于axios请求后端数据的url
  // contentpath: xenv ? '/api/' : router.options.base
  contentpath:  'http://127.0.0.1:8082/'
};

 

 

参照:

《springboot+vue2.x 解决session跨域失效问题.doc》

下载本文的Word格式文档,以方便收藏与打印。