定義:跨域是指從一個域名的網頁去請求另一個域名的資源
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里面版本不一致,導致版本沖突或者各種問題
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
@Configuration public class CorsConfig { private CorsConfiguration buildConfig() { CorsConfiguration corsConfiguration = new CorsConfiguration(); corsConfiguration.addAllowedOrigin( "*" ); // 1 corsConfiguration.addAllowedHeader( "*" ); // 2 corsConfiguration.addAllowedMethod( "*" ); // 3 return corsConfiguration; } @Bean public CorsFilter corsFilter() { UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration( "/**" , buildConfig()); // 4 return new CorsFilter(source); } } |
后來改為Filter方式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
@Component public class CorsFilter implements Filter { final static org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(CorsFilter. class ); public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletResponse response = (HttpServletResponse) res; HttpServletRequest reqs = (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); } public void init(FilterConfig filterConfig) {} public void destroy() {} } |
后來改為Filter方式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
@Component public class CorsFilter implements Filter { final static org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(CorsFilter. class ); public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletResponse response = (HttpServletResponse) res; HttpServletRequest reqs = (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); } public void init(FilterConfig filterConfig) {} public void destroy() {} } |
網上很多資料都是教按以上方法設置,但是我這里就是設置不成功的。出現下面問題
1
|
<span style="color:#ff0000;">Fetch API cannot load https://atfcapi.alpha.elenet.me/atfcapi/project/mainPageList. The value of the 'Access-Control-Allow-Origin' </span> |
1
|
<span style="color:#ff0000;">header in the response must not be the wildcard '*' when the request's credentials mode is 'include'. Origin 'https://atfcapi-test.faas.elenet.me' is therefore not allowed access.</span> |
目前為止,不知道為什么這樣配置不可以,然后改為設置單個域名,如下顯示
1
|
response.setHeader( "Access-Control-Allow-Origin" , "https://atfcapi-test.faas.elenet.me" ); |
這樣設置就成功了,但是我們有好幾個環境,同一套代碼,寫死一個域名并解決不了問題,
按照很多網絡文章中所說,設置多個域名如下:
1
|
response.setHeader( "Access-Control-Allow-Origin" , "https://atfcapi-test.faas.elenet.me,https://atfcapi-test-beta.faas.elenet.me" ); |
但是設置完以后,并不好用,出現如下錯誤信息:
1
|
<span style="color:#ff6666;">Fetch API cannot load https://atfcapi.alpha.elenet.me/atfcapi/project/getProjects. The 'Access-Control-Allow-Origin' header contains multiple values </span> |
1
|
<span style="color:#ff6666;">'https://atfcapi-test.faas.elenet.me,https://atfcapi-test-beta.faas.elenet.me', but only one is allowed. Origin 'https://atfcapi-test.faas.elenet.me' is therefore not allowed access. Have the server send the header with a valid value, or, if an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.</span> |
設置為以下方式也還是錯誤:
1
2
|
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" ); |
最后采用了一種和設置為* 的方式一樣的辦法,代碼如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
@Component public class CorsFilter implements Filter { final static org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(CorsFilter. class ); public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletResponse response = (HttpServletResponse) res; HttpServletRequest reqs = (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); } public void init(FilterConfig filterConfig) {} public void destroy() {} } |
從request 中的header中獲取Origin,來做配置,最終成功并滿足需求。
其實有些東西還是一知半解,但是起碼曲線救國也是一種解決方法。
總結
以上就是本文關于Spring boot跨域設置實例詳解的全部內容,希望對大家有所幫助。如有不足之處,歡迎留言指出。感謝朋友們對本站的支持!
原文鏈接:http://blog.csdn.net/u011517841/article/details/68490586