Um servlet que busque uma página/redirecione requisições para outro servidor

4 respostas
M

Boa tarde, galera!

Estou com um “pequeno” problema e gostaria de saber se o que eu quero é possível.

Eu quero criar um servlet que busque uma página de outro servidor e a envie para o usuário como se a página estivesse no meu servidor. Além disso, quando o usuário fizer uma requisição dentro dessa página (enviar um formulário, por exemplo), esse servlet deverá redirecionar essa requisição (POST e GET) para o servidor que forneceu a página e devolver o resultado (uma outra página qualquer) devolta ao usuário.

Eu preciso fazer isso por dois motivos:

  1. Como não posso incluir um código (server-side) na página do outro servidor, preciso autenticar o usuário e determinar se ele pode ou não acessar aquela página através do meu servidor.
  2. O usuário NÃO PODE SABER A URL DA PÁGINA! Pois essa página não possui autenticação e, caso o usuário descubra a url dela, ele poderia repassar essa url para pessoas que, de outra forma, não deveriam ter acesso à ela.

Vocês sabem se isso é possível? Se for, como ficaria a implementação disso? Se não for possível, existe alguma outra alternativa para o problema?

4 Respostas

Ygor

Boa tarde mmatto;

Passei por um problema semelhante;

Eu tinha uma pagina de login em um determinado servidor feito em uma tecnologia, se o usuario fosse aceito seria redirecionado para um outro servidor que estaria utilizando uma outra tecnologia, porém essa pagina deveria estar chumbada, ou seja barra de endereços ocultas e com aparencia de popup;

O unico meio que eu conheço de abrir uma pagina assim é através de javascript:

window.open('','','scrollbars=no,menubar=no,top=0,left=0,resizable=yes,toolbar=no,status=no');

No meu caso eu trabalhei com os oncomplete dos botoes do prime faces que chamava uma função em js; Esse js fazia uma verificação em um campo hidden com um valor boleano que iria vir direto de um manegedBean. Se fosse true, redirecionava, se fosse false exibia o erro;

Foi mais ou menos essa idéia que eu utilizei

M

No Java não teria uma maneira de executar um POST ou GET pra outro servidor e “escrever” o resultado como html?
Eu tenho quase certeza que seja possível, só não descobri uma maneira de fazer isso, ainda.

Nessa sua solução, o usuário não tinha como descobrir a URL? Botão direito e “Propriedades da Página”? Ou através de algum atalho do navegador que permita reabrir a página numa nova janela? Outro problema são os atalhos do navegador, como, por exemplo, CTRL+P. Quando você imprime uma página, a URL dela fica no rodapé da página. Outro problema é que a URL da página fica armazenada no histórico do navegador.

Com certeza deve ter alguma maneira de “camuflar” a página como sendo do seu servidor, e não de outro. Um exemplo são as páginas chamadas de “Proxy anônimo” que muita gente usa no trabalho para burlar o firewall da empresa e acessar o Orkut, por exemplo. As páginas abertas por esses proxys são carregadas como sendo deles mesmo.

Ygor

Boa tarde mmatto;

Agora entendi realmente qual a sua dúvida, infelizmente não vou poder te ajudar muito pq isso ja está além do meu conhecimento hahaha

…mas creio que a solução seja algo do tipo;(abstraindo um pouco)Tu cria um servlet que ira analisar as requisições(verificar se usuario esta logado, se tem permissão ou qualquer coisa que seja necessária) e ira se comunicar com um outro servlet, e a resposta deste segundo servlet sera mostrada para o usuario pelo primeiro servlet.

Não sei qual o suporte que java fornece para esse tipo de tarefa, mas creio que seja possível sim!

M

Consegui fazer alguns progressos!

Criei uma html inicial que possui um formulário com um campo de texto onde o usuário informar a url. Ao enviar esse formulário, o servlet abaixo busca a página usando as classes URL e URLConnection. Então eu uso a biblioteca Jsoup para alterar os atributos HREF e SRC de todos os elementos DOM que estejam como relativo para absoluto (usando como base a url informada pelo usuário). Isso faz com que imagens, scripts e css sejam baixados do servidor certo, e não do meu servidor.

Segue o código-fonte do servlet:

import java.io.IOException;
import java.io.PrintWriter;
import java.net.URL;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;

public class TunelServlet extends HttpServlet {

	private static final long serialVersionUID = -4675061985025674960L;

    @Override
	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    	// Busca a página informada pelo usuário, pegando o html e escrevendo-o
    	// como sendo do meu servidor.
    	carregarPagina(request.getParameter("url"), response);
	}

	private void carregarPagina(String url, HttpServletResponse response) {
		response.setContentType("text/html");
		try {
			URL pagina = new URL(url);
			
			PrintWriter out = response.getWriter();
			
			// Pega o html da página solicitada, fazendo um "parse" para que
			// os elementos DOM possam ser extraídos e acessados.
			Document doc = Jsoup.parse(pagina, 3*1000);
			// Navega por cada elemento DOM da página...
			for (Element e : doc.children()) {
				// Se o elemento possuir os atributos HREF e/ou SRC usando
				// caminhos relativos, esses atributos são alterados para
				// usarem o caminho absoluto.
				relativoParaAbsoluto(e);
			}
			
			// Escreve o html alterado da página solicitada como se
			// fosse uma página do meu servidor.
			out.println(doc.outerHtml());
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	private void relativoParaAbsoluto(Element e) {
		// Se o elemento possuir outros elementos filhos...
		for (Element c : e.children()) {
			// Chama a mesma função para cada um dos elementos filhos.
			relativoParaAbsoluto(c);
		}
		// Se o elementos possuir o atributo HREF, altera o caminho para
		// absoluto.
		if (e.attr("href") != "")
			e.attr("href", e.absUrl("href"));
		// Se o elementos possuir o atributo HREF, altera o caminho para
		// absoluto.
		if (e.attr("src") != "")
			e.attr("src", e.absUrl("src"));
	}
	
}

Ainda falta implementar um forma de redirecionar as requisições de formulários da página carregada para o seu servidor de origem e escrever os resultados como sendo do meu servidor (posso usar o mesmo método usado quando o usuário solicita a página pela primeira vez).

Mas estou com um problema que ainda não sei como resolver:
Eu consegui fazer com que as imagens, scripts externos e css’s externos fossem baixados corretamente pelo browser do usuário (usando a biblioteca Jsoap, como explicado acima). Mas quando os elementos html são criados dinamicamente pelo javascript, eu não consegui alterar os caminhos relativos para absolutos. Acho que o Jsoap não consegue fazer isso. Alguém tem alguma sugestão?

Criado 18 de agosto de 2010
Ultima resposta 20 de ago. de 2010
Respostas 4
Participantes 2