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
相关信息的问题。