pure-admin + FastAPI 登录密码 RSA 加密落地全流程

发布时间:2026/10/17 12:55:25

pure-admin + FastAPI 登录密码 RSA 加密落地全流程 做后台管理系统的人应该都遇到过同一个问题登录时密码到底怎么传给后端才安全之前我在接一个管理后台项目时前端选了纯开源免费、开箱即用的pure-admin框架后端用FastAPI提供接口前后端密码传输一直用的是明文虽然是内网系统但每次看到请求里躺着完整的密码心里总是不踏实。后来花了一个周末把登录密码改成加密传输前端拿到RSA公钥加密、后端用私钥解密再配合数据库里的Hash校验整套链路才算真正闭环。这篇文章我把自己落地这套方案的过程完整梳理了一遍包括技术选型的纠结、前后端的详细实现、联调时踩的坑以及那些网上教程不会明说的细节。适合正在用pure-admin当后台脚手架、后端用FastAPI写接口的开发者参考也适合所有想搞明白“密码加密传输到底怎么落地”的人。1. 需求分析与技术选型思路1.1 明文传密码到底有什么问题先说结论只要不是纯本地单机应用密码都不应该明文传输。哪怕你的系统部署在公司内网也不代表安全网络抓包、日志泄漏、代理中间人任何一环出问题密码就直接暴露了。很多人会说“我们用了HTTPS密码就算明文传也没关系”。这句话对一半。HTTPS解决的是传输链路加密但如果后端日志里不小心打了请求参数或者某个反向代理记录了POST body密码一样会以明文形式出现在磁盘上。更关键的是很多后台系统初期部署时HTTPS证书配置不规范、内部调用走了HTTP这时候明文密码就是裸奔状态。我在项目里定的原则是密码必须做到端到端的加密不依赖传输层安全即使中间环节有人拿到数据也无法还原出原始密码。这就引入了常见的几种加密方案。1.2 主流密码加密方案对比市面上常见的做法有这么几类方案加密方式安全性适用场景缺点MD5/SHA摘要单向散列弱极少单独使用可彩虹表破解已不推荐前端MD5盐单向散列加盐中老系统兼容盐需协商仍可被拦截重放AES对称加密共享密钥加解密中高内部系统密钥分发困难前端暴露后易被提取RSA非对称加密公钥加密/私钥解密高登录密码等敏感字段加密长度受限适合小块数据SM2国产非对称公钥加密/私钥解密高政务/金融合规要求前端库生态不如RSA完善实际项目里我最终选了RSA非对称加密这条路线原因有三个第一RSA的前端实现非常成熟pure-admin本身基于Vue3可以直接用JSEncrypt或者Web Crypto API不需要额外引重量级加密库。第二登录密码本身是极小的一段数据一般不超过64字节RSA-2048完全塞得下不需要像大文件那样走混合加密。第三公钥可以在前端随便暴露私钥只放在后端这个模型天然适合前后端分离架构。1.3 最终方案RSA HTTPS双层保险我采用的不是“二选一”而是“双层叠加”传输层HTTPS保证链路加密防中间人。应用层前端用RSA公钥加密密码后端私钥解密保证即使HTTPS被绕过或日志泄漏原始密码依然不可读。解密之后后端拿到明文密码再用BCrypt去数据库里比对Hash。注意这里有个关键点解密出来的明文密码只存在于后端内存中用完即丢不落地、不打日志。数据库里存的永远是BCrypt加盐哈希这才是完整的密码安全链条。这样设计之后整个链路是用户输入 → 前端RSA加密 → HTTPS传输 → 后端RSA解密 → BCrypt比对 → 签发Token。每一步的作用都很清晰后面我会逐一拆解实现。2. 前后端整体设计与接口约定2.1 整体交互流程拆解在设计接口之前先画出完整的时序逻辑理清每一步谁负责什么用户输入账号密码点击登录。前端从后端拉取RSA公钥或内置公钥。我采用接口动态拉取这样后续轮换密钥不需要重新发版前端。前端用公钥加密密码字符串得到密文。前端将{ username, encryptedPassword }发送给后端登录接口。后端用私钥解密得到明文密码。后端根据username查询用户用BCrypt比对密码Hash。校验通过后签发JWT Token返回前端。前端将token存入本地存储并跳转首页。这套流程里/auth/public-key和/auth/login是两个核心接口。前者返回RSA公钥后者接收加密后的密码并完成校验。2.2 后端FastAPI接口定义我用FastAPI重写了后端接口核心依赖是python-jose、cryptography、passlib下面是我最终敲定的接口路径和数据格式GET /auth/public-key → 返回公钥字符串 POST /auth/login → 接收 { username, password_encrypted }登录接口的入参用Pydantic模型做强校验避免脏数据直接进入业务逻辑from pydantic import BaseModel class LoginRequest(BaseModel): username: str password_encrypted: str class LoginResponse(BaseModel): access_token: str token_type: str bearer expires_in: int 7200接口返回统一结构前端不用做太多容错判断。这里我特意把字段名定为password_encrypted而不是password语义更清晰也避免别人一看字段名就用明文往这里传。2.3 前端pure-admin的改造切入点pure-admin框架的登录逻辑集中在src/views/login.vue和src/api/user.ts这类位置。框架本身提供了完整的登录表单、路由守卫、token管理我只需要做三件事在登录表单提交时劫持密码字段先做RSA加密再塞进请求体。封装一个getPublicKey请求登录前先拉取公钥。在接口请求层统一处理加密逻辑避免业务代码里到处散落加密代码。我对pure-admin的评价是它的代码结构比同类框架清晰很多登录相关的逻辑非常集中改造起来不需要到处打补丁。如果你的项目已经用了pure-admin下面这部分的代码可以直接对照自己的文件结构做迁移。3. 后端FastAPI核心实现3.1 项目结构和依赖准备我的后端项目使用了 FastAPI SQLAlchemy Passlib 的组合。这个组合不是最快的但胜在稳定、资料多、团队接手成本低。先把依赖列出来pip install fastapi uvicorn cryptography passlib[bcrypt] python-jose四个库各司其职fastapiuvicorn提供API服务和异步处理能力。cryptography负责RSA密钥生成、加载、加密解密。passlib[bcrypt]对解密后的明文密码做BCrypt哈希校验。python-jose签发和校验JWT。3.2 RSA密钥生成与管理RSA密钥对的生成有两条路径一种是让后端启动时自动生成另一种是用脚本预生成密钥文件放在指定目录。我在生产环境用的是第二种因为密钥文件需要持久化如果每次重启都重新生成旧客户端手里的公钥就失效了。用cryptography库生成密钥对的脚本如下from cryptography.hazmat.primitives.asymmetric import rsa from cryptography.hazmat.primitives import serialization from pathlib import Path def generate_key_pair(save_dir: str ./keys): Path(save_dir).mkdir(exist_okTrue) # 生成2048位RSA私钥 private_key rsa.generate_private_key( public_exponent65537, key_size2048 ) # 保存私钥PKCS8格式不加密——因为放在后端服务器服务启动时需要无密码加载 with open(f{save_dir}/private_key.pem, wb) as f: f.write(private_key.private_bytes( encodingserialization.Encoding.PEM, formatserialization.PrivateFormat.PKCS8, encryption_algorithmserialization.NoEncryption() )) # 提取公钥并保存 public_key private_key.public_key() with open(f{save_dir}/public_key.pem, wb) as f: f.write(public_key.public_bytes( encodingserialization.Encoding.PEM, formatserialization.PublicFormat.SubjectPublicKeyInfo ))有个细节值得说私钥我用了NoEncryption()保存这意味着如果服务器被人拖走了密钥文件私钥就泄露了。所以密钥文件的权限一定要设成600并且存放在数据库配置文件同级或独立密钥目录中不能跟随静态资源目录暴露出去。生产环境的密钥管理我建议至少做到三点密钥文件禁止进入Git仓库、服务器上只保留私钥数据库连接所需的可读权限、定期轮换并支持双密钥并存实现平滑切换。如果公司有KMS或者密钥管理平台直接接入更好。3.3 公钥接口与登录接口实现公钥接口很简单启动时读取公钥文件内容缓存到内存避免每次请求都做IOfrom fastapi import APIRouter from cryptography.hazmat.primitives import serialization router APIRouter(prefix/auth, tags[auth]) # 启动时加载公钥 with open(keys/public_key.pem, rb) as f: PUBLIC_KEY_STR f.read().decode() router.get(/public-key) async def get_public_key(): return {public_key: PUBLIC_KEY_STR, algorithm: RSA}登录接口是核心逻辑稍微复杂一点。解密过程用私钥比对过程用Passlib完整代码如下from fastapi import APIRouter, HTTPException from cryptography.hazmat.primitives.asymmetric import padding from cryptography.hazmat.primitives import hashes from passlib.context import CryptContext import base64 router APIRouter(prefix/auth, tags[auth]) pwd_context CryptContext(schemes[bcrypt], deprecatedauto) # 这两行仅示意实际应从配置中心加载 PRIVATE_KEY_PATH keys/private_key.pem def load_private_key(): with open(PRIVATE_KEY_PATH, rb) as f: return serialization.load_pem_private_key(f.read(), passwordNone) private_key load_private_key() def decrypt_password(encrypted_b64: str) - str: 将前端传来的base64密文解密为原始密码字符串 try: encrypted_bytes base64.b64decode(encrypted_b64) decrypted_bytes private_key.decrypt( encrypted_bytes, padding.OAEP( mgfpadding.MGF1(algorithmhashes.SHA256()), algorithmhashes.SHA256(), labelNone ) ) return decrypted_bytes.decode(utf-8) except Exception as e: raise HTTPException(status_code400, detail密码解密失败请重试或刷新页面后再次登录) router.post(/login) async def login(req: LoginRequest): # 第一步解密前端传过来的密码 password decrypt_password(req.password_encrypted) # 第二步从数据库查出用户 user get_user_by_username(req.username) if not user: # 刻意统一错误提示避免暴露用户是否存在 raise HTTPException(status_code401, detail用户名或密码错误) # 第三步BCrypt比对注意这里比较的是解密后的明文密码与数据库存储的hash if not pwd_context.verify(password, user.password_hash): raise HTTPException(status_code401, detail用户名或密码错误) # 第四步签发JWT token create_access_token({sub: user.username}, expires_minutes120) return LoginResponse(access_tokentoken)这里有个容易被忽略的细节RSA加密是长度受限的。RSA-2048配合OAEP填充最大只能加密约190字节的内容。密码通常远小于这个限制所以没问题。如果你需要加密的是一整段用户信息比如手机号密码验证码拼在一起的字符串就要考虑用AES随机密钥加密数据、再用RSA加密AES密钥的混合方案了。3.4 数据库密码存储与校验逻辑数据库里存的密码我在建表时就定了调只存BCrypt哈希不存原始密码也不存可还原的加密密文。BCrypt的特点是自动加盐、计算缓慢即使哈希库被拖走暴力破解的成本也非常高。用户注册或初始化密码时用Passlib生成Hashfrom passlib.context import CryptContext pwd_context CryptContext(schemes[bcrypt], deprecatedauto) def hash_password(plain_password: str) - str: return pwd_context.hash(plain_password) def verify_password(plain_password: str, password_hash: str) - bool: return pwd_context.verify(plain_password, password_hash)Passlib默认的BCrypt版本会自动生成随机的16字节盐哈希结果里已经包含了盐值信息校验时直接从数据库读出的哈希字符串里提取盐进行比对。这意味着即使两个用户设置相同的密码数据库中存储的哈希也是完全不同的这样能有效防止基于频率分析的密码猜测。这里我想强调一个很多人犯过的错误把前端加密后的密文直接存进数据库然后在校验时“解密数据库里的密文再比对”。这是完全错误的设计等于让RSA密文变成了另一种形式的“明文密码”。正确的做法是RSA加密只负责传输过程落地存储必须用BCrypt这种单向哈希。传输层的可逆加密和存储层的不可逆哈希各司其职不能混为一谈。4. 前端pure-admin核心实现4.1 环境准备与依赖安装前端部分我的项目用的Vue3 TypeScriptpure-admin框架自身已经集成了Axios封装和统一的请求拦截。加密这块我选了JSEncrypt原因很简单它对RSA的封装非常友好几行代码就能完成公钥加载和加密而且TypeScript类型定义完善。安装依赖npm install jsencrypt如果你不想引入第三方库直接用Web Crypto API也能实现但代码量会多一些且需要处理浏览器兼容性。对于后台管理系统来说客户端环境基本可控JSEncrypt够用且省心。4.2 加密工具封装我在src/utils/crypto.ts里封装了一个加密模块统一管理公钥获取和密码加密逻辑import JSEncrypt from jsencrypt /** * 使用RSA公钥加密字符串 * param publicKey 后端返回的公钥PEM字符串 * param plainText 需要加密的原始字符串 * returns base64编码的密文 */ export function rsaEncrypt(publicKey: string, plainText: string): string { const encryptor new JSEncrypt() encryptor.setPublicKey(publicKey) const encrypted encryptor.encrypt(plainText) if (!encrypted) { throw new Error(RSA加密失败请检查公钥格式或内容长度) } return encrypted }这个模块只做一件事加密。公钥的获取和管理单独放在API层因为登录接口和公钥接口的调用时机不同需要配合登录流程。4.3 登录逻辑改造从明文到密文pure-admin默认的登录逻辑是直接拿着loginForm.username和loginForm.password调接口。我改成两步走第一步调公钥接口拿公钥// src/api/auth.ts import request from /utils/request export interface PublicKeyResponse { public_key: string algorithm: string } export function getPublicKey() { return request.getPublicKeyResponse(/auth/public-key) } export interface LoginParams { username: string password_encrypted: string } export function loginApi(data: LoginParams) { return request.post(/auth/login, data) }第二步在登录页面里编排流程先取公钥再加密密码最后发送请求// src/views/login.vue 中登录方法的核心逻辑 import { rsaEncrypt } from /utils/crypto import { getPublicKey, loginApi } from /api/auth const handleLogin async () { if (!loginForm.username || !loginForm.password) { ElMessage.warning(请输入用户名和密码) return } // 防止用户多次点击loading状态一定要有 loading.value true try { // 第一步获取RSA公钥 const keyRes await getPublicKey() const publicKey keyRes.public_key // 第二步加密密码 const encryptedPwd rsaEncrypt(publicKey, loginForm.password) // 第三步发送登录请求 const res await loginApi({ username: loginForm.username, password_encrypted: encryptedPwd }) // 第四步token存储交给pure-admin统一处理 authStore.setToken(res.access_token) await authStore.getUserInfo() router.push(/) } catch (error) { console.error(登录失败, error) } finally { loading.value false } }整个改动只在登录方法内部进行不需要动pure-admin的全局请求封装和路由守卫。这也是pure-admin比较优秀的地方默认的登录流程本身就收敛在一个方法里不像有些框架把登录逻辑散落在好几层。4.4 公钥缓存与异常兜底有一个体验细节不能忽略每次登录都请求一次公钥没问题但不应该让公钥获取失败导致用户完全无法登录。我做了两层缓冲第一层公钥请求成功后缓存在内存或Vuex里五分钟内有效重复登录不需要多次请求。// 模块级变量缓存公钥 let cachedPublicKey: string | null null let cacheTime 0 const CACHE_TTL 5 * 60 * 1000 // 5分钟 export async function getPublicKeyCached() { if (cachedPublicKey Date.now() - cacheTime CACHE_TTL) { return cachedPublicKey } const res await getPublicKey() cachedPublicKey res.public_key cacheTime Date.now() return cachedPublicKey }第二层如果公钥接口异常前端直接提示“加密服务暂不可用”而不是发一个明文密码过去。这里有个原则宁可让用户登录失败也不能降级成明文传输。安全方案的底线就是出了问题拒绝服务而不是自动降级到不安全的状态。5. 联调测试与问题排查实录5.1 联调过程记录前后端并联的时候我习惯先各自验证再放一起打。在后端单测里我写了一个模拟前端加密的用例确保FastAPI端能正确解密JSEncrypt生成的密文# 模拟前端用JSEncrypt生成的密文 def test_login_encrypt_decrypt_roundtrip(): from cryptography.hazmat.primitives.asymmetric import padding from cryptography.hazmat.primitives import hashes import base64 # 加载公钥 with open(keys/public_key.pem, rb) as f: public_key serialization.load_pem_public_key(f.read()) # 模拟前端加密 plain_text MyPassword123 encrypted public_key.encrypt( plain_text.encode(utf-8), padding.OAEP( mgfpadding.MGF1(algorithmhashes.SHA256()), algorithmhashes.SHA256(), labelNone ) ) encrypted_b64 base64.b64encode(encrypted).decode() # 调用登录接口 response client.post(/auth/login, json{ username: tester, password_encrypted: encrypted_b64 }) assert response.status_code ! 400 # 解密成功的标志是不报密码解密失败这个用例看起来很笨但非常有效。它能快速暴露前端JSEncrypt和后端cryptography库之间填充方案不匹配的问题。联调时最常见的错误就是前端用PKCS1 v1.5填充后端用SAEP填充或者反过来结果解密出来的全是乱码或者直接报错。5.2 常见问题速查表我把这轮实际开发中遇到的高频问题全部整理成了一张表方便大家直接对照问题现象可能原因解决方案前端加密后登录接口报“密码解密失败”RSA填充方案不一致前端JSEncrypt默认PKCS1 v1.5后端OAEP需按此调整或明确指定一致算法推荐后端也兼容PKCS1 v1.5或前端改用对应填充密文很长超过了某个长度无法加密尝试加密的内容超过RSA-2048限制确认加密内容仅为密码而非整个请求体如需加密更多字段改用AES混合加密公钥接口能通但公钥字符串解析失败前端拿到的公钥多了换行符或格式错误公钥接口返回时确保是标准PEM字符串前端先trim再setPublicKey数据库密码比对始终失败用户密码注册时没走BCrypt哈希检查用户创建逻辑必须用pwd_context.hash()而不是存明文登录成功后刷新页面掉登录态JWT未正确存储到pure-admin指定的本地存储确认使用了authStore.setToken()而非自己另搞一套存储key解密后密码末尾有多余字符base64解码或字符串编码问题统一前端用UTF-8编码后端decrypt_bytes.decode(utf-8)5.3 独家避坑技巧第一关于JSEncrypt的填充方式。JSEncrypt默认使用RSA_PKCS1_PADDING也就是PKCS1 v1.5而后端Python的cryptography库默认推荐OAEP。我在对接时踩了一脚前端JSEncrypt加密出来的密文后端用OAEP解不开后来在解密函数里换成padding.PKCS1v15()就通了。如果你不想改后端填充也可以用支持OAEP的前端库比如encrypt-long或forge但JSEncrypt生态最成熟我建议后端兼容两种填充方式或者在公钥接口里返回填充算法标识前端按标识选择对应库。def decrypt_password(encrypted_b64: str) - str: encrypted_bytes base64.b64decode(encrypted_b64) # 兼容JSEncrypt默认的PKCS1 v1.5填充 decrypted_bytes private_key.decrypt( encrypted_bytes, padding.PKCS1v15() ) return decrypted_bytes.decode(utf-8)这里有个安全冗余PKCS1 v1.5填充理论上存在选择密文攻击风险如果系统对安全等级有更高要求建议前端改用OAEP填充如用Web Crypto API后端也同步使用OAEP。普通内部管理后台PKCS1v15在HTTPS保护下也能接受但必须在代码注释里标明风险方便后续升级。第二千万不能把明文密码放进前端日志。我见过有人为了方便排查问题在console.log里直接打印了loginForm.password这是非常危险的操作。浏览器开发者工具谁都能打开一旦密码出现在控制台相当于主动泄露。我封装的rsaEncrypt函数内部也不会把原始密码暴露出去只在出错时提示加密失败。第三JWT的过期时间不要设得太长。后台管理系统的token我一般设为2小时配合pure-admin的自动刷新token机制用户体验和安全性都兼顾到了。如果你用pure-admin做企业内部系统建议了解框架自带的token刷新流程别自己臆想一套。第四公钥轮换时注意旧token和旧公钥的兼容。我刚开始做密钥轮换时只想着后端换新密钥结果登录页缓存了旧公钥部分用户一直登不上。解决方案是前端缓存公钥时附加一个版本号或失效时间后端更换密钥后前端能自动拉取新公钥。6. 从登录到全站加密思维扩展6.1 同方案能否扩展至其它敏感字段登录密码加密的方案完整落地之后我意识到一个问题它不止适用于密码。手机号、身份证号、邮箱、银行卡号等敏感字段如果只是跟随普通请求走都有被抓包或日志泄漏的风险。前端完全可以复用已有的rsaEncrypt工具函数在后端接口对应字段加解密逻辑也完全一致。但这里有个效率取舍RSA加密非常慢而且密文长度始终大于原文如果所有接口的敏感字段都做RSA加密响应速度必然受拖累。我的建议是只对登录密码、找回密码验证码、更换手机号二次校验这几个场景做RSA加密普通查询接口的敏感数据脱敏展示即可不必过度加密。6.2 更进一步的方案AESRSA混合加密如果你的接口需要加密的字段很多或者包含较长的业务数据RSA直接上就不合适了。这时候的行业标准做法是混合加密前端生成一个随机的AES密钥用AES加密整个业务数据再用RSA公钥加密AES密钥把“AES密钥密文业务数据密文”一起发给后端。后端先用RSA私钥解出AES密钥再用AES密钥解密业务数据。这个方案比单纯RSA更灵活前端加密长度几乎不受限后端解密速度也更快。代价是代码复杂度上了一个台阶。我这次登录场景没有使用混合加密但如果项目的敏感字段数量多且零散建议直接一步到位做混合加密方案。6.3 pure-admin的扩展经验总结pure-admin这套框架经过这次改造我的整体评价是改造成本低、扩展性好、社区活跃。它的登录模块、路由守卫、权限控制都是标准化的适合快速构建后台。和FastAPI搭配时前端只需稍微调整请求封装就能适应后端接口风格变化整体联调比传统模板Vue2方案顺畅得多。如果你准备从零搭建一套pure-admin FastAPI的项目我的建议是先跑通登录全流程再做权限路由最后才做业务模块。登录环节的加密设计一定要在第一个版本就做进去否则后期重构的成本是前期的数倍。6.4 最后的实操心得这套加密登录方案上线后我看了一遍后端所有日志和数据库备份确认没有出现过任何明文密码的影子。数据库里整列的BCrypt哈希请求日志里只有密文和用户名这才算达到我心里对密码处理的最低安全线。回想整个改造过程最大的收获不是RSA本身而是想清楚了一层逻辑前端的加密解决的是传输安全问题后端的Hash解决的是存储安全问题二者缺一不可。很多人只做了其中一步就自以为足够了实际上数据在半路和掉地上都是不安全的。如果你也在用pure-admin和FastAPI建议抽一个下午把登录流程完整走一遍加密改造。遇到解密失败的问题不要慌先确认填充方式再确认公钥格式前后端分开调试一般都能在半小时内解决。改完之后你会明显感觉到再也不用担心密码裸奔了。
延伸阅读

