掃二維碼與項(xiàng)目經(jīng)理溝通
我們在微信上24小時(shí)期待你的聲音
解答本文疑問/技術(shù)咨詢/運(yùn)營咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流
做Web開發(fā),經(jīng)常會遇到跨域問題,小伙伴們在面試中,也經(jīng)常被問到。這不,又有一位工作3年的小伙伴被問到這樣一道題,說前后端分離后,如果解決跨域問題。

10年積累的網(wǎng)站設(shè)計(jì)制作、成都做網(wǎng)站經(jīng)驗(yàn),可以快速應(yīng)對客戶對網(wǎng)站的新想法和需求。提供各種問題對應(yīng)的解決方案。讓選擇我們的客戶得到更好、更有力的網(wǎng)絡(luò)服務(wù)。我雖然不認(rèn)識你,你也不認(rèn)識我。但先網(wǎng)站設(shè)計(jì)制作后付款的網(wǎng)站建設(shè)流程,更有鳳慶免費(fèi)網(wǎng)站建設(shè)讓你可以放心的選擇與我們合作。
今天,我給大家分享一下我的理解。
這個(gè)問題也有很多小伙伴單獨(dú)問過我,很多小伙伴知道如何解決跨域問題,但是卻說不清楚跨域到底是怎么產(chǎn)生的。所以,回答跨域解決方案之前,我們先來介紹一下跨域產(chǎn)生的原因。
因?yàn)橐话愕臑g覽器都有一個(gè)安全機(jī)制,叫做同源策略限制。所謂同源策略就是指用戶輸入的URL中包含的協(xié)議、域名、端口都完全相同。也就是說,我們使用瀏覽器訪問網(wǎng)頁時(shí),必須符合同源策略的請求才能訪問。如果有一項(xiàng)不同,瀏覽器會覺得有安全風(fēng)險(xiǎn),就不想讓你使用這個(gè)接口的數(shù)據(jù)。
比如,在http://localhost:8080/index 頁面中,用Ajax訪問https://localhost:8081/index.json接口數(shù)據(jù)的時(shí)候,這兩個(gè)URL的協(xié)議和端口不相同,也就是不同源,這就產(chǎn)生了跨域訪問。當(dāng)然,瀏覽器還是會將這個(gè)請求發(fā)送到后臺服務(wù)器,但是,瀏覽器不會接收服務(wù)器響應(yīng)結(jié)果。
舉個(gè)更通俗的例子,就好比你去肯德基點(diǎn)餐,非要點(diǎn)一碗蘭州拉面,店員雖然很鄙視你,但他還是會打電話問一下蘭州拉面館問一下,蘭州拉面館說不給肯德基供貨。所以,你沒有吃到蘭州拉面。這其中,有個(gè)反常的操作,就是雖然你點(diǎn)的蘭州拉面,但是肯德基店員還是幫你打電話問了,是拉面館不給肯德基供貨的,如果拉面館說給肯德基供貨而且把面送過來了,那么你就能吃到蘭州拉面了。
這個(gè)案例中,店員就相當(dāng)于是瀏覽器,肯德基呢就相當(dāng)于當(dāng)前看到的網(wǎng)頁,蘭州拉面館就是相當(dāng)于后臺服務(wù)的接口。肯德基和蘭州拉面不是同一個(gè)老板,相當(dāng)于是不同源。拉州拉面就是你想要的接口數(shù)據(jù)。
但如果使用Postman等開發(fā)工具進(jìn)行交互是不會出現(xiàn)跨域問題的,這是瀏覽器特有的限制。
其實(shí),跨域問題也并不是前后端分離后才有的,后端開發(fā)的程序員一般都遇到過跨域問題。只是前后端分離開發(fā)以后,前端開發(fā)體現(xiàn)跨域問題更加明顯了,經(jīng)常要找后端開發(fā)人員來解決。
為了支持跨域訪問,瀏覽器設(shè)置了預(yù)檢機(jī)制。也就是說在發(fā)出跨域請求時(shí), 瀏覽器會自動(dòng)發(fā)出一個(gè)查詢請求,稱為預(yù)檢請求, 用來確認(rèn)目標(biāo)資源是否支持跨域。
如果請求要滿足以下條件,瀏覽器才不會發(fā)送預(yù)檢請求:
(1)請求方法是GET 、PosT .HEAD其中任意一個(gè)
(2)請求頭中包含Accept、Accept-Language、Content-Language、Content-Type、DPR、Downlink、Save-Data、Viewport.Width、Width字段。
(3)Content-Type的值是text/plain 、multipart/form-data ,application/x-ww-form-urlencoded 中任意一個(gè)。
但是,在實(shí)際項(xiàng)目開發(fā)中,我們請求的Content-Type一般是是text/html、application/json等格式,或者使用自定義請求頭,都會觸發(fā)預(yù)檢請求。
瀏覽器獲取到預(yù)檢請求的響應(yīng)結(jié)果之后,判斷服務(wù)器如果授權(quán)允許訪問這個(gè)資源,就會再次請求真正的URL,如果不允許就會報(bào)這樣一個(gè)錯(cuò)。
has been blocked by CORS policy : No 'Access-contro1-A11ow-Origin' header is present on the requested resource.
我們可以利用瀏覽器的預(yù)檢機(jī)制。
我只需要在后端服務(wù)添加CORS策略的配置就可以解決跨域問題。CORS全稱是Cross Origin Resource Sharing,翻譯過來叫做跨域資源共享。具體解決方案,有以下4種:
1)如果是普通的Web項(xiàng)目,只需要在服務(wù)的根目錄下添加一個(gè)crossdomain.xml文件即可。文件格式如下:
當(dāng)然,使用這種方式不夠靈活,在授權(quán)過度的情況下,會存在一些安全隱患。
2)如果是Spring項(xiàng)目的話,可以添加一個(gè)處理跨域的過濾器或者攔截器。如代碼所示:
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", "POST, GET, OPTIONS, DELETE"); response.setHeader("Access-Control-Max-Age", "3600"); response.setHeader("Access-Control-Allow-Headers", "x-requested-with"); chain.doFilter(req, res); } }3)如果是Spring Boot項(xiàng)目的話,只需要在方法上添加@CrossOrigin注解即可,如代碼所示:
@GetMapping("/list") @CrossOrigin public List list(){ ... } 如果需要支持跨域的方法非常多情況下,可以添加過濾器,比Spring更簡潔,如代碼所示:
@Configuration public class CorsConfig { @Bean public CorsFilter corsFilter(){ CorsConfiguration corsConfiguration = new CorsConfiguration(); corsConfiguration.addAllowedOrigin("*"); corsConfiguration.addAllowedHeader("*"); corsConfiguration.addAllowedMethod("*"); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**",corsConfiguration); return new CorsFilter(source); } }4)Spring Boot項(xiàng)目還有一種更方便的方式,可以實(shí)現(xiàn)WebMvcConfigurer接口來實(shí)現(xiàn)跨域支持,如代碼所示:
@Configuration public class CorsConfiguration implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowed0riginPatterns( "*") .allowedMethods("GET","POST","PUT","DELETE","HEAD","OPTIONS") .allowCredentials(true)I .maxAge(3600) .allowedHeaders("*");l } }只需要重寫addCorsMapping() 方法就可以了。
以上就是對Java Web跨域問題的解決方案。

我們在微信上24小時(shí)期待你的聲音
解答本文疑問/技術(shù)咨詢/運(yùn)營咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流