西部數(shù)碼 空間做2個網(wǎng)站什么是新媒體運營
背景
在oneapi這個前后端都有的開源項目中,我想接入chatnextweb到oneapi的后端。
由于需要二開chatnextweb,添加登錄注冊功能,考慮到j(luò)ava后端的性能問題和內(nèi)存占用,決定不重啟寫個服務(wù),而是將登錄注冊接入到oneapi的登錄注冊api,沒錯,和oneapi的前端公用一套登錄注冊
熬了個大夜后,終于對接好了登錄注冊,并且數(shù)據(jù)寫成功的流轉(zhuǎn)了起來。
就在我以為沒問題的時候,問題來了,前端在使用登錄后的功能時,自動跳轉(zhuǎn)到了登錄頁面,沒錯,前端判定當(dāng)前頁面出于未登錄的狀態(tài)。于是麻煩的debug開始了......
問題分析過程
梳理了一遍前端代碼邏輯,關(guān)于是否登錄的判斷取決于token是否為空,在登錄后,前端會將獲取到了token暫存
緊接著在調(diào)用其他登錄后的界面時,前端判斷token是否為空,如果為空就不展示,并且跳轉(zhuǎn)到登錄界面,以下截圖效果差不多,雖然沒有登錄跳轉(zhuǎn)邏輯,但也放上來了
經(jīng)過debug后,發(fā)現(xiàn)后端返回的token為空,梳理了后端代碼,發(fā)現(xiàn)后端的鑒權(quán)是通過cookie和session,前端是通過token,但是問題不大,后端在注冊時也會生成token,只需要調(diào)用獲取token的接口即可。
于是我這么做了,新的問題也這么來了,鑒權(quán)失敗,后端解析cookie里面的用戶數(shù)據(jù),解析為空.......
又分析了一波后端代碼,發(fā)現(xiàn)在登錄時,后端會將用戶信息封裝到session里面,然后保存到cookie中
最后封裝后的cookie是這樣的:
session=MTY5NTAwNTA3N3xEWDhFQVFMX2dBQUJFQUVRQUFCc180QUFCQVp6ZEhKcGJtY01CQUFDYVdRRGFXNTBCQUlBQWdaemRISnBibWNNQ2dBSWRYTmxjbTVoYldVR2MzUnlhVzVuREFZQUJISnZiM1FHYzNSeWFXNW5EQVlBQkhKdmJHVURhVzUwQkFNQV84Z0djM1J5YVc1bkRBZ0FCbk4wWVhSMWN3TnBiblFFQWdBQ3y5yImQjaV60qV8krs0fEG0tfGUzIu6sOCXYOTtpJaUlw==; Path=/; Expires=Wed, 18 Oct 2023 02:44:37 GMT; Max-Age=2592000
那么為什么會解析為空呢?oneapi自帶的前端能正常解析,但新接入的前端解析就為空,為什么呢?網(wǎng)上給出的答案是因為跨域了,導(dǎo)致傳入的cookie是新的cookie,所以沒有數(shù)據(jù),抱著懷疑的態(tài)度,我在后端寫了一個獲取cookie中用戶數(shù)據(jù)的接口,并通過postman進(jìn)行調(diào)用,嘗試驗證傳入的cookie。
果然,網(wǎng)上果然不是很靠譜,用戶數(shù)據(jù)成功解析,傳入的cookie沒有問題。
繼續(xù)分析,說是非同源跨域?qū)е碌?#xff0c;cookie無法傳入到后端,我想了想,前端調(diào)用localhost:3001/getCookie,然后轉(zhuǎn)發(fā)到localhost:3000/getCookie,確實是非同源跨域,于是有了兩種解決方案
- 使用代理
- 手動傳入Cookie
使用代理
按照oneapi前端設(shè)置代理的方法進(jìn)行設(shè)置,發(fā)現(xiàn)不可行,暫時放棄這條思路(感覺深究下去,使用代理是一定可行的,比如使用nginx等。)
手動傳入Cookie
主要是想嘗試一下手動傳入Cookie,因為有大佬說它就是采用這種方案
居然還是解析失敗,這就奇怪了
除了手動傳入cookie,我還嘗試添加 credentials: 'include',作用是即使跨域,也能成功傳入cookie,但也不行
于是又開始了debug的過程,看了很多篇博客后,找到一個思路可行的,說后端需要配置跨域訪問,記得之前看到過后端跨域的代碼,又翻出來看了看,發(fā)現(xiàn)了問題:
func CORS() gin.HandlerFunc {config := cors.DefaultConfig()config.AllowAllOrigins = trueconfig.AllowCredentials = trueconfig.AllowMethods = []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"}config.AllowHeaders = []string{"*"}return cors.New(config)
}func DefaultConfig() Config {return Config{AllowMethods: []string{"GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"},AllowHeaders: []string{"Origin", "Content-Length", "Content-Type"},AllowCredentials: false,MaxAge: 12 * time.Hour,}
}
問題就出在 AllowCredentials: false, 這一行,chatgpt告訴我,這代表了后端設(shè)置了不允許跨域認(rèn)證,就是說你可以跨域,但不可以認(rèn)證鑒權(quán)
所以前端調(diào)用不管是 手動傳入cookie,還是添加 credentials: 'include',都不行,因為跨域了。
那么解決辦法就很明顯了,不要讓它跨域,又得出了兩個解決方案,使用代理,或者寫全url。
關(guān)于寫完整domain(就是url)
如果不寫全量url,最后訪問的是3001,也就是前端地址,然后前端再通過next等某些操作進(jìn)行轉(zhuǎn)發(fā)到3000(沒細(xì)看),也就導(dǎo)致了非同源
所以需要寫完整domain,并且可以不用手動傳cookie
fetch('http://localhost:3000/api/user/token', {method: 'GET',headers: {"Content-Type": "application/json",},
})
總結(jié)
成功傳入cookie的方案總結(jié):
- 使用代理
- 使用全量domain