node.js如何实现双 Token + Cookie 存储 + 无感刷新机制
node.js如何实现双 Token + Cookie 存储 + 无感刷新机制
为什么要实施双token机制?
优点 | 描述 |
---|---|
安全性 | Access Token 短期有效,降低泄露风险;Refresh Token 权限受限,仅用于获取新 Token |
用户体验 | 用户无需频繁重新登录,Token 自动刷新过程对用户透明 |
灵活性 | 独立控制不同 Token 的生命周期,适应各种场景需求 |
可管理性 | 支持多设备登录管理,便于撤销特定设备的登录状态 |
性能优化 | 减少数据库查询次数,提升系统响应速度 |
实现方案:
模块 | 实现方式 |
---|---|
登录接口 | 返回 accessToken 和 refreshToken ,分别存入 Cookie |
Access Token | 短时效 JWT,用于请求鉴权 |
Refresh Token | 长时效 JWT,用于刷新 Access Token |
Token 校验方式 | 后端从 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_token | VARCHAR(255) | 加密后的 RefreshToken |
---|---|---|
expires_at | DATETIME | RefreshToken 过期时间 |
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/user'const 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
相关文章:
node.js如何实现双 Token + Cookie 存储 + 无感刷新机制
node.js如何实现双 Token Cookie 存储 无感刷新机制 为什么要实施双token机制? 优点描述安全性Access Token 短期有效,降低泄露风险;Refresh Token 权限受限,仅用于获取新 Token用户体验用户无需频繁重新登录,Toke…...
如何从 iPhone 获取照片:5 个有效解决方案
有时,我们在 iPhone 上积累了太多照片,因此有必要从 iPhone 上删除照片。无论您的设备需要更多空间,还是只是想备份珍贵的记忆以妥善保管,您都可以找到从 iPhone 上拍摄照片的有效方法。您可以选择完成任务的最佳方式。 第 1 部分…...
大模型知识
############################################################## 一、vllm大模型测试参数和原理 tempreature top_p top_k ############################################################## tempreature top_p top_k 作用:总体是控制模型的发散程度、多样…...
微软正式发布 SQL Server 2025 公开预览版,深度集成AI功能
微软在今年的 Build 2025 大会上正式发布了 SQL Server 2025 公开预览版,标志着这一经典数据库产品在 AI 集成、安全性、性能及开发者工具方面的全面升级。 AI 深度集成与创新 原生向量搜索:SQL Server 2025 首次将 AI 功能直接嵌入数据库引擎ÿ…...
git中,给分支打标签
1.创建标签 标签可以是轻量级标签或带注释的标签两种 轻量级标签 git tag <tag-name> 带注释的标签 git tag -a <tag-name> -m "标签信息" 2.查看标签 git tag 查看标签详细信息 git show <tag-name> 3.推送标签到远程仓库 推送指定标签…...
微软 Build 2025:开启 AI 智能体时代的产业革命
在 2025 年 5 月 19 日的微软 Build 开发者大会上,萨提亚・纳德拉以 "我们已进入 AI 智能体时代" 的宣言,正式拉开了人工智能发展的新纪元。这场汇聚了奥特曼、黄仁勋、马斯克三位科技领袖的盛会,不仅发布了 50 余项创新产品&#…...
k8s面试题-ingress
场景:我通过deployment更新pod,ingress是怎么把新的请求流量发送到我新的pod的?是怎么监控到我更新的pod的? 在 Kubernetes 中,Ingress 是一种 API 对象,用于管理外部访问到集群内服务的 HTTP 和 HTTPS 路…...
时间序列预测的迁移学习
在本文中,我们将了解如何将迁移学习应用于时间序列预测,以及如何在多样化的时间序列数据集上训练一次预测模型,之后无需训练即可在不同数据集上进行预测。我们将使用开源 Darts 库,仅用几行代码即可完成所有这些操作。你可以点击此…...
react中运行 npm run dev 报错,提示vite.config.js出现错误 @esbuild/win32-x64
在React项目中运行npm run dev时,如果遇到vite.config.js报错,提示esbuild/win32-x64在另一个平台中被使用,通常是由于依赖冲突或缓存问题导致的。解决方法是删除node_modules文件夹,并重新安装依赖。 如下图: 解决办…...
量子计算模拟:从理论到实践
量子计算作为现代物理学与计算机科学的前沿交叉领域,正逐渐从纯理论研究走向实际应用。本文将介绍一个基于Python的量子计算模拟框架,重点探讨量子比特、量子门操作以及量子态的演化等核心概念,并通过可视化手段直观展示量子态的特性。 量子…...
143.重排链表的尝试
listnode* p0cur,cur->nextq;p0->next有没有改变 ChatGLM 让我们逐步分析这段代码,看看 p0->next 是否发生了改变。 假设我们有一个链表,cur 是当前节点,q 是另一个节点。代码如下: 代码生成完成 C代码 首先&#…...
精准识别记忆细胞!Elabscience PE Anti-Human/Mouse CD44 抗原特异性抗体
概述 CD44 是一种广泛表达的细胞表面黏附分子,参与细胞迁移、炎症反应及肿瘤转移等关键生物学过程。Elabscience 推出的PE Anti-Human/Mouse CD44 Antibody [IM7](货号:E-AB-F1100D)是一款高特异性、高灵敏度的流式抗体ÿ…...
OpenCV CUDA模块特征检测与描述------一种基于快速特征点检测和旋转不变的二进制描述符类cv::cuda::ORB
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 cv::cuda::ORB 是 OpenCV 库中 CUDA 模块的一部分,它提供了一种基于快速特征点检测和旋转不变的二进制描述符的方法,用于…...
OpenCV CUDA模块特征检测与描述------创建一个 盒式滤波器(Box Filter)函数createBoxFilter()
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 cv::cuda::createBoxFilter 是 OpenCV CUDA 模块中的一个工厂函数,用于创建一个 盒式滤波器(Box Filter)&…...
【八股战神篇】Spring高频面试题汇总
专栏简介 Bean 的生命周期了解么? 延伸 谈谈自己对于 Spring IoC 的了解 延伸 什么是动态代理? 延伸 动态代理和静态代理的区别 延伸 Spring AOP的执行流程 延伸 Spring的事务什么情况下会失效? 延伸 专栏简介 八股战神篇专栏是基于各平台共上千篇面经,上万道…...
高阶数据结构——红黑树实现
目录 1.红黑树的概念 1.1 红黑树的规则: 1.2 红黑树的效率 2.红黑树的实现 2.1 红黑树的结构 2.2 红黑树的插入 2.2.1 不旋转只变色(无论c是p的左还是右,p是g的左还是右,都是一样的变色处理方式) 2.2.2 单旋变色…...
java综合交易所13国语言,股票,区块链,外汇,自带客服系统运营级,有测试
这套pc和H5是一体的,支持测试,目前只有外汇和区块链,某站居然有人卖3.8w,还觉得自己这个价格很好 自带客服系统,虽然是老的,但是可玩性还是很高的,也支持c2c,理财,质押&a…...
六:操作系统虚拟内存之缺页中断
深入理解操作系统:缺页中断 (Page Fault) 的处理流程 在上一篇文章中,我们介绍了虚拟内存和按需调页 (Demand Paging) 的概念。虚拟内存为每个进程提供了巨大的、独立的虚拟地址空间,并通过页表 (Page Table) 将虚拟页面 (Virtual Page) 映射…...
iOS 15.4.1 TrollStore(巨魔商店)安装教程详解:第二篇
🚀 iOS 15.4.1 TrollStore(巨魔商店)安装教程详解 ✨ 前言🛠️ 如何安装 TrollStore?第一步:打开 Safari 浏览器第二步:选择对应系统版本安装方式第三步:访问地址,下载配…...
【JAVA】比较器Comparator与自然排序(28)
JAVA 核心知识点详细解释 Java中比较器Comparator的概念和使用方法 概念 Comparator 是 Java 中的一个函数式接口,位于 java.util 包下。它用于定义对象之间的比较规则,允许我们根据自定义的逻辑对对象进行排序。与对象的自然排序(实现 Comparable 接口)不同,Comparat…...
bitbar环境搭建(ruby 2.4 + rails 5.0.2)
此博客为武汉大学WA学院网络安全课程,理论课大作业Web环境搭建。 博主搭了2天!!!血泪教训是还是不能太相信ppt上的教程。 一开始尝试了ppt上的教程,然后又转而寻找网络资源 cs155源代码和docker配置,做到…...
Spring Boot接口通用返回值设计与实现最佳实践
一、核心返回值模型设计(增强版) package com.chat.common;import com.chat.util.I18nUtil; import com.chat.util.TraceUtil; import lombok.AllArgsConstructor; import lombok.Data; import lombok.Getter;import java.io.Serializable;/*** 功能: 通…...
线上 Linux 环境 MySQL 磁盘 IO 高负载深度排查与性能优化实战
目录 一、线上告警 二、问题诊断 1. 系统层面排查 2. 数据库层面分析 三、参数调优 1. sync_binlog 参数优化 2. innodb_flush_log_at_trx_commit 参数调整 四、其他优化建议 1. 日志文件位置调整 2. 生产环境核心参数配置模板 3. 突发 IO 高负载应急响应方案 五、…...
React--函数组件和类组件
React 中的函数组件和类组件是两种定义组件的方式,它们有以下主要区别: 1. 语法与定义方式 函数组件: 是 JavaScript 函数,接收 props 作为参数,返回 JSX。 const MyComponent (props) > {return <div>Hell…...
GitHub 趋势日报 (2025年05月20日)
本日报由 TrendForge 系统生成 https://trendforge.devlive.org/ 🌐 本日报中的项目描述已自动翻译为中文 📈 今日整体趋势 Top 10 排名项目名称项目描述今日获星总星数语言1virattt/ai-hedge-fundAI对冲基金团队⭐ 1781⭐ 31163Python2public-apis/pub…...
uni.getLocation()和uni.openSetting()
文章目录 环境背景问题分析问题1问题2 uni.getLocation()和uni.openSetting()的区别和联系其它uni.getLocation()的failuni.openSetting()的authSetting对象 参考 环境 Windows 11 专业版HBuilder X 4.65微信开发者工具 Stable 1.06.2412050 背景 在小程序开发中,…...
医疗行业数据共享新实践:如何用QuickAPI打通诊疗全流程数据壁垒
在医疗行业,数据的高效流转直接影响诊疗效率和患者体验。某三甲医院在数字化转型中发现,虽然已积累大量核心业务数据,但各科室系统间的数据互通仍存在明显瓶颈——检验科的报告无法实时同步至门诊系统,药房库存数据与采购系统脱节…...
管理会议最佳实践:高效协同与价值最大化
1.会前准备:明确目标与计划 1.1 明确会议目的 1.1.1 必要性评估 开会前需自问是否真的需要开会,若问题可通过邮件、文档或异步沟通解决,则应避免开会,以节省时间和资源。 1.1.2 目标定义 清晰定义会议目标,如决策、信息同步、创意讨论等,并提前告知参与者,使大家明确参…...
万物智联,重塑未来:鸿蒙操作系统的实战突破与生态崛起
鸿蒙操作系统(HarmonyOS)作为华为自主研发的分布式操作系统,自2019年发布以来,已从技术探索迈入大规模商用阶段。截至2025年,鸿蒙系统不仅成为全球第二大移动操作系统,更在政企数字化、工业制造、金融科技等…...
人工智能路径:技术演进下的职业发展导航
当生成式AI能够自主完成创意设计、商业分析和代码编写时,职业发展的传统路径正在被重新测绘。人工智能路径不再是一条预设的直线,而演变为包含多重可能性的动态网络——未来的职业成功,将取决于在技术变革中持续定位自身价值节点的能力。 一…...
深入理解Java虚拟机之垃圾收集器篇(垃圾回收器的深入解析待完成TODO)
目录 **一. 如何判断对象的存亡**引用计数算法:可达性分析算法: **二. Java中的四种引用****三. 垃圾回收算法****1. 标记 - 清除算法****2. 标记 - 复制算法****3. 标记 - 整理算法****4. 分代收集理论**(了解即可) **四. 十种主流垃圾收集器****3.1 Serial 收集器****3.2 Par…...
牛客网 NC16407 题解:托米航空公司的座位安排问题
牛客网 NC16407 题解:托米航空公司的座位安排问题 题目分析 解题思路 本题可以采用深度优先搜索(DFS)来解决: 从左上角开始,按行优先顺序遍历每个座位对于每个座位,有两种选择: 选择该座位(如果满足条件…...
拉普拉斯高斯(LoG)滤波器掩模的注意事项
目录 问题: 解答: 一、高斯函数归一化:消除幅度偏差 1. 归一化的定义 2. 为何必须归一化? 二、拉普拉斯系数和为零:抑制直流项干扰 1. 拉普拉斯算子的特性 2. 系数和不为零的后果 三、直流项如何影响零交叉点&…...
OSPF基础实验-多区域
互联接口、IP地址如下图所示,所有设备均创建Loopback0,其IP地址为10.0.x.x/24,其中x为设备编号。 R1、R3的所有接口以及R2的GE0/0/4接口属于OSPF区域2,R2、R4的Loopback0接口及互联接口属于OSPF区域0,R4、R5的互联接口…...
ERP 与 WMS 对接深度解析:双视角下的业务与技术协同
在企业数字化运营的复杂体系中,ERP(企业资源规划)与 WMS(仓储管理系统)的有效对接,已成为优化供应链管理、提升运营效率的关键环节。本文将从 ERP 和 WMS 两个核心视角出发,深度剖析两者对接过程…...
基于 Node.js 的 HTML 转 PDF 服务
这是一个基于 Node.js 开发的 Web 服务,主要功能是将 HTML 内容转换为 PDF 文件。项目使用了 Express 作为 Web 框架,Puppeteer 作为 PDF 生成引擎,提供了简单易用的 API 接口。前端开发人员提供了一个简单而强大的 HTML 转 PDF 解决方案&…...
Java阻塞队列(BlockingQueue)的使用:ArrayBlockingQueue类、LinkedBlockingQueue类
1、阻塞队列的介绍 Java 中的阻塞队列(BlockingQueue) 是多线程编程中用于协调生产者和消费者线程的重要工具,属于 java.util.concurrent 包。它的核心特点是:当队列为空时,消费者线程会被阻塞,直到队列中有新元素;当队列满时,生产者线程会被阻塞,直到队列有空闲…...
esp32cmini SK6812 2个方式
1 #include <SPI.h> // ESP32-C系列的SPI引脚 #define MOSI_PIN 7 // ESP32-C3/C6的SPI MOSI引脚 #define NUM_LEDS 30 // LED灯带实际LED数量 - 确保与实际数量匹配! #define SPI_CLOCK 10000000 // SPI时钟频率 // 颜色结构体 st…...
2025年 PMP 6月 8月 专题知识
2025年 PMP 6月 8月 专题知识 文章目录 2025年 PMP 6月 8月 专题知识三点估算1. 概念:2. 原理: 决策树1. 概念:2. 步骤: 真题 三点估算 1. 概念: 三点估算常用于估算活动持续时间(也可以用于估算成本);源自计划评审技术(PERT&am…...
一文理解TCP与UDP
Socket套接字 Socket套接字,是由系统提供用于网络通信的技术,是基于TCP/IP协议的网络通信的基本操作单元。 基于Socket套接字的网络程序开发就是网络编程。 Socket套接字主要针对传输层协议划分为如下三类: 流套接字:使用传输层…...
智能指针RAII
引入:智能指针的意义是什么? RAll是一种利用对象生命周期来控制程序资源(如内存、文件句柄、网络连接、互斥量等等)的简单技术。 在对象构造时获取资源,接着控制对资源的访问使之在对象的生命周期内始终保持有效&#…...
AI护航化工:《山西省危化品视频智能分析指南》下的视频分析重构安全体系
化工和危化品行业的AI智能视频分析应用:构建安全与效率新范式 一、行业背景与挑战 化工和危化品行业是国民经济的重要支柱,但生产过程涉及高温、高压、易燃易爆等高风险场景。传统安全监管依赖人工巡检和固定监控设备,存在效率低、盲区多、…...
GitHub SSH Key 配置详细教程(适合初学者,Windows版)-学习记录4
GitHub SSH Key 配置详细教程(适合初学者,Windows版) 本教程适用于在 Windows 系统下,将本地 Git 仓库通过 SSH 方式推送到 GitHub,适合没有配置过 SSH key 的初学者。 1. 检查是否已有 SSH key 打开 Git Bash 或 Po…...
初识Linux · NAT 内网穿透 内网打洞 代理
目录 前言: 内网穿透和打洞 NAPT表 内网穿透 内网打洞 正向/反向代理 前言: 本文算是网络原理的最后一点补充,为什么说是补充呢,因为我们在前面第一次介绍NAT的时候详细介绍的是报文从子网到公网,却没有介绍报文…...
docker-compose使用详解
Docker-Compose 是 Docker 官方提供的容器编排工具,用于简化多容器应用的定义、部署和管理。其核心功能是通过 YAML 配置文件(docker-compose.yml)定义服务、网络和存储卷,并通过单一命令实现全生命周期的管理。以下从核心原理、安…...
使用计算机视觉实现目标分类和计数!!超详细入门教程
什么是物体计数和分类 在当今自动化和技术进步的时代,计算机视觉作为一项关键工具脱颖而出,在物体计数和分类任务中提供了卓越的功能。 无论是在制造、仓储、零售,还是在交通监控等日常应用中,计算机视觉系统都彻底改变了我们感知…...
并发编程中的对象组合的哲学
文章目录 引言对象组合与安全委托实例封闭技术基于监视器模式的对象访问对象不可变性简化委托原子维度的访问现有容器的并发安全的封装哲学使用继承使用组合小结参考引言 本文将介绍通过封装技术,保证开发者不对整个程序进行分析的情况下,就可以明确一个类是否是线程安全的,…...
03-Web后端基础(Maven基础)
1. 初始Maven 1.1 介绍 Maven 是一款用于管理和构建Java项目的工具,是Apache旗下的一个开源项目 。 Apache 软件基金会,成立于1999年7月,是目前世界上最大的最受欢迎的开源软件基金会,也是一个专门为支持开源项目而生的非盈利性…...
禁忌搜索算法:从原理到实战的全解析
禁忌搜索算法:从原理到实战的全解析 一、算法起源与核心思想 禁忌搜索(Tabu Search, TS)由美国工程院院士Fred Glover于1986年正式提出,其灵感源于人类的记忆机制——通过记录近期的搜索历史(禁忌表)&…...
从加密到信任|密码重塑车路云一体化安全生态
目录 一、密码技术的核心支撑 二、典型应用案例 三、未来发展方向 总结 车路云系统涉及海量实时数据交互,包括车辆位置、传感器信息、用户身份等敏感数据。其安全风险呈现三大特征: 开放环境威胁:V2X(车与万物互联࿰…...