SpringBoot中Ajax跨域及Cookie无法获取丢失问题怎么解决

在写自己项目的登录注册页面时, 因为我的注册和更改密码功能采用了邮箱验证, 在发送验证码的时候后端会向响应数据中添加一个cookie

Cookie cookie = new Cookie(toEmail.split("
@"
)[0],verCode);

cookie.setMaxAge(30*60);

response.addCookie(cookie);

然后在点击注册或更改密码时, 后端会从请求中获取Cookie获得邮箱与验证码信息

Cookie[] cookies = request.getCookies();

在本地进行测试时, Cookie能正确添加进响应中, 也能正确获取

SpringBoot中Ajax跨域及Cookie无法获取丢失问题解决方案

但是在把项目打包上云, 再进行ajax访问时就出现了问题, Cookie获取失败了!

再响应标头中分明有set-Cookie, 但是再第二次的请求标头中却找不到Cookie

服务端获取cookie失败报错, 注册和更改密码需要使用Cookie的功能失效, 在查找文档后发现错误来源于springboot和ajax的跨域cookie丢失问题, 由于我是刚接触后端的小白,

这里只贴出我的解决方案

1. ajax请求中 需要携带上 xmlhttp.withCredentials = true;

var xmlhttp = new XMLHttpRequest();

xmlhttp.withCredentials = true;

xmlhttp.open("
GET"
, readyUrl, true);

xmlhttp.send();

2. 添加 corsConfig 配置类(这一步可能是化蛇填足,欢迎找茬)

package com.crisp.myblog.config;


import org.springframework.context.annotation.Configuration;

import org.springframework.web.servlet.config.annotation.CorsRegistry;

import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;



@Configuration
public class corsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("
/**"
)
//是否发送Cookie
.allowCredentials(true)
//放行哪些原始域
.allowedOriginPatterns("
这里填你前端代码所在的域名:端口"
)
.allowedMethods(new String[]{"
GET"
, "
POST"
, "
PUT"
, "
DELETE"
})
.allowedHeaders("
*"
)
.exposedHeaders("
*"
);

}
}

3. 给Controller中的api中的response设置响应头, 键为"
Access-Control-Allow-Origin"
访问控制允许来源,http请求头信息,设定允许资源共享(跨域)的源

response.setHeader("
Access-Control-Allow-Origin"
,request.getHeader("
Origin"
));

值为 request.getHeader("
Origin"
), 表示当前请求资源所在页面的协议和域名

组合在一起表示 允许当前请求资源跨域访问后端资源

这三部均设置好后我就能够重新获取到cookie了

2022-12-09 更新内容:

发现了更加简洁方便的方法, 添加跨域请求过滤器

用到了德鲁伊数据池依赖包的StringUtils.isEmpty 方法, 报错了的话自己写一个替换就行

import com.alibaba.druid.util.StringUtils;

import org.springframework.stereotype.Component;

import javax.servlet.*;

import javax.servlet.annotation.WebFilter;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import java.io.IOException;



@Component
public class crispFilter implements Filter {

@Override
public void init(FilterConfig filterConfig) throws ServletException {
Filter.super.init(filterConfig);

}

@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest)servletRequest;

HttpServletResponse response = (HttpServletResponse) servletResponse;

System.out.println("
跨域请求过滤器启动"
);

if (request.getRequestURL().toString().matches("
.+.ico$"
)) {
filterChain.doFilter(servletRequest, servletResponse);

} else {
String origin = request.getHeader("
Origin"
);

// 简单请求跨域,如果是跨域请求在响应头里面添加对应的Origin
if (!StringUtils.isEmpty(origin)) {
response.addHeader("
Access-Control-Allow-Origin"
, origin);

}
// 非简单请求跨域
response.addHeader("
Access-Control-Allow-Headers"
, "
content-type"
);

// 允许跨域请求的方法
response.addHeader("
Access-Control-Allow-Methods"
, "
*"
);

// 携带cookie的跨域
response.addHeader("
Access-Control-Allow-Credentials"
, "
true"
);


// 放行方法
filterChain.doFilter(servletRequest, servletResponse);

}
}

@Override
public void destroy() {
Filter.super.destroy();

}
}

随着互联网的快速发展,前后端分离的方式成为了主流开发方式。而Ajax跨域及Cookie无法获取丢失问题也成为了前端开发中经常遇到的问题。本文将介绍SpringBoot中如何解决这些问题,帮助开发者更好地实现前后端分离开发。
1. Ajax跨域问题解决方案
前端使用Ajax进行跨域请求时,如果目标地址与源地址不同,就会出现跨域问题。这时可以使用SpringBoot的CORS机制进行解决。CORS是跨域资源共享,通过在服务端设置响应头来实现跨域访问。
在SpringBoot中,可以通过在Controller中使用@CrossOrigin注解或自定义一个配置类来实现CORS。
@CrossOrigin注解示例:
```
@RestController
@RequestMapping(\"/api\")
@CrossOrigin(origins = \"http://localhost:8080\")
public class ApiController {
@GetMapping(\"/users\")
public List getUsers() {
...
}
}
```
自定义配置类示例:
```
@Configuration
public class CorsConfig {
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry
.addMapping(\"/api/**\")
.allowedOrigins(\"http://localhost:8080\")
.allowedMethods(\"GET\", \"POST\")
.allowedHeaders(\"*\")
.allowCredentials(true)
.maxAge(3600);
}
};
}
}
```
2. Cookie无法获取丢失问题解决方案
前端使用Ajax进行请求时,如果目标地址所在域名与当前页面所在域名不同,就会出现Cookie无法获取丢失的问题。这时可以通过设置响应头中的Access-Control-Allow-Credentials为true,来允许携带Cookie。
在SpringBoot中,需要在配置中设置AllowCredentials为true,如下:
```
@Configuration
public class CorsConfig {
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry
.addMapping(\"/api/**\")
.allowedOrigins(\"http://localhost:8080\")
.allowedMethods(\"GET\", \"POST\")
.allowedHeaders(\"*\")
.allowCredentials(true)
.maxAge(3600);
}
};
}
@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration().applyPermitDefaultValues();
configuration.setAllowCredentials(true);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration(\"/**\", configuration);
return source;
}
}
```
以上就是SpringBoot中Ajax跨域及Cookie无法获取丢失问题的解决方案。这些解决方案不仅适用于SpringBoot,也适用于其他后端框架。通过掌握这些知识,开发者可以更好地实现前后端分离开发,提高开发效率。