JSON Web Token (JWT)的简单介绍、验证过程及令牌刷新思路

目录
一、JWT
1、什么是Jwt
2、为什么要使用Jwt
3、应用场景
4.Jwt的组成
4.1、Header
4.2、Payload
4.3、signature
二、Jwt验证过程
1、生成Jwt令牌
2、解析旧的Jwt
3、复制Jwt
4、Jwt有效时间测试
三、Jwt令牌刷新思路
1、配置JwtFilter过滤器
2、登录生成Jwt令牌
3、配置CorsFilter过滤器
4、Vuex存储Jwt令牌
5、修改main.js
6、配置axios请求响应头
前言:
随着前后端分离的发展,以及数据中心的建立,越来越多的公司会创建一个中心服务器,服务于各种产品线。而这些产品线上的产品,它们可能有着各种终端设备,包括但不仅限于浏览器、桌面应用、移动端应用、平板应用、甚至智能家居。
这些设备与中心服务器之间会进行http通信,一般来说,中心服务器至少承担着认证和授权的功能。例如登录:各种设备发送消息到中心服务器,然后中心服务器响应一个身份令牌,当这种结构出现后,就出现一个问题:它们之间还能使用传统的cookie方式传递令牌信息吗?
其实,也是可以的,因为cookie在传输中无非是一个消息头而已,只不过浏览器对这个消息头有特殊处理罢了。但浏览器之外的设备肯定不喜欢cookie,因为浏览器有着对cookie完善的管理机制,但是在其他设备上,就需要开发者自己手动处理了。
JWT 的出现就是为了解决这个问题!!!
一、JWT
1、什么是Jwt
JSON Web Token (JWT)是一个开放标准(RFC 7519),它定义了一种紧凑的、自包含的方式,用于作为JSON对象在各方之间安全地传输信息。该信息可以被验证和信任,因为它是数字签名的。是目前最流行的跨域身份验证解决方案;
RFC 7519:RFC 7519 - JSON Web Token (JWT)
2、为什么要使用Jwt
它要解决的问题,就是为多种终端设备,提供统一的、安全的令牌格式。因此,jwt只是一个令牌格式而已,你可以把它存储到cookie,也可以存储到localstorage,没有任何限制!同样的,对于传输,你可以使用任何传输方式来传输jwt,一般来说,我们会使用消息头header来传输它。
比如:当登录成功后,服务器可以给客户端响应一个Jwt。
HTTP/1.1 200 OK
...
set-cookie:token=jwt令牌
authorization:jwt令牌
...{..., token:jwt令牌}
可以看到,jwt令牌可以出现在响应的任何一个地方,客户端和服务器自行约定即可。
当然,它也可以出现在响应的多个地方,比如为了充分利用浏览器的 cookie,同时为了照顾其他设备,也可以让 jwt 出现在 set-cookie 和 authorization 或 body 中,尽管这会增加额外的传输量。
总之,Jwt的精髓在于去中心化,数据是保存在客户端的。
3、应用场景
- 认证:认证是JWT的最常用场景。只要用户完成登录,其随后的请求都会包含JWT,以允许用户访问经由当前JWT授权的路由、服务或者是资源。由于开销小且能够被简单应用在跨域访问上,JWT在分布式站点上所支持的单点登录(SSO)已经是当前它被广泛应用的一个特性。
- 信息交换:JWT是一种在各参与方之间安全传递信息的良好方法。由于JWT可以被签名(例:使用公钥/秘钥对),因而可用于确认发送者自称的身份。除此之外,由于signature使用header和payload进行计算,也可以验证内容没有被篡改。
JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密。
4.Jwt的组成
一个Jwt实际上就是一个字符串,它由三部分组成:
-
Header(头部)
-
Payload(载荷)
-
Signature(签名)
eyJhbGciOiJIUzI1NiJ9.
eyJzdWIiOiJ7fSIsImlzcyI6InpraW5nIiwiZXhwIjoxNTYyODUwMjM3LCJpYXQiOjE1NjI4NDg0MzcsImp0aSI6ImM5OWEyMzRmMDc4NzQyZWE4YjlmYThlYmYzY2VhNjBlIiwidXNlcm5hbWUiOiJ6c3MifQ.
WUfqhFTeGzUZCpCfz5eeEpBXBZ8-lYg1htp-t7wD3I4
它是一个很长的字符串因此,中间用点(.)分隔成三个部分。
注意,Jwt 内部是没有换行的,这里只是为了便于展示,将它写成了几行。
4.1、Header
典型的JWT header包含两个部分:
-
typ(type)属性,用来标识整个token字符串是一个JWT字符串,即JWT。
-
alg(algorithm)属性,用来说明这个JWT签发的时候所使用的签名和摘要算法,比如HMAC SHA256或者RSA。
{"alg": "HS256","typ": "JWT"
}
4.2、Payload
JWT token的第二部分是包含了声明的payload,声明(要求)是一个实体的表述加上额外信息,一共有三种形式的声明:注册、公有和私有;
- 注册声明
它的json结构实际上是对JWT要传递的数据的一组声明,这些声明被JWT标准称为claims,它的一个属性值对其实就是一个claim(要求),每一个claim的都代表特定的含义和作用。
{"iss":"发行者","iat":"发布时间","exp":"到期时间","sub":"主题","aud":"听众","nbf":"在此之前不可用","jti":"JWT ID"
}
| 属性 | 说明 |
|---|---|
| iss(Issuser) | 代表这个JWT的签发主体 |
| sub(Subject) | 代表这个JWT的主体,即它的所有人 |
| aud(Audience) | 代表这个JWT的接收对象 |
| exp(Expiration time) | 是一个时间戳,代表这个JWT的过期时间 |
| nbf(Not Before) | 是一个时间戳,代表这个JWT生效的开始时间,意味着在这个时间之前验证JWT是会失败的 |
| iat(Issued at) | 是一个时间戳,代表这个JWT的签发时间 |
| jti(JWT ID) | 是JWT的唯一标识 |
- 公有声明
公有声明可以加入任何信息,一般会添加用户相关信息或者业务需要的信息,但不建议添加敏感信息,因为该部分会在客户端解密。
- 私有声明
私有声明是提供者和使用者所共同定义的声明,一般不建议存放敏感信息,因为base64是对称解密,基本等同于明文信息。
如果把JWT用于认证, 那么JWT标准内规定的几个claim就足够用了,甚至只需要其中一两个就可以了,假如想往JWT里多存一些用户业务信息,比如角色和用户名等,这倒是可以用私有声明来添加。
4.3、signature
JWT的第三部分是签名信息,Signature由三部分组成:
-
header(base64加密后)
-
payload(base64加密后)
-
secret (盐)
签名需要将base64加密后的header和payload使用.连接,然后通过header所使用的加密方式进行加盐(secret)组合加密,产生了jwt的第三部分。以使用HMAC SHA256算法为例;
按照前面alg可用值的说明,HS256其实包含的是两种算法:HMAC算法和SHA256算法,前者用于生成摘要,后者用于对摘要进行数字签名。这两个算法也可以用HMAC SHA256来统称;
HMACSHA256(base64UrlEncode(header) + "." +base64UrlEncode(payload),secret)
签名是用于验证消息在传递过程中有没有被更改,并且,对于使用私钥签名的token,它还可以验证JWT的发送方是否为它所称的发送方。
算法不同,签名结果不同。
二、Jwt验证过程
可将绑定的资源中src(ElementUI之Jwt)目录下的JwtUtils.java和JwtDemo.java导入到项目中的util包下:
1、生成Jwt令牌
//定义私有声明
Map<String, Object> claims = new HashMap<String, Object>();
claims.put("username", "zss");
claims.put("age", 18);
//根据私有声明和JWT的token有效时间生成JWT
String jwt = JwtUtils.createJwt(claims, JwtUtils.JWT_WEB_TTL);//获取JWT中的声明信息,包括:私有声明和标准声明
Claims parseJwt = JwtUtils.parseJwt(jwt);
for (Map.Entry<String, Object> entry : parseJwt.entrySet()) {System.out.println(entry.getKey() + "=" + entry.getValue());
}
//获取token令牌的签发时间
Date d1 = parseJwt.getIssuedAt();
//获取token令牌的过期时间
Date d2 = parseJwt.getExpiration();
System.out.println("令牌签发时间:" + sdf.format(d1));
System.out.println("令牌过期时间:" + sdf.format(d2));
2、解析旧的Jwt
解析旧的JWT。如果超过JWT本身定义的过期时间,则直接抛出ExpiredJwtException
//旧的JWT令牌
String oldJwt = "eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1NjM2NzY0NDQsImlhdCI6MTU2MzY3NDY0NCwiYWdlIjoxOCwianRpIjoiMzE5MmYxOTg4NzFkNGVkZWIyMzU0MmY3NWVhMWI5NDciLCJ1c2VybmFtZSI6InpzcyJ92.4VnkdvGNNe8U1EiKaLz7h6bOJkVGSGtfqojcP_y-0Cc";
Claims parseJwt = JwtUtils.parseJwt(oldJwt);
for (Map.Entry<String, Object> entry : parseJwt.entrySet()) {System.out.println(entry.getKey() + "=" + entry.getValue());
}
Date d1 = parseJwt.getIssuedAt();
Date d2 = parseJwt.getExpiration();
System.out.println("令牌签发时间:" + sdf.format(d1));
System.out.println("令牌过期时间:" + sdf.format(d2));
3、复制Jwt
模拟Session功能(Tomcat默认session过期时间:30分钟)。当有访问的情况下,自动延长jwt中的token令牌过期时间,在原有时间上+30秒;
String oldJwt = "eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1NjM2NzUzMDAsImlhdCI6MTU2MzY3MzUwMCwiYWdlIjoxOCwianRpIjoiYjY5MmE5ZjZkMGZhNDMyN2I1YWY2NTI5OGMzMjQ5MTYiLCJ1c2VybmFtZSI6InpzcyJ9.asHGMPFKURMLnooK29abAuKEdLOHBycAuTovNuGQio0";
String jwt = JwtUtils.copyJwt(oldJwt, JwtUtils.JWT_WEB_TTL);
Claims parseJwt = JwtUtils.parseJwt(jwt);
for (Map.Entry<String, Object> entry : parseJwt.entrySet()) {System.out.println(entry.getKey() + "=" + entry.getValue());
}
Date d1 = parseJwt.getIssuedAt();
Date d2 = parseJwt.getExpiration();
System.out.println("令牌签发时间:" + sdf.format(d1));
System.out.println("令牌过期时间:" + sdf.format(d2));
4、Jwt有效时间测试
生成新的Jwt令牌,设置令牌有效时间3秒钟,在3秒钟后再次解析Jwt令牌提示令牌已过期。
Map<String, Object> claims = new HashMap<String, Object>();
claims.put("username", "zss");
String jwt = JwtUtils.createJwt(claims, 3 * 1000L);
System.out.println(jwt);
Claims parseJwt = JwtUtils.parseJwt(jwt);
Date d1 = parseJwt.getIssuedAt();
Date d2 = parseJwt.getExpiration();
System.out.println("令牌签发时间:" + sdf.format(d1));
System.out.println("令牌过期时间:" + sdf.format(d2));
三、Jwt令牌刷新思路
使用ssm+vue+elementui实现jwt验证。
1、配置JwtFilter过滤器
导入JwtFilter.java到utils包下,并注意配置顺序问题:CorsFilter > JwtFilter > SpringMVC核心控制器
<!-- JwtFilter -->
<filter><filter-name>jwtFilter</filter-name><filter-class>com.wsl.ssm.jwt.JwtFilter</filter-class>
</filter>
<filter-mapping><filter-name>jwtFilter</filter-name><url-pattern>/*</url-pattern>
</filter-mapping>
2、登录生成Jwt令牌
在登录成功后,使用JwtUtil工具类生成JWT,并将Jwt令牌添加到响应头(response)中带到前端页面。在这里可以将用户对应用户基本信息和用户角色信息保存到私有claim中。
if(userVo.getUsername().equals("admin")&&userVo.getPassword().equals("123")){//私有要求claimMap<String,Object> json=new HashMap<String,Object>();json.put("username", userVo.getUsername());//生成JWT,并设置到response响应头中String jwt=JwtUtils.createJwt(json, JwtUtils.JWT_WEB_TTL);response.setHeader(JwtUtils.JWT_HEADER_KEY, jwt);return new JsonResponseBody<>("用户登陆成功!",true,0,null);
}else{return new JsonResponseBody<>("用户名或密码错误!",false,0,null);
}
3、配置CorsFilter过滤器
浏览器只能访问默认的响应头,例如:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma等,如果想让浏览器能访问到其他的响应头的话,需要在服务器上设置。在CorsFilter跨域过滤器的doFilter方法中配置其他响应头的支持。
//允许客户端发一个新的请求头jwt
httpResponse.setHeader("Access-Control-Allow-Headers","Origin,X-Requested-With, Content-Type, Accept, jwt");
//允许客户端处理一个新的响应头jwt
httpResponse.setHeader("Access-Control-Expose-Headers", "jwt");
4、Vuex存储Jwt令牌
使用vuex保存后端服务器提交过来的Jwt,分别在state、getters、mutation中定义信息。
- state.js
export default {jwt:null } - getters.js
export default {getJwt:(state)=>{return state.jwt;} } - mutation.js
export default {setJwt:function (state, payload){state.jwt = payload.jwt;} }
5、修改main.js
解决axios从响应头获得jwt令牌并保存到vuex,通过修改main.js中的配置window.vm=new Vue({});获取Vue根实例对象。
window.vm = new Vue({el: '#app',router,store,components: { App },template: '<App/>'
})
6、配置axios请求响应头
在vue的http.js中配置axios的请求响应拦截器,用于存取Jwt,并将Jwt信息保存到Vuex中。
// 请求拦截器
axios.interceptors.request.use(function(config) {let jwt=window.vm.$store.getters.jwt;//console.log(jwt);if(jwt)config.headers['jwt']=jwt;return config;
}, function(error) {return Promise.reject(error);
});// 响应拦截器
axios.interceptors.response.use(function(response) {let jwt=response.headers['jwt'];if(jwt)window.vm.$store.commit('setJwt',{jwt:jwt});return response;
}, function(error) {return Promise.reject(error);
});
注:可通过使用vuex-along解决刷新state初始化问题。
相关文章:
JSON Web Token (JWT)的简单介绍、验证过程及令牌刷新思路
目录 一、JWT 1、什么是Jwt 2、为什么要使用Jwt 3、应用场景 4.Jwt的组成 4.1、Header 4.2、Payload 4.3、signature 二、Jwt验证过程 1、生成Jwt令牌 2、解析旧的Jwt 3、复制Jwt 4、Jwt有效时间测试 三、Jwt令牌刷新思路 1、配置JwtFilter过滤器 2、登录生成Jwt令…...
xxl-job入门
xxl-job , 定时任务 分布式 , 带来的问题的 解决方案 像之前 很多项目都用到定时任务, 但是如果要改为 分布式, 那么定时任务 就要用到 xxl-job 1.用户画像 拼多多,看了某个东西后,推荐类似东西, 做埋…...
100.【C语言】数据结构之二叉树的堆实现(顺序结构) 1
目录 1.顺序结构 2.示意图 编辑 从物理结构还原为逻辑结构的方法 3.父子节点编号的规律 4.顺序存储的前提条件 5.堆的简介 堆的定义 堆的两个重要性质 小根堆和大根堆 6.堆的插入 7.堆的实现及操作堆的函数 堆的结构体定义 堆初始化函数HeapInit 堆插入元素函…...
大模型 VS 大语言模型
最近很多朋友搞不懂大模型和大预言模型的区别,总是把大模型就认为是大语言模型。 今天就用这篇帖子做一个科普。 大模型 概念:大模型是指拥有超大规模参数(通常在十亿个以上)、复杂计算结构的机器学习模型。它通常能够处理海量数…...
Linux高阶——1117—TCP客户端服务端
目录 1、sock.h socket常用函数 网络初始化函数 首次响应函数 测试IO处理函数 获取时间函数 总代码 2、sock.c SOCKET() ACCEPT()——服务端使用这个函数等待客户端连接 CONNECT()——客户端使用这个函数连接服务端 BIND()——一般只有服务端使用 LISTEN()——服务端…...
【Qt】Qt 在main.cpp中使用tr()函数报错
1. 问题 Qt 在main.cpp中使用tr()报错。 error: tr was not declared in this scope2. 解决方法 main.cpp中注意如下: //添加头文件 #include <QObject>//添加QObject QObject::tr("Hello")3. 参考 Qt tr()函数不起效的小问题...
面向对象高级(5)接口
面向对象高级(5) 接口 接口就是规范,定义的是一组规则,体现了现实世界中“如果是...则必须能...”的思想。继承是一个"是不是"的is-a关系,而接口实现则是 "能不能"的has-a关系。 1、接口的定义格…...
uniapp发布android上架应用商店权限
先看效果: 实现原理: 一、利用uni.addInterceptor的拦截器,在一些调用系统权限前拦截,进行弹窗展示,监听确定取消实现业务逻辑。 二、弹窗是原生nativeObj进行drawRect绘制的 三、权限申请调用使用的 plus.android.…...
Centos Stream 9安装Jenkins-2.485 构建自动化项目步骤
官网:https://www.jenkins.io/ 1 下载 环境准备: 版本支持查询:https://pkg.jenkins.io/redhat-stable/ 安装JDK17:https://blog.csdn.net/qq_44870331/article/details/140784297 yum -y install epel-release wget upgradew…...
电路模型和电路定理(二)
电路元件 是电路中最基本的组成单元。 电阻元件:表示消耗电能的元件 电感元件:表示产生磁场,储存磁场能的元件 电容元件:表示产生电场,储存电场能量的元件 电压源和电流源:表示将其他形式的能量转变成…...
瑞佑液晶控制芯片RA6807系列介绍 (三)软件代码详解 Part.10(让PNG图片动起来)完结篇
RA6807是RA8876M的缩小版,具备RA8876M的所有功能,只将MCU控制接口进行缩减,仅保留SPI-3和I2C接口,其它功能基本相同。 该芯片最大可控制854x600的分辨率,内建64Mbits显存,多个图层,使用起来相当…...
Qt常用控件 按钮
文章目录 1. QAbstractButton 简介2. QPushButton2.1 例子1,设置按钮的图标2.2 例子2,设置按钮快捷键 3. QRadioButton3.1 介绍3.2 例子1,选择性别3.3 例子2,试试其他的信号3.3 例子3,分组 4. QCheckBox4.1 介绍4.2 例…...
MySQL学习/复习10视图/用户/权限/语言连接数据库
一、视图 1.1创建视图 1.2视图影响基表 1.3基表影响视图 1.4删除视图 1.5视图使用规则 二、数据库的用户 2.1mysql中的user表 注意事项:主机/用户名/密码/权限 2.2用户的创建 注意事项:设置密码与登录地点需谨慎 2.3删除用户 注意事项:% 2.4…...
vulfocus在线靶场:tomcat-pass-getshell 弱口令 速通手册
目录 一、启动环境,访问页面,并登录,账号密码都是tomcat 二、哥斯拉打war包,图解 三、上传war包,图解 四、访问我们直接url/木马文件名/木马文件.jsp,是否存在了 五、 哥斯拉测试连接结果success&…...
c#:winform调用bartender实现打印(学习整理笔记)
效果 学习路径 C# winform调用Bartender进行自定义打印、批量打印、检索文件夹中的模板_哔哩哔哩_bilibili 一、初始环境搭建见: c#:winform引入bartender-CSDN博客https://blog.csdn.net/weixin_46001736/article/details/143989473?sharetypeblogdetail&s…...
牛客题库 21738 牛牛与数组
牛牛与数组题目链接 题目大意 牛牛喜欢这样的数组: 1:长度为n 2:每一个数都在1到k之间 3:对于任意连续的两个数A,B,A<=B 与(A % B != 0) 两个条件至少成立一个请问一共有多少满足条件的数组,对 1 e 9 + 7 1e^9+7 1e9+7 取模 输入格式 输入两个整数 n , k n,k n,…...
探索PDFMiner:Python中的PDF解析利器
文章目录 **探索PDFMiner:Python中的PDF解析利器**1. 背景介绍:为何选择PDFMiner?2. PDFMiner是什么?3. 如何安装PDFMiner?4. 简单库函数使用方法4.1 提取文本4.2 获取页面布局信息4.3 提取表格数据4.4 提取图像 5. 应…...
掌握Go语言中的异常控制:panic、recover和defer的深度解析
掌握Go语言中的异常控制:panic、recover和defer的深度解析 在Go语言的编程世界中,异常处理是一个不可忽视的话题。Go语言提供了panic、recover和defer三个关键字来处理程序中的异常情况。本文将深入探讨这三个关键字的工作原理、使用场景和最佳实践,帮助读者在实际编程中更…...
云讷科技Kerloud无人飞车专利发布
云讷科技Kerloud无人飞车获得了“一种室内外两用的四旋翼无人飞车”的实用新型专利证书,作为科教社区第一款四旋翼飞车,这项技术结合了无人机和无人车的优势,提供了一种能够在多种环境下使用的多功能飞行器。 这项设计的优势如下ÿ…...
企业信息化-走进身份管理之搭建篇
一、身份管理是什么 我们先要弄懂统一身份管理到底是什么? 统一身份管理(Unified Identity Manager,UIM),身份管理(Identity Management,简称IDM),也被称为IAM&#…...
双向可控硅交流控制电路基础知识及Multisim电路仿真
目录 2.2.2 双向可控硅交流控制电路 2.2.2.1 双向可控硅交流控制电路基础知识 2.2.2.2 双向可控硅交流控制Multisim电路仿真 摘要:本文介绍了双向可控硅交流控制电路的工作原理及Multisim仿真。该电路通过光耦隔离实现低压控制高压交流负载,采用过零触发方式降低干扰。控制…...
通过Docker部署FastAPI应用程序
🌞欢迎来到PyTorch深度学习实战的世界 🌈博客主页:卿云阁 💌欢迎关注🎉点赞👍收藏⭐️留言📝 📆首发时间:🌹2026年5月24日🌹 ✉️希望可以和大家…...
MacBook锁屏别慌!手把手教你用恢复模式+Apple ID重置开机密码(保姆级图文)
MacBook锁屏急救指南:3种安全解锁方案详解刚泡好的咖啡还在冒热气,手指悬在键盘上方却突然僵住——那个每天输入几十次的密码,此刻竟怎么也想不起来了。MacBook屏幕上冰冷的"密码错误"提示像一堵墙,将你与所有工作资料、…...
量子纠错新突破:VarQEC变分编码技术解析
1. 量子纠错基础与VarQEC创新点量子计算的核心挑战在于量子态的脆弱性——环境噪声会导致量子信息不可逆的丢失。传统量子纠错(QEC)采用类似经典重复码的思路,通过将逻辑量子比特编码到多个物理比特上构建纠错码。例如著名的[[5,1,3]]完美码使用5个物理比特保护1个逻…...
WSL2终端颜值与效率双飞:保姆级oh-my-zsh配置指南(含autojump、语法高亮插件)
WSL2终端颜值与效率双飞:保姆级oh-my-zsh配置指南(含autojump、语法高亮插件)在开发者的日常工作中,终端是使用频率最高的工具之一。一个高效、美观的终端环境不仅能提升工作效率,还能让枯燥的命令行操作变得愉悦。对于…...
Windows 批量解压 TAR 文件脚本:支持文件数量校验、断点续解压和自动跳过
文章目录一、需求说明二、脚本功能三、为什么使用 7-Zip1. 7-Zip 支持命令行调用2. 方便读取 tar 包内部文件列表3. 支持跳过已存在文件,适合断点续解压4. 对 tar 文件支持比较稳定5. 适合处理大量小文件场景四、完整 BAT 脚本五、使用前需要修改的地方六、脚本运行…...
Claude Code 2026 全命令实战:6分钟开发完整坦克对战游戏
文章目录前言第一步:新建文件夹,然后输入一个单词第二步:/plan命令,比产品经理还贴心的规划师第三步:看着AI写代码,自己在旁边喝咖啡第四步:/rewind命令,程序员的后悔药第五步&#…...
别再交智商税了!实测告诉你:用AI写论文,哪款软件控制重复率和AI率效果最好?
眼下毕业生和科研工作者的焦虑点很集中:论文查重率好不容易过关,AIGC疑似率却频频爆红;花了大把时间手动改写降AI痕迹,重复率又反弹回来。想靠普通工具同时守住查重和AI两道防线,根本就是天方夜谭。 事实上通用模型AI…...
初次在Taotoken模型广场切换不同模型进行文本生成的体验
🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 初次在Taotoken模型广场切换不同模型进行文本生成的体验 作为一名开发者,初次接触大模型聚合平台时,最关心…...
ComfyUI-WanVideoWrapper:新手必看的AI视频生成终极指南
ComfyUI-WanVideoWrapper:新手必看的AI视频生成终极指南 【免费下载链接】ComfyUI-WanVideoWrapper 项目地址: https://gitcode.com/GitHub_Trending/co/ComfyUI-WanVideoWrapper 在AI视频生成领域,你是否曾因复杂的代码和繁琐的配置而望而却步&…...
