php - Laravel 5.2:在 Chrome 上修改 Iframe 表单时出现 TokenMismatchException?
问题描述
我有 5.2 版的 Laravel 应用程序来创建可以使用 iframe 修改到任何网页的动态表单,几个月前表单工作正常,但由于以下原因现在不能在 Chrome(最新版本)上工作:
此 Set-Cookie 未指定“SameSite”属性,默认为 samesite=lax,并被阻止,因为它来自不是对顶级导航的响应的 corss-site 响应。Set-Cookie 必须设置为“SameSite=None”才能启用跨站点请求。
这是具有所有属性的 iframe:
<iframe src="https://local.testproject.com/iframe/MSvnBNB9FT4H4m7kNi1OSJtdomsAxW3XnR6KZn1W9dStupbBLjYSfn7txRUNIDCa0UWCR4RbeiWJaMgy6JSDbZXzsFf8C6u32pUD5TiHPqJzxQiLwXXYm8SsUqHqhhoV" sandbox="allow-forms allow-modals allow-popups allow-scripts allow-same-origin allow-top-navigation" style="width: 100%; height: 650px; border: none;"></iframe>
如需进一步查看随附的屏幕截图:https ://prnt.sc/u6el89
我研究了很多,但还没有找到任何东西。甚至我自定义了核心文件vendor\symfony\http-foundation\Cookie.php
以下是自定义Cookie.php
文件:
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\HttpFoundation;
/**
* Represents a cookie.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
class Cookie
{
protected $name;
protected $value;
protected $domain;
protected $expire;
protected $path;
protected $secure;
protected $httpOnly;
protected $sameSite;
/**
* Constructor.
*
* @param string $name The name of the cookie
* @param string $value The value of the cookie
* @param int|string|\DateTimeInterface $expire The time the cookie expires
* @param string $path The path on the server in which the cookie will be available on
* @param string $domain The domain that the cookie is available to
* @param bool $secure Whether the cookie should only be transmitted over a secure HTTPS connection from the client
* @param bool $httpOnly Whether the cookie will be made accessible only through the HTTP protocol
*
* @throws \InvalidArgumentException
*/
public function __construct($name, $value = null, $expire = 0, $path = '/', $domain = null, $secure = false, $httpOnly = true, $sameSite='None')
{
// from PHP source code
if (preg_match("/[=,; \t\r\n\013\014]/", $name)) {
throw new \InvalidArgumentException(sprintf('The cookie name "%s" contains invalid characters.', $name));
}
if (empty($name)) {
throw new \InvalidArgumentException('The cookie name cannot be empty.');
}
// convert expiration time to a Unix timestamp
if ($expire instanceof \DateTimeInterface) {
$expire = $expire->format('U');
} elseif (!is_numeric($expire)) {
$expire = strtotime($expire);
if (false === $expire || -1 === $expire) {
throw new \InvalidArgumentException('The cookie expiration time is not valid.');
}
}
$this->name = $name;
$this->value = $value;
$this->domain = $domain;
$this->expire = $expire;
$this->path = empty($path) ? '/' : $path;
$this->secure = (bool) $secure;
$this->httpOnly = (bool) $httpOnly;
$this->sameSite = $sameSite;
}
/**
* Returns the cookie as a string.
*
* @return string The cookie
*/
public function __toString()
{
$str = urlencode($this->getName()).'=';
if ('' === (string) $this->getValue()) {
$str .= 'deleted; expires='.gmdate('D, d-M-Y H:i:s T', time() - 31536001);
} else {
$str .= urlencode($this->getValue());
if ($this->getExpiresTime() !== 0) {
$str .= '; expires='.gmdate('D, d-M-Y H:i:s T', $this->getExpiresTime());
}
}
if ($this->path) {
$str .= '; path='.$this->path;
}
if ($this->sameSite) {
$str .= '; SameSite='.$this->sameSite();
}
if ($this->getDomain()) {
$str .= '; domain='.$this->getDomain();
}
if (true === $this->isSecure()) {
$str .= '; secure';
}
if (true === $this->isHttpOnly()) {
$str .= '; httponly';
}
return $str;
}
/**
* Gets the name of the cookie.
*
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* Gets the value of the cookie.
*
* @return string
*/
public function getValue()
{
return $this->value;
}
/**
* Gets the domain that the cookie is available to.
*
* @return string
*/
public function getDomain()
{
return $this->domain;
}
/**
* Gets the time the cookie expires.
*
* @return int
*/
public function getExpiresTime()
{
return $this->expire;
}
/**
* Gets the path on the server in which the cookie will be available on.
*
* @return string
*/
public function getPath()
{
return $this->path;
}
/**
* Checks whether the cookie should only be transmitted over a secure HTTPS connection from the client.
*
* @return bool
*/
public function isSecure()
{
return $this->secure;
}
/**
* Checks whether the cookie will be made accessible only through the HTTP protocol.
*
* @return bool
*/
public function isHttpOnly()
{
return $this->httpOnly;
}
/**
* Whether this cookie is about to be cleared.
*
* @return bool
*/
public function isCleared()
{
return $this->expire < time();
}
/**
* Whether this cookie same site.
*
* @return bool
*/
public function sameSite()
{
return $this->sameSite;
}
}
还添加了参数config/session.php
:
/*
|--------------------------------------------------------------------------
| Same-Site Cookies
|--------------------------------------------------------------------------
|
| This option determines how your cookies behave when cross-site requests
| take place, and can be used to mitigate CSRF attacks. By default, we
| do not enable this as other CSRF protection services are in place.
|
| Supported: "lax", "strict", "none"
|
*/
'same_site' => 'None'
之后,我在以下方法中修改vendor\laravel\framework\src\Illuminate\Foundation\Http\Middleware\VerifyCsrfToken.php
并添加了新参数:same_site
protected function addCookieToResponse($request, $response)
{
$config = config('session');
$response->headers->setCookie(
new Cookie(
'XSRF-TOKEN', $request->session()->token(), time() + 60 * $config['lifetime'],
$config['path'], $config['domain'], $config['secure'], false, $config['same_site']
)
);
return $response;
}
还是没有运气!我知道修改核心不是好习惯,但我只是想让这件事发挥作用。请指导我怎样才能做到这一点?
谢谢
解决方案
推荐阅读
- python - Python:AttributeError:“客户端”对象没有属性“命令”
- python - 根据值从数据框中删除所有行
- python - 下一页 Selenium with Scrapy 不工作
- javascript - 对每次随机生成的数组进行冒泡排序
- powershell - 根据用户输入从 CSV 文件中为 WinSCP .NET 程序集选择 SFTP 连接数据
- node.js - 在 Redis 中处理并发请求
- hyperledger-fabric - 频道创建失败。密钥组频道申请问题
- java - 使用 Do-while 循环创建三角乘法表
- javascript - NodeJS - 在数组中的每个元素之间按顺序循环遍历数组
- javascript - Vue如何将prop数据分配给arraylist