ApiPost 中配置自动获取 Token 并调用业务接口完整指南

ApiPost 中配置自动获取 Token 并调用业务接口完整指南

一、目标

在 ApiPost 中实现:每次发送业务请求时,自动判断 Token 是否过期,过期则自动调用认证接口获取新 Token,无需手动操作。


二、整体流程

点击"发送"业务请求 ↓ 全局预执行脚本自动运行 ↓ 检查环境变量中 token 是否存在且未过期 ↓ 过期/为空 → 自动调用认证接口 → 解析响应 → 存入环境变量 未过期 → 跳过,使用缓存 token ↓ 全局 Header 自动拼装 Authorization: Bearer {{token}} ↓ 业务请求正常发送

注:

博客:

https://blog.csdn.net/badao_liumang_qizhi

三、配置步骤

3.1 配置环境变量

位置:右上角「环境管理」→ 新建/选择环境

添加以下变量(初始值留空):

变量名初始值说明
base_urlhttp://127.0.0.1:8080本地服务地址
token(空)脚本自动填充
token_time(空)记录获取时间,用于过期判断

3.2 配置全局请求头

位置:全局参数 → Header 标签页

添加一条:

参数名参数值
AuthorizationBearer {{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 0res是 undefined 或解析方式不对用兼容写法逐个尝试,先打印typeof res
apt is not defined版本不支持 apt换成pm
btoa is not defined环境不支持 btoaBuffer.from(str).toString('base64')替代
Token 获取成功但接口仍 401Header 没生效检查全局 Header 是否写了Bearer {{token}}(注意空格)
每次都重新获取 Tokentoken_time变量没设置上检查变量名拼写,确认apt.variables.set可用
认证接口返回 401client_id 或密码错误单独新建一个接口手动测试认证地址是否可达

九、方案对比

方案优点缺点适用场景
全局预执行脚本全自动,一次配置永久生效需要版本支持 sendRequest日常开发首选
单独 Token 接口 + 后执行脚本所有版本都支持过期后需手动点一次版本不支持 sendRequest
bat 脚本复制到剪贴板零配置每次手动操作临时使用