urlencoded Barra invertida está quebrando a URL

Sobre o sistema

Eu tenho URLs deste formato no meu projeto:

http://project_name/browse_by_exam/type/tutor_search/keyword/class/new_search/1/search_exam/0/search_subject/0 

Onde keyword / class pair significa pesquisar com a palavra-chave “class”.

Eu tenho um arquivo index.php comum que é executado para cada módulo no projeto. Existe apenas uma regra de reescrita para remover o index.php do URL: –

 RewriteCond $1 !^(index\.php|resources|robots\.txt) RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^(.*)$ index.php [L,QSA] 

Eu estou usando urlencode () ao preparar o URL de pesquisa e urldecode () ao ler o URL de pesquisa.

Problema

Apenas o caractere de barra invertida está quebrando URLs, causando erro de página 404 não encontrada. Por exemplo, se eu pesquisar one/two o URL é

 http://project_name/browse_by_exam/type/tutor_search/keyword/one%2Ftwo/new_search/1/search_exam/0/search_subject/0/page_sort/ 

Como faço para corrigir isso? Eu preciso manter index.php escondido no URL. Caso contrário, se isso não fosse necessário, não haveria nenhum problema com a barra e eu poderia ter usado este URL: –

 http://project_name/index.php?browse_by_exam/type/tutor_search/keyword/one %2Ftwo/new_search/1/search_exam/0/search_subject/0 

O Apache nega todos os URLs com %2F na parte do caminho, por motivos de segurança: os scripts não podem normalmente (ou seja, sem rewrite) informar a diferença entre %2F e / devido à variável de ambiente PATH_INFO ser automaticamente decodificada por URL (o que é estúpido , mas uma parte de longa data da especificação CGI, então não há nada que possa ser feito sobre isso).

Você pode desativar esse recurso usando a diretiva AllowEncodedSlashes , mas observe que outros servidores da Web ainda o desautorizam (sem nenhuma opção para desativá-lo) e que outros caracteres também podem ser tabus (por exemplo, %5C ) e que %00 em particular, sempre será bloqueado pelo Apache e pelo IIS. Portanto, se seu aplicativo dependesse da possibilidade de ter %2F ou outros caracteres em uma parte do caminho, você estaria limitando suas opções de compatibilidade / implantação.

Eu estou usando urlencode () ao preparar o URL de pesquisa

Você deve usar rawurlencode() , não urlencode() para escaping de partes de caminho. urlencode() é nomeado incorretamente, é na verdade para dados application/x-www-form-urlencoded , como na string de consulta ou no corpo de uma solicitação POST, e não para outras partes da URL.

A diferença é que + não significa espaço em partes do caminho. rawurlencode() produzirá corretamente %20 , o que funcionará tanto em dados codificados como em outras partes da URL.

No Apache, AllowEncodedSlashes On impediria que a solicitação fosse imediatamente rejeitada com um erro 404.

Apenas outra ideia sobre como consertar isso.

Substitua% 2F por% 252F após a codificação de URL

PHP

 function custom_http_build_query($query=array()){ return str_replace('%2F','%252F', http_build_query($query)); } 

Lidar com o pedido via htaccess

.htaccess

 RewriteCond %{REQUEST_URI} ^(.*?)(%252F)(.*?)$ [NC] RewriteRule . %1/%3 [R=301,L,NE] 

Recursos

http://www.leakon.com/archives/865

 $encoded_url = str_replace('%2F', '/', urlencode($url)); 

Eu tive o mesmo problema com barra no url get param, no meu caso seguindo o código php funciona:

 $value = "hello/world" $value = str_replace('/', '/', $value;?> $value = urlencode($value);?> # $value is now hello%26%2347%3Bworld 

Primeiro eu substituo a barra por entidade html e depois faço a codificação url.

Na minha conta de hospedagem, esse problema foi causado por uma regra do ModSecurity que foi definida para todas as contas automaticamente. Ao relatar esse problema, o administrador removeu rapidamente essa regra da minha conta.

Use um caractere diferente e substitua o lado do servidor de barras

Por exemplo, o Drupal.org usa% 21 (o caractere de marca de excalação!) para representar a barra em um parâmetro de url.

Ambos os links abaixo funcionam:

https://api.drupal.org/api/drupal/includes%21common.inc/7

https://api.drupal.org/api/drupal/includes!common.inc/7

Se você estiver preocupado que o caractere possa colidir com um caractere no parâmetro, use uma combinação de caracteres.

Assim, seu URL seria http: // project_name / browse_by_exam / type / tutor_search / palavra-chave / one_-! Two / new_search / 1 / search_exam / 0 / search_subject / 0

altere-o com js e converta-o de volta para o lado do servidor slash.

Uma solução padrão para esse problema é permitir barras, fazendo com que o parâmetro que pode conter barras reduza o último parâmetro na url.

Para um URL de código de produto, você teria então …

 mysite.com/product/details/PR12345/22 

Por um termo de pesquisa você teria

 http://project/search_exam/0/search_subject/0/keyword/Psychology/Management 

(A palavra chave aqui é Psicologia / Administração)

Não é uma grande quantidade de trabalho processar os primeiros parâmetros “nomeados” e concatenar os restantes como código do produto ou palavra-chave.

Algumas estruturas têm esse recurso integrado em suas definições de roteamento.

Isso não é aplicável ao caso de uso envolvendo dois parâmetros que contêm barras.

é simples para mim usar base64_encode

 $term = base64_encode($term) $url = $youurl.'?term='.$term 

depois de decodificar o termo

 $term = base64_decode($['GET']['term']) 

desta forma codifique o “/” e “\”

Eu uso a function javascript encodeURI () para a parte de URL que tem barras que devem ser vistas como caracteres em vez de endereço http. Por exemplo:

 "/api/activites/" + encodeURI("?categorie=assemblage&nom=Manipulation/Finition") 

veja http://www.w3schools.com/tags/ref_urlencode.asp

Eu resolvi isso usando duas funções personalizadas assim:

 function slash_replace($query){ return str_replace('/','_', $query); } function slash_unreplace($query){ return str_replace('_','/', $query); } 

Então, para codificar eu poderia chamar:

 rawurlencode(slash_replace($param)) 

e decodificar eu poderia chamar

 slash_unreplace(rawurldecode($param); 

Felicidades!

Você pode usar %2F se usá-lo desta maneira:
?param1=value1&param2=value%2Fvalue

mas se você usar /param1=value1/param2=value%2Fvalue isso causará um erro.