当前位置: 首页 > news >正文

有哪些建设工程类网站全球速卖通是什么平台

有哪些建设工程类网站,全球速卖通是什么平台,江油网站网站建设,怎么营销推广node.js如何实现双 Token Cookie 存储 无感刷新机制 为什么要实施双token机制#xff1f; 优点描述安全性Access Token 短期有效#xff0c;降低泄露风险#xff1b;Refresh Token 权限受限#xff0c;仅用于获取新 Token用户体验用户无需频繁重新登录#xff0c;Toke…node.js如何实现双 Token Cookie 存储 无感刷新机制 为什么要实施双token机制 优点描述安全性Access Token 短期有效降低泄露风险Refresh Token 权限受限仅用于获取新 Token用户体验用户无需频繁重新登录Token 自动刷新过程对用户透明灵活性独立控制不同 Token 的生命周期适应各种场景需求可管理性支持多设备登录管理便于撤销特定设备的登录状态性能优化减少数据库查询次数提升系统响应速度 实现方案 模块实现方式登录接口返回 accessToken 和 refreshToken分别存入 CookieAccess Token短时效 JWT用于请求鉴权Refresh Token长时效 JWT用于刷新 Access TokenToken 校验方式后端从 Cookie 中读取 token即 Access Token前端 Axios使用响应拦截器统一处理 Token 失效和自动刷新 使用 JWT 生成两个 Token Access Token短时效用于接口认证例如有效期为 15 分钟Refresh Token长时效用于刷新 Access Token例如有效期为 7 天 在用户登录时返回这两个 Token并将 Refresh Token 存储在数据库中当 Access Token 过期后客户端使用 Refresh Token 请求新的 Access Token如果 Refresh Token 也过期或无效则强制重新登录 具体代码实现 1. 安装依赖 cookie-parser用来解析 Cookie 中的 Token npm install jsonwebtoken bcryptjs cookie-parser 2. 数据库添加两个字段 refresh_tokenVARCHAR(255)加密后的 RefreshTokenexpires_atDATETIMERefreshToken 过期时间 3. 在后端cors跨域中间中添加属性 // 将cors注册为全局中间件 app.use(cors({origin: http://localhost:5173, // 前端地址credentials: true // 允许携带凭证cookies }))3. 登录逻辑改造添加双token 添加配置文件config.js module.exports {jwtSecretKey: yke;eky1]239_jwt87-2up34,refreshTokenSecretKey: yke;eky1]239_refresh87-2up34,accessExpiresIn: 15m, // 访问令牌有效期refreshExpiresIn: 7d, // 刷新令牌有效期accessExpiresInSec: 15 * 60, // 秒数refreshExpiresInSec: 7 * 24 * 60 * 60 // 秒数 }jwt生成accessToken访问token、refreshToken刷新token // 生成access token const accessToken jwt.sign({ id: user.id, username: user.username, email: user.email },config.jwtSecretKey,{ expiresIn: config.accessExpiresIn } ) // 生成refresh token const refreshToken jwt.sign({ id: user.id, username: user.username, email: user.email },config.refreshTokenSecretKey,{ expiresIn: config.refreshExpiresIn } )生成token过期时间和refreshToken一起存入数据库 const expiresAt new Date()expiresAt.setSeconds(expiresAt.getSeconds() config.refreshExpiresInSec)将accessToken访问token、refreshToken刷新token存入cookie // 设置cookie res.cookie(token, accessToken, {maxAge: config.accessExpiresInSec * 1000,httpOnly: true,secure: true,path: / }) res.cookie(refresh_token, refreshToken, {maxAge: config.refreshExpiresInSec * 1000,httpOnly: true,secure: true,path: /api/user/refresh-token, // 限制路径提高安全性sameSite: none })登录逻辑完整代码 // 用户登录的处理函数 exports.login (req, res) {// 接收表单数据const userInfo req.bodyconsole.log(userInfo)// 查询用户信息const sqlStr_name select * from user where username?db.query(sqlStr_name, [userInfo.username], (err, results) {if (err) {return res.send({ status: 1, message: err })}// 执行sql语句成功但是获取的条数不等于1if (results.length 0) {return res.send({ status: 1, message: 该用户不存在 })}// 判断密码是否正确const cmpresult bcrypt.compareSync(userInfo.password, results[0].password)if (!cmpresult) {return res.send({ status: 1, message: 密码错误 })}// 在服务器端生成Token字符串const user { ...results[0] }// 生成access tokenconst accessToken jwt.sign({ id: user.id, username: user.username, email: user.email },config.jwtSecretKey,{ expiresIn: config.accessExpiresIn })// 生成refresh tokenconst refreshToken jwt.sign({ id: user.id, username: user.username, email: user.email },config.refreshTokenSecretKey,{ expiresIn: config.refreshExpiresIn })// 将refresh token存储到数据库中const expiresAt new Date()expiresAt.setSeconds(expiresAt.getSeconds() config.refreshExpiresInSec)const sqlStr_refreshToken update user set refresh_token?, expires_at? where id?db.query(sqlStr_refreshToken, [refreshToken, expiresAt, user.id], (err) {if (err) {console.error(保存refreshToken失败:, err)return res.send({ status: 1, message: 保存refreshToken失败 })}// 设置cookieres.cookie(token, accessToken, {maxAge: config.accessExpiresInSec * 1000,httpOnly: true,secure: true,path: /})res.cookie(refresh_token, refreshToken, {maxAge: config.refreshExpiresInSec * 1000,httpOnly: true,secure: true,path: /api/user/refresh-token, // 限制路径提高安全性sameSite: none})res.send({status: 0,message: 登录成功,data: {username: results[0].username}})}) }) }4. 实现token刷新接口 创建新路由/refreshToken // token刷新接口 exports.refreshToken (req, res) {// 直接从cookie中获取刷新token 前端不需要再单独把token传入请求头const refreshToken req.cookies.refresh_token// 判断refresh token是否存在if (!refreshToken) {return res.send({ status: 1, message: 缺少refreshToken请先登录 })}try {// 验证refreshTokenconst decoded jwt.verify(refreshToken, config.refreshTokenSecretKey)// 查询用户是否存在且refreshToken匹配const sql select * from user where id? and refresh_token?db.query(sql, [decoded.id, refreshToken], (err, results) {if (err) {return res.send({ status: 1, message: 无效的refreshToken err.message })}const user results[0]// 生成新的access tokenconst accessToken jwt.sign({ id: user.id, username: user.username, email: user.email },config.jwtSecretKey,{ expiresIn: config.accessExpiresIn })// 更新accessToken到Cookieres.cookie(token, accessToken, {maxAge: config.accessExpiresInSec * 1000,httpOnly: true,secure: true,path: /})res.send({status: 0,message: accessToken刷新成功,data: {token: accessToken}})})} catch (error) {return res.status(403).send({ status: 1, message: token已过期请重新登录 })} }5. 响应拦截器中处理token import axios from axios import { message } from antd import { refreshTokenService } from /api/userconst instance axios.create({baseURL: http://localhost:3333, // 你的API服务器地址timeout: 10000, // 请求超时时间headers: {Content-Type: application/json},// 必须加上这个选项才能跨域携带withCredentials: true })// 添加请求拦截器 instance.interceptors.request.use((config) {// 后端将token存在了cookie中这里不需要携带tokenreturn config},(err) Promise.reject(err) )// 标记是否正在刷新 Token防止并发刷新 let isRefreshing false // 保存所有因 Token 失效而等待新 Token 的请求回调函数 let refreshSubscribers [] // 成功获取到新的 Token 后执行所有等待的请求 function onRefreshed(newToken) {refreshSubscribers.forEach((cb) cb(newToken))refreshSubscribers [] } // 将等待刷新 Token 的请求封装成一个回调函数加入队列中 function addRefreshSubscriber(callback) {refreshSubscribers.push(callback) } // 响应拦截器 instance.interceptors.response.use((res) {console.log(res) // 摘取核心响应数据if (res.data.status 0) {return res}// 处理业务失败message.error({type: error, content: res.data.message || 服务异常})return Promise.reject(res.data)},async (err) {// 错误的特殊情况 401权限不足或token过期 拦截到登录const originalRequest err.config// 判断是否是 401 并且不是已经重试过的请求if (err.response?.status 401 !originalRequest._retry) {originalRequest._retry true// 控制 Token 刷新流程防止多次刷新if (!isRefreshing) {// 标记刷新状态isRefreshing truetry {const res await refreshTokenService()const newToken res.data.data.token// 重试请求onRefreshed(newToken)} catch {// 刷新失败message.error({ type: error, content: 登录已过期请重新登录 })// 跳转登录if (window.location.pathname ! /login) {history.push(/login)}} finally {isRefreshing false}}// 把当前请求放入队列等待 Token 刷新后再重发return new Promise((resolve) {addRefreshSubscriber((newToken) {originalRequest.headers[Authorization] Bearer ${newToken}resolve(instance(originalRequest))})})} else {// 错误的默认情况 》 只给提示message.error({ type: error, content: err.response.data.message || 服务异常 })}return Promise.reject(err)} )export default instance
http://www.pierceye.com/news/25649/

