JSPWiki logo
Strona główna
Zbieranina
Serwisy
Porady
Projekty
Humor sektora IT
TODO
Nowości
Ostatnie zmiany
Kontakt

Find pages
Unused pages
Undefined pages
Page Index

Set your name in
UserPreferences

Edit this page


Referenced by
Projekty




JSPWiki v2.2.33


Google_jsessionid


Google oraz inne wyszukiwarki i linki z jsessionid

Wprowadzenie

Każy wie co to jest sesja w aplikacji webowej. Jedyne co klient wie o sesji to jest jej identyfikator. Jest on zwykle przechowywany w cookie o nazwie jsessionid. W przypadku gdy klient nie obsługuje cookie kontener serwletów przepisuje odpowiednio generowane adresy stron dodając do linków ciąg znaków ;jsessionid=......

Oczywiście kontener nie przepisuje tych adresów sam z siebie. Służy do tego odpowiednia metoda encodeURL. Wywoływana jest ona choćby przez tagi <c:url> biblioteki JSTL czy tagi <html:...> biblioteki Struts.

Problem pojawia się wtedy gdy roboty sieciowe indeksują nasz serwis. Zwykle nie obsługują one cookies, więc aplikacja 'jak głupia' za każdym razem tworzy nową sesję i generuje nowe linki z doklejonymi identyfikatorami nowych sesji. Koszt tworzenie nowych sesji dla każdego requestu można pominąć, robot na tyle żadko odwiedza kolejne strony, że nie jest to problem. Prawdziwy problem jest ze zwielokrotnionymi linkami do stron: wiele razy indeksowane są te same strony, każda z innym id sesji. Co w przypadku np. Googla może skutkować obniżaniem rankingu strony.

Dla przykładu, rezultat z Googla: strony zindeksowanych wraz z id sesji.

Rozwiązanie

Rozwiązanie jest śmiesznie proste. Otóż w filtrze podmieniamy obiekt ServletResponse na własny z odpowiednią implementacją metody encodeURL(). Efekt jest taki, że aplikacja pracuje tak jak dawniej, tylko linki nie są kodowane.

Kod całego filtra wygląda więc następująco:

package org.rydzewski.common.filters.encode;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;

public class EncodeFilter implements Filter {

	public void init(FilterConfig arg0) throws ServletException {
	}

	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
		ServletResponse myResponse = new HttpServletResponseWrapper((HttpServletResponse) response) {
			public String encodeUrl(String url) {
				return url;
			}
			public String encodeURL(String url) {
				return url;
			}
			public String encodeRedirectUrl(String url) {
				return url;
			}
			public String encodeRedirectURL(String url) {
				return url;
			}
		};
		
		chain.doFilter(request, myResponse);
	}

	public void destroy() {
	}

}

Ulepszone rozwiązanie

Przedstawię tutaj najlepsze wg mnie rozwiązanie. Najlepsze z kilku powodów:

  • nie musimy zmieniać nic w kodzie aplikacji (dodajemy tylko jeden wpis do pliku web.xml),
  • jest wydajne (inne rozwiązania np. parsują generowany kod HTML i usuwają z niego ciągi znaków jsessionid),
  • mamy kontrolę którym użytkownikom (przeglądarkom) nie wysłamy linków z jseessionid (poprzez sprawdzanie nagłówka User-Agent),
  • użytkownicy z wyłączoną obsługą cookies nadal mogą pracować z aplikacją (pod warunkiem że ich przeglądarka nie jest zablokowana).

Kod filtra jest generalnie analogiczny do tego przedstawionego wyżej, sprawdzany jest jednak nagłówek User-Agent i jeśli podmiana obiektu HttpServletResponse ma miejsce tylko wtedy jeśli pasuje on do nagłówków uznanych za nagłówki robotów sieciowych.

Filtr włączamy w pliku web.xml w następujący sposób:

	<filter>
		<filter-name>EncodeURLFilter</filter-name>
		<filter-class>org.rydzewski.common.filters.encode.BlockEncodeURLFilter</filter-class>
		<init-param>
			<param-name>disableRobots</param-name>
			<param-value>true</param-value>
		</init-param>
		<!--
		<init-param>
			<param-name>robotsRegex</param-name>
			<param-value>^.*google.*$</param-value>
		</init-param>
		-->
	</filter>
	<filter-mapping>
		<filter-name>EncodeURLFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

Powyższa konfiguracja włączy filtr dla wszystkich requestów oraz będzie reagować na nagłówki User-Agent robotów sieciowych.

Lista robotów sieciowych jest zdefiniowana następująco:

	/** lista nagłówków User-Agent którymi identyfikują się znane roboty sieciowe */
	private static String[] robots = { 
		"ia_archive", 	// Alexa
		"scooter",		// AltaVista
		"Ask Jeeves",	// Ask Jeeves
		"Googlebot",	// Google
		"msnbot",		// MSN
		"Szukacz",		// Szukacz
		"OnetSzukaj",	// Onet Szukaj
		"holmes",		// holmes/onet
		"Mediapartners-Google"	// google adsense
	};

Widać tam również zakomentowany parametr robotsRegex. Za jego pomocą można skonfigurować filtr do pracy z podanym wyrażeniem regularnym zamiast z wyrażeniem budowanym na podstawie domyślnej listy.

Dokumentacja

JavaDOC

Kod źródłowy

Moduł BlockEncodeURLFilter w repozytorium CVS

Attachments:



Go to top   Edit this page   More info...   Attach file...
This page last changed on 14-Mar-2007 09:51:22 GMT by mikolajr.