请描述一下如何在SpringBoot项目中实现跨域请求(CORS)的处理?

在Web开发中,出于安全考虑,浏览器通常会阻止一个域的JavaScript代码访问另一个域的资源,这种策略被称为“同源策略”。跨源资源共享(CORS)是一种机制,它允许或拒绝来自不同源的Web页面对服务器资源的请求。在Spring Boot应用中,你可以通过几种方法来处理CORS。

1. 全局CORS配置

你可以通过重写WebMvcConfigureraddCorsMappings方法来实现全局CORS配置。这种方式会应用到你的整个Spring Boot应用。

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("http://example.com")
                .allowedMethods("GET", "POST", "PUT", "DELETE")
                .allowedHeaders("*")
                .allowCredentials(true);
    }
}

在这个配置中,addMapping("/**")表示对所有的URL都可以进行跨域请求。allowedOrigins指定了哪些原始域可以访问资源,allowedMethods指定了允许的HTTP方法,allowedHeaders允许的头信息,allowCredentials用于表示是否允许发送Cookie信息。

2. 控制器方法级别的CORS配置

如果你只希望对某些特定的请求处理函数启用CORS,你可以在这些函数上使用@CrossOrigin注解。

@RestController
@RequestMapping("/api")
public class MyController {

    @CrossOrigin(origins = "http://example.com")
    @GetMapping("/example")
    public String example() {
        return "Example";
    }
}

在这个例子中,只有/api/example这个请求支持从http://example.com发起的跨域请求。

3. 使用@CrossOrigin注解在类级别上配置CORS

你也可以将@CrossOrigin注解用在控制器类上,这样该控制器类中的所有请求处理方法都会支持CORS。

@CrossOrigin(origins = "http://example.com", maxAge = 3600)
@RestController
@RequestMapping("/api")
public class MyController {
    // ... 省略方法 ...
}

在这个例子中,maxAge属性定义了预检请求的缓存时间(以秒为单位)。

4. 通过Filter处理CORS

另一种比较底层的方式是创建一个自定义的过滤器,然后在过滤器中设置CORS头。

@Component
public class SimpleCORSFilter implements Filter {

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
            throws IOException, ServletException {

        HttpServletResponse response = (HttpServletResponse) res;
        HttpServletRequest request = (HttpServletRequest) req;

        response.setHeader("Access-Control-Allow-Origin", "http://example.com");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "x-requested-with, authorization");

        if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
            response.setStatus(HttpServletResponse.SC_OK);
        } else {
            chain.doFilter(req, res);
        }
    }

    // ... 省略其他方法 ...
}

在这个自定义Filter中,我们可以针对进入应用的HTTP请求设置响应头,从而使得特定的域可以接收到响应。

注意

虽然可以通过设置allowedOrigins("*")来允许所有的域进行跨域请求,但这种做法并不安全,因为它允许任何网站发送请求到你的服务端。在实际生产环境中,建议指定确切的、可信的域名列表,或者使用其他安全策略来限制跨域访问。

发表评论

后才能评论