JWT单点登录实战:从原理到企业级安全认证方案
如果你正在开发多系统集成的企业应用或者维护一个包含多个子站点的平台那么单点登录SSO一定是你绕不开的技术话题。而 JWTJSON Web Token作为现代认证方案的核心组件其重要性不言而喻。但很多开发者对 JWT 的理解停留在“生成 token、验证 token”的层面真正在单点登录场景下部署时却频频踩坑。这篇文章不会重复那些随处可见的 JWT 概念介绍而是聚焦于一个核心问题在真实的单点登录系统中JWT 的认证流程到底应该如何设计才能兼顾安全、性能和可维护性我们将从单点登录的业务场景出发拆解 JWT 在其中的关键作用并通过完整的代码示例展示从登录到鉴权的全流程。无论你是正在选型的技术负责人还是需要落地实现的开发工程师都能从中获得可直接复用的实践方案。1. 这篇文章真正要解决的问题单点登录的本质是一次登录多处通行。想象一下你的公司有 OA 系统、CRM 系统、财务系统如果每个系统都需要单独登录员工每天要重复输入多次账号密码体验极差。单点登录解决了这个问题但随之而来的是认证架构的复杂性。JWT 在单点登录中扮演着安全凭证的角色。它不像传统的 Session 方案需要在服务端存储登录状态而是通过加密的 Token 自包含用户信息。这种无状态特性非常适合分布式系统但也带来了新的挑战Token 安全性如何防止 Token 被窃取后滥用权限动态更新用户权限变更后如何让已签发的 Token 及时失效跨域认证多个不同域名的系统间如何安全传递 Token性能与存储如何在减少服务端存储压力的同时保证认证效率本文将围绕这些实际问题给出基于 JWT 的单点登录完整解决方案。如果你面临以下场景这篇文章会特别有用正在从单体应用向微服务架构迁移需要统一的认证方案现有系统认证混乱希望引入标准的单点登录机制对 JWT 有基础了解但在实际项目中遇到具体技术问题2. 基础概念与核心原理2.1 单点登录SSO的本质单点登录不是一项具体的技术而是一种认证架构模式。其核心思想是集中认证分布式授权。所有子系统共享同一个认证中心用户只需在认证中心登录一次即可访问所有相互信任的系统。传统 Session 方案的问题在于每个子系统都需要维护自己的 Session 存储跨域 Session 共享实现复杂服务端存储压力随用户量线性增长而基于 Token 的 SSO 方案通过无状态的认证令牌解决了这些问题。2.2 JWT 的结构与工作原理JWT 由三部分组成用点号分隔Header.Payload.SignatureHeader头部指定令牌类型和签名算法{ alg: HS256, typ: JWT }Payload负载包含声明用户信息和其他元数据{ sub: 1234567890, name: John Doe, iat: 1516239022, exp: 1516242622 }Signature签名用于验证令牌完整性// 伪代码示例 signature HMACSHA256( base64UrlEncode(header) . base64UrlEncode(payload), secret )JWT 的关键特性自包含所有必要信息都在 Token 中减少数据库查询可验证通过签名确保内容未被篡改无状态服务端不需要存储会话信息2.3 JWT 在 SSO 中的角色定位在单点登录架构中JWT 通常作为访问令牌Access Token使用。认证中心负责签发 JWT各个子系统通过验证 JWT 签名来确认用户身份。这种设计实现了认证与业务的解耦。3. 环境准备与前置条件3.1 技术栈选择本文示例基于以下技术栈但核心思路适用于任何语言认证中心Spring Boot 2.7 作为 SSO 服务器子系统Spring Boot 作为业务系统示例JWT 库jjwt 0.11.5Java JWT 实现数据库MySQL 8.0 用于用户存储可选演示用3.2 项目结构规划建议采用多模块 Maven 项目sso-demo/ ├── sso-server/ # 认证中心 ├── sso-client-a/ # 子系统A ├── sso-client-b/ # 子系统B └── common-jwt/ # JWT 工具类共享模块3.3 依赖配置认证中心 pom.xml 关键依赖dependencies dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency dependency groupIdio.jsonwebtoken/groupId artifactIdjjwt-api/artifactId version0.11.5/version /dependency dependency groupIdio.jsonwebtoken/groupId artifactIdjjwt-impl/artifactId version0.11.5/version scoperuntime/scope /dependency dependency groupIdio.jsonwebtoken/groupId artifactIdjjwt-jackson/artifactId version0.11.5/version scoperuntime/scope /dependency /dependencies4. 核心流程拆解4.1 单点登录的完整认证流程基于 JWT 的单点登录包含以下关键步骤未登录访问用户访问子系统A被重定向到认证中心统一认证用户在认证中心登录生成 JWT令牌传递认证中心重定向回子系统A携带 JWT令牌验证子系统A验证 JWT 签名和有效期跨系统访问用户访问子系统B携带 JWT 直接认证4.2 JWT 的生命周期管理每个 JWT 都有明确的生命周期生成用户成功登录后认证中心签发传递通过 URL 参数、Cookie 或 Header 在系统间传递验证业务系统验证签名、有效期和业务规则刷新接近过期时通过刷新令牌获取新 Token失效过期或被加入黑名单后失效5. 完整示例与代码实现5.1 JWT 工具类封装首先创建通用的 JWT 工具类供认证中心和子系统共用// 文件路径common-jwt/src/main/java/com/example/sso/jwt/JwtUtil.java Component public class JwtUtil { private static final String SECRET_KEY your-256-bit-secret-change-in-production; private static final long EXPIRATION_TIME 3600000; // 1小时 /** * 生成 JWT */ public String generateToken(UserDetails userDetails) { MapString, Object claims new HashMap(); claims.put(username, userDetails.getUsername()); claims.put(roles, userDetails.getAuthorities()); return Jwts.builder() .setClaims(claims) .setSubject(userDetails.getUsername()) .setIssuedAt(new Date(System.currentTimeMillis())) .setExpiration(new Date(System.currentTimeMillis() EXPIRATION_TIME)) .signWith(SignatureAlgorithm.HS256, SECRET_KEY) .compact(); } /** * 验证 JWT 并解析用户信息 */ public UserDetails parseToken(String token) { try { Claims claims Jwts.parser() .setSigningKey(SECRET_KEY) .parseClaimsJws(token) .getBody(); String username claims.getSubject(); ListString roles (ListString) claims.get(roles); return new User(username, , roles.stream() .map(SimpleGrantedAuthority::new) .collect(Collectors.toList())); } catch (Exception e) { throw new RuntimeException(JWT 验证失败, e); } } /** * 验证 Token 是否有效 */ public boolean validateToken(String token) { try { Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token); return true; } catch (Exception e) { return false; } } }5.2 认证中心登录接口认证中心负责用户认证和 JWT 签发// 文件路径sso-server/src/main/java/com/example/sso/controller/AuthController.java RestController RequestMapping(/auth) public class AuthController { Autowired private JwtUtil jwtUtil; Autowired private UserService userService; /** * 用户登录接口 */ PostMapping(/login) public ResponseEntityLoginResponse login(RequestBody LoginRequest request) { // 1. 验证用户名密码 UserDetails userDetails userService.authenticate(request.getUsername(), request.getPassword()); // 2. 生成 JWT String token jwtUtil.generateToken(userDetails); // 3. 返回登录结果 LoginResponse response new LoginResponse(); response.setToken(token); response.setExpiresIn(3600); response.setTokenType(Bearer); return ResponseEntity.ok(response); } /** * JWT 验证接口供子系统调用 */ PostMapping(/validate) public ResponseEntityValidationResponse validateToken(RequestParam String token) { boolean isValid jwtUtil.validateToken(token); ValidationResponse response new ValidationResponse(); response.setValid(isValid); if (isValid) { response.setUserDetails(jwtUtil.parseToken(token)); } return ResponseEntity.ok(response); } } // 登录请求DTO Data class LoginRequest { private String username; private String password; } // 登录响应DTO Data class LoginResponse { private String token; private String tokenType; private Integer expiresIn; } // 验证响应DTO Data class ValidationResponse { private boolean valid; private UserDetails userDetails; }5.3 子系统 JWT 拦截器子系统需要拦截请求并验证 JWT// 文件路径sso-client-a/src/main/java/com/example/client/config/JwtInterceptor.java Component public class JwtInterceptor implements HandlerInterceptor { Autowired private JwtUtil jwtUtil; Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 1. 从请求中获取 Token String token getTokenFromRequest(request); if (token null) { // 重定向到认证中心登录页 redirectToSsoLogin(request, response); return false; } // 2. 验证 Token 有效性 if (!jwtUtil.validateToken(token)) { // Token 无效重新登录 redirectToSsoLogin(request, response); return false; } // 3. 将用户信息设置到请求上下文中 UserDetails userDetails jwtUtil.parseToken(token); request.setAttribute(currentUser, userDetails); return true; } private String getTokenFromRequest(HttpServletRequest request) { // 从 Header 获取 String authHeader request.getHeader(Authorization); if (authHeader ! null authHeader.startsWith(Bearer )) { return authHeader.substring(7); } // 从 URL 参数获取适用于重定向场景 String tokenParam request.getParameter(token); if (tokenParam ! null) { return tokenParam; } // 从 Cookie 获取 Cookie[] cookies request.getCookies(); if (cookies ! null) { for (Cookie cookie : cookies) { if (jwt_token.equals(cookie.getName())) { return cookie.getValue(); } } } return null; } private void redirectToSsoLogin(HttpServletRequest request, HttpServletResponse response) throws IOException { String redirectUrl request.getRequestURL().toString(); String ssoLoginUrl http://sso-server:8080/auth/login?redirect URLEncoder.encode(redirectUrl, UTF-8); response.sendRedirect(ssoLoginUrl); } }5.4 拦截器配置注册拦截器到 Spring MVC// 文件路径sso-client-a/src/main/java/com/example/client/config/WebMvcConfig.java Configuration public class WebMvcConfig implements WebMvcConfigurer { Autowired private JwtInterceptor jwtInterceptor; Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(jwtInterceptor) .addPathPatterns(/**) .excludePathPatterns(/auth/callback, /static/**, /error); } }6. 运行结果与效果验证6.1 启动服务验证启动认证中心cd sso-server mvn spring-boot:run启动子系统Acd sso-client-a mvn spring-boot:run -Dserver.port8081访问子系统 在浏览器访问http://localhost:8081/dashboard应该被重定向到认证中心登录页。6.2 登录流程验证提交登录表单curl -X POST http://localhost:8080/auth/login \ -H Content-Type: application/json \ -d {username:admin,password:password}预期响应{ token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..., tokenType: Bearer, expiresIn: 3600 }使用 Token 访问受保护接口curl -X GET http://localhost:8081/api/user/profile \ -H Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...预期响应用户信息证明 JWT 验证成功。6.3 跨系统访问验证启动子系统Bcd sso-client-b mvn spring-boot:run -Dserver.port8082使用同一 Token 访问子系统Bcurl -X GET http://localhost:8082/api/orders \ -H Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...应该能正常获取订单数据证明单点登录生效。7. 常见问题与排查思路问题现象可能原因排查方式解决方案Token 验证失败1. 密钥不匹配2. Token 过期3. 签名算法不一致1. 检查认证中心和子系统密钥配置2. 查看 Token 过期时间3. 验证签名算法配置1. 统一密钥配置2. 调整 Token 有效期3. 固定使用相同算法重定向循环1. 拦截器配置错误2. Token 获取逻辑问题1. 检查排除路径配置2. 调试 Token 提取逻辑1. 正确配置排除路径2. 确保回调接口不被拦截跨域问题1. 子系统域名不同2. CORS 配置缺失1. 检查浏览器控制台错误2. 验证 CORS 配置1. 配置正确的 CORS 规则2. 使用代理或同域名部署Token 被盗用1. Token 传输未加密2. 缺乏刷新机制1. 检查网络传输安全2. 分析 Token 使用模式1. 强制使用 HTTPS2. 实现 Token 刷新和黑名单7.1 典型错误示例错误在 Filter 中直接重定向// 错误写法 - 在 Filter 中重定向会导致问题 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) { if (!validateToken(token)) { ((HttpServletResponse) response).sendRedirect(/login); // 可能引发异常 return; } chain.doFilter(request, response); }正确使用异常处理重定向// 正确写法 - 通过异常统一处理 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) { try { if (!validateToken(token)) { throw new AuthenticationException(Token 验证失败); } chain.doFilter(request, response); } catch (AuthenticationException e) { // 统一异常处理中处理重定向 handleAuthenticationFailure(request, response, e); } }8. 最佳实践与工程建议8.1 安全增强措施1. 使用非对称加密算法生产环境建议使用 RS256 等非对称加密// 使用 RSA 非对称加密 private static final PrivateKey privateKey // 从证书加载私钥 private static final PublicKey publicKey // 从证书加载公钥 public String generateToken(UserDetails userDetails) { return Jwts.builder() .setClaims(claims) .signWith(SignatureAlgorithm.RS256, privateKey) // 私钥签名 .compact(); } public boolean validateToken(String token) { return Jwts.parser() .setSigningKey(publicKey) // 公钥验证 .parseClaimsJws(token); }2. 实现 Token 刷新机制避免频繁重新登录// 刷新 Token 接口 PostMapping(/refresh) public ResponseEntityLoginResponse refreshToken(RequestParam String refreshToken) { // 验证刷新令牌有效性 if (!refreshTokenService.validate(refreshToken)) { throw new RuntimeException(刷新令牌无效); } // 生成新的访问令牌 String newAccessToken jwtUtil.generateToken(...); return ResponseEntity.ok(new LoginResponse(newAccessToken)); }8.2 性能优化建议1. 减少 JWT 体积只存储必要信息避免过度负载// 好的实践 - 只存用户ID和角色 claims.put(userId, user.getId()); claims.put(roles, user.getRoleCodes()); // 不是完整角色对象 // 避免的做法 - 存储过多信息 claims.put(user, user); // 整个用户对象序列化2. 实现本地验证缓存减少重复的签名验证开销Component public class JwtCacheService { private final CacheString, UserDetails tokenCache Caffeine.newBuilder() .expireAfterWrite(10, TimeUnit.MINUTES) .maximumSize(10000) .build(); public UserDetails getCachedUser(String token) { return tokenCache.getIfPresent(token); } public void cacheUser(String token, UserDetails user) { tokenCache.put(token, user); } }8.3 生产环境配置1. 密钥管理绝对不要将密钥硬编码在代码中# application-prod.properties jwt.secret${JWT_SECRET_KEY:default-secret-change-in-production} jwt.expiration36002. 监控与日志添加详细的认证日志Slf4j Component public class JwtUtil { public boolean validateToken(String token) { try { Jwts.parser().setSigningKey(secret).parseClaimsJws(token); log.info(JWT验证成功: {}, extractUsername(token)); return true; } catch (ExpiredJwtException e) { log.warn(JWT已过期: {}, e.getClaims().getSubject()); return false; } catch (Exception e) { log.error(JWT验证失败: {}, e.getMessage()); return false; } } }9. 总结与后续学习方向本文详细拆解了 JWT 在单点登录系统中的完整认证流程。关键要点总结架构清晰认证中心负责签发子系统负责验证职责分离安全优先使用合适的签名算法管理好密钥安全性能平衡在无状态和缓存之间找到平衡点异常完备完善的错误处理和日志记录在实际项目中你还需要进一步考虑扩展学习方向OAuth 2.0 集成如何将 JWT SSO 与第三方登录整合微服务架构在 Spring Cloud Gateway 中统一处理 JWT 认证权限细化基于 JWT 声明实现更精细的权限控制安全加固防范 JWT 重放攻击、注入攻击等安全威胁实践建议先从简单的内部系统开始实践逐步扩展到生产环境建立完善的 Token 监控和告警机制定期进行安全审计和密钥轮换JWT 单点登录是一个看似简单实则充满细节的技术主题。希望本文的实践方案能帮助你在实际项目中少走弯路构建安全可靠的认证系统。建议收藏本文在具体实施过程中参考对应的代码示例和排查指南。

