Java 如何解决跨域问题
程序员文章站
2022-03-31 08:35:57
引言我们在开发过程中经常会遇到前后端分离而导致的跨域问题,导致无法获取返回结果。跨域就像分离前端和后端的一道鸿沟,君在这边,她在那边,两两不能往来.什么是跨域(cors)跨域(cors)是指不同域名之...
引言
我们在开发过程中经常会遇到前后端分离而导致的跨域问题,导致无法获取返回结果。跨域就像分离前端和后端的一道鸿沟,君在这边,她在那边,两两不能往来.
什么是跨域(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", "*"); 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-credentials", "true"); return true; } }
三、实现 webmvcconfigurer
@configuration @suppresswarnings("springjavaautowiredfieldswarninginspection") public class appconfig implements webmvcconfigurer { @override public void addcorsmappings(corsregistry registry) { registry.addmapping("/**") // 拦截所有的请求 .allowedorigins("http://www.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 access-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<void> 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<string>() {{ add(kv.getvalue().get(0)); }}); }); return chain.filter(exchange); })); } }
以上就是java 如何解决跨域问题的详细内容,更多关于java 解决跨域问题的资料请关注其它相关文章!