为了账号安全,请及时绑定邮箱和手机立即绑定

Symfony 4.3 PHP:如何从 302 重定向响应中读取 cookie?

Symfony 4.3 PHP:如何从 302 重定向响应中读取 cookie?

PHP
繁花如伊 2022-01-02 17:18:17
我想做什么(在控制器中)接收请求,基于该请求发送外部 HTTP 请求解析响应,基于返回响应我计划有多个功能都遵循这种模式。他们一个接一个地被调用。Symfony 4.3 引入了 HttpClient 组件和 BrowserKit 组件,乍一看似乎符合要求。但事实证明,事情变得更加复杂。外部 HTTP 请求被发送到使用 cookie 跟踪会话的服务器,这应该不会太不寻常。如果在没有 cookie 的情况下发送请求,服务器总是以相同的登录页面内容进行响应。所以我们需要cookie。不用担心,对初始请求的响应带有一个“Set-Cookie”标头,其中包含在后续请求中在“Cookie”标头中发送的 cookie。带有 cookie 的响应的 HTTP 状态是“302 Found”,它在正常的 Web 环境中,使用 Web 浏览器重定向到请求中具有相同 cookie 的下一个页面。在我的 Symfony 控制器中复制这个动作似乎非常棘手。扩展我现在想做的第 2 步:2.a. 发送外部 HTTP 请求2.b. 从 302 响应中读取 cookie(不带自动重定向)2.c. 设置后续请求的“Cookie”头,值来自2.b。2.d. 将请求发送到新目标(在 302 响应的“Location”标头中设置)这是控制器中的一些代码:use Symfony\Component\HttpClient\HttpClient;use Symfony\Component\HttpClient\Exception\RedirectionException;use Symfony\Component\HttpFoundation\JsonResponse;public function init(Request $request): JsonResponse{    $url = "external url";    $client = HttpClient::create();    try {        $response = $client->request('GET', $url, [            'max_redirects' => -1        ]);    } catch (RedirectionException $redirectionException) {    }    return new JsonResponse([], 200);}不设置 max_redirects 意味着客户端遵循重定向并最终返回 200 响应而没有任何 cookie。将该值设置为 -1 将引发重定向异常,并且带有 cookie 的 302 响应似乎丢失了。我也试过 HttpBrowser 组件:$cookieJar = new CookieJar();$client = new HttpBrowser(HttpClient::create(), null, $cookieJar);$client->request('GET', $url);但是我得到了一个没有 cookie 的 200 响应,因为它会自动跟随重定向。我知道这里提到的组件是 Symfony 4.3 的新组件并且是“实验性的”,但我也不认为我的任务过于复杂或不寻常。但也许 Symfony 有其他的 http 客户端更适合这项任务?
查看完整描述

1 回答

?
芜湖不芜

TA贡献1796条经验 获得超7个赞

事实证明,通过为 Symfony 尝试其他 HTTP 客户端组件而不是本机组件,这个任务更容易完成。所以我暂时把 Symfony HttpClient 和 HttpBrowser 放在一边。我设法用 guzzlehttp/guzzle 6.3.3 版解决了这个问题。这是我的控制器功能中的样子:


use GuzzleHttp\Client;

use Symfony\Component\HttpFoundation\Cookie;

use Symfony\Component\HttpFoundation\JsonResponse;

use Symfony\Component\HttpFoundation\Request;


public function init(Request $request): JsonResponse {

    $client = new Client([

        'base_uri' => 'an external domain',

        'cookies' => true

    ]);

    // get the 302 response, without following

    $response = $client->get('path',[

        'allow_redirects' => false

    ]);

    // get the cookie from the 302 response

    $jar = new \GuzzleHttp\Cookie\CookieJar(true,[$response->getHeader('Set-Cookie')]);

    // follow the redirect manually, with the cookie from the 302 response

    $redirectResponse = $client->request('GET', $response->getHeader('Location')[0], [

        'cookies' => $jar

    ]);


    $jsonResponse = new JsonResponse(['message' => 'my message'],200);

    $originalCookie = Cookie::fromString($response->getHeader('Set-Cookie')[0]);

    $newCookie = Cookie::create(

        $originalCookie->getName(),

        $originalCookie->getValue(),

        $originalCookie->getExpiresTime(),

        '/',

        'my domain',

        false,

        true,

        $originalCookie->isRaw(),

        $originalCookie->getSameSite()

    );


    $jsonResponse->headers->setCookie($newCookie);

    return $jsonResponse;

}

cookie 不能从响应中获取,否则它永远不会被发回,因为域或路径不匹配。因此,我创建了一个与原始 cookie 非常相似的新 cookie,然后将其发送回浏览器。这样 cookie 会在后续请求中返回,并且数据内容可以被转发。


这里出现的其他问题是必须在外部服务器上处理的同源要求。


我仍然对如何使用本地 Symfony 4.3 组件完成所有这些操作感兴趣,或者,如果有人可以确认这是不可能的。


查看完整回答
反对 回复 2022-01-02
  • 1 回答
  • 0 关注
  • 359 浏览

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号