12人参与 • 2025-06-10 • Java
在spring boot 中给我们提供了一个注解 @crossorigin 来实现跨域,这个注解可以实现方法级别的细粒度的跨域控制。
我们可以在类或者方添加该注解,如果在类上添加该注解,该类下的所有接口都可以通过跨域访问,如果在方法上添加注解,那么仅仅只限于加注解的方法可以访问。
@slf4j @restcontroller @requestmapping(value = apppath.service_location_url + "/appointment") @api(value = "appointmentcontroller",tags = "预约列表接口") @crossorigin public class appointmentcontroller { @autowired private liveappointmentservice appointmentservice; @requestmapping @apioperation(value = "预约列表分页查询", response = csliveappointmentdto.class) public jsonresult<pageinfo> getappointmentlist(appointmentlistdto dto){ log.info("getappointmentlist vo:{}", jsonutil.tojsonstr(dto)); pageinfo<csliveappointmentdto> appointmentlist = appointmentservice.getappointmentlist(dto); return jsonresult.success(appointmentlist); } }
@crossorigin 注解不生效问题
在spring框架4.2版本后,spring给出了注解的方式解决问题。
即在controller控制器中,在controller注解上方添加@crossorigin注解。
但是使用这种方式后也有可能仍然出现跨域问题,解决方案就是:
@slf4j @restcontroller @requestmapping(value = apppath.service_location_url + "/appointment") @api(value = "appointmentcontroller",tags = "预约列表接口") @crossorigin public class appointmentcontroller { @autowired private liveappointmentservice appointmentservice; @apioperation(value = "预约列表分页查询", response = csliveappointmentdto.class) //@getmapping("getlist") @requestmapping(method = requestmethod.get) public jsonresult<pageinfo> getappointmentlist(appointmentlistdto dto){ log.info("getappointmentlist vo:{}", jsonutil.tojsonstr(dto)); pageinfo<csliveappointmentdto> appointmentlist = appointmentservice.getappointmentlist(dto); return jsonresult.success(appointmentlist); } }
@configuration public class webmvcconfig implements webmvcconfigurer { @override public void addcorsmappings(corsregistry registry) { registry.addmapping("/**") .allowedorigins("*") .allowedmethods("post","get","options") .allowedheaders("*") .allowcredentials(false).maxage(3600); } }
@webfilter(filtername = "corsfilter") @configuration @order(ordered.highest_precedence) @slf4j public class corsfilter implements filter { @value("${allow.headers:x-requested-with,authorization,content-type}") private string allowheaders; @value("${allow.origin:https://xxx.com}") private string alloworigin; @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-origin", "http://xxx:9091"); response.setheader("access-control-allow-credentials", "true"); response.setheader("access-control-allow-methods", "post, get, patch,options, delete, put"); response.setheader("access-control-max-age", "3600"); response.setheader("access-control-allow-headers", allowheaders); // response.setheader("access-control-allow-headers", "*"); log.info("corsfilter res {},{}", response.getheader("access-control-allow-origin"), response.containsheader("access-control-allow-origin")); chain.dofilter(req, res); } }
跨域不生效问题
(1)、@order(ordered.highest_precedence)如果有登录拦截,要将跨域filter等级提升为最高优先级
(2)、 response.setheader(“access-control-allow-headers”, “");
(3)、 response.setheader(“access-control-allow-origin”, "”)
//指定允许其他域名访问 ‘access-control-allow-origin:http://172.80.0.206'//一般用法(,指定域,动态设置),3是因为不允许携带认证头和cookies //是否允许后续请求携带认证信息(cookies),该值只能是true,否则不返回
(4)、 response.setheader(“access-control-allow-methods”, “post, get, patch,options, delete, put”);options 在预检请求复杂请求中也会使用到
(5)、 如果有spring security结合使用需要添加该过滤器
@configuration public class securityconfig extends websecurityconfigureradapter { @override protected void configure(httpsecurity security) throws exception { security.csrf().disable(); security.headers().frameoptions().disable(); //加入过滤器 security.addfilterbefore(new corsfilter(), usernamepasswordauthenticationfilter.class); } }
前面要么是*,实际需求是根据业务参数定制化
@webfilter(filtername = "corsfilter", urlpatterns = "/*", initparams = {@webinitparam(name = "alloworigin", value = "*"), @webinitparam(name = "allowmethods", value = "get,post,put,delete,options"), @webinitparam(name = "allowcredentials", value = "true"), @webinitparam(name = "allowheaders", value = "content-type,x-token")}) public class corsfilter implements filter { private string alloworigin; private string allowmethods; private string allowcredentials; private string allowheaders; private string exposeheaders; @override public void init(filterconfig filterconfig) throws servletexception { alloworigin = filterconfig.getinitparameter("alloworigin"); allowmethods = filterconfig.getinitparameter("allowmethods"); allowcredentials = filterconfig.getinitparameter("allowcredentials"); allowheaders = filterconfig.getinitparameter("allowheaders"); exposeheaders = filterconfig.getinitparameter("exposeheaders"); } @override public void dofilter(servletrequest servletrequest, servletresponse servletresponse, filterchain filterchain) throws ioexception, servletexception { httpservletrequest request = (httpservletrequest) servletrequest; httpservletresponse response = (httpservletresponse) servletresponse; if (!stringutils.isempty(alloworigin)) { if(alloworigin.equals("*")){ // 设置哪个源可以访问 response.setheader("access-control-allow-origin", alloworigin); }else{ list<string> alloworiginlist = arrays.aslist(alloworigin.split(",")); if (alloworiginlist != null && alloworiginlist.size() > 0) { string currentorigin = request.getheader("origin"); if (alloworiginlist.contains(currentorigin)) { response.setheader("access-control-allow-origin", currentorigin); } } } } if (!stringutils.isempty(allowmethods)) { //设置哪个方法可以访问 response.setheader("access-control-allow-methods", allowmethods); } if (!stringutils.isempty(allowcredentials)) { // 允许携带cookie response.setheader("access-control-allow-credentials", allowcredentials); } if (!stringutils.isempty(allowheaders)) { // 允许携带哪个头 response.setheader("access-control-allow-headers", allowheaders); } if (!stringutils.isempty(exposeheaders)) { // 允许携带哪个头 response.setheader("access-control-expose-headers", exposeheaders); } filterchain.dofilter(servletrequest, servletresponse); } @override public void destroy() { } }
原理和前面类似
import org.springframework.context.annotation.bean; import org.springframework.context.annotation.configuration; import org.springframework.web.cors.corsconfiguration; import org.springframework.web.cors.reactive.corswebfilter; import org.springframework.web.cors.reactive.urlbasedcorsconfigurationsource; import org.springframework.web.util.pattern.pathpatternparser; @configuration public class corsconfig { @bean public corswebfilter corsfilter() { corsconfiguration config = new corsconfiguration(); config.setallowcredentials(boolean.true);//允许cookie跨域 config.addallowedmethod("*"); config.addallowedorigin("*"); config.addallowedheader("*");//不要设置成*,参考前面 urlbasedcorsconfigurationsource source = new urlbasedcorsconfigurationsource(new pathpatternparser()); source.registercorsconfiguration("/**", config); return new corswebfilter(source); } }
注:在下层服务不需要在做任何跨域配置,例如注解@crossorigin,否则会由于配置冲突导致依然出现跨域问题
server { listen 8000; server_name localhost; # / 表示匹配路径为/的url location / { proxy_pass http://需要跨域的域名:5500; } # /user 表示访问以/user 开头 的地址 如/username,/user/find等 location /user { proxy_pass http://需要跨域的域名:3000; } }
# # wide-open cors config for nginx # location / { #### 对options请求,会设置很多的请求头,并返回204 if ($request_method = 'options') { add_header 'access-control-allow-origin' '*'; add_header 'access-control-allow-methods' 'get, post, options'; # # custom headers and headers various browsers *should* be ok with but aren't # add_header 'access-control-allow-headers' 'dnt,user-agent,x-requested-with,if-modified-since,cache-control,content-type,range'; # # tell client that this pre-flight info is valid for 20 days # add_header 'access-control-max-age' 1728000; add_header 'content-type' 'text/plain; charset=utf-8'; add_header 'content-length' 0; return 204; } if ($request_method = 'post') { add_header 'access-control-allow-origin' '*'; add_header 'access-control-allow-methods' 'get, post, options'; add_header 'access-control-allow-headers' 'dnt,user-agent,x-requested-with,if-modified-since,cache-control,content-type,range'; add_header 'access-control-expose-headers' 'content-length,content-range'; } if ($request_method = 'get') { add_header 'access-control-allow-origin' '*'; add_header 'access-control-allow-methods' 'get, post, options'; add_header 'access-control-allow-headers' 'dnt,user-agent,x-requested-with,if-modified-since,cache-control,content-type,range'; add_header 'access-control-expose-headers' 'content-length,content-range'; } }
以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。
您想发表意见!!点此发布评论
版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。
发表评论