前端使用axios发送Post请求,预检不通过(无法携带cookie),无法加载响应数据(跨域)
后端Spring boot 的controller层 就是标准的格式只是在controller类的上面加上了一个注解@CrossOrigin。(以及指定特定的参数)
目录
前端原始代码
const contentLogin = await myAxios.post('/user/login',
{
userAccount : userAccount.value,
userPassword : userPassword.value
},{
withCredentials:true , //携带上cookie
headers: {
//post请求默认就是该类型
'Content-Type': 'application/json'
},
})
后端Spring boot 的controller层 就是标准的格式
只是在controller类的上面加上了一个注解@CrossOrigin
解决问题
前端代码不变 依旧和原来一样
后端通过配置类的形式去解决
@Configuration
public class CorsConfig {
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
.allowedHeaders("*")
.allowCredentials(true)
.maxAge(3600);
}
};
}
}
在代码中,我们使用Java SpringBoot的@Configuration注解和@Bean注解创建了一个CorsConfig类,并实现了WebMvcConfigurer接口,重写了addCorsMappings方法,设置了CORS跨域头。
其中:
allowedOrigins设置为"*"表示允许来自任意域名的请求,
allowedMethods设置为"GET", "POST", "PUT", "DELETE", "OPTIONS"表示允许这些HTTP方法的请求,
allowCredentials设置为true表示允许携带凭证信息的请求,
maxAge设置为3600表示设置缓存时间为1小时。
后端通过注解的形式去解决
在controller类的上面加上注解 @CrossOrigin()
@CrossOrigin(origins = "*", maxAge = 3600, allowedHeaders = "*", allowCredentials = "true")
需要注意的是,@CrossOrigin注解只能用于控制器方法或控制器类上,并且不能同时使用@CrossOrigin注解和WebMvcConfigurer配置类来实现CORS跨域请求。如果在控制器类和方法上都使用了@CrossOrigin注解,则方法级别的注解将覆盖类级别的注解。
如果上面的代码报错:
When allowCredentials is true, allowedOrigins cannot contain the special value "*" since that cannot be set on the "Access-Control-Allow-Origin" response header. To allow credentials to a set of origins, list them explicitly or consider using "allowedOriginPatterns" instead.
则修改成下面这个 含义一样
@CrossOrigin(originPatterns ="*", maxAge = 3600, allowedHeaders = "*", allowCredentials = "true")
@CrossOrigin()该注解的默认数值是什么?
- origins:默认值为"*",表示允许来自任意域名的请求。
- methods:默认值为GET、POST、HEAD,表示允许这些HTTP方法的请求。
- allowedHeaders:默认值为空数组,表示不允许携带任何请求头。
- exposedHeaders:默认值为空数组,表示不允许在响应头中暴露任何响应头。
- allowCredentials:默认值为false,表示不允许携带凭证信息的请求。
- maxAge:默认值为1800秒,表示设置缓存时间为30分钟。
@CrossOrigin(origins = "http://example.com", maxAge = 3600, allowCredentials = true)
在这个例子中,我们设置了origins为"http://example.com",maxAge为3600,allowCredentials为true,表示只允许来自"http://example.com"域名的请求,缓存时间为1小时,并且允许携带凭证信息的请求。
问题出现的原因
简单介绍cookie
如果是第一次登录,前端发送请求时是没有cookie的,因为cookie是在服务器端生成并发送给客户端的。当服务器端返回响应时,会在响应头中设置Set-Cookie字段,将cookie发送给客户端。客户端在收到响应后会保存这个cookie,并在后续的请求中自动携带上这个cookie。
预检不通过的原因
对于预检不通过的问题,可能是由于跨域请求时浏览器默认会进行CORS预检(OPTIONS请求),而服务器端没有正确处理OPTIONS请求导致的。为了解决这个问题,可以在服务器端添加CORS跨域头,或者在服务器端的请求处理逻辑中加入对OPTIONS请求的处理。(就是上面的配置类解决 或者 使用注解的方式)
为什么相同的请求内容将Post方式改成Get方式后就可以携带上cookie并且成功的返回数据?( 为什么Post请求需要预检)
在默认情况下,浏览器在发送跨域的POST请求时,会自动发送OPTIONS请求进行预检,以确定服务器是否支持跨域请求。如果OPTIONS请求返回的响应头中没有设置Access-Control-Allow-Credentials字段为true,浏览器就会拒绝发送带有凭证信息(如cookie)的POST请求。
而在发送GET请求时,浏览器不会发送OPTIONS请求进行预检,因此可以直接发送带有凭证信息的GET请求。所以如果将POST请求改成GET请求,就可以携带上cookie了。
如果需要在发送跨域的POST请求时携带上cookie,需要在服务器端设置Access-Control-Allow-Credentials为true,并在响应头中设置Access-Control-Allow-Origin字段为请求头中的Origin值,表示允许来自该域名的请求携带凭证信息。
同时,还需要在发送请求时设置withCredentials为true,表示允许携带凭证信息。
如果服务器端已经设置好了CORS跨域头,但仍然不能携带上cookie,可能是由于请求头中的Origin值与服务器端设置的Access-Control-Allow-Origin值不匹配导致的。
更多推荐
所有评论(0)