相关新闻

电子烟雾化原理、健康风险与使用建议

电子烟雾化原理、健康风险与使用建议

1. 电子烟雾化原理与成分解析 电子烟通过电池供电加热烟油产生气溶胶,这个过程中涉及复杂的物理化学变化。与传统燃烧型香烟不同,电子烟采用雾化技术,将烟油转化为可吸入的微小颗粒。但"水蒸气"这个说法具有严重误导性,…

2026/8/1 17:41:55 阅读更多 →
AI 写的代码 bug 都是批量的,我们用五道关口稳住了交易核心系统

AI 写的代码 bug 都是批量的,我们用五道关口稳住了交易核心系统

一次故障归因会后,所有人都沉默了 上个月我们做了一件事,把过去半年的线上故障拉出来做了个完整归因。 结果出来的那天,会议室里安静了好几秒。 不是故障数量有多吓人。说实话,故障数跟去年同期比差不多,甚至还略少一点…

2026/8/1 17:41:55 阅读更多 →
LangChain4j权限管理实战:Java AI框架访问控制设计

LangChain4j权限管理实战:Java AI框架访问控制设计

1. 项目概述 今天我们来聊聊Java开发中一个经典面试题:如何在LangChain4j框架中实现访问控制和权限管理。这个问题看似基础,实则涵盖了现代分布式系统开发中的核心安全机制设计。 LangChain4j作为Java生态中新兴的AI应用框架,其权限管理方案…

