ApiPost 中配置自动获取 Token 并调用业务接口完整指南
ApiPost 中配置自动获取 Token 并调用业务接口完整指南
一、目标
在 ApiPost 中实现:每次发送业务请求时,自动判断 Token 是否过期,过期则自动调用认证接口获取新 Token,无需手动操作。
二、整体流程
点击"发送"业务请求 ↓ 全局预执行脚本自动运行 ↓ 检查环境变量中 token 是否存在且未过期 ↓ 过期/为空 → 自动调用认证接口 → 解析响应 → 存入环境变量 未过期 → 跳过,使用缓存 token ↓ 全局 Header 自动拼装 Authorization: Bearer {{token}} ↓ 业务请求正常发送注:
博客:
https://blog.csdn.net/badao_liumang_qizhi
三、配置步骤
3.1 配置环境变量
位置:右上角「环境管理」→ 新建/选择环境
添加以下变量(初始值留空):
| 变量名 | 初始值 | 说明 |
|---|---|---|
base_url | http://127.0.0.1:8080 | 本地服务地址 |
token | (空) | 脚本自动填充 |
token_time | (空) | 记录获取时间,用于过期判断 |
3.2 配置全局请求头
位置:全局参数 → Header 标签页
添加一条:
| 参数名 | 参数值 |
|---|---|
Authorization | Bearer {{token}} |
{{token}}是环境变量的引用语法,ApiPost 会在发送时自动替换为实际值。
3.3 配置全局预执行脚本
位置:全局参数 → 预执行脚本(Pre-request Script)标签页
四、预执行脚本(通用模板)
4.1 OAuth2 Password Grant 模式
适用于通过 OAuth2 认证服务获取 Token 的场景。
// ===== 配置区域(替换为你的实际值)=====varAUTH_URL="https://your-auth-server.com/oauth/token";varCLIENT_ID="your_client_id";varCLIENT_PASSWORD="your_client_password";varUSERNAME="your_username";varPASSWORD="your_password";varTOKEN_EXPIRE_MS=14400000;// token 有效期(毫秒),此处为 4 小时// ===== 配置区域结束 =====lettoken=apt.variables.get("token");lettokenTime=apt.variables.get("token_time");letnow=Date.now();// 判断 token 是否存在且未过期if(!token||!tokenTime||(now-Number(tokenTime))>TOKEN_EXPIRE_MS){letbase64=btoa(CLIENT_ID+":"+CLIENT_PASSWORD);apt.sendRequest({url:AUTH_URL,method:"POST",header:{"Content-Type":"application/x-www-form-urlencoded","Authorization":"Basic "+base64},body:{mode:"urlencoded",urlencoded:[{key:"grant_type",value:"password"},{key:"username",value:USERNAME},{key:"password",value:PASSWORD}]}},function(err,res){if(err){console.log("获取token失败: "+err);return;}// 兼容多种响应格式解析letdata;try{if(res.json&&typeofres.json==='function'){data=res.json();}elseif(res.body){data=JSON.parse(res.body);}elseif(res.text&&typeofres.text==='function'){data=JSON.parse(res.text());}elseif(typeofres==='string'){data=JSON.parse(res);}else{data=res;}}catch(e){console.log("解析响应失败: "+e.message);console.log("原始响应: "+String(res));return;}if(data&&data.access_token){apt.variables.set("token",data.access_token);apt.variables.set("token_time",String(Date.now()));console.log("Token已自动刷新");}else{console.log("响应中没有access_token: "+JSON.stringify(data).substring(0,200));}});}4.2 普通登录接口模式
适用于通过常规登录接口(POST JSON body)获取 Token 的场景。
// ===== 配置区域 =====varLOGIN_URL="https://your-server.com/api/login";varLOGIN_BODY={username:"your_username",password:"your_password"};// token 在响应中的路径,如 data.token 或 data.access_tokenvarTOKEN_FIELD="data.token";varTOKEN_EXPIRE_MS=7200000;// 2 小时// ===== 配置区域结束 =====lettoken=apt.variables.get("token");lettokenTime=apt.variables.get("token_time");letnow=Date.now();if(!token||!tokenTime||(now-Number(tokenTime))>TOKEN_EXPIRE_MS){apt.sendRequest({url:LOGIN_URL,method:"POST",header:{"Content-Type":"application/json"},body:{mode:"raw",raw:JSON.stringify(LOGIN_BODY)}},function(err,res){if(err){console.log("登录失败: "+err);return;}letdata;try{if(res.json&&typeofres.json==='function'){data=res.json();}elseif(res.body){data=JSON.parse(res.body);}elseif(typeofres==='string'){data=JSON.parse(res);}else{data=res;}}catch(e){console.log("解析失败: "+e.message);return;}// 按路径提取 token(支持 data.token 这种嵌套路径)lettokenValue=TOKEN_FIELD.split('.').reduce(function(obj,key){returnobj?obj[key]:null;},data);if(tokenValue){apt.variables.set("token",tokenValue);apt.variables.set("token_time",String(Date.now()));console.log("Token已自动刷新");}else{console.log("找不到token字段: "+JSON.stringify(data).substring(0,200));}});}4.3 从 Set-Cookie 中提取 Token
适用于登录后 Token 放在响应头 Cookie 中的场景。
// ===== 配置区域 =====varLOGIN_URL="https://your-server.com/login";varLOGIN_BODY={username:"your_username",password:"your_password"};varCOOKIE_NAME="your_jwt_cookie_name";// 如 coc_jwt、session_token 等varTOKEN_EXPIRE_MS=7200000;// ===== 配置区域结束 =====lettoken=apt.variables.get("token");lettokenTime=apt.variables.get("token_time");letnow=Date.now();if(!token||!tokenTime||(now-Number(tokenTime))>TOKEN_EXPIRE_MS){apt.sendRequest({url:LOGIN_URL,method:"POST",header:{"Content-Type":"application/json"},body:{mode:"raw",raw:JSON.stringify(LOGIN_BODY)}},function(err,res){if(err){console.log("登录失败: "+err);return;}// 从响应头中提取 Set-Cookieletcookies="";if(res.headers){// headers 可能是数组或对象if(Array.isArray(res.headers)){res.headers.forEach(function(h){if(h.key&&h.key.toLowerCase()==='set-cookie'){cookies+=h.value+";";}});}elseif(res.headers['set-cookie']){cookies=res.headers['set-cookie'];}elseif(res.headers['Set-Cookie']){cookies=res.headers['Set-Cookie'];}}// 正则提取指定 cookie 的值letregex=newRegExp(COOKIE_NAME+"=([^;]+)");letmatch=cookies.match(regex);if(match&&match[1]){apt.variables.set("token",match[1]);apt.variables.set("token_time",String(Date.now()));console.log("Token已从Cookie中提取并刷新");}else{console.log("Cookie中未找到"+COOKIE_NAME);console.log("实际Cookie: "+cookies.substring(0,200));}});}五、脚本关键 API 说明
5.1 全局对象兼容性
| ApiPost 版本 | 全局对象 | 说明 |
|---|---|---|
| ApiPost 7+ | apt | 新版本推荐使用 |
| ApiPost 旧版 | pm | 兼容 Postman 风格 |
如果
apt报错就换pm,反之亦然。
5.2 核心 API
| API | 作用 |
|---|---|
apt.variables.get("key") | 获取环境变量 |
apt.variables.set("key", "value") | 设置环境变量 |
apt.sendRequest(options, callback) | 在脚本中发送 HTTP 请求 |
btoa(string) | Base64 编码(用于 Basic Auth) |
console.log(msg) | 控制台输出调试信息 |
5.3 sendRequest 参数结构
apt.sendRequest({url:"完整URL",method:"POST",// GET / POST / PUT / DELETEheader:{// 请求头(对象格式)"Content-Type":"application/json","Authorization":"Basic xxx"},body:{mode:"urlencoded",// urlencoded | raw | formdataurlencoded:[// mode 为 urlencoded 时{key:"name",value:"value"}],raw:'{"key":"val"}'// mode 为 raw 时}},function(err,res){// err: 错误信息,成功时为 null// res: 响应对象});5.4 响应解析兼容写法
由于不同版本res的结构不同,推荐使用兼容写法:
letdata;try{if(res.json&&typeofres.json==='function'){data=res.json();// 方式1: res.json()}elseif(res.body){data=JSON.parse(res.body);// 方式2: res.body 是字符串}elseif(res.text&&typeofres.text==='function'){data=JSON.parse(res.text());// 方式3: res.text()}elseif(typeofres==='string'){data=JSON.parse(res);// 方式4: res 直接是字符串}else{data=res;// 方式5: res 本身就是对象}}catch(e){console.log("解析失败: "+e.message);}六、调试技巧
6.1 查看脚本控制台输出
发送请求后,在 ApiPost 底部找到控制台(Console)面板,查看console.log的输出。
6.2 调试响应结构
如果不确定res的实际结构,先加上:
console.log("响应类型: "+typeofres);console.log("响应内容: "+JSON.stringify(res).substring(0,300));根据打印结果确定正确的解析方式。
6.3 强制刷新 Token
手动清空环境变量中的token值,下次发送请求时脚本会重新获取。
七、业务接口配置示例
配置好全局脚本和 Header 后,新建业务接口只需关注业务本身:
- URL:
{{base_url}}/api/your-endpoint - Method:POST
- Body(raw JSON):
{"pageNum":1,"pageSize":10}不需要手动填写 Authorization,全局配置会自动处理。
八、常见问题
| 问题 | 原因 | 解决 |
|---|---|---|
Unexpected token u in JSON at position 0 | res是 undefined 或解析方式不对 | 用兼容写法逐个尝试,先打印typeof res |
apt is not defined | 版本不支持 apt | 换成pm |
btoa is not defined | 环境不支持 btoa | 用Buffer.from(str).toString('base64')替代 |
| Token 获取成功但接口仍 401 | Header 没生效 | 检查全局 Header 是否写了Bearer {{token}}(注意空格) |
| 每次都重新获取 Token | token_time变量没设置上 | 检查变量名拼写,确认apt.variables.set可用 |
| 认证接口返回 401 | client_id 或密码错误 | 单独新建一个接口手动测试认证地址是否可达 |
九、方案对比
| 方案 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 全局预执行脚本 | 全自动,一次配置永久生效 | 需要版本支持 sendRequest | 日常开发首选 |
| 单独 Token 接口 + 后执行脚本 | 所有版本都支持 | 过期后需手动点一次 | 版本不支持 sendRequest |
| bat 脚本复制到剪贴板 | 零配置 | 每次手动操作 | 临时使用 |