Usando um caractere de barra nos URLs do Spring

Usando um caractere de barra nos URLs do Spring

1. Introdução

Quando desenvolvemos serviços da web,we may need to deal with complex or unexpected URL paths that can contain slashes. Como conseqüência, podemos encontrar problemas com os servidores ou estruturas da web que estamos usando.

O Spring especificamente pode ser um pouco complicado a esse respeito, devido às configurações padrão que ele fornece.

Neste tutorial,we’ll show some common solutions and recommendations for handling URLs with slashes in Spring. Também veremos por que não devemos usar alguns hacks comuns para contornar esses problemas. Continue lendo para saber mais sobre isso!

2. Analise a solicitação manualmente

Em nossos serviços da Web, às vezes precisamos mapear todas as solicitações sob um determinado caminho para o mesmo terminal. Para piorar a situação, talvez não saibamos como será o restante do caminho. Talvez também seja necessário receber esse caminho como parâmetro para usá-lo posteriormente.

Digamos que possamos receber solicitações com qualquer caminho em/mypaths:

http://localhost:8080/mypaths/any/custom/path

E suponha que queiramos armazenar todos esses caminhos diferentes em um banco de dados para saber quais solicitações estamos recebendo.

A primeira solução que provavelmente virá à nossa mente é capturar a parte dinâmica do caminho emPathVariable:

@GetMapping("mypaths/{anything}")
public String pathVariable(@PathVariable("anything") String anything) {
    return anything;
}

Infelizmente, logo descobrimos quethis returns a 404 if the PathVariable contains a slash. O caractere de barra é o delimitador de caminhoURI standard, e tudo o que vem depois dele conta como um novo nível na hierarquia de caminho. Como esperado, o Spring segue esse padrão.

Podemos facilmentesolve this by creating a fallback for all the requests under a certain path by using the * curinga *:

@GetMapping("all/**")
public String allDirectories(HttpServletRequest request) {
    return request.getRequestURI()
        .split(request.getContextPath() + "/all/")[1];
}

Em seguida, temos que analisar o URI nós mesmos para obter a parte do caminho em que estamos interessados.

This solution is very convenient when working with URL-like parameters, mas como veremos na próxima seção, não é suficiente para alguns outros casos.

3. Use parâmetros de consulta

Em contraste com nosso exemplo anterior, há outros casos em que não estamos apenas mapeando caminhos diferentes, mas recebendoString como um parâmetro no URL.

Vamos imaginar que em nosso exemplo anterior, fazemosa request with a path parameter that contains consecutive slashes:

http://localhost:8080/all/http://myurl.com

A princípio, poderíamos pensar que isso deveria funcionar, mas logo percebemos que nosso controlador retornahttp:/myurl.com.. Isso acontece porqueSpring Security normalizes the URLs and replaces any double-slash with a single one.

O Spring também normaliza outras seqüências em URLs, como percursos de caminho. Ele toma essas precauçõesto prevent malicious URLs from bypassing the defined security constraints, conforme explicado emofficial Spring Security documentation.

Nesses casos, é altamente recomendável usar parâmetros de consulta em seu lugar:

@GetMapping("all")
public String queryParameter(@RequestParam("param") String param) {
    return param;
}

Desta forma, podemos receber qualquer parâmetroString sem essas restrições de segurança, e nosso serviço web ficará mais robusto e seguro.

4. Evitar soluções alternativas

As soluções que apresentamos podem implicar em algumas mudanças no design de nossos mapeamentos. Isso pode nos levar a usar algumas soluções comuns para fazer com que nossos pontos de extremidade originais funcionem ao receber barras nos URLs.

A solução mais comum é provavelmente codificar as barras nos parâmetros do caminho. No entanto,some security vulnerabilities were reported in the past and most web and application servers reacted to it by disallowing the encoded slashes by default. Ainda é possível alterar esse comportamento apenas alterando a configuração correspondente, como emTomcat.

Outros, comoApache Server, foram um pouco mais longe e introduziram uma opção para permitir barras codificadas sem decodificá-las, de forma que não sejam interpretadas como delimitadores de caminho. Em qualquer caso,this is not recommended and it can introduce potential security risks.

Por outro lado, os frameworks da web também tomam algumas precauções. Como vimos antes,Spring adds some mechanisms as protection against less strict servlet containers. Portanto, caso permitamos barras invertidas em nosso servidor, ainda precisamos permiti-las no Spring.

Por fim, existem outros tipos de soluções alternativas, como alterar a normalização de URI que o Spring fornece por padrão. Como antes, devemos ser muito cautelosos se alterarmos esses padrões.

5. Conclusão

Neste breve artigo, mostramos algumas soluções para lidar com barras em URLs no Spring. Também introduzimos alguns problemas de segurança que podem surgir se alterarmos as configurações padrão de servidores ou estruturas como Spring.

Como regra geral, os parâmetros de consulta geralmente são a melhor solução para lidar com barras em URLs.

Como sempre, o código-fonte completo dos exemplos está disponívelover on GitHub.