2026/8/1 17:41:55 阅读更多 →

最新新闻

实战分享 | 基于深度学习的实时车道线检测与可视化系统

实战分享 | 基于深度学习的实时车道线检测与可视化系统

🚗 实战分享 | 基于深度学习的实时车道线检测与可视化系统 前言 最近在研究自动驾驶感知模块时,发现车道线检测是一个非常有意思的方向。今天给大家分享一个我基于 UFLD-v2 实现的实时车道线检测与可视化系统,不仅能检测车道线,还…

2026/8/1 18:38:18 阅读更多 →
节点小宝4.0远程控制软件的技术革新与应用

节点小宝4.0远程控制软件的技术革新与应用

1. 节点小宝4.0的远程控制革新远程控制软件市场已经很久没有让人眼前一亮的创新了。大多数产品要么停留在简单的桌面共享功能,要么就是堆砌各种复杂功能让普通用户望而生畏。节点小宝4.0的发布,确实给这个领域带来了久违的新鲜空气。作为一个长期关注远程…

2026/8/1 18:38:18 阅读更多 →
AI Agent在DevOps中的智能化实践与架构解析

AI Agent在DevOps中的智能化实践与架构解析

1. 项目概述:当AI Agent遇上DevOps去年在为一个跨国电商平台重构CI/CD流水线时,我第一次尝试将AI Agent引入部署流程。某个凌晨三点,系统自动检测到即将发布的版本存在内存泄漏风险,AI Agent不仅中止了部署,还给出了修…

