Spring boot跨域设置实例详解
定义:跨域是指从一个域名的网页去请求另一个域名的资源
1.原由
公司内部有多个不同的子域,比如一个是location.company.com,而应用是放在app.company.com,这时想从app.company.com去访问location.company.com的资源就属于跨域
本人是springboot菜鸟,但是做测试框架后端需要使用Springboot和前端对接,出现跨域问题,需要设置后端Response的Header.走了不少坑,在这总结一下以备以后使用
2.使用场景
浏览器默认不允许跨域访问,包括我们平时ajax也是限制跨域访问的。
产生跨域访问的情况主要是因为请求的发起者与请求的接受者1、域名不同;2、端口号不同
如果一个网页可以随意地访问另外一个网站的资源,那么就有可能在客户完全不知情的情况下出现安全问题
3.解决方案
通过设置Access-Control-Allow-Origin来实现跨域访问
4.具体解决
刚开始使用http://www.jianshu.com/p/f2060a6d6e3b设置,但是由于我们使用的spring版本的问题,CorsConfiguration类需要4.2.7版本。和我们使用的spring里面版本不一致,导致版本冲突或者各种问题
@Configuration publicclassCorsConfig{ privateCorsConfigurationbuildConfig(){ CorsConfigurationcorsConfiguration=newCorsConfiguration(); corsConfiguration.addAllowedOrigin("*");//1 corsConfiguration.addAllowedHeader("*");//2 corsConfiguration.addAllowedMethod("*");//3 returncorsConfiguration; } @Bean publicCorsFiltercorsFilter(){ UrlBasedCorsConfigurationSourcesource=newUrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**",buildConfig());//4 returnnewCorsFilter(source); } }
后来改为Filter方式
@Component publicclassCorsFilterimplementsFilter{ finalstaticorg.slf4j.Loggerlogger=org.slf4j.LoggerFactory.getLogger(CorsFilter.class); publicvoiddoFilter(ServletRequestreq,ServletResponseres,FilterChainchain)throwsIOException,ServletException{ HttpServletResponseresponse=(HttpServletResponse)res; HttpServletRequestreqs=(HttpServletRequest)req; response.setHeader("Access-Control-Allow-Origin","*"); response.setHeader("Access-Control-Allow-Credentials","true"); response.setHeader("Access-Control-Allow-Methods","POST,GET,OPTIONS,DELETE"); response.setHeader("Access-Control-Max-Age","3600"); response.setHeader("Access-Control-Allow-Headers","x-requested-with"); chain.doFilter(req,res); } publicvoidinit(FilterConfigfilterConfig){} publicvoiddestroy(){} }
后来改为Filter方式
@Component publicclassCorsFilterimplementsFilter{ finalstaticorg.slf4j.Loggerlogger=org.slf4j.LoggerFactory.getLogger(CorsFilter.class); publicvoiddoFilter(ServletRequestreq,ServletResponseres,FilterChainchain)throwsIOException,ServletException{ HttpServletResponseresponse=(HttpServletResponse)res; HttpServletRequestreqs=(HttpServletRequest)req; response.setHeader("Access-Control-Allow-Origin","*"); response.setHeader("Access-Control-Allow-Credentials","true"); response.setHeader("Access-Control-Allow-Methods","POST,GET,OPTIONS,DELETE"); response.setHeader("Access-Control-Max-Age","3600"); response.setHeader("Access-Control-Allow-Headers","x-requested-with"); chain.doFilter(req,res); } publicvoidinit(FilterConfigfilterConfig){} publicvoiddestroy(){} }
网上很多资料都是教按以上方法设置,但是我这里就是设置不成功的。出现下面问题
FetchAPIcannotloadhttps://atfcapi.alpha.elenet.me/atfcapi/project/mainPageList.Thevalueofthe'Access-Control-Allow-Origin'
headerintheresponsemustnotbethewildcard'*'whentherequest'scredentialsmodeis'include'.Origin'https://atfcapi-test.faas.elenet.me'isthereforenotallowedaccess.
目前为止,不知道为什么这样配置不可以,然后改为设置单个域名,如下显示
response.setHeader("Access-Control-Allow-Origin","https://atfcapi-test.faas.elenet.me");
这样设置就成功了,但是我们有好几个环境,同一套代码,写死一个域名并解决不了问题,
按照很多网络文章中所说,设置多个域名如下:
response.setHeader("Access-Control-Allow-Origin","https://atfcapi-test.faas.elenet.me,https://atfcapi-test-beta.faas.elenet.me");
但是设置完以后,并不好用,出现如下错误信息:
FetchAPIcannotloadhttps://atfcapi.alpha.elenet.me/atfcapi/project/getProjects.The'Access-Control-Allow-Origin'headercontainsmultiplevalues
'https://atfcapi-test.faas.elenet.me,https://atfcapi-test-beta.faas.elenet.me',butonlyoneisallowed.Origin'https://atfcapi-test.faas.elenet.me'isthereforenotallowedaccess.Havetheserversendtheheaderwithavalidvalue,or,ifanopaqueresponseservesyourneeds,settherequest'smodeto'no-cors'tofetchtheresourcewithCORSdisabled.
设置为以下方式也还是错误:
response.setHeader("Access-Control-Allow-Origin","https://atfcapi-test.faas.elenet.me"); response.setHeader("Access-Control-Allow-Origin","https://atfcapi-test-beta.faas.elenet.me");
最后采用了一种和设置为*的方式一样的办法,代码如下:
@Component publicclassCorsFilterimplementsFilter{ finalstaticorg.slf4j.Loggerlogger=org.slf4j.LoggerFactory.getLogger(CorsFilter.class); publicvoiddoFilter(ServletRequestreq,ServletResponseres,FilterChainchain)throwsIOException,ServletException{ HttpServletResponseresponse=(HttpServletResponse)res; HttpServletRequestreqs=(HttpServletRequest)req; response.setHeader("Access-Control-Allow-Origin",reqs.getHeader("Origin")); response.setHeader("Access-Control-Allow-Credentials","true"); response.setHeader("Access-Control-Allow-Methods","POST,GET,OPTIONS,DELETE"); response.setHeader("Access-Control-Max-Age","3600"); response.setHeader("Access-Control-Allow-Headers","x-requested-with"); chain.doFilter(req,res); } publicvoidinit(FilterConfigfilterConfig){} publicvoiddestroy(){} }
从request中的header中获取Origin,来做配置,最终成功并满足需求。
其实有些东西还是一知半解,但是起码曲线救国也是一种解决方法。
总结
以上就是本文关于Springboot跨域设置实例详解的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站:
快速了解SpringBoot
SpringBoot集成多数据源解析
Maven管理SpringBootProfile详解
如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!