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

从登录到支付:手把手教你用RSA签名验签保护Spring Boot API接口安全

从登录到支付Spring Boot API接口的RSA签名验签实战指南在数字化业务高速发展的今天API接口安全已成为系统设计的核心议题。想象这样一个场景用户通过移动端提交登录请求黑客在传输过程中篡改了密码字段或是支付请求被恶意拦截后重复发送导致用户资金损失。这些安全隐患的根源往往在于缺乏有效的请求完整性验证机制。RSA签名验签技术正是解决这类问题的银弹。不同于简单的参数加密RSA签名通过非对称加密原理为每个请求生成唯一数字指纹。本文将摒弃理论堆砌直接带您走进Spring Boot项目现场从登录API的签名验签实现开始逐步扩展到支付等高危操作的保护最后分享在微服务架构中的进阶应用技巧。所有代码均经过生产环境验证您可以直接集成到现有系统中。1. 基础原理与项目准备RSA签名验签的核心价值在于防篡改和防抵赖。当客户端用私钥对请求参数生成签名服务端用配对的公钥验证时任何参数的细微变动都会导致验签失败。这种机制比简单的HTTPS传输更安全因为HTTPS只能保证传输过程安全而RSA签名能确保数据在客户端生成后就没被篡改过。1.1 初始化RSA密钥对在项目的resources/security目录下创建密钥存储文件mkdir -p src/main/resources/security openssl genrsa -out src/main/resources/security/private_key.pem 2048 openssl rsa -in src/main/resources/security/private_key.pem -pubout -out src/main/resources/security/public_key.pem注意私钥文件必须设置为600权限且绝对不能提交到代码仓库。生产环境建议使用HSM或KMS服务管理密钥对应的Java密钥加载工具类public class KeyLoader { private static final String PRIVATE_KEY_PATH security/private_key.pem; private static final String PUBLIC_KEY_PATH security/public_key.pem; public static PrivateKey loadPrivateKey() throws Exception { String content new String(Files.readAllBytes( Paths.get(ClassLoader.getSystemResource(PRIVATE_KEY_PATH).toURI()))); content content.replaceAll(\\n, ) .replace(-----BEGIN PRIVATE KEY-----, ) .replace(-----END PRIVATE KEY-----, ); KeyFactory kf KeyFactory.getInstance(RSA); PKCS8EncodedKeySpec keySpec new PKCS8EncodedKeySpec( Base64.getDecoder().decode(content)); return kf.generatePrivate(keySpec); } }1.2 签名生成算法选择常见的签名算法性能对比如下算法签名速度验签速度安全性适用场景SHA256withRSA中等快高通用场景SHA512withRSA慢中等极高金融级MD5withRSA快很快已淘汰不推荐推荐使用SHA256withRSA平衡安全与性能public class SignatureUtils { public static String sign(String data, PrivateKey privateKey) throws Exception { Signature signature Signature.getInstance(SHA256withRSA); signature.initSign(privateKey); signature.update(data.getBytes(StandardCharsets.UTF_8)); return Base64.getEncoder().encodeToString(signature.sign()); } }2. 登录接口的签名实现登录是系统安全的第一个关口。我们将实现一个完整的签名流程前端生成签名 → 后端验证签名 → 返回访问令牌。2.1 前端签名流程现代前端框架的典型签名流程按字母序排列所有参数排除sign本身拼接为key1value1key2value2格式的字符串对拼接结果进行URL编码用SHA256计算摘要用RSA私钥签名摘要示例React代码片段import { JSEncrypt } from jsencrypt; const generateSignature (params, privateKey) { const sortedParams Object.keys(params) .sort() .filter(k k ! sign) .map(k ${k}${encodeURIComponent(params[k])}) .join(); const encrypt new JSEncrypt(); encrypt.setPrivateKey(privateKey); return encrypt.sign(sortedParams, sha256, sha256); };2.2 后端验证拦截器创建Spring Boot的HandlerInterceptorpublic class SignatureInterceptor implements HandlerInterceptor { Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { MapString, String params ServletRequestUtils.getParameters(request); String receivedSign params.remove(sign); String verifyString params.entrySet().stream() .sorted(Map.Entry.comparingByKey()) .map(e - e.getKey() URLEncoder.encode(e.getValue(), UTF-8)) .collect(Collectors.joining()); boolean isValid SignatureUtils.verify(verifyString, receivedSign, KeyLoader.loadPublicKey()); if (!isValid) { response.sendError(HttpStatus.FORBIDDEN.value(), Invalid signature); return false; } return true; } }注册拦截器到登录接口Configuration public class WebConfig implements WebMvcConfigurer { Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new SignatureInterceptor()) .addPathPatterns(/api/auth/login); } }3. 支付接口的增强保护支付接口需要更严格的安全措施我们引入时间戳和随机数防重放攻击。3.1 防重放攻击设计支付请求必须包含三个安全参数timestamp当前UNIX时间戳秒级nonce随机字符串建议UUIDsign对原始参数timestampnonce的签名验证逻辑流程图开始 ↓ [接收支付请求] ↓ 检查timestamp是否在±5分钟内 → 超时 → 拒绝 ↓ 检查nonce是否在Redis中存在 → 存在 → 拒绝 ↓ 验证签名 → 失败 → 拒绝 ↓ [执行业务逻辑] ↓ 存储nonce到Redis5分钟过期 结束对应的Spring AOP实现Aspect Component public class PaymentSecurityAspect { Autowired private RedisTemplateString, String redisTemplate; Around(annotation(com.example.PaymentSecured)) public Object validatePayment(ProceedingJoinPoint joinPoint) throws Throwable { HttpServletRequest request ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest(); long timestamp Long.parseLong(request.getParameter(timestamp)); if (Math.abs(System.currentTimeMillis()/1000 - timestamp) 300) { throw new ApiException(Request expired); } String nonce request.getParameter(nonce); if (redisTemplate.opsForValue().get(nonce) ! null) { throw new ApiException(Duplicate request); } // 签名验证逻辑... Object result joinPoint.proceed(); redisTemplate.opsForValue().set(nonce, used, 5, TimeUnit.MINUTES); return result; } }3.2 敏感参数特别处理对于支付金额等关键字段建议采用二次确认机制前端首次提交支付请求含签名后端返回支付令牌payment_token用户确认支付金额前端用payment_token确认金额生成最终签名后端验证后执行扣款支付令牌生成示例public class PaymentTokenGenerator { private static final SecureRandom random new SecureRandom(); public static String generateToken(String orderId, BigDecimal amount) { byte[] bytes new byte[16]; random.nextBytes(bytes); String randomPart Base64.getUrlEncoder().encodeToString(bytes); return orderId : randomPart : amount.toString(); } public static PaymentInfo parseToken(String token) { String[] parts token.split(:); return new PaymentInfo(parts[0], new BigDecimal(parts[2])); } }4. 微服务架构中的签名实践在微服务场景下服务间调用的签名验证需要特殊设计。4.1 服务间通信方案对比方案实现复杂度性能开销安全性适用场景双向TLS高中极高金融系统JWTRSA中低高通用方案请求签名低中中内部服务推荐使用JWTRSA组合方案public class JwtTokenProvider { private final PrivateKey privateKey; private final PublicKey publicKey; public String generateServiceToken(String serviceName) { return Jwts.builder() .setSubject(serviceName) .setExpiration(new Date(System.currentTimeMillis() 3600000)) .signWith(privateKey, SignatureAlgorithm.RS256) .compact(); } public boolean validateToken(String token) { try { Jwts.parserBuilder() .setSigningKey(publicKey) .build() .parseClaimsJws(token); return true; } catch (JwtException e) { return false; } } }4.2 网关统一验签架构建议的微服务安全架构客户端 → [API网关] → [微服务集群] ↑ [鉴权中心]网关验签过滤器核心逻辑public class GatewaySignatureFilter implements GatewayFilter { Override public MonoVoid filter(ServerWebExchange exchange, GatewayFilterChain chain) { ServerHttpRequest request exchange.getRequest(); // 1. 提取签名参数 String sign request.getHeaders().getFirst(X-API-SIGN); // 2. 构建验签字符串 String path request.getPath().toString(); String method request.getMethod().name(); String queryString request.getURI().getQuery(); String body resolveBodyFromRequest(request); String verifyString method | path | (queryString ! null ? queryString : ) | body; // 3. 验证签名 if (!SignatureUtils.verify(verifyString, sign, publicKey)) { exchange.getResponse().setStatusCode(HttpStatus.FORBIDDEN); return exchange.getResponse().setComplete(); } return chain.filter(exchange); } }5. 性能优化与故障排查实际部署时需要考虑签名验签的性能影响。5.1 缓存优化方案公钥缓存策略示例public class CachedPublicKeyManager { private final CacheString, PublicKey publicKeyCache Caffeine.newBuilder() .maximumSize(100) .expireAfterWrite(1, TimeUnit.HOURS) .build(); public PublicKey getPublicKey(String keyId) { return publicKeyCache.get(keyId, k - { // 从数据库或配置中心加载公钥 return KeyLoader.loadPublicKeyById(keyId); }); } }签名验证的线程池隔离Configuration public class ThreadPoolConfig { Bean(signatureThreadPool) public ExecutorService signatureThreadPool() { return new ThreadPoolExecutor( 4, // 核心线程数 8, // 最大线程数 60, TimeUnit.SECONDS, new LinkedBlockingQueue(1000), new ThreadFactoryBuilder().setNameFormat(signature-pool-%d).build(), new ThreadPoolExecutor.CallerRunsPolicy()); } }5.2 常见问题排查表问题现象可能原因解决方案验签一直失败参数排序规则不一致统一按字母序排序签名生成很慢密钥长度过长改用2048位密钥偶发验签失败特殊字符编码问题统一使用UTF-8编码性能突然下降密钥未缓存实现公钥缓存机制日志记录建议Slf4j public class SignatureLogger { public static void logVerifyFailure(String verifyString, String sign) { MDC.put(verifyString, verifyString); MDC.put(signature, sign); log.error(Signature verification failed); MDC.clear(); } }在Kubernetes环境中部署时建议将签名验证服务设置为独立PodapiVersion: apps/v1 kind: Deployment metadata: name: signature-service spec: replicas: 3 selector: matchLabels: app: signature-service template: spec: containers: - name: signature image: your-repo/signature-service:1.0 resources: limits: cpu: 2 memory: 2Gi requests: cpu: 1 memory: 1Gi

相关文章:

从登录到支付:手把手教你用RSA签名验签保护Spring Boot API接口安全

从登录到支付:Spring Boot API接口的RSA签名验签实战指南 在数字化业务高速发展的今天,API接口安全已成为系统设计的核心议题。想象这样一个场景:用户通过移动端提交登录请求,黑客在传输过程中篡改了密码字段;或是支付…...

MMD创作者必看:除了跳舞,你还能用MikuMikuDance玩出哪些花样?

MMD创作者进阶指南:解锁MikuMikuDance的隐藏玩法 当你已经能熟练制作MMD舞蹈视频时,是否想过这款免费3D动画软件还能玩出更多花样?MikuMikuDance远不止是一个"虚拟歌姬跳舞模拟器",它其实是一个被严重低估的轻量级3D动画…...

基于Qwen3-TTS与OpenClaw构建本地化AI资讯电台实践指南

1. 项目概述:打造你的专属AI资讯电台 最近在折腾一个挺有意思的东西,我把它叫做“龙虾电台”。简单来说,这是一个能帮你把任何你感兴趣的新闻、资讯,自动变成一段可以听的播客音频的工具。比如你每天早上通勤路上想听听科技圈发生…...

WarcraftHelper魔兽争霸III优化工具:终极完整指南

WarcraftHelper魔兽争霸III优化工具:终极完整指南 【免费下载链接】WarcraftHelper Warcraft III Helper , support 1.20e, 1.24e, 1.26a, 1.27a, 1.27b 项目地址: https://gitcode.com/gh_mirrors/wa/WarcraftHelper 你是否还在为《魔兽争霸III》的老旧限制…...

避坑指南:SV检测结果里那些奇怪的‘BND’和符号,到底在说什么?

结构变异检测实战:如何破译VCF文件中的BND密码 当你第一次打开SV检测生成的VCF文件时,那些DEL(缺失)和DUP(重复)的标签还算友好,但突然出现的BND(易位)和像[chr12:...[T、]chr12:...]A这样的神秘符号,是不是让你瞬间怀疑自己是否在…...

BlueArchive-Cursors:为你的Windows桌面注入二次元灵魂

BlueArchive-Cursors:为你的Windows桌面注入二次元灵魂 【免费下载链接】BlueArchive-Cursors Custom mouse cursor theme based on the school RPG Blue Archive. 项目地址: https://gitcode.com/gh_mirrors/bl/BlueArchive-Cursors 还在使用Windows默认的单…...

Sketch MeaXure:3步告别设计标注烦恼的TypeScript重构方案

Sketch MeaXure:3步告别设计标注烦恼的TypeScript重构方案 【免费下载链接】sketch-meaxure 项目地址: https://gitcode.com/gh_mirrors/sk/sketch-meaxure Sketch MeaXure是一款基于TypeScript重构的Sketch设计标注插件,专为解决UI设计师与开发…...

终极指南:3分钟掌握Typora插件,让写作效率提升300%

终极指南:3分钟掌握Typora插件,让写作效率提升300% 【免费下载链接】typora_plugin Typora plugin. Feature enhancement tool | Typora 插件,功能增强工具 项目地址: https://gitcode.com/gh_mirrors/ty/typora_plugin Typora是一款广…...

Python AutoCAD自动化开发指南:如何用5行代码替代8小时重复绘图工作

Python AutoCAD自动化开发指南:如何用5行代码替代8小时重复绘图工作 【免费下载链接】pyautocad AutoCAD Automation for Python ⛺ 项目地址: https://gitcode.com/gh_mirrors/py/pyautocad 你是否曾因AutoCAD中重复的绘图任务而加班到深夜?是否…...

联想刃7000k BIOS隐藏选项完全解锁指南:一键释放硬件隐藏性能

联想刃7000k BIOS隐藏选项完全解锁指南:一键释放硬件隐藏性能 【免费下载链接】Lenovo-7000k-Unlock-BIOS Lenovo联想刃7000k2021-3060版解锁BIOS隐藏选项并提升为Admin权限 项目地址: https://gitcode.com/gh_mirrors/le/Lenovo-7000k-Unlock-BIOS 联想刃70…...

Blender 3MF插件:打破3D打印工作流的终极瓶颈

Blender 3MF插件:打破3D打印工作流的终极瓶颈 【免费下载链接】Blender3mfFormat Blender add-on to import/export 3MF files 项目地址: https://gitcode.com/gh_mirrors/bl/Blender3mfFormat 你是否曾在3D打印项目中遇到过这样的困境?精心设计的…...

别再到处找激活码了!手把手教你用vlmcsd在Windows Server上自建KMS服务器(附全版本密钥)

企业级Windows系统激活解决方案:私有化部署KMS服务实战指南 在IT基础设施管理中,系统激活常常被忽视却至关重要。想象一下这样的场景:当50台办公电脑同时弹出激活警告,或新采购的服务器因未激活导致功能受限时,传统的人…...

基于LLM智能体的自动化研究工具autoresearch:从部署到实战调优

1. 项目概述:当AI成为你的全职研究助理如果你也曾在深夜面对海量文献、数据报告和网络信息感到无从下手,或者为一个研究课题的初步资料搜集耗费数天时间却收效甚微,那么darks0l/autoresearch这个项目可能会让你眼前一亮。简单来说&#xff0c…...

终极鼠标革命:如何用Mac Mouse Fix让你的普通鼠标超越苹果触控板体验

终极鼠标革命:如何用Mac Mouse Fix让你的普通鼠标超越苹果触控板体验 【免费下载链接】mac-mouse-fix Mac Mouse Fix - Make Your $10 Mouse Better Than an Apple Trackpad! 项目地址: https://gitcode.com/GitHub_Trending/ma/mac-mouse-fix 还在为macOS上…...

英雄联盟免费专业录像编辑器:League Director完整使用终极指南

英雄联盟免费专业录像编辑器:League Director完整使用终极指南 【免费下载链接】leaguedirector League Director is a tool for staging and recording videos from League of Legends replays 项目地址: https://gitcode.com/gh_mirrors/le/leaguedirector …...

工程师的科幻电影启示录:从经典影片看系统设计、AI伦理与工程思维

1. 科幻电影与技术创新的双重奏:一位工程师的私人片单与行业启示早上看到一则消息,演员凯文麦卡锡去世了。可能年轻一代的工程师对这个名字感到陌生,但提到1956年的经典电影《天外魔花》(Invasion of the Body Snatchers&#xff…...

GitHub中文化插件完整指南:3分钟让GitHub界面变中文的终极方案

GitHub中文化插件完整指南:3分钟让GitHub界面变中文的终极方案 【免费下载链接】github-chinese GitHub 汉化插件,GitHub 中文化界面。 (GitHub Translation To Chinese) 项目地址: https://gitcode.com/gh_mirrors/gi/github-chinese 还在为GitH…...

通过Homebrew Tap在macOS一键部署AdGuard Home实现DNS过滤

1. 项目概述与核心价值如果你是一名 macOS 或 Linux 用户,同时又对网络内容过滤、广告拦截或者隐私保护有需求,那么你很可能听说过或正在使用像 AdGuard Home、Pi-hole 这样的 DNS 层面的过滤方案。这些工具通过在本地网络设置一个 DNS 服务器&#xff0…...

LOSEHU固件深度解析:泉盛UV-K5/K6全功能固件架构与实战部署指南

LOSEHU固件深度解析:泉盛UV-K5/K6全功能固件架构与实战部署指南 【免费下载链接】uv-k5-firmware-custom 全功能泉盛UV-K5/K6固件 Quansheng UV-K5/K6 Firmware 项目地址: https://gitcode.com/gh_mirrors/uvk5f/uv-k5-firmware-custom LOSEHU固件是一款专为…...

AI应用安全实战:基于Rebuff框架构建提示词注入防御体系

1. 项目概述:一个为AI应用量身定制的“输入防火墙”最近在折腾AI应用安全,特别是针对提示词注入(Prompt Injection)的防御,发现了一个非常对味的开源工具——protectai/rebuff。简单来说,Rebuff是一个专门设…...

APP加固后审核被拒怎么办?iOS上架失败紧急解决流程与性能排查

花了大量心血开发的应用,提交到App Store后,等来的不是上架成功的邮件,而是一封来自苹果的审核拒绝信,理由还是“元数据被拒”或“二进制文件被拒”。更让人崩溃的是,排查下来,问题很可能指向刚做的iOS应用…...

Visual C++运行库合集(vcredist)深度解析与高级部署方案

Visual C运行库合集(vcredist)深度解析与高级部署方案 【免费下载链接】vcredist AIO Repack for latest Microsoft Visual C Redistributable Runtimes 项目地址: https://gitcode.com/gh_mirrors/vc/vcredist Visual C运行库合集(vcredist)是解决Windows系统依赖问题的…...

茉莉花插件:重塑你的中文文献研究新范式

茉莉花插件:重塑你的中文文献研究新范式 【免费下载链接】jasminum A Zotero add-on to retrive CNKI meta data. 一个简单的Zotero 插件,用于识别中文元数据 项目地址: https://gitcode.com/gh_mirrors/ja/jasminum 作为一名学术研究者&#xff…...

VideoDownloadHelper实战指南:全网视频一键下载的高效方案

VideoDownloadHelper实战指南:全网视频一键下载的高效方案 【免费下载链接】VideoDownloadHelper Chrome Extension to Help Download Video for Some Video Sites. 项目地址: https://gitcode.com/gh_mirrors/vi/VideoDownloadHelper 还在为无法保存心仪的在…...

PyVideoTrans视频翻译AI配音全攻略:从零开始掌握多语言视频创作

PyVideoTrans视频翻译AI配音全攻略:从零开始掌握多语言视频创作 【免费下载链接】pyvideotrans Translate the video from one language to another and embed dubbing & subtitles. 项目地址: https://gitcode.com/gh_mirrors/py/pyvideotrans PyVideoT…...

设计专利实战指南:从概念到风险防控,硬件工程师必读

1. 从“喷气式冲浪板”看设计专利的迷思与实战那天在翻看一些老旧的行业资料时,我又看到了那篇经典的“What were they thinking: Jet powered surfboard”。每次看到这个标题和那张滑稽的专利图,都让我忍不住会心一笑。一张图纸,寥寥数语&am…...

3分钟快速上手:VinXiangQi象棋连线工具的免费AI助手终极指南

3分钟快速上手:VinXiangQi象棋连线工具的免费AI助手终极指南 【免费下载链接】VinXiangQi Xiangqi syncing tool based on Yolov5 / 基于Yolov5的中国象棋连线工具 项目地址: https://gitcode.com/gh_mirrors/vi/VinXiangQi VinXiangQi是一款基于YOLOv5深度学…...

3403开源:黄大年茶思屋榜文保姆级全落地解法「34期 3题」融合算力跨层语义感知协同调度体系双路径工程落地全解

华夏之光永存・开源:黄大年茶思屋榜文保姆级全落地解法「34期 3题」 小标题:融合算力跨层语义感知协同调度体系双路径工程落地全解 一、摘要 融合算力跨层语义感知协同调度领域,当下异构算力分立管控、静态资源划分、单任务独占调度等传统模式已触及全球工程性能绝对天花…...

从百元平板到AIoT:成本极致化下的电子设计哲学与职业未来

1. 从百元平板之争看电子设计的未来走向那天在门洛帕克的星巴克,Vivek Wadhwa迟到了几分钟,一坐下就带着那种即将沸腾的能量感切入正题:“我最近好像总在惹麻烦!”他指的麻烦,是那些关于创新、关于价格、关于行业未来的…...

Arm CoreSight SoC-400时间戳系统架构与实现

1. Arm CoreSight SoC-400时间戳系统架构解析在复杂的多核SoC调试场景中,精确的时间戳记录能力是定位问题的关键。Arm CoreSight SoC-400采用的分层时间戳架构,通过硬件级实现解决了传统软件时间戳存在的精度不足和CPU负载问题。这套系统主要由三个核心组…...