2026/8/1 18:38:18 阅读更多 →
LeetCode Hot 100 | 图论(C++ 题解)

LeetCode Hot 100 | 图论(C++ 题解)

LeetCode Hot 100 | 图论(C 题解) Hot100 图论:200 / 994 / 207 / 208。 目录LeetCode Hot 100 | 图论(C 题解)一、200. Number of Islands(岛屿数量)🟡 中等题目描述图解解题思路C …

2026/8/1 18:38:17 阅读更多 →
SolidWorks装配体边界获取技术解析与C#实现

SolidWorks装配体边界获取技术解析与C#实现

1. SolidWorks装配体边界获取技术解析 在机械设计领域,获取装配体的精确边界尺寸是进行空间规划、干涉检查和包装设计的基础工作。作为主流的三维CAD软件,SolidWorks提供了完善的API接口供开发者扩展功能。通过C#进行二次开发,我们可以实现自…

2026/8/1 18:38:17 阅读更多 →
免费足球数据分析终极指南:无需API密钥获取30+联赛完整数据

免费足球数据分析终极指南:无需API密钥获取30+联赛完整数据

免费足球数据分析终极指南:无需API密钥获取30联赛完整数据 【免费下载链接】football.json Free open public domain football data in JSON incl. English Premier League, Bundesliga, Primera Divisin, Serie A and more - No API key required ;-) 项目地址: …

2026/8/1 18:37:17 阅读更多 →

日新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/1 0:00:48 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/1 0:00:48 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/1 0:00:48 阅读更多 →

周新闻

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 数据集6000张 完整源码已标注数据集训练好的模型环境配置教程程序运行说明文档,可以直接使用!系统支持图片、视频、摄像头等多种方式检测裂缝,功能强大实用。 1数据集6000张 8各类别

2026/8/1 13:02:46 阅读更多 →
深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

pubg数据集 精选原图1.42万数据 1.49万标签 无任何重复、算法增强或冗余图像! pubg绝地求生目标检测数据集 1分类:e_body,14905个标签,txt格式 共计14244张图,99%为640*640尺寸图像 适合yolo目标检测、AI训练关键词&am…

2026/8/1 5:19:34 阅读更多 →
Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex检测数据集数据集详情检测类别: allies enemy tag图片总量:7247张训练集:5139张验证集:1425张测试集:683张标注状态:全部已标注,即拿即用数据格式:支持YOLO格式及其他格式&#…

2026/8/1 10:33:33 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/1 0:00:48 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/1 0:00:48 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/1 0:00:48 阅读更多 →