Tag Archives: J2EE

J2EE – zabezpečení webové aplikace

Tento příspěvek popisuje, jak zabezpečit webovou aplikaci napsanou na platformě Java a běžící na aplikačním serveru GlassFish. Cílem bude zabránit přístupu na vybrané stránky těm uživatelům, kteří nemají přidělenou potřebnou roli.

1. Vytvoření databáze

  • vytvoříme databázi (v zásadě je jedno, jaký typ DB zvolíme, já použil MySQL)
  • tabulka User (Id: email, FK: Grouptable_email)
  • tabulka Grouptable (Id: email, Varchar: groupid)

2. Nastavení aplikačního serveru

  • otevřeme admin consoli
  • v menu vybereme: Configuration → Security → Realms
  • vytvoříme nový Realm:
    • name: Database
    • classname: com.sun.enterprise.security.auth.realm.jdbc.JDBCRealm
    • další property – viz. obrázek

  • v menu vybereme: Configuration → Security a jako default realm vybereme Database
  • dále vytvoříme connection pool (Resources → JDBC → Connection Pools)
  • vytvoříme JNDI, které nazveme „CeltsMysqlDS“ (Resources → JDBC → JDBC Resources)

    3. Vytvoření a nastavení enterprise aplikace

  • např. v prostředí Netbeans IDE vytvoříme enterprise aplikaci
    • J2EE_security (.ear)
    • J2EE_security-ejb (.jar)
    • J2EE_security-war (.war)
  • nastavíme web.xml
    • nastavíme způsob autentifikace
    • nastavíme logovací a chybovou stránku:

    <login-config>
            <auth-method>FORM</auth-method>
            <form-login-config>
                <form-login-page>/login.jsf</form-login-page>
                <form-error-page>/loginError.jsf</form-error-page>
            </form-login-config>
    </login-config>
    

    • nastavíme seznam uživatelských rolí:

    <security-role>
            <description>READWRITE</description>
            <role-name>READWRITE</role-name>
    </security-role>
    <security-role>
            <description>SUPERWRITE</description>
            <role-name>SUPERWRITE</role-name>
    </security-role>
    <security-role>
            <description>ADMIN</description>
            <role-name>ADMIN</role-name>
    </security-role>
    

    • nastavíme security constraint:

    <security-constraint>
            <display-name>Editation</display-name>
            <web-resource-collection>
                <web-resource-name>edit.jsf</web-resource-name>
                <description/>
                <url-pattern>/edit.jsf</url-pattern>
                <http-method>GET</http-method>
                <http-method>POST</http-method>
                <http-method>HEAD</http-method>
                <http-method>PUT</http-method>
                <http-method>OPTIONS</http-method>
                <http-method>TRACE</http-method>
                <http-method>DELETE</http-method>
            </web-resource-collection>
            <auth-constraint>
                <description>vkládat nesmí uživatel read-only</description>
                <role-name>READWRITE</role-name>
                <role-name>SUPERWRITE</role-name>
                <role-name>ADMIN</role-name>
            </auth-constraint>
            <user-data-constraint>
                <description/>
                <transport-guarantee>NONE</transport-guarantee>
            </user-data-constraint>
    </security-constraint>
    

    • Pokud se bude chtít uživatel dostat na stránku /edit.jsf, bude muset mít jednu z definovaných rolí – tedy buď READWRITE, SUPERWRITE či ADMIN.
    • namapujeme role v konfiguračním souboru sun-web.xml (je nutné ho vytvořit ve stejném adresáři, ve kterém je web.xml):

    <sun-web-app error-url="">
      <context-root>/SecurityGUI</context-root>
      <security-role-mapping>
        <role-name>ADMIN</role-name>
        <group-name>3</group-name>
      </security-role-mapping>
      <security-role-mapping>
        <role-name>READWRITE</role-name>
        <group-name>1</group-name>
      </security-role-mapping>
      <security-role-mapping>
        <role-name>SUPERWRITE</role-name>
        <group-name>2</group-name>
      </security-role-mapping>
      <class-loader delegate="true"/>
      <jsp-config>
        <property name="keepgenerated" value="true">
          <description>Keep a copy of the generated servlet class' java code.</description>
        </property>
      </jsp-config>
    </sun-web-app>
    

    • Pokud tedy bude mít uživatel v tabulce “grouptable” nastavenou hodnotu “groupid” na “1”, přidělí mu aplikace po zalogování roli “READWRITE”.
    • Nyní jsme zprovoznili zabezpečení naší testovací aplikace. J2EE nám samozřejmě také umožní zjistit, jaký klient je právě zalogovaný. Na úrovni webové aplikace to zjišťujeme následujícím způsobem (následující funkce vrátí username zalogovaného uživatele, případně null pro nezalogovaného uživatele):

    public String getLoginName() {
      Principal principal = FacesContext.getCurrentInstance().getExternalContext().getUserPrincipal();
      if (principal == null) {
        return null;
      } else {
        return principal.getName();
      }
    }
    

    • Na úrovni aplikační vrstvy (v EJB), postupujeme takto:
      vytvoříme referenci na context

      @Resource
      SessionContext context;
      

      v mětodě dále:

      Principal principal = context.getCallerPrincipal();
      

    • Chceme-li, aby J2EE zajistilo, že se některá funkce bude spouštět pouze v případě, že má uživatel přiřazenou některou roli, vytvoříme před metodou anotaci @RolesAllowed:

    @RolesAllowed("manager")
    public Country getCountryByIso(String iso) { ... }
    

    • Chceme-li v metodě testovat, zda má uživatel přiřazenou některou roli vytvoříme anotaci @DeclareRoles před třídou:

    @Stateless
    @DeclareRoles({"manager", "manager2"})
    public class CommonDAOBean implements CommonDAOBeanLocal { … }
    

    • poté je možné v metodě použít:

    context.isCallerInRole("manager");
    

    • Pokud bychom na začátku nedeklarovali role, nastala by výjimka.

    Sun Certified Java Programmer

    Tak jsem se zúčastnil mého prvního testu na certifikaci. A protože o tom tady píšu, tak je jasné, že jsem ho i udělal :-) Konkrétně šlo o Sun Certified Programmer for the Java Platform, Standard Edition 6 (CX-310-065).

    Vzhledem k tomu, že jsem nevěděl do čeho jdu, tak jsem se snažil ve chvilkách volného času učit. Pro přípravu je bezvadná, i když často zbytečně podrobná, tato knížka http://www.amazon.com/SCJP-Certified-Programmer-Java-310-065/dp/0071591060/ref=sr_1_1?ie=UTF8&s=books&qid=1269886588&sr=1-1 Na konci každé kapitoly je seznam nejdůležitějších znalostí a hlavně ukázkové příklady.

    Když to teď porovnám s těmi v reálném testu, tak musím říct, že v té knížce mi připadaly mnohem zákeřnější.
    Například nějaký složitější zdrojový kód a vy máte určit, co bude jeho výsledkem. No a odpověď byla, že to nepůjde zkompilovat, protože tam chybí jeden import. Na druhou stranu vás to aspoň vycvičí v pozornosti, což se mi několikrát během ostrého testu hodilo.

    No, abych to uzavřel, velká část otázek mně přišla nesmyslná. Týkaly se totiž toho, co za vás zkontroluje kompilátor. Na druhou stranu, jsem se během studia občas dozvěděl něco nového a také už snad nebudu muset tak často hledat v dokumentaci :-).

    Také je dobré, že se na konci testu dozvíte, jak jste dopadli v jednotlivých oblastech. Detailní popis zkoušených oblastí najdete na této stránce http://in.sun.com/training/catalog/courses/CX-310-065.xml

    Výčtový typ v jazyku Java

    Od verze javy 5.0 jsou k dispozici výčtové typy, které přináší především zvýšení typové bezpečnosti.
    Definice a použití jednoduchého výčtového typu je podobná jako v jazycích C/C++.
    Například:

    enum Color { RED, GREEN, BLUE }
    
    Color color = Color.BLUE;
    //...
    switch (color) {
        case BLUE:
            //do something
            break;
        default:
            //do something
    }
    

    Na rozdíl od C nebo C++ je enum v javě mnohem mocnější. Výše uvedenou definici si lze představovat jako zkratku za

    class Color {
        public static final Color RED   = new Color();
        public static final Color GREEN = new Color();
        public static final Color BLUE  = new Color();
        
        protected Color() {}
    }
    

    Proto je možné definovat uvnitř enumu metody nebo přidávat atributy, což jde vidět v následujícím příkladu.
    Je zde uveden výčtový typ plemen psů. U každého plemene chceme mít uvedenou minimální váhu a výšku v kohoutku.
    Navíc umí každé plemeno psa štěkat. Protože jediný československý vlčák štěká česky, přepíšeme jeho metodu bark.
    Také přepíšeme metodu toString tak, aby se názvy plemen vypisovaly malými písmeny a místo podtržítek byly mezery.

    enum DogTribe {
        GERMAN_SHAPHERD_DOG(61, 30),
        GIANT_SCHNAUZER(65, 32),
        CZECHOSLOVAKIAN_WOLFDOG(65, 26) {
            @Override
            public String bark() {
                return "haf-haf";
            }
        };
    
        public String bark() {
            return "bow-wow";
        }
    
        public int getDogMinHeight() {
            return this.dogMinHeight;
        }
    
        public int getDogMinWeight() {
            return this.dogMinWeight;
        }
    
        @Override
        public String toString() {
            return this.name().toLowerCase().replace('_', ' ');
        }
    
        private DogTribe(int dogMinHeight, int dogMinWeight) {
            this.dogMinHeight = dogMinHeight;
            this.dogMinWeight = dogMinWeight;
        }
    
        private int dogMinHeight; //measured in cm in withers
        private int dogMinWeight; //measured in kg
    }
    
    public class Main {
        public static void main(String[] args) {
            for (DogTribe tribe: DogTribe.values()) {
                System.out.println(tribe);
                System.out.println("\tMinimal height: " + tribe.getDogMinHeight());
                System.out.println("\tMinimal weight: " + tribe.getDogMinWeight());
                System.out.println("\t" + tribe.bark());
            }
        }
    }
    

    Zabezpečený přístup k LDAPu pomocí JNDI.

    V tomto příspěvku je nastíněno, jak lze pracovat s LDAPem v jazyku java. Protože se často přenáší citlivá data je zde ukázáno, jak se připojit přez ssl.

    Předpokládáme, že je na LDAP serveru povolena možnost připojovaní přez protokol LDAPS na portu 636. Navíc klient musí mít ve své keystore uložen certifikát serveru nebo jeho certifikační autority.

    Continue reading