相关文章:

  • 网站开发与服务器匹配推广公司经营范围
  • 做动画相册在哪个网站好国内室内设计师
  • 做网站用盗版PS镇海住房和建设交通局网站
  • 一个外国人做汉字网站php网站开发招聘需求
  • 长春网站公司网站个人备案麻烦吗
  • 好大夫在线个人网站王建设阿里巴巴国际站入口
  • 现在中国空间站有几个人上海智能模板建站
  • api模式网站开发如何建设网站安全
  • 东莞网站建设纸品包装wordpress美术馆插件
  • 织梦dedecms医院类网站在线预约挂号插件个人所得税app下载
  • 网站优化的链接建设青岛建设房地产招聘信息网站
  • 国家建设网站脱贫地区农副产品网络销售平台
  • 有些网站勤换域名企业外贸网站
  • 设计网站如何推广方案免费素材库
  • 滨江道网站建设iis 配置网站 404页面
  • 海外建站推广网站 如何做用户统计
  • 怎么找回网站电商网站设计平台
  • 网站域名有了 网站如何建设企拓客软件怎么样
  • 网站建设中申请备案杭州网站建设路
  • 建站公司如何月入十万广告发布
  • 江苏商城网站制作公司网站运营的主要工作内容
  • 网站模板带手机站郑州网站推广公司信息
  • 买了虚拟主机怎么建设网站太原百度网站快速优化
  • 京东网站开发需求公司网站的建设怎么做
  • 护肤品网站建设分析网站优化前景
  • 国外创意海报设计网站wordpress域名配置
  • 网站后台培训方案网络推广方案总结
  • 深圳动画设计公司旺道seo推广系统怎么收费
  • 12380网站建设情况的报告个人博客网站中文模板
  • 知识付费网站开发教程宁波网站建设多少钱一年