更多相关文章

2026/10/17 12:55:25

LFR人工网络生成包实战:从参数配置到社区发现基准评测

简介:LFR人工网络生成包面向网络科学、复杂网络与社区检测方向的研究生、教师及算法工程师,用于生成带明确社区结构、幂律度分布与混合特性的基准网络,解决社区检测算法评估、网络演化模拟与韧性分析中缺少可控测试数据的问题。压缩包共62个文…

2026/10/17 12:55:25

VLingNav:自适应推理与视觉辅助语言记忆的具身导航方案

1. 项目概述与核心背景1.1 具身导航难在哪?这几年做具身智能相关的工作,绕不开一个核心场景:让一个机器人或者仿真智能体只靠摄像头看到的画面和一句自然语言指令,在陌生环境里自己找路、自己避障、自己在目标位置停下来。这就是视…

2026/10/17 12:55:25

make命令参数与特殊目标实战指南:工程级构建控制详解

1. 这不是教科书,是我在项目里天天用的 make 命令速查手册你有没有过这种经历:改完一行 C 代码,敲make等了 8 秒,结果发现它又把整个内核模块全重编了一遍?或者在 CI 流水线上,make test明明该只跑单元测试…

2026/10/17 15:35:38

终端AI编程助手Super Code实战:安装配置、使用技巧与避坑指南

