目录

解决问题

后端通过配置类的形式去解决

后端通过注解的形式去解决

问题出现的原因

简单介绍cookie

预检不通过的原因

为什么相同的请求内容将Post方式改成Get方式后就可以携带上cookie并且成功的返回数据?( 为什么Post请求需要预检)


    前端原始代码

  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值不匹配导致的。

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