Java 如何解决跨域问题

网友投稿 268 2023-01-28

Java 如何解决跨域问题

引言

我们在开发过程中经常会遇到前后端分离而导致的跨域问题,导致无法获取返回结果。跨域就像分离前端和后端的一道鸿沟,君在这边,她在那边,两两不能往来.

什么是跨域(CORS)

跨域(CORS)是指不同域名之间相互访问。跨域,指的是浏览器不能执行其他网站的脚本,它是由浏览器的同源策略所造成的,是浏览器对于javascript所定义的安全限制策略。

什么情况会跨域

同一协议, 如http或https

同一IP地址, 如127.0.0.1

同一端口, 如8080

以上三个条件中有一个条件不同就会产生跨域问题。

解决方案

前端解决方案

使用jsONP方式实现跨域调用;

使用NodeJS服务器做为服务代理,前端发起请求到NodeJS服务器, NodeJS服务器代理转发请求到后端服务器;

后端解决方案

nginx反向代理解决跨域

服务端设置Response Header(响应头部)的Access-Control-Allow-Origin

在需要跨域访问的类和方法中设置允许跨域访问(如Spring中使用@CrossOrigin注解);

继承使用Spring Web的CorsFilter(适用于Spring MVC、Spring Boot)

实现WebMvcConfigurer接口(适用于Spring Boot)

具体方式

一、使用Filter方式进行设置

使用Filter过滤器来过滤服务请求,向请求端设置Response Header(响应头部)的Access-Control-Allow-Origin属性声明允许跨域访问。

@WebFilter

public class CorsFilter implements Filter {

@Override

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

HttpServletResponse response = (HttpServletResponse) res;

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

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

response.setHeader("Access-Control-Max-Age", "3600");

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

response.setHeader("Access-Control-Allow-Credentials", "true");

chain.doFilter(req, res);

}

}

二、继承 HandlerInterceptorAdapter

@Component

public class CrossInterceptor extends HandlerInterceptorAdapter {

@Override

public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

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

FYOHEN response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");

response.setHeader("Access-Control-Max-Age", "3600");

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

response.setHeader("Access-Control-Allow-CredentiaFYOHENls", "true");

return true;

}

}

三、实现 WebMvcConfigurer

@Configuration

@SuppressWarnings("SpringjavaAutowiredFieldsWarningInspection")

public class AppConfig implements WebMvcConfigurer {

@Override

public void addCorsMappings(CorsRegistry registry) {

registry.addMapping("/**") // 拦截所有的请求

.allowedOrigins("http://abc.com") // 可跨域的域名,可以为 *

.allowCredentials(true)

.allowedMethods("*") // 允许跨域的方法,可以单独配置

.allowedHeaders("*"); // 允许跨域的请求头,可以单独配置

}

}

四、使用Nginx配置

location / {

add_header Access-Control-Allow-Origin *;

add_header Access-Control-Allow-Headers X-Requested-With;

add_header Ahttp://ccess-Control-Allow-Methods GET,POST,PUT,DELETE,OPTIONS;

if ($request_method = 'OPTIONS') {

return 204;

}

}

五、使用 @CrossOrgin 注解

如果只是想部分接口跨域,且不想使用配置来管理的话,可以使用这种方式

在Controller使用

@CrossOrigin

@RestController

@RequestMapping("/user")

public class UserController {

@GetMapping("/{id}")

public User get(@PathVariable Long id) {

}

@DeleteMapping("/{id}")

public void remove(@PathVariable Long id) {

}

}

在具体接口上使用

@RestController

@RequestMapping("/user")

public class UserController {

@CrossOrigin

@GetMapping("/{id}")

public User get(@PathVariable Long id) {

}

@DeleteMapping("/{id}")

public void remove(@PathVariable Long id) {

}

}

Spring Cloud Gateway 跨域配置

spring:

cloud:

gateway:

globalcors:

cors-configurations:

'[/**]':

# 允许跨域的源(网站域名/ip),设置*为全部

# 允许跨域请求里的head字段,设置*为全部

# 允许跨域的method, 默认为GET和OPTIONS,设置*为全部

allow-credentials: true

allowed-origins:

- "http://xb.abc.com"

- "http://sf.xx.com"

allowed-headers: "*"

allowed-methods:

- OPTIONS

- GET

- POST

- DELETE

- PUT

- PATCH

max-age: 3600

注意: 通过gateway 转发的其他项目,不要进行配置跨域配置

有时即使配置了也不会起作用,这时你可以根据浏览器控制的错误输出来查看问题,如果提示是 response 中 header 出现了重复的 Access-Control-* 请求头,可以进行如下操作

import java.util.ArrayList;

import org.springframework.cloud.gateway.filter.GatewayFilterChain;

import org.springframework.cloud.gateway.filter.GlobalFilter;

import org.springframework.cloud.gateway.filter.NettyWriteResponseFilter;

import org.springframework.core.Ordered;

import org.springframework.http.HttpHeaders;

import org.springframework.stereotype.Component;

import org.springframework.web.server.ServerWebExchange;

import reactor.core.publisher.Mono;

@Component("corsResponseHeaderFilter")

public class CorsResponseHeaderFilter implements GlobalFilter, Ordered {

@Override

public int getOrder() {

// 指定此过滤器位于NettyWriteResponseFilter之后

// 即待处理完响应体后接着处理响应头

return NettyWriteResponseFilter.WRITE_RESPONSE_FILTER_ORDER + 1;

}

@Override

public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {

return chain.filter(exchange).then(Mono.defer(() -> {

exchange.getResponse().getHeaders().entrySet().stream()

.filter(kv -> (kv.getValue() != null && kv.getValue().size() > 1))

.filter(kv -> (

kv.getKey().equals(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN)

|| kv.getKey().equals(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS)

|| kv.getKey().equals(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS)

|| kv.getKey().equals(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS)

|| kv.getKey().equals(HttpHeaders.ACCESS_CONTROL_MAX_AGE)))

.forEach(kv -> {

kv.setValue(new ArrayList() {{

add(kv.getValue().get(0));

}});

});

return chain.filter(exchange);

}));

}

}

以上就是Java 如何解决跨域问题的详细内容,更多关于Java 解决跨域问题的资料请关注我们其它相关文章!

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:快递单号查询免费api(快递单号查询免费查询快递100)
下一篇:Gradle的基本使用
相关文章

 发表评论

暂时没有评论,来抢沙发吧~