項目中遇到跨域問題睛驳,在不設(shè)置CORS跨域的情況下,開發(fā)使用代理解決跨域問題膜廊。
流程:
- 先獲取驗證碼乏沸,直接加載url的方式獲得,返回值中帶cookie
- 登錄請求爪瓜,是異步請求axios蹬跃,需帶上cookie
難點:
- 跨域采用代理方式,用proxyTable
- 登錄請求頭里加入cookie铆铆, axios設(shè)置withCredentials: true
- cookie作用范圍蝶缀,需配置代理服務(wù)器丹喻。
本文是參考另一位博友的文章,由于他沒有給出相應(yīng)的關(guān)鍵代碼翁都,我這里補充一下碍论;
原文參考:http://www.cnblogs.com/strinkbug/p/6073806.html
引用:
有2個業(yè)務(wù)接口需要轉(zhuǎn)發(fā)到82的服務(wù)器上:
../user/getCode.do
../user/doLogin.do
現(xiàn)象:
使用上述的2個接口實現(xiàn)用戶登錄功能,首先顯示登錄頁面柄慰,調(diào)用../user/getCode.do獲取驗證碼鳍悠,然后用戶界面輸入用戶名、密碼和驗證碼坐搔,點擊登錄之后調(diào)用../user/doLogin.do接口實現(xiàn)登錄藏研。結(jié)果../user/doLogin.do后端總是找不到驗證碼,因為瀏覽器沒有把cookie中的JSESSIONID傳遞過來概行。無法登錄的話蠢挡,后續(xù)的所有其他接口都無法調(diào)用了。
分析:
通過chrome的network凳忙,可以看到如下信息:
那么現(xiàn)在的問題就是為什么在點擊立即登錄之后袒哥,瀏覽器為什么沒有在請求中帶上上次返回的cookie信息呢?
仔細(xì)看response header中的set-cookie頭可以發(fā)現(xiàn)消略,其中有一個Path=/webserver/,說明這個cookie是有適用范圍的瞎抛。只能在/webserver/路徑下使用
而我們代碼中使用的路徑是這么寫的: ../user/getCode.do艺演,沒有包含webserver信息,這樣瀏覽器自然就認(rèn)為這個請求和上次返回的那個cookie不匹配桐臊。
解決方法:
解決方法有2中:
一種是在請求的時候帶上/webserver/前綴胎撤,比如把上文的 ../user/getCode.do改為 ../webserver/user/getCode.do;
第二種是修改代理的實現(xiàn)断凶,把82服務(wù)器上返回的http頭上的set-cookie內(nèi)的Path改為 Path=/伤提,代碼如下。
在vue的webpack腳手架中的build/dev-server.js內(nèi)的 * Object.keys(proxyTable).forEach(function (context) * 的實現(xiàn)改為如下形式
// dev-server.js
Object.keys(proxyTable).forEach(function (context) {
var options = proxyTable[context]
if (typeof options === 'string') {
options = {
target: options,
onProxyRes(proxyRes, req, res) {
//set-cookie:JSESSIONID=6F766ED2EEEBEAA9245F7F908A848857; Path=/webserver/; HttpOnly
var oldCookie = proxyRes.headers['set-cookie']
if(oldCookie== null || oldCookie.length==0){
delete proxyRes.headers['set-cookie']
return
}
console.log(oldCookie)
var oldCookieItems = oldCookie[0].split(';')
var newCookie = ''
for(var i=0; i < oldCookieItems.length; ++i){
if(newCookie.length >0)
newCookie += ';'
if(oldCookieItems[i].indexOf('Path=') >= 0)
newCookie += 'Path=/'
else
newCookie += oldCookieItems[i]
}
proxyRes.headers['set-cookie'] = [newCookie]
//proxyRes.headers['x-addedygc'] = 'foobar'; // add new header to response
//delete proxyRes.headers['connection']; // remove header from response
}
}
}
app.use(proxyMiddleware(context, options))
})
關(guān)鍵代碼補充:
- config/index.js
dev: {
env: require('./dev.env'),
port: 9528,
autoOpenBrowser: true,
assetsSubDirectory: 'static',
assetsPublicPath: '/',
proxyTable: {
'/auth': 'http://127.0.0.1:8080/Coolmart', //驗證碼路徑
'/api': { //axios請求路徑
changeOrigin: true,
target: 'http://127.0.0.1:8080',
pathRewrite: {
'^/api': '/Coolmart'
}
},
}
- fetch.js
// 創(chuàng)建axios實例
const service = axios.create({
baseURL: process.env.BASE_API, // api
// timeout: 5000, // 請求超時時間
withCredentials: true // 請求帶上cookie
});
總的流程:
1认烁, 網(wǎng)頁中請求驗證碼肿男,通過代理,因不是axios請求却嗡,是直接訪問的舶沛,拿到返回值,獲取cookie窗价,此時cookie的path是一個相對路徑(Path=/webserver/)
2如庭, dev-server.js 會將該cookie的path改寫成 path=/
3, 登錄請求發(fā)起axios撼港,帶上作用范圍為/ 的cookie坪它,若不改骤竹,則無法帶上該cookie。
4往毡, 訪問成功