日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
前后端分離項(xiàng)目,如何解決跨域問題?

403 Forbidden 是HTTP協(xié)議中的一個(gè)狀態(tài)碼(Status Code),意味著后端服務(wù)雖然成功解析了請(qǐng)求,但前端卻沒有訪問該資源的權(quán)限。

10年積累的成都網(wǎng)站設(shè)計(jì)、網(wǎng)站建設(shè)經(jīng)驗(yàn),可以快速應(yīng)對(duì)客戶對(duì)網(wǎng)站的新想法和需求。提供各種問題對(duì)應(yīng)的解決方案。讓選擇我們的客戶得到更好、更有力的網(wǎng)絡(luò)服務(wù)。我雖然不認(rèn)識(shí)你,你也不認(rèn)識(shí)我。但先建設(shè)網(wǎng)站后付款的網(wǎng)站建設(shè)流程,更有赤峰林西免費(fèi)網(wǎng)站建設(shè)讓你可以放心的選擇與我們合作。

那怎么解決這個(gè)問題呢?通常有兩個(gè)思路:

  • 前端使用 Nodejs 代理(開發(fā)環(huán)境下,生產(chǎn)環(huán)境下可以用 Nginx 替代)
  • 或者后端開啟跨域資源共享

一、關(guān)于跨域

跨域?qū)τ谇昂蠖碎_發(fā)者來說,就像一塊狗皮膏藥,無論是面試還是開發(fā)中,都會(huì)經(jīng)常遇到。

之所以出現(xiàn)跨域問題,是因?yàn)闉g覽器的同源策略,為了隔離潛在的惡意文件,為了防御來自歪門邪道的攻擊,瀏覽器限制了從同一個(gè)源加載的文檔或腳本與來自另一個(gè)源的資源進(jìn)行交互。

前面我們提到了,前端跑在 8080 端口下,后端跑在 9002 端口下,這種情況就屬于不同的源(域名不同,協(xié)議不同,端口不同),所以 8080 端口下的前端請(qǐng)求直接訪問 9002 端口下的后端接口時(shí)就訪問失敗了。

那正確的打開方式是什么呢?我們前面也提到了,前端使用 Nodejs 代理或者后端開啟跨域資源共享,我們一一來實(shí)踐下。

二、Nodejs 代理

在 Nodejs 出現(xiàn)之前,JavaScript 編寫的程序通常需要在用戶的瀏覽器上執(zhí)行,Node.js 出現(xiàn)后,JavaScript 也能用于服務(wù)端編程了。Nodejs 一系列的內(nèi)置模塊使得程序可以脫離 IIS、Apache 這種 Web 服務(wù)作為獨(dú)立的服務(wù)器執(zhí)行。

我們使用 Nodejs 來解決跨域問題的思路就是,在本地創(chuàng)建一個(gè)虛擬服務(wù)器,對(duì) 8080 端口下的前端請(qǐng)求進(jìn)行代理,同時(shí)接收 9002 端口下的服務(wù)器端響應(yīng),這樣服務(wù)端和服務(wù)端進(jìn)行數(shù)據(jù)的交互就不會(huì)出現(xiàn)跨域問題了。

第一步,配置 Nodejs 代理服務(wù)