1. 为什么我最终选择了"终端里的AI编程助手"而不是再装一个IDE插件先说说我遇到的真实场景。上个月我接手了一个线上服务的排查工作,服务器是Linux环境,所有操作都只能通过SSH终端完成。那台机器上没有装任何IDE,所以我遇到的每个报…

2026/10/17 15:35:38

并发编程核心概念详解:从进程线程到锁与死锁

1. 一切要从“程序卡住”说起你在某个业务系统里写过这样一个功能:批量拉取几百家上游接口的数据,然后逐条清洗入库。第一次跑的时候你发现,整个过程要花四十多分钟,而真正在“计算”的时间其实不到一半,绝大部分时间都…

2026/10/17 15:35:38

基于Spring Boot与MySQL的小型超市管理系统设计与实现

简介:本资源为基于SpringBoot的小型超市管理系统毕业设计全套资料,面向计算机专业学生及Java初学者,解决零售场景下数字化管理断层、供应链信息孤岛与动态决策支持不足等问题。系统采用B/S架构,集成商品分类管理、采购流程优化与销…

2026/10/17 15:35:38

年会大屏抽奖翻车后,我拆解了JS手机号批量滚动抽奖代码

简介:这份资源提供了一套基于JavaScript的手机号批量滚动抽奖实现代码,面向需要为年会、晚会或选秀类活动制作现场抽奖环节的前端开发者与活动策划人员。核心解决随机抽取且不重复、定时器驱动滚动展示、中奖人数可控等实际问题,适合具备基础…

