Cactus – testovanie servlet filtrov

8. června 2004

V tomto článku, venovanom testovaciemu frameworku Cactus, budeme pokračovať v testovaní funkčnosti servlet filtrov. Pôjde o servlet, ktorého jedinou úlohou je overiť, či klient je autentifikovaný. Preto dnes využijeme vedomosti, ktoré sme nadobudli v predchádzajúcom článku a ďalej si ich rozšírime.

Testovať správne fungovanie filtrov môžeme v dvoch rovinách. Môžeme testovať správnu funkčnosť vnútorných metód filtra ako takého. Avšak v princípe sa tento spôsob nelíši od testovania funkčnosti servletov, preto sa mu nemusíme venovať. Pri filtroch, ktoré sú primárne súčasťou „reťaze“ nás môže zaujímať, či filter nespôsobí jej prerušenie. Za týmto účelom sa používa nový typ test case-u s názvom FilterTestCase, ktorým otestujeme túto potenciálnu možnosť. Budeme tiež potrebovať triedu, ktorou nasimulujeme fungovanie dvojice filter-servlet.

Filtre boli prvýkrát predstavené s verziou Java Servlets 2.3 a ich bežnou úlohou je predspracovanie užívateľskej požiadavky, alebo následné spracovanie odpovede zaslanej servletom. Filtre fungujú ako určitý prostredník v tom, že môžu byť použité pred alebo po tom, čo je zavolaný servlet samotný. Často sa využívajú na zabezpečenie aplikácie, na autentifikáciu užívateľa, na pridanie rôznych ďalších informácií k požiadavke a podobne.

Na začiatok si vytvoríme servlet filter, ktorý ma za úlohu overiť, či užívateľ je autentifikovaný. V prípade že nie je, bude automaticky presmerovaný na prihlasovaciu stránku. Nasleduje výpis kódu filtra SecurityFilter.

SecurityFilter.java:

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.security.Principal;
public class SecurityFilter implements Filter {
 public void init(FilterConfig config) { }
 public void doFilter(ServletRequest req,
                      ServletResponse res,
                      FilterChain chain)
                  throws IOException, ServletException {
  Principal principal = (
             (HttpServletRequest) req).getUserPrincipal();
  if (principal == null) {
   req.setAttribute(„errorMessage“,“Nie ste prihlásený!“);
   req.getRequestDispatcher(„/login.jsp“).forward(req,res);
  } else {
   // toto je inštancia pomocnej triedy MyFilterChain
   chain.doFilter(req,res);
  }
 }
 public void destroy() { }
}

Ako vidíte, filter je veľmi jednoduchý. Na začiatku si zistíme, či objekt triedy java.security.Principal nie je null. Ak je, ide o neautentifikovaného klienta a v tom prípade ho presmerujeme na login stránku spolu s príslušnými parametrami. Ak je prihlásený, pokračujeme vo vykonávaní filtra. Teraz napíšeme Cactus test case, ktorý obsahuje dva testy. Prvý test overí, či v prípade, ak je klient autentifikovaný, sa filter úspešne vykoná a reťaz pokračuje ďalej. Druhý test overí presný opak. Ak užívateľ nie je autentifikovaný, reťaz sa preruší a požiadavka nebude predaná servletu, prípadne ďalšiemu článku v reťazi.

TestSecurityFilter.java:

import org.apache.cactus.FilterTestCase;
import org.apache.cactus.WebRequest;
import org.apache.cactus.client.authentication.*;
public class TestSecurityFilter extends FilterTestCase {
 private SecurityFilter filter;
 private MyFilterChain myChain;
 public TestSecurityFilter(String name) {
  super(name);
 }
 public void setUp() {
  this.filter = new SecurityFilter();
  this.myChain = new MyFilterChain();
 }
 // nastavíme BASIC autentifikáciu
 public void beginAuthenticatedUser(WebRequest webRequest) {
  webRequest.setRedirectorName(„SecureFilterRedirector“);
  webRequest.setAuthentication(
               new BasicAuthentication(„user“,“pwd“));
 }
 // otestujeme situáciu, keď klient je autentifikovaný
 public void testAuthenticatedUser() throws Exception {
  this.myChain.setExpectedInvocation(true);
  this.filter.doFilter(
                 this.request,this.response,this.myChain);
  this.myChain.verify();
 }
 // otestujeme situáciu, keď klient nie je autentifikovaný
 public void testNonAuthenticatedUser() throws Exception {
  this.myChain.setExpectedInvocation(false);
  this.filter.doFilter(
                 this.request,this.response,this.myChain);
  this.myChain.verify();
 }
}

