ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Postman接口测试鉴权全攻略:Cookie、Session与Token从原理到实战

Postman接口测试鉴权全攻略:Cookie、Session与Token从原理到实战 做接口测试这些年被鉴权坑过的次数两只手数不过来。前几天还有朋友跑来问我明明Postman里登录接口通了返回也正常结果下一个请求直接甩了个401回来查了半天才发现是请求头里压根没带凭证。这个场景太典型了所以今天把cookie、token、session这套鉴权体系在Postman里的完整用法梳理清楚从原理到实操再到高频报错排查一次性讲透。这篇内容不是给你背概念的而是解决实际问题为什么登录成功后接口还是401token怎么自动提取、自动带上、自动续期cookie和session到底什么关系遇到“token exchange failed”这类报错从哪里下手适合刚接触Postman的测试新手也适合后端开发在联调时遇到鉴权问题时翻出来参考。1. 先搞清楚三种鉴权机制到底在解决什么问题1.1 HTTP协议为什么需要“鉴权”这回事HTTP是个无状态协议说人话就是服务器默认不记得“你是谁”。你上一次请求是谁发来的服务器根本不关心每一次请求对它来说都是一个陌生人。就像你去健身房前台不可能记住每一个会员的长相你每次进门都得自己掏出会员卡前台刷一下卡才知道你是几级会员、能不能进泳池区。接口测试里的鉴权就是把这张“会员卡”通过某种方式塞进HTTP请求里让服务器每次都能确认“哦是你”。而Postman作为客户端工具最大的作用就是帮你自动保存这张“会员卡”并且在你发出请求的时候自动带上它。如果这一步没弄对后面所有接口全都会挂在鉴权上。1.2 Cookie、Session、Token各管什么这三者经常放在一起说但它们的定位完全不同Cookie存储在客户端的一小段数据格式是键值对由服务器通过Set-Cookie响应头下发之后浏览器或Postman会在每次请求时自动携带它。它本身只是一个“存储载体”没有业务逻辑。Session存储在服务端的会话数据。服务器收到请求后会用session id去内存或Redis里查对应的会话数据。session id通常放在cookie里传给客户端客户端下次带着cookie来服务器就知道你是谁、登录状态还在不在。Token通常指一段经过签名的字符串比如JWT客户端收到后保存下来后续请求放在Authorization请求头里。服务端验证token的签名和有效期不需要像session那样在服务端保存状态。我用一个表把这几个维度的区别列清楚维度CookieSessionTokenJWT数据存放位置客户端服务端客户端服务端是否存状态不存但可能配合session存内存/数据库/Redis不存无状态传输方式自动放在Cookie头session id放在Cookie或URL通常放Authorization头主要安全问题CSRF、容易被截获session劫持、会话固定token泄露、密钥泄露过期处理Expires/Max-Age服务端会话过期时间exp过期时间适合场景传统网页登录传统服务端渲染项目前后端分离、移动端、开放API实际项目里Cookie和Session经常是配套出现的服务器创建一个session对象并保存同时把一个带有session id的cookie塞给客户端。Session负责存业务数据cookie负责“指路”。Token则是另一条路线服务端不保存状态全靠token自身的签名和过期时间来保证可信。1.3 常见鉴权流程的完整链路不管用哪种方式鉴权流程本质上都是一套客户端把账号密码发给服务器。服务器校验通过创建一个凭证要么在响应头里给Set-Cookie要么在响应体里返回一段token。客户端保存这个凭证。之后每次请求都带上这个凭证。服务器校验凭证合法性校验通过才返回业务数据。理解这个链路是关键。很多人在Postman里卡住就是因为只做了第1步和第2步第4步没做到。才导致“登录成功但业务接口全挂”的尴尬局面。2. Postman里处理Cookie鉴权的完整实操2.1 实战场景先用登录接口拿到Cookie举个最常见的例子一个后台管理系统登录接口长这样POST https://api.example.com/admin/login Content-Type: application/json { username: admin, password: 123456 }在Postman里直接发送这个请求如果登录成功你会在响应头的Set-Cookie里看到类似这样的内容Set-Cookie: session_idabc123def456; Path/; HttpOnly; SameSiteLax注意这一步Postman其实已经默默把这个cookie存到它自己的“Cookie管理器”里了。这就是Postman里的Cookie Jar机制它像浏览器一样按域名自动保存服务器下发的cookie并在后续请求中自动带上。怎么确认Postman存没存在请求面板里点击“Cookies”按钮通常在Send按钮旁边的小图标打开后能看到当前域名下的所有cookie。如果session_id躺在列表里说明第一步已经成功了。2.2 Postman自动Cookie管理机制Postman的Cookie管理是按域名隔离的。它保存cookie时不仅看key和value还会匹配域名、路径、是否Secure、是否HttpOnly等属性。这意味着登录接口域名是api.example.com那Postman只会把cookie自动带给你发往api.example.com的请求。如果你后续请求的URL写的是example.com或者www.example.com看起来像是同一个网站但Postman不会把这个cookie带过去因为域名不严格匹配。这是我见过最多人踩的坑。解决方案很简单要么把所有接口统一用一个域名要么在业务请求里手动加Header。如果你需要手动确认Postman自动带cookie的效果可以直接查看请求的Headers标签页。注意一点如果在请求里手动写了Cookie这个HeaderPostman会优先使用你手写的值而不是Cookie Jar里的自动值。很多人想自定义cookie却发现一直不生效多半就是这里出了问题。2.3 手动构造Cookie的两种方式有些场景下服务器下发的cookie不够用或者你需要模拟特定登录态比如在测试环境用一个已经登录的账号状态去调接口这时候就得手动构造cookie。第一种方式最直接在Headers标签页里添加一个名为Cookie的请求头值写成浏览器里复制出来的那一串字符串比如Cookie: session_idabc123def456; user_tokenxyz789; localezh-CN多个cookie直接用分号加空格分隔。这种方式最原始也最直观适用于一次性调试。第二种方式更正规打开“Cookies”管理窗口点击“Add Cookie”逐条添加Key和Value同时可以设置Domain、Path、Expires等属性。这样Postman会把这个cookie存到Cookie Jar里后续请求按域名自动匹配比每次手写Header要干净得多。我推荐优先用Cookie管理窗口去维护因为它更符合接口真实运行时的行为。手写Header适合临时验证但项目里接口一多手写Header容易漏、容易错而且写在集合里也会让用例的可读性变差。2.4 Cookie常见问题速查现象大概率原因解决办法登录接口返回了Set-Cookie但业务接口还是401请求域名不匹配Postman没有自动带cookie统一域名或在业务请求手动加Cookie Header浏览器里复制来的cookie粘到Postman里报错复制时带上了一些无效属性或换行清理分号和空格统一压缩成一行Cookie值里有中文服务端解析乱码cookie不支持非ASCII字符先在浏览器里用encodeURIComponent编码后再粘入手动填了Cookie但请求没发送出去Header值里带了换行或非法字符检查Header值是否包含\n、\r登录接口的Set-Cookie在响应里能看到但Cookie Jar里没有该cookie标记了Secure而当前请求是HTTP改用HTTPS请求或临时把Secure属性去掉另外提一句有些网站登录后返回的不止一个Set-Cookie可能还有domain.example.com这种跨子域cookie。这时候如果Postman没保存去Cookie管理窗口手动添加时可以带上Domain属性Postman会按照这个域去匹配后续请求比死磕请求URL的域名要灵活得多。3. Token鉴权从登录到动态关联的全流程3.1 Token和Cookie在Postman里的处理方式差异Token的携带方式不像cookie那样靠“自动匹配”它更常见的是放在Authorization请求头里格式通常是Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...Token方案在前后端分离项目里非常常见。它的特点是“无状态”服务器不需要像session那样保存一份会话记录只要token没过期、签名能被验证就认为是合法请求。但也正因为无状态token一旦泄漏或者过期处理起来比cookie更棘手。在Postman里核心任务就是三件事拿到token、存好token、让每个业务接口都能动态引用它。Postman有专门的Authorization栏你完全不需要手搓Header。选择类型为“Bearer Token”然后在右侧输入框里填token变量名即可。这样Postman自动帮你生成Authorization: Bearer xxx的请求头简洁不容易出错。3.2 用Tests脚本从登录响应中提取Token手工复制token再粘贴到每个请求里这种事情做一次两次还行接口一多就成灾难。而且token通常有过期时间今天复制好的token明天可能就失效了。正确做法是让Postman在登录请求返回后用脚本自动提取token并保存到环境变量或集合变量里。在登录请求的“Tests”标签页写入类似这样的脚本const res pm.response.json(); if (res.code 200 res.data res.data.token) { pm.environment.set(api_token, res.data.token); console.log(token已保存 res.data.token); } else { console.log(登录失败 JSON.stringify(res)); }这里假设登录接口返回的JSON结构是{ code: 200, data: { token: xxx } }。实际接口千差万别如果返回结构不是这样可以根据真实格式来调整取值路径。有些接口的token藏在响应头的某个字段比如X-Auth-Token那可以用另一种写法const token pm.response.headers.get(X-Auth-Token); if (token) { pm.environment.set(api_token, token); }还有一种情况响应体是一大段HTML或者非标准JSON没法用json()解析那就用正则硬抠const tokenMatch pm.response.text().match(/token\s*:\s*([^])/); if (tokenMatch tokenMatch[1]) { pm.environment.set(api_token, tokenMatch[1]); }正则方案比较暴力但胜在通用反正只是测试环境拿数据没必要纠结优雅。3.3 在Authorization栏配置Bearer Token而不是手动拼接拿到token并存入变量后接下来就是让每个业务接口都引用它。这里强烈建议用Postman的Authorization栏而不是手写Header。具体操作打开任意一个需要鉴权的请求点击“Authorization”标签页类型选“Bearer Token”在Token输入框中填入{{api_token}}。注意这里填的是变量引用不是直接把token值写死。Postman在发送请求时会自动把变量替换成当前环境变量里的真实值。这样做的优势是不同环境切换方便。开发环境填{{dev_token}}测试环境填{{test_token}}切换环境时自动换值。避免手动拼Header导致格式错误。手写Authorization: Bearer {{api_token}}虽然也能用但容易漏空格、拼错大小写。集合里所有请求统一走同一个变量后续token刷新逻辑只改登录脚本就行不用每个接口都动。需要注意一个优先级问题如果请求里手动写了名为Authorization的HeaderPostman会优先用Header里的值Authorization栏里配置的Bearer Token就不再生效。排查401问题的时候先去看请求实际发出去的Header长什么样别凭印象。3.4 Token失效与自动续签不用手动复制也能跑完整个集合做自动化测试时最头疼的就是token过期。你半夜跑一个Collection Runner跑到第50个用例突然token失效后面全挂。要解决这个问题思路是在集合级别做统一的token检查和刷新逻辑。一种比较实用的做法是在每个请求的Pre-request Script里检查token是否存在、是否快过期如果不存在或快过期就自动调用登录接口重新获取。示例脚本如下// pre-request script const token pm.environment.get(api_token); const expired pm.environment.get(token_expire); if (!token || !expired || Date.now() parseInt(expired)) { pm.sendRequest({ url: https://api.example.com/login, method: POST, header: { Content-Type: application/json }, body: { mode: raw, raw: JSON.stringify({ username: admin, password: 123456 }) } }, function (err, res) { if (err) { console.error(重新登录失败 err); return; } const json res.json(); if (json.data json.data.token) { pm.environment.set(api_token, json.data.token); pm.environment.set(token_expire, String(Date.now() 3600 * 1000)); console.log(token已自动刷新); } }); }这个脚本放在Collection的Pre-request Script里集合里每一个请求发出前都会先跑一遍。逻辑很简单token不存在或者过期时间到了就先登录一次把新token写回环境变量再继续发请求。注意这里用的是pm.sendRequest它是异步的但Postman会等它执行完再发送当前请求所以可以放心用在流程里。另外如果项目用的是JWT并且有refresh_token机制也可以更优雅地做用refresh_token去换新的access_token而不是每次都用账号密码重新登录。换token的请求比登录请求更轻量适合临时凭证有效期短、长期凭证有效期长的场景。思路完全一样就是把登录接口换成刷新接口把账号密码换成refresh_token。3.5 Postman Flows处理Token的小技巧Postman Flows是Postman 10之后推出的可视化自动化功能很多人拿它做多接口串联。Flows里处理token也很方便核心思路仍然是通过变量传递。在Flows里登录请求的输出节点可以接一个“脚本”节点用JS代码解析响应并设置环境变量。后续的请求节点需要token时在Body或Header里引用{{api_token}}即可。和普通请求唯一的区别是在Flows的画布上更容易看到数据从哪里来、到哪里去调试体验更直观。如果你还在用旧式的“Collection Runner 脚本”方案不用急着迁移。Flows适合流程复杂的可视化编排一般接口测试场景用Collection Runner加上pre-request脚本已经足够。4. Session鉴权、跨工具联动与高频报错排查4.1 Session到底怎么在Postman里模拟Session在Postman里其实没有专门的“Session类型”选择你模拟的其实还是cookie带上session id的过程。因为服务端通常就是通过读取cookie里的session id去找会话数据的。如果你用的是PHP比如Laravel这类传统框架session的cookie名称往往不是session_id而是类似laravel_session这样的自定义名称。比如Laravel里默认的session cookie叫laravel_session而且它的值不只是session id还带一点加密签名信息。在Postman里调试这类项目时登录成功后去看响应头里的Set-Cookie把那个完整的cookie保存下来后续请求才会被服务端识别。Java的Servlet项目则常见JSESSIONIDSpring Security还可能有额外的Cookie名称。动手调试之前先打开浏览器开发者工具的Network面板看登录成功后到底种了哪些cookie一句“不同框架cookie名称不同”能帮你少走很多弯路。Session机制的典型问题就是服务端会话状态会过期。默认情况下Tomcat的session超时时间通常是30分钟Redis存储的session也有自己的过期策略。在Postman里遇到“登录成功后隔一段时间再调接口又返回401”多半就是session过期了重新执行一次登录请求就好。4.2 高频报错逐条拆解做鉴权相关测试时下面的报错几乎每个人都遇到过我把排查思路统一列出来报错信息可能原因排查步骤there is no session with idsession已过期、服务端清除了会话数据、或会话id传错重新登录拿到新session id检查cookie名称是否正确token exchange failed: token endpoint returned status 403token端点返回403一般是客户端凭证错误、IP被限制、地区限制或网络策略拦截查看token请求的实际响应体确认client_id/client_secret检查是否被网关拦截sign-in could not be completed token exchange failed客户端访问token端点时网络不通或请求被拦截抓包确认token端点是否可达、证书是否正常、参数是否齐全your access token could not be refreshedrefresh_token过期、refresh逻辑失败检查refresh_token是否过期重新走登录流程session file locked (timeout)本地框架的会话文件被多个进程同时占用一般是异常退出后留下的锁文件导致关闭重复进程删除锁文件后再试login failed. check api token or gitlab version客户端与服务的版本不兼容或token配置有误核对API token和版本要求遇到这种问题我习惯的第一步不是去看业务代码而是先把登录接口和token刷新接口的响应完整抓下来看服务器到底回了什么错误码和错误描述。大部分鉴权报错都不是玄学返回信息里已经写明了原因只是很多人没点开响应体去看。另外有个通用排查技巧用一个不经过任何变量的裸请求去试登录接口和token接口如果裸请求能成功那就是Postman的变量、环境或脚本哪里配置错了如果裸请求也失败那就是接口本身或网络链路的问题。这个二分法能快速锁定问题范围效率非常高。4.3 从Postman到JMeterCookie和Token怎么搬很多人在Postman里调试通过后要转成JMeter做性能测试这时就会遇到“JMeter里怎么带cookie、怎么带token”的问题。先说cookie。JMeter里有现成的“HTTP Cookie Manager”相当于是Postman Cookie Jar的平替版。把它加到线程组下面JMeter就会自动处理响应里的Set-Cookie并在后续请求中自动带上匹配域名的cookie。不需要手动添加Cookie头也不需要在每个请求里单独配置。再说token。因为JMeter需要从登录接口的响应里提取token所以通常用“正则表达式提取器”或者“JSON Extractor”来做。比如登录接口返回{data: {token: xxx}}用一个JSON Extractor变量名填api_tokenJSON Path表达式填$.data.token默认值留空。然后在其他请求的Authorization Header里引用${api_token}即可。这里有一个容易踩的坑正则表达式提取器的作用域是“某个取样器的子节点”如果放在登录请求的子节点提取结果只对同一个线程组中之后执行的请求可见如果放在控制器层级不对后面的请求就拿不到变量。最好的做法是把提取器放在登录请求下并且确保登录请求在业务请求之前执行。4.4 联动Burp、Reqable等工具时的注意事项调试过程中我经常需要在Postman和Burp Suite之间切换比如要看某个请求发送出去后在网络层的真实表现或者要做中间人拦截分析。在Burp里修改cookie是非常直观的在请求包的Headers里直接改Cookie字段改完放行就能看到服务器响应。用Reqable这类工具时它的一个常见诉求是“怎么把响应里的cookie自动代入下一个接口”。思路和Postman类似先看响应里有没有Set-Cookie然后在“脚本”或“后处理步骤”里解析并设置成变量下一个请求引用变量即可。不同工具实现方式略有差异但逻辑完全一致。联动时最需要注意的是在Burp里测试cookie时最好关掉Postman的自动Cookie管理否则两边互相干扰容易让人困惑。我通常是Postman负责验证业务逻辑、Burp负责看网络交互细节各干各的避免混淆。4.5 防泄露的几个习惯和鉴权相关的凭证都属于敏感信息尤其在做接口测试、调试、写技术文章的时候容易随手就把真实token或cookie截图发出去了。这里有几个可以养成的习惯截图前把token、session id、cookie值用打码或者替换成假数据。不要把一个带着真实凭证的Postman集合导出发到公开仓库哪怕是私有仓库也尽量别放。要分享的话把环境变量里的敏感值替换成占位符。使用各种模型辅助编程或写脚本时注意别把真实的api_key、token粘贴到聊天窗口里。可以在本地先用普通字符串占位跑通了再替换为实际值。这个习惯看着小事但真出问题的时候挺麻烦。接口测试本身动的就是权限相关的东西多留一分意识不是坏事。5. 把“账号预登录”这套思路扩展到团队协作鉴权处理不仅在Postman单机操作里重要在团队协作里同样关键。常见的痛点是新同事拿到一个Postman集合导入后跑不通因为环境变量里token是空的、环境域名是错的。解决思路是在集合里做一个“预登录”请求把它放在集合的最前面后面其他请求都通过变量引用token。新同事导入集合后只需要做两件事把环境变量里的账号密码改成自己的然后先跑一次预登录请求之后所有业务请求只要依赖{{api_token}}的都能直接跑通。还可以把预登录请求做成一键式加一个“Run Collection”流程第一步就是登录接口后面跟着业务用例。这样每次跑集合token会自动刷新不用人肉维护。这个方案是我在实际项目里用得最顺的一种比自己费劲去给同事解释“你要先手动复制token再粘进去”要省心得多。6. 写在最后接口测试的鉴权本质上就是用Postman模拟真实用户“登录并且带着凭证发起请求”的完整行为。cookie、session、token只是凭证的三种不同形态理解了它们的存储位置、传输方式和过期机制很多所谓“玄学报错”都能迎刃而解。我个人在实际项目里的习惯是能自动就不手动能用变量就不写死每个集合先搭好登录和token刷新机制再往里面填业务用例。这样跑起来省心排查问题也快。最后再分享一个小技巧如果你经常被某个环境的登录态折腾得焦头烂额不如花10分钟写一个“全局登录脚本”放在集合的Pre-request Script里让token彻底做到无感自动刷新。一开始可能觉得没必要但遇到一次凌晨跑冒烟测试跑到一半全红的情况你就会明白这个脚本值多少钱了。
返回列表