专业编程教程与实战项目分享平台

网站首页 > 技术文章 正文

详细介绍在Spring Boot项目中如何解决跨域问题?

ins518 2024-12-10 15:55:46 技术文章 17 ℃ 0 评论

在现代Web应用程序中,前端和后端往往分离,前端可能部署在一个服务器上,后端API部署在另一个服务器上。这时,就可能会遇到跨域问题(CORS,Cross-Origin Resource Sharing)。跨域是指浏览器因安全性限制,阻止网页去访问不同域、协议或端口的资源。为了保证前端应用能够正常与后端进行数据交互,需要通过跨域资源共享(CORS)来解决。

本文将详细介绍在Spring Boot项目中如何解决跨域问题,包含常见的解决方案及配置方法。

什么是跨域问题?

跨域问题是指在前端页面中发起的请求,目标服务器与当前页面的域名、协议或端口不一致时,浏览器会因为同源策略(Same-Origin Policy)而阻止这些请求。

同源策略规定,只有当请求的目标与当前页面具有相同的协议、域名和端口时,才允许访问;否则会被浏览器拦截,导致前端无法正常获取资源或数据。

例如,当前页面地址是 http://localhost:8080,但你在前端发起请求访问 http://localhost:9000/api/data,就会产生跨域问题。

Spring Boot中解决跨域问题的方法

使用@CrossOrigin注解

Spring Boot提供了一个非常方便的注解@CrossOrigin,可以用来标注需要允许跨域请求的方法或类。这是解决跨域问题最简单的方法。

在Controller类上使用@CrossOrigin

我们可以在控制器类上使用@CrossOrigin注解,表示该控制器中的所有API都支持跨域请求。

@RestController
@CrossOrigin // 允许所有域名跨域访问
public class MyController {

    @GetMapping("/api/data")
    public String getData() {
        return "Hello from Spring Boot!";
    }
}

在单个方法上使用@CrossOrigin

如果只希望某个特定的API支持跨域请求,可以在该方法上使用@CrossOrigin注解。如下所示。

@RestController
public class MyController {

    @CrossOrigin(origins = "http://localhost:3000")  // 仅允许localhost:3000跨域请求
    @GetMapping("/api/data")
    public String getData() {
        return "Hello from Spring Boot!";
    }
}

常用的@CrossOrigin属性

  • origins: 设置允许跨域的源地址(可以是单个地址、多个地址或通配符*)。例如:origins = "http://localhost:3000", origins = "*"
  • methods: 设置允许跨域的HTTP方法(如GET、POST等)。默认值为RequestMethod.GET, RequestMethod.POST, RequestMethod.OPTIONS。
  • allowedHeaders: 设置允许的请求头部。
  • exposedHeaders: 设置暴露给浏览器的响应头部。
  • allowCredentials: 是否允许携带认证信息(如cookie)。默认为false。
  • maxAge: 浏览器缓存预检请求的时间,单位是秒。

使用全局CORS配置

@CrossOrigin注解只适用于个别的控制器或方法,如果你希望对整个应用程序中的所有API都支持跨域请求,可以通过Spring Boot的全局配置来实现。

配置CORS映射

Spring Boot提供了一个WebMvcConfigurer接口,可以通过实现这个接口来自定义全局的CORS配置。这种方式可以避免在每个Controller中都加上@CrossOrigin注解,代码更加简洁。可以集中管理跨域配置,方便修改和维护。

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        // 配置跨域规则
        registry.addMapping("/api/**")  // 指定允许跨域的路径
                .allowedOrigins("http://localhost:3000")  // 允许的源
                .allowedMethods("GET", "POST")  // 允许的HTTP方法
                .allowedHeaders("*")  // 允许的请求头
                .allowCredentials(true)  // 是否允许携带凭证
                .maxAge(3600);  // 设置预检请求的缓存时间
    }
}

配置详解

  • addMapping("/api/**"): 配置允许跨域请求的路径,/api/**表示所有以/api/开头的路径都支持跨域。
  • allowedOrigins("http://localhost:3000"): 允许从http://localhost:3000域发起的跨域请求。如果需要支持多个源,可以传入多个URL。
  • allowedMethods("GET", "POST"): 允许的HTTP方法。如果不设置,默认支持GET、POST和OPTIONS。
  • allowedHeaders("*"): 允许所有请求头。可以根据需要进行限制。
  • allowCredentials(true): 设置是否允许跨域请求携带凭证(如Cookies)。默认为false。
  • maxAge(3600): 设置浏览器预检请求(OPTIONS请求)的缓存时间。

使用过滤器解决跨域

除了使用@CrossOrigin注解和WebMvcConfigurer进行全局配置外,我们还可以通过自定义过滤器来处理跨域问题,可以对特定的路径或条件进行控制。还可以在过滤器中加入更多逻辑,比如自定义请求头或对特定IP进行限制等。如下所示。

@WebFilter("/*")  // 配置该过滤器拦截所有请求
public class CORSFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletResponse res = (HttpServletResponse) response;
        res.setHeader("Access-Control-Allow-Origin", "*");  // 允许所有来源的跨域请求
        res.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");  // 允许的HTTP方法
        res.setHeader("Access-Control-Allow-Headers", "Origin, Content-Type, Accept, Authorization");  // 允许的请求头
        res.setHeader("Access-Control-Allow-Credentials", "true");  // 是否允许携带认证信息
        res.setHeader("Access-Control-Max-Age", "3600");  // 设置预检请求的有效期
        chain.doFilter(request, response);
    }

    @Override
    public void destroy() {
    }
}

在Spring Boot中启用自定义过滤器

为了在Spring Boot中启用这个过滤器,需要在配置类中进行注册

@Configuration
public class FilterConfig {

    @Bean
    public FilterRegistrationBean<CORSFilter> corsFilter() {
        FilterRegistrationBean<CORSFilter> registrationBean = new FilterRegistrationBean<>();
        registrationBean.setFilter(new CORSFilter());
        registrationBean.addUrlPatterns("/api/*");  // 只对/api/*路径的请求生效
        return registrationBean;
    }
}

总结

在Spring Boot项目中,跨域问题是前后端分离架构中常见的问题。选择哪种方式取决于项目的需求和复杂度。总的来说,Spring Boot提供了灵活且简便的跨域处理机制,帮助我们高效地解决前后端分离中的跨域问题。

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表