Ako si môžete všimnúť tento filter test case je založený na využívaní pomocnej triedy MyFilterChain, ktorej úlohou je overiť, či vykonávanie filtra bude pokračovať alebo bude prerušené v závislosti od toho, či je klient autentifikovaný. Na tento účel obsahuje dve testovacie metódy testAuthenticatedUser() a testNonAuthenticatedUser(). V obidvoch metódach ako prvé zavoláme metódu setExpectedInvocation(), čím nastavíme logický prepínač v triede MyFilterChain a tým ovplyvníme priebeh metódy verify(). Nasleduje volanie metódy doFilter(), ktorej predáme potrebné parametre a metódy verify(), ktorá overí výsledky testu. Nasleduje výpis triedy MyFilterChain.

MyFilterChain.java:

import junit.framework.Assert;
import javax.servlet.*;
import java.io.IOException;
 public class MyFilterChain implements FilterChain {
 private boolean shouldBeInvoked;
 private boolean wasInvoked;
 public void doFilter(
                     ServletRequest req, ServletResponse res)
                 throws IOException, ServletException {
  this.wasInvoked = true;
 }
 // rozhodovací ukazovateľ
 public void setExpectedInvocation(boolean shouldBeInvoked) {
  this.shouldBeInvoked = shouldBeInvoked;
 }
 // overovacia metóda
 public void verify() {
  if (this.shouldBeInvoked) {
   Assert.assertTrue(„SecurityFilter was done.“,
                                            this.wasInvoked);
  } else {
   Assert.assertFalse(„SecurityFilter was break.“,
                                            this.wasInvoked);
  }
 }
}

Výsledok našich testov bude nasledovný:

Výsledok testov

V minulom článku sme načrtli spôsob, ako nakonfigurovať prostredie, v ktorom chceme realizovať testy využívajúce autentifikáciu užívateľa. Povedali sme si, že v prípade serveru Tomcat je nutné editovať minimálne súbor web.xml príslušnej testovanej aplikácie. Aby sme túto tému dokončili, uvádzam kompletný výpis deskriptora aplikácie, ktorý zabezpečí funkčnosť nášho testu:

<web-app>
 <filter>
  <filter-name>FilterRedirector</filter-name>
  <filter-class>
   org.apache.cactus.server.FilterTestRedirector
  </filter-class>
 </filter>
 <filter-mapping>
  <filter-name>FilterRedirector</filter-name>
  <url-pattern>/FilterRedirector</url-pattern>
 </filter-mapping>
 <filter>
  <filter-name>SecureFilterRedirector</filter-name>
  <filter-class>
   org.apache.cactus.server.FilterTestRedirector
  </filter-class>
 </filter>
 <filter-mapping>
  <filter-name>SecureFilterRedirector</filter-name>
  <url-pattern>/SecureFilterRedirector</url-pattern>
 </filter-mapping>
 <security-constraint>
  <web-resource-collection>
   <web-resource-name>FilterTest</web-resource-name>
   <url-pattern>/SecureFilterRedirector</url-pattern>
   <http-method>POST</http-method>
   <http-method>GET</http-method>
  </web-resource-collection>
  <auth-constraint>
   <role-name>filter</role-name>
  </auth-constraint>
 </security-constraint>
 <login-config>
  <auth-method>BASIC</auth-method>
 </login-config>
 <security-role>
  <role-name>filter</role-name>
 </security-role>
 <servlet>
  <servlet-name>ServletTestRunner</servlet-name>
  <servlet-class>
   org.apache.cactus.server.runner.ServletTestRunner
  </servlet-class>
 </servlet>
 <servlet>
  <servlet-name>ServletRedirector</servlet-name>
  <servlet-class>
   org.apache.cactus.server.ServletTestRedirector
  </servlet-class>
 </servlet>
 <servlet-mapping>
  <servlet-name>ServletTestRunner</servlet-name>
  <url-pattern>/str</url-pattern>
 </servlet-mapping>
 <servlet-mapping>
  <servlet-name>ServletRedirector</servlet-name>
  <url-pattern>/ServletRedirector</url-pattern>
 </servlet-mapping>
</web-app>

V prípade, že v konfiguračnom súbore tomcat-users.xml nie je vytvorený požadovaný užívateľ a jeho rola, je nutné editovať aj tento súbor. Všetky potrebné súbory vrátane deskriptora aplikácie vám ponúkam na stiahnutie.

Starší komentáře ke článku

Pokud máte zájem o starší komentáře k tomuto článku, naleznete je zde.

Štítky: Články

Mohlo by vás také zajímat

Nejnovější

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *