使用 CSRF 令牌登录 Cypress
Cypress Login with CSRF token
我真的很想扩展这个话题 "Logging in with CSRF token" 因为我已经用头撞墙好几个星期了,我不能是唯一遇到这个问题的人。所有关于通过 POST 登录或使用 CSRF 登录的话题都不可避免地回到上面的 link.
然而 link 中描述的食谱似乎对我不起作用。他们都假设 CSRF 令牌是在您访问登录页面后创建的。但在我们的网站上,CSRF 令牌仅在您登录后创建。
我用 Postman 进行了测试,在您登录之前 HTML 或 header 中没有 CSRF 令牌。
我还在 Cypress 中使用以下代码对其进行了测试:
describe('gimme dat csrf token', () => {
it('try to get the csrf token', () => {
cy.visit(Cypress.env('url'))
cy.getCookie('YII_CSRF_TOKEN')
.then(async (c) => {
cy.log(c.value)
return c.value
})
})
})
这将 return 出错,因为没有 YII_CSRF_TOKEN
Type Error
Cannot read properties of null (reading 'value')
如果我之前添加了一个登录步骤,它将 return CSRF 令牌的值如预期的那样:
import {Login} from "../../pages/login/Login";
describe('gimme dat csrf token', () => {
it('try to get csrf token', () => {
cy.visit(Cypress.env('url'))
login.loginCredentials(Cypress.env('userEmail'), Cypress.env('userPass')) //added login
cy.getCookie('YII_CSRF_TOKEN')
.then(async (c) => {
cy.log(c.value)
return c.value
})
})
})
因此上述 link 中的策略 #1(从 HTML 解析令牌)和 #2(从响应 headers 解析令牌)无法工作。
秘诀 #3 也不可行,因为我们有多个实时系统要测试,我们无法公开 /csrf 路由
这只剩下策略 #4,我们一直在使用它。
有什么想法或者我们是否坚持将“手动”登录步骤添加到每个规范文件?
我认为策略 #1 和 #2 依赖于浏览器记住凭据并将它们提供给登录页面,就像 Whosebug 页面一样 - 您不必每次访问都登录。
主要区别在于您使用了 cy.visit()
而不是食谱中显示的 cy.request()
。
如果您仍然无法成功获取令牌,请尝试使用 cy.session()
登录。它只会在每个会话中调用一次登录函数。
/*
Enable use of cy.session() and new behavior to handle caching
and restoring cookies, localStorage, and sessionStorage.
*/
Cypress.config('experimentalSessionSupport', true)
describe('...', () => {
beforeEach(() => {
cy.session(() => {
login.loginCredentials(Cypress.env('userEmail'), Cypress.env('userPass'))
})
})
it('try to get csrf token', () => {
cy.getCookie('YII_CSRF_TOKEN')
.then((c) => {
cy.log(c.value)
})
})
})
我真的很想扩展这个话题 "Logging in with CSRF token" 因为我已经用头撞墙好几个星期了,我不能是唯一遇到这个问题的人。所有关于通过 POST 登录或使用 CSRF 登录的话题都不可避免地回到上面的 link.
然而 link 中描述的食谱似乎对我不起作用。他们都假设 CSRF 令牌是在您访问登录页面后创建的。但在我们的网站上,CSRF 令牌仅在您登录后创建。
我用 Postman 进行了测试,在您登录之前 HTML 或 header 中没有 CSRF 令牌。
我还在 Cypress 中使用以下代码对其进行了测试:
describe('gimme dat csrf token', () => {
it('try to get the csrf token', () => {
cy.visit(Cypress.env('url'))
cy.getCookie('YII_CSRF_TOKEN')
.then(async (c) => {
cy.log(c.value)
return c.value
})
})
})
这将 return 出错,因为没有 YII_CSRF_TOKEN
Type Error
Cannot read properties of null (reading 'value')
如果我之前添加了一个登录步骤,它将 return CSRF 令牌的值如预期的那样:
import {Login} from "../../pages/login/Login";
describe('gimme dat csrf token', () => {
it('try to get csrf token', () => {
cy.visit(Cypress.env('url'))
login.loginCredentials(Cypress.env('userEmail'), Cypress.env('userPass')) //added login
cy.getCookie('YII_CSRF_TOKEN')
.then(async (c) => {
cy.log(c.value)
return c.value
})
})
})
因此上述 link 中的策略 #1(从 HTML 解析令牌)和 #2(从响应 headers 解析令牌)无法工作。
秘诀 #3 也不可行,因为我们有多个实时系统要测试,我们无法公开 /csrf 路由
这只剩下策略 #4,我们一直在使用它。
有什么想法或者我们是否坚持将“手动”登录步骤添加到每个规范文件?
我认为策略 #1 和 #2 依赖于浏览器记住凭据并将它们提供给登录页面,就像 Whosebug 页面一样 - 您不必每次访问都登录。
主要区别在于您使用了 cy.visit()
而不是食谱中显示的 cy.request()
。
如果您仍然无法成功获取令牌,请尝试使用 cy.session()
登录。它只会在每个会话中调用一次登录函数。
/*
Enable use of cy.session() and new behavior to handle caching
and restoring cookies, localStorage, and sessionStorage.
*/
Cypress.config('experimentalSessionSupport', true)
describe('...', () => {
beforeEach(() => {
cy.session(() => {
login.loginCredentials(Cypress.env('userEmail'), Cypress.env('userPass'))
})
})
it('try to get csrf token', () => {
cy.getCookie('YII_CSRF_TOKEN')
.then((c) => {
cy.log(c.value)
})
})
})