module.exports = {
dev: {
// Paths
assetsSubDirectory: 'static',
assetsPublicPath: '/',
proxyTable: {
'/api': {
target: 'http://localhost:9002', // 你請(qǐng)求的第三方接口
changeOrigin: false, // 在本地會(huì)創(chuàng)建一個(gè)虛擬服務(wù)端,然后發(fā)送請(qǐng)求的數(shù)據(jù),并同時(shí)接收請(qǐng)求的數(shù)據(jù),這樣服務(wù)端和服務(wù)端進(jìn)行數(shù)據(jù)的交互就不會(huì)有跨域問題
pathRewrite: { // 路徑重寫,
'^/api': '' // 替換target中的請(qǐng)求地址,也就是說以后你在請(qǐng)求http://api.codingmore.top/v2/XXXXX這個(gè)地址的時(shí)候直接寫成/api即可。
}
},
},
}

第二步,配置前端訪問請(qǐng)求路徑


module.exports = merge(prodEnv, {
NODE_ENV: '"development"',
VUE_APP_BASE_API: '"/api"'
// VUE_APP_BASE_API: '"http://localhost:9002"'
})

第三步,重啟前端服務(wù)

再次點(diǎn)擊「登錄」按鈕,可以看到請(qǐng)求的 URL 發(fā)生了改變,原來是 http://localhost:9002/users/login,現(xiàn)在是 http://localhost:8080/api/users/login。與此同時(shí),可以看到多了一個(gè) Remote Address,端口也是 8080,也就是說經(jīng)過 Nodejs 的代理,前后端的交互在同一個(gè)源下面了,這樣就不會(huì)發(fā)生跨域問題了。

同時(shí),可以看得到,服務(wù)器端返回的狀態(tài)碼變成了 200,表示請(qǐng)求成功。

三、開啟跨域資源共享

跨域資源共享,也就是 Cross-Origin Resource Sharing,簡(jiǎn)拼為 CORS,是一種基于 HTTP 頭信息的機(jī)制,通過允許服務(wù)器標(biāo)識(shí)除了它自己以外的資源,從而實(shí)現(xiàn)跨域訪問。

第一步,開啟 CORS 支持

在 Spring Boot 應(yīng)用中,加入 CORS 的支持簡(jiǎn)單到不忍直視,添加一個(gè)配置類就可以了。

@Configuration
public class GlobalCorsConfig {
@Bean
public CorsFilter corsFilter() {
CorsConfiguration config = new CorsConfiguration();
// 設(shè)置你要允許的網(wǎng)站域名
config.addAllowedOrigin("http://localhost:8080");
//允許跨域發(fā)送cookie
config.setAllowCredentials(true);
//放行全部原始頭信息
config.addAllowedHeader("*");
//允許所有請(qǐng)求方法跨域調(diào)用
config.addAllowedMethod("*");
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
}

第二步,重啟后端服務(wù),再次點(diǎn)擊登錄按鈕,發(fā)現(xiàn)請(qǐng)求已經(jīng)可以正常訪問了。

本例中,后端返回 Access-Control-Allow-Origin: http://localhost:8080 就表示,跑在 9002 端口下的后端接口可以被 8080 端口的前端請(qǐng)求訪問。

如果允許所有域名進(jìn)行跨域調(diào)用的話,只需改變一行代碼即可。

//允許所有域名進(jìn)行跨域調(diào)用
config.addAllowedOriginPattern("*");
// 設(shè)置你要允許的網(wǎng)站域名
// config.addAllowedOrigin("http://localhost:8080");

對(duì)于 login 這種簡(jiǎn)單的請(qǐng)求來說,它們是不會(huì)觸發(fā) CORS 預(yù)檢的,因此不需要在服務(wù)器端增加其他配置就可以了。那什么是簡(jiǎn)單請(qǐng)求呢?

1)請(qǐng)求方法是以下三種方法之一:

  • HEAD
  • GET
  • POST

2)HTTP 的頭信息不超出以下幾種字段:

  • Accept
  • Accept-Language
  • Content-Language
  • Last-Event-ID
  • Content-Type:只限于三個(gè)值 application/x-www-form-urlencoded、multipart/form-data、text/plain

那對(duì)于會(huì)觸發(fā) CORS 預(yù)檢的非簡(jiǎn)單請(qǐng)求(比如說請(qǐng)求方法是 PUT 或 DELETE,或者 Content-Type 字段的類型是 application/json,或者請(qǐng)求消息頭包含了一些自定義的字段),該怎么辦呢?

非簡(jiǎn)單請(qǐng)求在正式通信之前,會(huì)增加一次 HTTP 查詢請(qǐng)求,稱為“預(yù)檢”請(qǐng)求。預(yù)檢請(qǐng)求通過后,才會(huì)返回正常的響應(yīng)內(nèi)容。

拿編程貓的文章管理頁來舉例,該頁面會(huì)向后端發(fā)起一個(gè) posts/queryPageable 的分頁查詢,該請(qǐng)求包含了一個(gè)自定義的消息頭 Authorization,于是瀏覽器認(rèn)為該請(qǐng)求是一個(gè)非簡(jiǎn)單請(qǐng)求,然后就會(huì)自動(dòng)發(fā)起一次 OPTIONS 請(qǐng)求,但由于我們的 Spring Boot 項(xiàng)目整合了 SpringsScurity 安全管理框架,沒有對(duì)OPTIONS請(qǐng)求放開登錄認(rèn)證,導(dǎo)致驗(yàn)證失敗,文章分頁請(qǐng)求的響應(yīng)數(shù)據(jù)就沒有返回回來。

第三步,通過以下代碼給 OPTIONS 請(qǐng)求放行。

public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
ExpressionUrlAuthorizationConfigurer.ExpressionInterceptUrlRegistry registry = httpSecurity
.authorizeRequests();
//允許跨域請(qǐng)求的OPTIONS請(qǐng)求
registry.antMatchers(HttpMethod.OPTIONS)
.permitAll();
}
}

再次重啟后端服務(wù),重新訪問文章列表接口,發(fā)現(xiàn)有響應(yīng)數(shù)據(jù)了。

非簡(jiǎn)單請(qǐng)求必須首先使用 OPTIONS 請(qǐng)求方法發(fā)起一個(gè)預(yù)檢請(qǐng)求到服務(wù)器端,以獲知服務(wù)器是否允許該實(shí)際請(qǐng)求。"預(yù)檢請(qǐng)求“的使用,避免了跨域請(qǐng)求對(duì)服務(wù)器的用戶數(shù)據(jù)造成未預(yù)期的影響。

我們來通過兩張圖片簡(jiǎn)單總結(jié)一下預(yù)檢請(qǐng)求的整個(gè)過程,第一張,發(fā)起 OPTIONS 預(yù)檢請(qǐng)求:

第二章,發(fā)起正式請(qǐng)求:

四、源碼路徑

編程貓后端源碼:

https://github.com/itwanger/coding-more

編程貓后臺(tái)管理的前端源碼:

https://github.com/itwanger/codingmore-admin-web


標(biāo)題名稱:前后端分離項(xiàng)目,如何解決跨域問題?
轉(zhuǎn)載來源:http://www.5511xx.com/article/dpogpdp.html