【问题标题】:How to deal with unencoded URL redirects to my website correctly?如何正确处理未编码的 URL 重定向到我的网站?
【发布时间】:2023-04-11 05:25:01
【问题描述】:

我们正在使用 CleverReach 将人们重定向到我们的网站,因为他们已经双重选择了他们的邮件帐户。我们将电子邮件作为查询参数重定向到我们的网站,例如:example.com/thanks?email=foo@bar.com(通过在 CleverReach 后端设置重定向,例如 example.com/thanks?email={EMAIL})。显然,email 参数没有被cleverreach 进行urlencoded。

现在,在 Drupal 中,如果 URL 是这样的:example.com/thanks?email=hello+world@bar.com 并使用此代码:

$request = \Drupal::request();
$email = $request->query->get('email');

$emailhello world@bar.com。现在,我不知道这里的正确处理是什么。显然,我不能告诉 CleverReach 事先对他们的重定向进行 urlencode。我什至不知道这是否是最佳做法,或者我是否需要实施某些东西......

我发现的唯一一件事是 $_SERVER['QUERY_STRING'] 包含“真实”字符串,我可以对其进行 urlencode 然后重定向,然后通过读取查询参数对它们进行 urldecode。但我觉得我缺少一些重要的内置功能。

TL;DR

如果网站使用非 urlencoded 查询参数重定向到我的网站,我该如何阅读它们?

我目前的做法:

<?php
public function redirectIfIllegalUri() {
  $request = \Drupal::request();
  $email = $request->query->get('email', '');

  $needsRedirect = (false !== strpos($email, ' ') || false !== strpos($email, '@'));

  if ($needsRedirect && isset($_SERVER['QUERY_STRING']) && false !== strpos($_SERVER['QUERY_STRING'], 'email=')) {

    $sqs = $_SERVER['QUERY_STRING'];
    $sqs = htmlspecialchars($sqs);
    $sqs = filter_var($sqs, FILTER_SANITIZE_STRING);
    $sqs = filter_var($sqs, FILTER_SANITIZE_ENCODED);
    $sqs = urldecode($sqs);
    $sqs = explode('&', $sqs);

    foreach ($sqs as $queryParam) {
      if (false === strpos($queryParam, 'email=')) continue;
      $values = explode('=', $queryParam);
      $email = $values[1];
    }

    $emailEncoded = urlencode($email);
    $query = $request->query->all();
    $query['email'] = $emailEncoded;

    $refreshUrl = Url::fromRoute('<current>');
    $refreshUrl->setOptions([
      'query' => $query,
    ]);

    $response = new RedirectResponse($refreshUrl->toString(), 301);
    $response->send();
    return;
  }
}

$request = \Drupal::request();
$email = urldecode($request->query->get('email', false));

drupal request() docs

【问题讨论】:

  • 我不太明白,?email=hello+world@bar.com hello world@bar.com 的 url 编码形式,这是一个无效的电子邮件地址,对吧?
  • @johnSmith 如果它的编码很好,那么为什么$_GET['email'] 返回hello world@bar.com 呢?我认为编码版本将+ 替换为%2B。此外,这实际上是一个有效的电子邮件地址
  • 那我不明白你的问题,如果$_GET['email'] 总是返回 urldecoded 你应该没问题,不是吗?当电子邮件未进行 url 编码时,您有什么错误?
  • 正如我所说,$_GET['email'] 返回hello world@bar.com 而我期望hello+world@bar.com
  • 该问题必须从 ClerverReach 方面解决:无论此链接是在电子邮件模板中还是在最终确认页面模板中,都应该能够正确地转义该部分 url。负责为新订阅者生成此链接的代码在哪里?

标签: php apache symfony drupal-8 cleverreach


【解决方案1】:

您面临的问题是当您从$_GET 全局变量中获取值时,+ 将被视为空格

目前在PHP 中不存在在没有urldecoding 的情况下返回这些值的方法,您需要构建一个自定义函数来实现您的要求:

一个简单的函数将通过使用这个函数返回未编码的输入:

function get_params() {
    $getData = $_SERVER['QUERY_STRING'];
    $getParams = explode('&', $getData);

    $getParameters = [];
    foreach ($getParams as $getParam) {
        $parsed = explode('=', $getParam);
        $getParameters[$parsed[0]] = $parsed[1];
    }

    return $getParameters;
}

如果您没有其他选择,可以使用此解决方案。通过使用此功能,您将始终获得编码的数据。

如果您可以对来自cleverreach 的值进行编码,那么最好的方法就是在那里对其进行编码。

cleverreach 中的值编码为电子邮件hello+world@bar.com 将为您提供此网址example.com/thanks?email=hello%2Bworld%40bar.com,在$_GET 中您将获得包含+ 符号的电子邮件。

【讨论】:

  • 嗯,这几乎就是我事先得到的。不过,我不确定这是否真的是最佳实践。只是读出查询字符串似乎很不安全。
  • 是的,这就是为什么我建议在cleverreach 中进行urlencode。这样你就不会有问题了。
猜你喜欢
  • 2022-12-16
  • 1970-01-01
  • 2011-07-03
  • 1970-01-01
  • 2016-03-30
  • 2021-01-31
  • 2014-10-29
  • 2013-03-23
  • 1970-01-01
相关资源
最近更新 更多