2023-07-18 更新
前後端分離項目建議還是使用token,也就是後端使用jsonwebtoken即jwt進行token的生成和驗證,token不存在本地,存在客户端,隨請求頭一起帶來,安全性還是有保障
同時跨域問題建議還是後端進行解決,最好不要前端進行反向代理,容易出問題,由於我使用nodejs作為後端,解決跨域問題代碼如下:
//安裝cors庫
npm i cors
//app.js 或者index.js文件引入
const express = require('express');
const cors = require('cors');
const app = express();
app.use(cors())
既然後端解決了跨域問題,那麼前端這邊就不需要進行反向代理了,即package.json中的proxy一行可以去掉了,然後記得把請求的地址也直接指向後端地址
注意,有個很重要的一點就是,如果後端也是在本地的話,前端一定不要把請求的後端的地址寫成localhost
即下面這種寫法
const url = 'http://localhost:xxxx
這種寫法本地開發沒有問題,但是打包後的前端發送請求如果是這個地址話就會404,所以還是修改為const url = 'http://127.0.0.1:xxxx'這樣不論是開發環境還是生產環境都不會有請求錯誤的問題了
由於興趣使然
加薪
的想法,由於本人是個菜雞前端,想要學習後端,自然從自己最熟悉的語言javascript入手,所以開始學習nodejs,在b站上找到一個不錯的學習視頻
node學習
按照這個視頻的進度。中後期的時候我已經可以利用node+express+mongoose+mongondb搭建後端服務器創造接口對數據進行增刪改查了。
在利用session做登錄驗證的時候,遇到了第一個問題:
登錄成功以後,session沒有在瀏覽器中保存,後端的代碼中無法通過請求頭的session拿到預設的數據,導致一直處在未登錄狀態,同時數據庫中,每一次登錄都會增加一條session數據。
如下圖,現在是登錄成功的狀態,並且按照代碼,後端給響應頭添加了session相關數據
但是後面跟着的請求,並沒有攜帶這次的session,導致鑑權失敗
首先看看對應的代碼:
後端主要代碼如下:
const mongoose = require('mongoose');
const express = require('express');
const cors = require('cors');
const indexRouter = require('./routes/index');
const session = require('express-session');
const MongoStore = require('connect-mongo');
const app = express();
app.use(session({
name:'sid',//設置cookie的name
secret: 'secret',//參與加密的字符串(簽名)
saveUninitialized: false,//是否每次請求都設置一個cookie用來存儲session的id
resave:true,//是否在每次請求的時候重新保存session
store: MongoStore.create({
mongoUrl:'mongodb://127.0.0.1:xxxx/數據庫名'
}),
cookie:{
httpOnly: true,//開啓後前端無法通過js操作session
maxAge:60*1000*5//過期時間
}
}))
app.use(express.json());//獲取請求體的中間件
app.use(cors())
首先是使用cors庫進行跨域相關操作
然後使用express-session庫進行session相關操作
使用connect-mongo庫搭配express-session進行數據庫的session寫入操作
下面是具體的api的處理,登錄請求來了以後,和數據庫中的用户數據進行對比,如果存在並且密碼正確,就在session中保存該次登錄的username和id。
router.post('/login', (req, response) => {
UserModel.findOne({ username: req.body.username }).then(res => {
console.log('登錄查詢成功',res)
if(res){
if(res.password===req.body.password){
req.session.username= res.username;
req.session._id=res._id;
response.json({
code:'0000',
msg:'登錄成功',
data:res.username
})
}else{
response.status(500).json({
code:'1001',
msg:'用户名或密碼錯誤',
data:null
})
}
}else{
response.status(404).json({
code:'1001',
msg:'用户不存在',
data:null
})
}
}).catch(err=>{
console.log('登錄查詢失敗',err)
response.status(500).json({
code:'1001',
msg:'登錄失敗',
data:err
})
})
})
接下來就是book接口的代碼了:
router.get('/book', (req, res) => {
console.log('session',req.session)
if(req.session.username){
console.log('已登錄')
BooksModel.find().then((data) => {
res.json({
code: '0000',
msg: '讀取成功',
data: data
})
}).catch(err => {
res.status(500).json({
code: '1001',
msg: '數據讀取失敗',
data: err
})
})
}else{
console.log('未登錄')
res.status(401).json({
code:'1002',
msg:'未登錄',
data:null
})
}
})
接口很簡單,首先進行session的判斷,如果session沒有相關的用户信息,就判定為未登錄。
按照這一套邏輯下來,只要登錄成功了,session中就一定會有用户相關的信息,但是很遺憾,book的接口中,無論如何都沒有用户相關的信息,而且請求頭中也沒有Cookie的相關值。
所以我就百度
react 不攜帶 session的解決辦法
根據網上五花八門的回答折騰了很久,什麼前端要在axios中設置axios.defaults.withCredentials= true; 什麼後端要設置app.set('trust proxy', 1) 之類的,折騰了很久,這些
全部都沒有用
本人親測,全部都沒有用
最後思來想去,靈光一閃,最終找到了問題所在
後端設置了允許跨域,前端這邊直接請求後端,沒有經過代理,導致每一個請求,都是無法追蹤的請求,也就解釋了為什麼數據庫中每一次登錄成功,都會新增一條session數據,而不是覆蓋。
但是前端為什麼不能設置cookie我現在暫且矇在鼓裏。
知道了問題所在,那麼就着手解決問題。
後端那邊把關於跨域相關的代碼去掉,即不在需要cors庫相關的操作
前端這邊在package.json文件中設置proxy,直接代理到後端的服務器的地址
同時請求中的url地址需要變為前端自己的地址,例如本地啓動localhost:3000,那麼地址就需要設置為http://localhost:3000/
這樣就解決了明明登錄以後,前端請求還是沒有攜帶session相關信息的問題。