1. 什么是session
Session
(会话)是指客户端与服务器之间建立的一种交互方式,通过在服务器上存储一个 session ID
,来跟踪用户的状态和信息。
- 跟踪用户状态:通过
Session
可以识别用户是否登录、用户所在的权限组等,从而对用户进行相应的操作和控制。 - 存储用户信息:通过
Session
可以在服务器端存储用户信息,例如购物车信息、表单数据等,可以在不同页面和请求之间进行传递和操作。 - 防止重复提交:利用
Session
可以在一段时间内防止用户重复提交表单,保证数据的完整性和准确性。 - 用户跟踪:通过
Session
可以记录用户访问网站的行为,从而分析用户行为、优化网站设计等。
Session
存储在服务器端的内存、硬盘或数据库等地方,具体存储的位置取决于 Session
中间件的配置。
Session
的工作原理是,服务器在收到客户端的请求之后,会将一个 Session ID
发送给客户端(一般是通过 Cookie
来存储,也可以通过查询字符串或者 HTTP 头部的方式来传递),客户端在后续的请求中通过这个 Session ID
来告诉服务器自己的身份和状态。服务器在收到客户端的请求后,根据 Session ID
来读取或更新相应的 Session
数据,实现对客户端状态的跟踪和管理。
2. session使用
安装session
npm i express-session --save
npm i @types/express-session -D
main.ts 添加
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { VersioningType } from '@nestjs/common';
import * as session from 'express-session';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.enableVersioning({
type: VersioningType.URI,
});
app.use(
session({
secret: 'yinuo', // 加密
rolling: true, // 每次请求添加cookie
name: 'yn-ssid', // 存在浏览器cookie中的key
cookie: { maxAge: null }, // 过期时间 ms
}),
);
await app.listen(3000);
}
bootstrap();
cookie的maxAge设置为1000 ,时间过了,session-Id变化了
maxAge设置为null
cookie中
3. 验证码登录案例
后端nestjs 验证码插件 svgCaptcha
npm install svg-captcha -S
前端代码:
使用 npm install element-plus -S
Login.vue
<template>
<div class="wraps">
<el-form :label-position="labelPosition" label-width="100px" :model="formLabelAlign" style="max-width: 460px">
<el-form-item label="账号">
<el-input v-model="formLabelAlign.name" />
</el-form-item>
<el-form-item label="密码">
<el-input type="password" v-model="formLabelAlign.password" />
</el-form-item>
<el-form-item label="验证码">
<div style="display:flex">
<el-input v-model="formLabelAlign.code" />
<img @click="resetCode" :src="codeUrl" alt="">
</div>
</el-form-item>
<el-form-item>
<el-button @click="submit">登录</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script setup lang='ts'>
import { onMounted, reactive, ref } from 'vue';
const codeUrl = ref<string>('/api/user/code')
// 默认写成图片地址,每次点击获 需要重新更新视图
const resetCode = () => codeUrl.value = codeUrl.value + '?' + Math.random()
const labelPosition = ref<string>('right')
const formLabelAlign = reactive({
name: "",
password: "",
code: ""
})
const submit = async () => {
await fetch('/api/user/create', {
method: "POST",
body: JSON.stringify(formLabelAlign),
headers: {
'content-type': 'application/json'
}
}).then(res => res.json())
}
</script>
<style>
* {
padding: 0;
margin: 0;
}
.wraps {
display: flex;
justify-content: center;
align-items: center;
height: inherit;
}
html,
body,
#app {
height: 100%;
}
</style>
代理
server: {
proxy: {
'/api': {
target: 'http://localhost:3000',
changeOrigin: true,
rewrite: path => path.replace(/^\/api/, '')
}
}
}
后端代码:
import * as svgCaptcha from 'svg-captcha';
@Controller('user')
export class UserController {
constructor(private readonly userService: UserService) {}
@Post('create')
createCode(@Body() body, @Req() req) {
// 判断两次的code是否相等
if (
body?.code?.toLocaleLowerCase() === req.session.code.toLocaleLowerCase()
) {
return {
code: 1,
message: '验证成功',
};
} else {
return {
code: 0,
message: '验证失败',
};
}
}
@Get('code')
createCaptcha(@Req() req, @Res() res) {
console.log('打印***req,res', req.session, res.type);
//每次重新请求,会生成新的验证码
const captcha = svgCaptcha.create({
size: 4, //生成几个验证码
fontSize: 50, //文字大小
width: 100, //宽度
height: 34, //高度
background: '#cc9966', //背景颜色
});
req.session.code = captcha.text; //存储验证码记录到session
res.type('image/svg+xml');
res.send(captcha.data);
}
}