2026/10/17 15:35:38

PyTorch实现神经风格迁移:VGG19与Gram矩阵让照片秒变梵高画作

先问一个我自己也琢磨了很久的问题:当你把一张随手拍的照片丢进某个工具,几秒钟后得到一张星空流转的“梵高版”图片时,你有没有想过,机器到底是怎么把“这张照片里有什么”和“画家的笔触怎么画”这两件事分开的?这背…

2026/10/17 15:30:38

影视聚合源码搭建避坑指南:从解压到播放的完整实践

简介:神马影视8.8源码最新优化版面向视频网站搭建者与后台运维学习者,提供一套经过性能与稳定性改进的在线影视系统源码,适合具备一定PHP与数据库基础、希望研究视频平台后台架构的技术人员参考。压缩包共1个文件,为单个sql数据库…

2026/10/16 5:33:43

Python调用Gemini Structured Outputs实现工单路由门禁

客服工单最怕的不是模型“答错一句话”,而是它给出一段看起来合理的说明,程序却从中猜错优先级。通俗做法是:要求模型只交 JSON(JavaScript Object Notation,轻量数据格式),再让代码验证它。Gem…

2026/10/16 4:03:48

Spring Boot超市进销存系统毕设实战:从需求拆解到答辩通关

最近带的一个学生项目组里,有A同学跑来问我:选什么毕设题目最稳妥,既能让评审老师觉得工作量够,又不会在答辩时被问到语无伦次。我第一反应就是推荐基于Spring Boot的超市仓库管理系统——也就是超市进销存系统。这个题目乍一看平…

2026/10/17 14:20:58

Flutter StatefulWidget 生命周期核心解析

很多刚开始接触 Flutter 的朋友,在看完一堆“Hello World”和基础组件之后,大概率都会撞上同一堵墙:StatefulWidget 里那堆 initState、build、dispose 方法,到底什么时候被调用?为什么顺序是那样?在里面到…

2026/10/17 0:04:32

PlanarSLAM:面向曼哈顿世界的点线面联合SLAM系统

简介:本资源是面向机器人视觉与SLAM研究者的C开源RGB-D SLAM系统实现,专为结构化室内场景(如办公室、走廊)设计,通过融合点、线、平面三类几何特征并引入“曼哈顿世界”假设,显著提升位姿跟踪鲁棒性与稠密地…

2026/10/17 0:04:32

TDH Workflow调度实战:从DAG依赖驱动到任务编排与故障排查

1. 从一个调度脚本说起:TDH Workflow到底在解决什么问题第一次接触TDH的Workflow,是在一个数据清洗项目里。当时团队每天要跑几十个ETL任务,任务之间有严格的先后依赖——A表清洗完才能跑B表的关联,B表跑完才能触发C表的聚合。最开…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