跨域测试
你将学到
- Cypress绕过同源策略的技术方案
- 跨域内容的限制与解决方案
网络安全
浏览器遵循严格的同源策略。这意味着当<iframe>
的源策略不匹配时,浏览器会限制它们之间的访问。
由于Cypress在浏览器内部工作,它必须始终能直接与远程应用通信。不幸的是,浏览器天然会阻止这种行为。
为解决这些限制,Cypress通过JavaScript代码、浏览器内部API和网络代理的组合策略来"遵守"同源策略规则。我们的目标是在无需修改应用代码的情况下完全自动化测试——我们基本实现了这一点。
Cypress的底层实现
- 代理所有HTTP/HTTPS流量
- 改变托管URL以匹配被测应用
- 使用浏览器内部API处理网络层流量
当Cypress首次加载时,其内部应用会运行在随机端口,如http://localhost:64874/__/
。
在测试中执行第一个cy.visit()
命令后,Cypress会将URL改为远程应用的源地址,从而解决同源策略的首要障碍。你的应用代码会像在Cypress外部一样执行,所有功能正常运作。
Cypress必须分配和管理浏览器证书以实现实时流量修改。你会看到Chrome显示"SSL证书不匹配"的警告,这是预期行为。底层我们充当自己的CA机构,动态颁发证书来拦截原本无法访问的请求。我们仅对当前测试的源执行此操作,其他流量则直接放行。
注意,Cypress允许你为HTTPS站点可选地配置CA/客户端证书。详见配置客户端证书。如果远程服务器要求提供配置URL的客户端证书,Cypress会予以提供。
限制
尽管我们竭尽全力确保应用在Cypress中正常运行,但仍需注意以下限制:
不同源测试需要cy.origin()
Cypress会改变自身主机URL以匹配你的应用。除cy.origin
外,Cypress要求单个测试中所有导航URL保持相同源。
如果尝试访问两个不同源,必须使用cy.origin
包装第二个域的Cypress命令。否则,导航后命令会超时失败,因为这些命令实际仍在第一个域上执行。
没有cy.origin()
时,你可以在不同测试中访问不同源,但不能在同一个测试中这样做。
不使用cy.origin
会报错的测试案例
- 点击指向不同源的
<a>
链接后执行后续命令 - 提交导致重定向到不同源的
<form>
表单后执行命令 - 应用中执行如
window.location.href = '...'
跳转到不同源后执行命令
这些情况下,除非使用cy.origin
命令,否则Cypress将失去自动化能力并报错。
继续阅读了解常见问题的解决方案。
重新启用 document.domain 注入
自 Cypress v14.0.0 起,默认不再向 text/html
页面注入 document.domain
。
这意味着现在当测试中需要在不同 源 之间导航时,必须使用 cy.origin()
。此前,cy.origin()
仅在同一测试中导航至不同 超级域名 时才需要。
通过将 injectDocumentDomain 配置选项设为 true
,Cypress 将尝试向 text/html
页面注入 document.domain
。
超级域名由主机名的最后两个元素组成,以 .
(点号)分隔。例如 https://www.cypress.io
的超级域名是 cypress.io
。启用此选项后,在 https://www.cypress.io
和 https://docs.cypress.io
之间导航时不需要使用 cy.origin()
,但在 https://www.cypress.io
和 https://www.auth0.com
之间导航时仍需使用。
- 这会导致某些网站出现问题,特别是那些使用 源键代理集群 的网站。
- 此选项已被弃用,将在未来的 Cypress 版本中移除。