从URL中删除任何未列入白名单的参数

时间:2013-11-04 09:52:39

标签: regex apache .htaccess url mod-rewrite

我需要删除不在白名单中的任何参数,例如网址:

abc.com/somePage?phone=1234&stipAway=asd&fax=324&stripDown=disappear&zip=zip

应该看:

abc.com/somePage?phone=1234&fax=324&zip=zip

相关问题:Rewrite URL using .htaccess file in case there is used parameters which is not in white list

P.S。在提到的前两个答案中,需要更复杂的解决方案。为了使之易于理解,我将举例说明:

abc.com/somePage2?stripAway=asd&fax=324&stripDown=disappear&phone=1234&zip=zip

应该看:

abc.com/somePage2?fax=324&phone=1234&zip=zip

abc.com/somePage3?stripAway=asd&stripDown=disappear

应该看:

abc.com/somePage3

2 个答案:

答案 0 :(得分:0)

以下应该适合你:

RewriteEngine On

RewriteCond %{QUERY_STRING} ^(?:.*?&)?(phone=[^&]*)(?:.*?&)(fax=[^&]*)(?:.*?&)(zip=[^&]*) [NC]
RewriteRule ^ %{REQUEST_URI}?%1%2%3 [L,R=302]

PS:这是假设白名单参数出现在上面的顺序,即电话,传真,邮编

答案 1 :(得分:0)

如果列表有序,anubhava的答案要好于我的。如果不保证列表有序,则可以使用以下规则。它使用Jon Lin uses in this answer

的技术
RewriteCond %{QUERY_STRING}           ^(.*&|)(?!(phone|fax|zip))[^=]+=
RewriteCond ##%{QUERY_STRING}         (.*?)##(|.*&)(phone)=([^&]+)
RewriteCond %1&%3=%4##%{QUERY_STRING} (.*?)##(|.*&)(fax)=([^&]+)
RewriteCond %1&%3=%4##%{QUERY_STRING} (.*?)##(|.*&)(zip)=([^&]+)
RewriteRule ^(.*)$ $1?%3=%4%1 [R,L]

那么,它做了什么?如果第一个条件可以找到与(phone|fax|zip)不匹配的参数(负向预测),则该条件才为真。接下来的三个RewriteCond捕获您要保留的每个参数,并在自定义##分隔符之前准备一个查询字符串。如果该分隔符恰好位于查询字符串中,则会发生奇怪的事情。

这种方法的缺点是,如果不存在这三个参数中的一个,则不会应用该规则。我个人会把这个白名单放在页面本身,而不是试图通过.htaccess过滤它。


编辑:如果某些参数是可选的,您可以使用以下怪物:

RewriteCond %{QUERY_STRING} ^((.*?)&|)(?!(phone|fax|zip))[^=]+=[^&]+(&.*|)$
RewriteRule ^(.*)$ $1?%2%4 [R,E=Redir:1]

RewriteCond %{QUERY_STRING} ^&(.*)$
RewriteRule ^(.*)$ $1?%1 [R,E=Redir:1]

RewriteCond %{ENV:Redir} =1
RewriteRule ^ - [R,L]

基本上,如果字符串中的参数与前瞻中的参数不匹配,它将匹配该参数之前的部分和该参数后面的部分并重新构造查询字符串。第二个规则是,如果第一个参数不是“白名单”(或者它只是以&开头),则防止它吞噬整个查询字符串,最后一条规则是尽量将重定向的数量保持在最小值。请注意,如果请求中的参数太多而未列入白名单,则浏览器将显示错误(检测到重定向链)。


相反,我建议过滤页面本身。在PHP中它将类似于以下代码。如果您决定使用其他httpdeamon,这将使维护此白名单更容易,并且不会破坏所有内容。

<?php
$whitelist = Array( 'phone', 'fax', 'zip' );
foreach( $_GET as $k => $v ) {
  if( !in_array( $k, $whitelist ) )
    unset( $_GET[$k] );
}

#And the same for $_POST and $_REQUEST