您的位置:

解决Java跨域问题的几种方法

一、Ajax及跨域问题

Ajax是一种技术,通过局部刷新页面,可以在用户操作不刷新页面的情况下完成交互,给用户带来更好的交互体验。但是,Ajax请求和响应的数据是通过XMLHttpRequest对象进行交互,需要与服务器进行跨域操作才能够正常传输数据。跨域操作的限制是浏览器安全机制下的结果,也是为了保护用户数据安全的措施。

通常情况下,Ajax跨域问题表现为请求数据失败,控制台会报以下提示:

Access to XMLHttpRequest at 'http://someurl.com' from origin 'http://yourdomain.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

这是因为服务器未设置访问控制策略,浏览器无法获取响应。

解决办法:

1、后端设置Access-Control-Allow-Origin响应头

在后端响应中,设置Access-Control-Allow-Origin响应头,允许指定的来源域访问服务器,例如:

response.setHeader("Access-Control-Allow-Origin", "*");

其中,*表示允许所有域名访问,也可以指定单个域名。特别需要注意的是,如果Access-Control-Allow-Origin中指定的域名与当前访问的域名不一致,那么浏览器会阻止获取响应数据。

2、使用JSONP方式跨域

JSONP(JSON with Padding)是一种跨域数据传输的技术,使用script标签通过GET请求获取数据,可以解决Ajax跨域问题。一般的JSON返回数据格式是:

{
    "key":"value"
}

而JSONP返回的数据格式是::

callback({
    "key":"value"
})

其中,callback是一个函数名,通过GET请求传递给服务器,在返回数据的时候,服务器会返回该函数的调用,实现跨域数据传输的目的。

3、使用代理服务器

代理服务器相当于一个中间人,请求发给它,代理服务器再转发给真正的服务器。在实际使用中,前端请求不再向真正的服务器,而是向代理服务器发起请求,由代理服务器转发请求,在转发的过程中,将Access-Control-Allow-Origin响应头设置成自己的域名。这种方式的优势在于可以掩盖真正的服务器IP地址,提高服务器的安全性。

二、Java Spring Boot解决跨域问题

如果我们使用的是Java后端框架Spring Boot,可以使用Spring Boot提供的CorsConfiguration配置来解决跨域问题。当然,在配置之前,需要先导入Spring Boot的依赖。在pom.xml文件中添加以下代码:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
</dependency>

然后,在Spring Boot的启动类中添加以下代码:

import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurerAdapter() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/**")
                        .allowedOrigins("*")
                        .allowedMethods("GET", "POST", "PUT", "DELETE")
                        .allowedHeaders("*")
                        .allowCredentials(true)
                        .maxAge(3600);
            }
        };
    }
}

通过addMapping方法,将允许处理所有请求路径;allowedOrigins设置允许跨域请求的域名, *表示允许所有域名访问;allowedMethods设置允许的http请求方式;allowedHeaders设置允许的请求头;allowCredentials设置是否允许发送Cookie;maxAge设置预检请求的有效期。

三、Java Nginx配置

如果服务器使用的是Nginx,可以配置Nginx来解决跨域问题。在Nginx的配置文件中添加以下代码:

server {
    listen       80;
    server_name  yourdomain.com;

    location / {
        add_header Access-Control-Allow-Origin *;
        add_header Access-Control-Allow-Methods *;
        add_header Access-Control-Allow-Headers *;
        # 如果需要支持Cookie
        add_header Access-Control-Allow-Credentials true;
        # Access-Control-Max-Age用于对响应结果进行缓存
        add_header Access-Control-Max-Age 3600;
        proxy_pass http://yourbackend.com; # 实际后端地址
    }
}

其中,add_header Access-Control-Allow-Origin *表示允许所有域名访问;add_header Access-Control-Allow-Methods *表示允许所有http请求方式;add_header Access-Control-Allow-Headers *表示允许所有请求头;add_header Access-Control-Allow-Credentials true表示允许发送Cookie。

四、Java Tomcat配置

还有另一种方式可以解决跨域问题,就是在Tomcat的conf/server.xml文件中添加以下代码:

<Host name="localhost"  appBase="webapps"
            unpackWARs="true" autoDeploy="true">
    <Context path="" docBase="xxxapp" reloadable="true">
        <filter>
            <filter-name>CorsFilter</filter-name>
            <filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
            <init-param>
                <param-name>cors.allowed.origins</param-name>
                <param-value>*</param-value>
            </init-param>
            <init-param>
                <param-name>cors.allowed.methods</param-name>
                <param-value>GET,POST,PUT,DELETE,OPTIONS</param-value>
            </init-param>
            <init-param>
                <param-name>cors.allowed.headers</param-name>
                <param-value>Content-Type,accept,Origin,X-Requested-With,Access-Control-Request-Method,Access-Control-Request-Headers</param-value>
            </init-param>
        </filter>
        <filter-mapping>
            <filter-name>CorsFilter</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>
    </Context>
</Host>

其中,host节点配置CORS过滤器,使其禁止对同一个源内的请求进行访问限制时有效。filter-name和filter-class使用CorsFilter,因为它是Tomcat自带的,无需再写自定义实现类。以上init-param都是默认的。

总结

以上是解决Java跨域问题的几种方法,可以根据具体情况选择适合自己的解决方案。无论采取哪种方式,理解跨域问题的本质,正确使用跨域技术,都是解决问题的关键。