经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » Java相关 » Spring Boot » 查看文章
springboot+vue2.x 解决session跨域失效问题
来源:cnblogs  作者:东方飘雪  时间:2019/10/9 9:00:27  对本文有异议

服务端SpringBoot2.x   :localhost:8082

前端Vue2.x                 :localhost:81

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

 

后端:

1.添加过滤器:

  1. package com.nsoft.gkzp.syscore.config.filter;
  2. import org.apache.logging.log4j.LogManager;
  3. import org.apache.logging.log4j.Logger;
  4. import org.springframework.web.bind.annotation.RequestMethod;
  5. import javax.servlet.*;
  6. import javax.servlet.annotation.WebFilter;
  7. import javax.servlet.http.HttpServletRequest;
  8. import javax.servlet.http.HttpServletResponse;
  9. import java.io.IOException;
  10. @WebFilter(urlPatterns = "/*", filterName = "corsFilter")
  11. public class CorsFilter implements Filter {
  12. final private static Logger logger = LogManager.getLogger(CorsFilter.class);
  13. @Override
  14. public void destroy() {
  15. }
  16. /**
  17. * 此过滤器只是处理跨域问题
  18. * @param servletRequest
  19. * @param servletResponse
  20. * @param chain
  21. * @throws ServletException
  22. * @throws IOException
  23. */
  24. @Override
  25. public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws ServletException, IOException {
  26. HttpServletRequest request = (HttpServletRequest) servletRequest;
  27. HttpServletResponse response = (HttpServletResponse) servletResponse;
  28. String origin = request.getHeader("Origin");
  29. if(origin == null) {
  30. origin = request.getHeader("Referer");
  31. }
  32. response.setHeader("Access-Control-Allow-Origin", origin);// 允许指定域访问跨域资源(这里不能写*,*代表接受所有域名访问,如写*则下面一行代码无效。谨记)
  33. response.setHeader("Access-Control-Allow-Credentials", "true");//true代表允许客户端携带cookie(此时origin值不能为“*”,只能为指定单一域名)
  34. response.setHeader("Access-Control-Allow-Methods", "GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH"); /// 允许浏览器在预检请求成功之后发送的实际请求方法名
  35. response.setHeader("Access-Control-Allow-Headers", "Authorization,Origin, X-Requested-With, Content-Type, Accept,Access-Token");// 允许浏览器发送的请求消息头
  36. //response.setHeader("Access-Control-Max-Age", "86400"); // 浏览器缓存预检请求结果时间,单位:秒
  37. chain.doFilter(request,response);
  38. }
  39. @Override
  40. public void init(FilterConfig filterConfig) throws ServletException {
  41. }
  42. }

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

  1. package com.nsoft.gkzp;
  2. import org.mybatis.spring.annotation.MapperScan;
  3. import org.springframework.boot.SpringApplication;
  4. import org.springframework.boot.autoconfigure.SpringBootApplication;
  5. import org.springframework.boot.web.server.ConfigurableWebServerFactory;
  6. import org.springframework.boot.web.server.ErrorPage;
  7. import org.springframework.boot.web.server.WebServerFactoryCustomizer;
  8. import org.springframework.boot.web.servlet.ServletComponentScan;
  9. import org.springframework.context.annotation.Bean;
  10. import org.springframework.http.HttpStatus;
  11. import org.springframework.web.servlet.config.annotation.CorsRegistry;
  12. import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
  13. import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
  14. /**
  15. * springboot入口
  16. * MapperScan("com.nsoft.gkzp.**.dao")为扫描mapper, 所以dao下面的类就不需要添加@mapper注解了
  17. * ServletComponentScan 添加了过滤器,故这里要添加@ServletComponentScan注解,spring才会扫描到过滤器(eg:com.nsoft.gkzp.syscore.config.filter.CorsFilter)
  18. */
  19. @SpringBootApplication
  20. @ServletComponentScan
  21. @MapperScan("com.nsoft.gkzp.**.dao")
  22. public class GzyGkzpApplication {
  23. public static void main(String[] args) {
  24. SpringApplication.run(GzyGkzpApplication.class, args);
  25. }
  26. /**
  27. * 在springboot整合vue前端时,vue使用url跳转时报404错误,此处代码解决此问题
  28. * 参照https://blog.csdn.net/Mr_EvanChen/article/details/83625082
  29. */
  30. @Bean
  31. public WebServerFactoryCustomizer<ConfigurableWebServerFactory> webServerFactoryCustomizer(){
  32. return factory -> {
  33. ErrorPage error404Page = new ErrorPage(HttpStatus.NOT_FOUND, "/index.html");
  34. factory.addErrorPages(error404Page);
  35. };
  36. }
  37. }

3. spring-session 2.x 中 Cookie里面了SameSite ,他默认值是 Lax 

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

  1. package com.nsoft.gkzp.syscore.config;
  2. import org.springframework.context.annotation.Bean;
  3. import org.springframework.context.annotation.Configuration;
  4. import org.springframework.session.web.http.CookieSerializer;
  5. import org.springframework.session.web.http.DefaultCookieSerializer;
  1. /**
    * 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都不一样,每次都是新的会话,导致获取不到用户信息
    */
  1. @Configuration public class SpringSessionConfig { public SpringSessionConfig() { } @Bean public CookieSerializer httpSessionIdResolver() { DefaultCookieSerializer cookieSerializer = new DefaultCookieSerializer(); // 取消仅限同一站点设置 cookieSerializer.setSameSite(null); return cookieSerializer; } }

 

前端:

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

  1. import axios from 'axios';
  2. axios.defaults.withCredentials=true;//让ajax携带cookie

 

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

我原来的代码:

1)写的注册页面:

 

 2)全局配置如下:

main.js

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

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

vue.config.js

  1. devServer: {
  2. open: true,
  3. host: '0.0.0.0',
  4. port: 80,
  5. https: false,
  6. hotOnly: false,
  7. before: app => {
  8. },
  9. proxy: {
  10. // 配置跨域
  11. '/api': {
  12. target: 'http://127.0.0.1:8082/',
  13. ws: true,
  14. changOrigin: true,
  15. pathRewrite: {
  16. '^/api': '/'
  17. }
  18. }
  19. }
  20. },

 

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

main.js:

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

 

 

另:为了安全起见,可在服务端设置可跨域访问的白名单地址,参照 https://blog.csdn.net/qq_15054679/article/details/90684703

 

 

 

参照:

https://www.cnblogs.com/zimublog/p/10786110.html

https://blog.csdn.net/qq_17555933/article/details/92017890

原文链接:http://www.cnblogs.com/zdyang/p/11636697.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号