k6性能测试传递CSRF Token遇ReferenceError问题求助
解决k6测试Laravel登录时CSRF Token传递失败的问题
错误原因分析
出现ReferenceError: token is not defined及Token传递失败,核心问题有以下几点:
- 变量作用域限制:第一个group内用
const声明的token属于块级作用域,第二个group无法访问。 - 变量名大小写错误:提取Token时写成了
Elem.attr('value'),实际变量名是小写的elem,JavaScript大小写敏感。 - 硬编码Cookie导致会话冲突:手动写入固定Cookie会和k6自动管理的Cookie Jar冲突,无法保持会话一致性。
- 请求Content-Type不匹配:登录请求同时设置了
application/json和application/x-www-form-urlencoded,且用JSON序列化payload,不符合Laravel默认表单提交格式。
修复步骤
- 将
token变量提升到main函数的顶层作用域,用let声明,让两个group都能访问。 - 修正变量名大小写:
elem.attr('value')。 - 移除手动硬编码的Cookie,改用k6自动管理的Cookie Jar(http模块默认自动处理)。
- 调整登录请求的payload为表单编码格式,统一Content-Type为
application/x-www-form-urlencoded。
修正后的完整脚本
import { parseHTML } from 'k6/html'; import { sleep, group, check } from "k6"; import http from 'k6/http' export const options = {} export default function main() { let response // 提升token到顶层作用域,让两个group都能访问 let token group('page_1 - 获取登录页及CSRF Token', function () { response = http.get('http://localhost:81/login', { headers: { 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:104.0) Gecko/20100101 Firefox/104.0', accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8', 'accept-language': 'en-US,en;q=0.5', 'upgrade-insecure-requests': '1', }, }) // 修正变量名大小写,正确提取Token const elem = response.html().find('input[name=_token]'); token = elem.attr('value'); console.log('提取到的CSRF Token: ' + token); check(response, { '登录页加载成功': (r) => r.status === 200, '成功提取CSRF Token': (r) => token !== undefined, }); }) sleep(1) // 模拟用户操作间隔 group('page_2 - 提交登录请求', function () { const url = 'http://localhost:81/customlogin'; // 使用表单格式的payload,而非JSON const payload = { _token: token, email: 'user', password: '1234', }; const params = { headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:104.0) Gecko/20100101 Firefox/104.0', accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8', 'accept-language': 'en-US,en;q=0.5', referer: 'http://localhost:81/login', }, }; response = http.post(url, payload, params); console.log('登录请求响应状态码: ' + response.status) check(response, { '登录请求成功': (r) => r.status === 200 || r.status === 302, // Laravel登录成功通常会跳转,状态码302 }); }) }
额外说明
- k6的
http模块默认会自动管理Cookie Jar,无需手动处理Cookie,确保会话连贯性。 - Laravel的CSRF验证不仅需要表单中的
_token字段,还需要Cookie中的XSRF-TOKEN保持一致,k6自动处理Cookie后会自动匹配。 - 登录成功后Laravel通常会返回302重定向,所以检查条件中加入了302状态码。
内容的提问来源于stack exchange,提问作者grubthomas
相关产品推荐
相关产品推荐

