【问题标题】:Redirect only real strings (letters) with htacces使用 htaccess 仅重定向真实的字符串(字母)
【发布时间】:2014-04-26 02:19:50
【问题描述】:

我想做的是让用户在命令行中输入搜索字符串并将他重定向到适当的页面。例如:用户键入:www.mydomain.com/something,我将他定向到 www.mydomain.com/page.php?id=27408

我所拥有的是 .htaccess 中的一个命令:ErrorDocument 404 /index_404.php 因此请求被发送到我的 php 脚本,在我的数据库中搜索正确的 id 并将他引导到请求的页面。 – 这很好用。

不幸的是,每个 404 错误(例如,一些图片未找到)都会发送到该 php 页面并打扰我,因此流量很大。我有一个重定向 301 的解决方案——但我的提供商的服务器不允许我通过 php-script 生成 .htaccess。

所以我的问题是:有没有办法检查请求是否只匹配字母并只重定向这些请求。类似的东西:

ErrorDocument 404(在 [a..z] 中的请求)/index_404.php

并让其余的默认处理?如果是这样,请发送一个体面的例子。

这里是我的 php-script 的基本代码:

if (isset($_SERVER["REQUEST_URI"])) {
    $in = $_SERVER["REQUEST_URI"];
    $in = str_replace("/","",$in); //  
    dbconnect();
    $sql = 'select * from menu where REPLACE(menu," ","") = "'. $in;    
    $result = @mysql_query($sql);
    if ($data = @mysql_fetch_array($result)) {
        $out = 'page.php?id='.$data['id'];                                  
    }
}

if (isset($out)) {
    header("Location: ".$out);
} else {
    header("Location: "."index.php");
}

【问题讨论】:

  • 你有点滥用ErrorDocument 并以一种不寻常的方式接近它。您可以发布一些index_404.php 以便我们了解您是如何进行重定向的吗? (通过 REQUEST_URI 或其他)这会更好,更传统地处理 RewriteRule...
  • 我同意。但我对 RewriteRule 不熟悉,所以我发布了这个问题。正如我所提到的,当 cms 创建新的菜单项时,我正在寻找一种无需操作 htaccess 的解决方案。 (上面添加了一个代码示例)。
  • 好的,感谢您发布代码。我将其充实到下面的答案中。

标签: php .htaccess


【解决方案1】:

如您所见,ErrorDocument 可用于当您要求将每个 mimetype 无例外地发送到那里,但您的情况并非如此。

让我们稍微重构一下你的 PHP 代码,这样你就可以打破对ErrorDocument 的依赖,并在你的.htaccess 中更恰当地使用mod_rewrite。不是从REQUEST_URI 读取,更传统的方法是构建PHP 脚本以期望$_GET 中的参数。

重写:

首先,设置重写。您只想匹配字母并将其发送到 PHP 脚本。 (这仍然使用index_404.php,但您可能需要重命名它,因为它不再处理 404)。 /abcdabcd/efg 之类的请求将被传递给 PHP 脚本。像/main.css 这样的真实现有文件不会发送到 PHP;该文件将被正确提供。对 /bad-image.png 等不存在文件的请求将与 RewriteRule 不匹配,因此将被视为常规 404。

RewriteEngine On
# If the request isn't for an actual existing file
# (so images, CSS aren't interrupted)
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
# Send letters-only (and slashes) URI's to PHP into the query string param in=
# /? also allows a trailing slash optionally
RewriteRule ^([A-Za-z\/]+)/?$ index_404.php?in=$1 [L]

注意:我使用[A-Za-z\/]+ 来允许大小写,还使用/,因为您有代码可以删除PHP 中的/。这允许将像 /abc/abc/def 这样的 URI 发送到 PHP。如果您只想允许/abc不允许 /abc/def,请改用[A-Za-z]+。如果您不想允许大写,只需删除 A-Z

现在 PHP 处理程序...

上面使用查询字符串发送到PHP。修改您的 PHP 以改为阅读 $_GET['in']

if (isset($_GET['in'])) {
  dbconnect();

  // Looks like you permit slashes as input but remove them here...
  $in = str_replace("/","",$_GET['in']);

  // You must escape this even though the Apache 
  // rewrite only permits a-z/
  $in = mysql_real_escape_string($in);

  // Get rid of those @ error suppressors
  $sql = "select * from menu where REPLACE(menu,' ','') = '$in'";

  // Do your query
  $result = mysql_query($sql);
  if ($data = mysql_fetch_array($result)) {
      $out = 'page.php?id='.$data['id'];                                  
  }
}
if (isset($out)) {
    header("Location: " . $out);
} else {
    header("Location: index.php");
}

请注意,mysql_*() 扩展在 PHP 5.5 中已弃用。它最终将从语言中删除,并且不应使用它编写新代码。相反,现在是开始学习使用PDOMySQLi 的时候了。两者都支持通过 prepare()/execute() which is the recommended way to secure your code against SQL injection 准备的语句。​​

【讨论】:

  • 即使使用德语元音变音也能完美运行:-> 看看代码RewriteRule ^([A-Za-z\xC3\xA4\xB6\xBC\x84\x96\x9C\/]+)/?$ /index_404.php?in=$1 [L]
    你的评论很好的例子对我有很大帮助,还有很多好的提示。很快我将阅读更多关于 PDO 的内容并摆脱 @(有趣的是它仍然存在......,我有点懒惰)。在这个例子中,mysql_real_escape_string 函数被从我身上删除,以保持简短(我知道 sql-injection),但我看看 prepare-execute。一直希望能写出更好的代码……
猜你喜欢
  • 2017-07-03
  • 2015-05-29
  • 2013-07-14
  • 2017-02-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-05
相关资源
最近更新 更多