Springboot后端CORS跨域资源共享

简介

CORS:全称"跨域资源共享"(Cross-origin resource sharing)。

  • CORS需要浏览器和服务器同时支持,才可以实现跨域请求,目前几乎所有浏览器都支持CORS,IE则不能低于IE10。CORS的整个过程都由浏览器自动完成,前端无需做任何设置,跟平时发送ajax请求并无差异。so,实现CORS的关键在于服务器,只要服务器实现CORS接口,就可以实现跨域通信。

  • Spring解决跨域问题其实很简单,可以在局部设置,也可以抽出一个配置类,我这里做的是整体,下面的代码直接粘过去就行不用改动。

@Configuration
public class CORSConfiguration {
    @Bean
    public WebMvcConfigurer CORSConfigurer() {
        return new WebMvcConfigurerAdapter() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/**")
                      .allowedOrigins("*")
                        .allowedMethods("*")
                        .allowedHeaders("*")
                        //.allowedMethods("GET", "POST", "DELETE", "PUT")
                        //设置是否允许跨域传cookie
                        .allowCredentials(true)
                        //设置缓存时间,减少重复响应
                        .maxAge(3600);
            }
        };
    }
}

其实这里写完就可以进行跨域请求了,但是浏览器这个坑爹的东西,跨域问题后面又跟着简单和复杂请求,下面先解释一下这两种请求:

  • 跨域请求又分为简单请求与复杂请求(这是下面解决问题的重点):

  • 1、 同时满足以下两种条件的,就是简单请求

(1) 请求方法是以下三种方法之一:

  • HEAD、 GET、POST

(2)HTTP的头信息不超出以下几种字段:

  • Accept、 Accept-Language、Content-Language、Last-Event-ID、
    Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain

2、上述只要有一条不满足就为复杂请求。

  • 在复杂请求中,有个地方是需要我们注意的:options预检请求,简单来说就是浏览器在发送复杂请求时的一种处理方式,在真正发送请求时候,会先发送一个预检请求,用来确定服务器响应是否正确,是否能接收真正的请求,如果options请求过后状态是500,那真正请求也就不在发送了。

  • 根据上面说的我们知道,options请求只是去检查,并不是真正的请求,也就不会携带数据,那么我们想要接收真正请求就需要将它放行,过滤掉。我这里权限用的是shiro,过滤器的写法都大同小异,后面会出一个springboot整合shiro的文章。

  • 下面代码直接复制进去就可以了。

import org.apache.shiro.web.filter.authc.UserFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.RequestMethod;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

public class ShiroUserFilter extends UserFilter {


    /*在访问过来的时候检测是否为OPTIONS请求,如果是就直接返回true*/
    @Override
    protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception {
        HttpServletResponse httpResponse = (HttpServletResponse) response;
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        if (httpRequest.getMethod().equals(RequestMethod.OPTIONS.name())) {
            setHeader(httpRequest,httpResponse);
            return true;
        }
        return super.preHandle(request,response);
    }

     /* 该方法会在验证失败后调用,因此重写改成传输JSON数据*/
    @Override
    protected void saveRequestAndRedirectToLogin(ServletRequest request, ServletResponse response) throws IOException {
        saveRequest(request);
        setHeader((HttpServletRequest) request,(HttpServletResponse) response);
        PrintWriter out = response.getWriter();
        //out.println(JSONObject.toJSONString(ResultUtil.error(ExceptionEnum.IS_NOT_LOGIN)));
        out.flush();
        out.close();
    }

 /* 实现跨域*/
    private void setHeader(HttpServletRequest request,HttpServletResponse response){
        //跨域的header设置
        response.setHeader("Access-control-Allow-Origin", "*");
        response.setHeader("Cache-Control","no-cache");
        response.setHeader("Access-Control-Allow-Headers",  "Origin, X-Requested-With, Content-Type, Accept");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET,PUT,OPTIONS, DELETE");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        //防止乱码,适用于传输JSON数据
        response.setHeader("Content-Type","application/json;charset=UTF-8");
        response.setStatus(HttpStatus.OK.value());
    }

    @Bean
    public FilterRegistrationBean registration(ShiroUserFilter filter) {
        FilterRegistrationBean registration = new FilterRegistrationBean(filter);
        registration.setEnabled(false);
        return registration;
    }

}

到这里整个的后端跨域也就都完成了。但是我在做这部分的时候,可以进行跨域请求,http请求状态为200,但是前端无法接收到参数,这里面有个小细节ajax在进行请求时候,由于浏览器的同源问题,默认只能收到同一域名下的cookie,所以出现了状态200,但是无数据的情况。
只需要在前端代码中加入下面的代码

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

在做跨域的时候发现好多文章里面都少了这部分,不然就算服务器同意跨域,浏览器也是不同意的。具体细节的话请看阮一峰大神的博客。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Spring Boot中配置后端CORS跨域资源共享)响应头可以通过以下几个步骤完成: 1. 添加CORS依赖:首先,在你的项目的pom.xml文件中添加以下CORS依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> </dependency> ``` 2. 创建一个CORS配置类:在你的项目中创建一个名为CORSConfig(或类似名称)的Java类,并添加以下内容: ```java @Configuration public class CORSConfig implements WebFluxConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("*") .allowedMethods("GET", "POST", "PUT", "DELETE") .allowedHeaders("*") .allowCredentials(true) .maxAge(3600); } } ``` 上述代码中,使用`CorsRegistry`来配置CORS。`.addMapping("/**")`表示允许所有的请求路径进行跨域请求。`.allowedOrigins("*")`表示允许所有的来源进行跨域请求。`.allowedMethods("GET", "POST", "PUT", "DELETE")`表示允许的HTTP方法。`.allowedHeaders("*")`表示允许所有的请求头。`.allowCredentials(true)`表示允许发送身份验证信息。`.maxAge(3600)`表示在指定时间内缓存这个CORS配置。 3. 启用CORS配置:在你的应用程序的启动类(通常是一个带有`@SpringBootApplication`注解的类)中添加`@EnableWebFlux`注解以启用WebFlux和CORS配置。 ```java @SpringBootApplication @EnableWebFlux public class YourApplication { public static void main(String[] args) { SpringApplication.run(YourApplication.class, args); } } ``` 以上就是在Spring Boot中配置后端CORS响应头的步骤。配置完成后,你的后端应用程序将允许来自任何来源的跨域请求。请根据你的具体需求进行必要的修改。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值