Devel.cz Lupa Měšec Podnikatel Root Zdroják.cz DigiZone Slunečnice Vitalia TopDrive KupDnes Navrcholu NovýTarif Dobrý web Weblogy Woko Jagg Computer.cz SK: MojeLinky

Hlavní navigace

Java na webovém serveru: Komentáře a integrace s Texy

Možnost vkládat komentáře, resp. schopnost přijímat od uživatelů formátovaný text, to je vlastnost, bez které se neobejde skoro žádný web. V dnešním díle přidáme do naší aplikace podporu komentářů a ukážeme si, jak je kontrolovat, aby nám do nich potenciální útočník nemohl podstrčit žádná závadná data, která by narušila naši stránku. Kromě XHTML a prostého textu umožníme čtenářům psát komentáře ještě v jednom formátu – Texy.

Tweetni to Twitter Jaggni to! Jagg Del.icio.us Delicious

Naše aplikace obsahuje (nebo spíš bude obsahovat) databázi hospod a jiných podobných podniků, a tak by bylo dobré, kdyby je návštěvníci mohli komentovat a napsat, jak se jim tam líbilo. Web je postavený na XHTML (nebo HTML) a tak se přímo nabízí tenhle formát použít i pro zadávání komentářů. Někteří uživatelé ho ale neovládají, a tak je dobré jim dát i jinou možnost – psaní v prostém textu (což bude většině lidí stačit) nebo Texy. Texy! je dílo Davida Grudla a slouží k snadnému zápisu formátovaného textu (i když mně osobně přijde přirozenější psát ostré závorky)

Přejdeme rovnou k věci a jako obvykle si stáhneme aktuální zdrojové kódy aplikace z Mercurialu:

$ hg pull
$ hg up "14. díl"

Případně je můžete stáhnout jako bzip2 archiv přes web.

Proces zpracování komentáře

Při odesílání si uživatel může vybrat, v jakém formátu komentář posílá (v další verzi bychom mohli přidat automatickou detekci). Tím se nám proces rozděluje na tři větve – v prostém textu alespoň přidáme na konce řádků <br/>, aby se řádky neslily v jeden nekonečný nepřehledný tok textu (když už si uživatel dal práci a napsal několik odstavců). V případě Texy předáme vstupní text externí službě. A do XHTML pak doplníme odstavce, pokud je uživatel nezadal sám. Pak se cesty opět spojují a komentář odešleme k validaci. Ta je důležitá, aby nám na stránku někdo nevložil škodlivý kód (javascript injection) nebo třeba příliš velké písmo nebo neuzavřenou HTML značku, která by narušila naši stránku.

Napojení na Texy

Jelikož je knihovna Texy napsaná v PHP a my používáme Javu, musíme nějak vyřešit propojení těchto dvou světů. Existuje sice i port Texy do Javy, ale vzhledem k tomu, že chybí formální specifikace Texy, rozhodl jsem se použít originální PHP implementaci. Vytvořil jsem velice jednoduché „API“ – pomocí HTTP POST odešleme prostý text na URL http://nekurak.net/texy/http/ a jako odpověď dostaneme XHTML. Implementace rozhraní na straně Javy:

public class Texy {
    /** TODO: parametrizovatelnost */
    private static final String URL_SLUZBY = "http://nekurak.net/texy/http/";
    private static final Logger log = Logger.getLogger(Texy.class.getSimpleName());
    public String preved(String text) throws TexyVyjimka {
    OutputStreamWriter wr = null;
    BufferedReader rd = null;
    try {
        URL url = new URL(URL_SLUZBY);
        URLConnection spojeni = url.openConnection();
        spojeni.setDoOutput(true);
        /** Odešleme data */
        wr = new OutputStreamWriter(spojeni.getOutputStream());
        wr.write(URLEncoder.encode(text, "UTF-8"));
        wr.flush();
        /** Přijmeme odpověď */
        rd = new BufferedReader(new InputStreamReader(spojeni.getInputStream()));
        StringBuffer vysledek = new StringBuffer();
        String radka;
        while ((radka = rd.readLine()) != null) {
        vysledek.append(radka);
        }
        return vysledek.toString();
    } catch (Exception e) {
        throw new TexyVyjimka("Chyba při zpracovávání textu: " + text, e);
    } finally {
        try {
        wr.close();
        } catch (IOException e) {
        log.log(Level.WARNING, "Selhalo zavírání OutputStreamWriteru", e);
        }
        try {
        rd.close();
        } catch (IOException e) {
        log.log(Level.WARNING, "Selhalo zavírání BufferedReaderu", e);
        }
    }
    }
}

Na straně serveru (PHP) je implementace tohoto rozhraní velice snadná, ale v Javě kvůli ní musíme psát víc kódu než je nutné (ošetřování chyb, řešení nízkoúrovňových operací). Texy funkcionalita je zapouzdřena ve třídě cz.frantovo.nekurak.ext.Texy, takže v budoucnu můžeme snadno přepsat rozhraní na SOAP webové služby či XML-RPC – nebo použít nativní implementaci Texy v Javě (port odkazovaný výše). Případně můžete v komentářích navrhnout, jak byste tuto úlohu řešili pomocí REST API, ale nemyslím si, že by to v tomto případě bylo vhodné.

XML schéma – XSD

Ať už uživatel zadal text pomocí Texy nebo jako prostý text, klíčová je nakonec validace výsledného XHTML.

Pro kontrolu povolených značek (a vůbec formátování) použijeme XML Schéma. Díky tomu nebudeme muset moc programovat a pouze deklarujeme, jaké značky případně atributy jsou povolené. Vytvořené schéma je velmi jednoduché – povoluje jen odstavce, tučné a skloněné písmo a ruční zalomení řádku. Další značky a atributy si můžete podle potřeby přidat do schématu v souboru komentář.xsd. Např. povolit odkazy nebo odrážky.

<?xml version="1.0" encoding="UTF-8" ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:element name="div">
    <xs:complexType>
        <xs:choice minOccurs="1" maxOccurs="unbounded">
        <xs:element name="p">
            <xs:complexType mixed="true">
            <xs:choice minOccurs="0" maxOccurs="unbounded">
                <xs:element name="em" type="xs:string"/>
                <xs:element name="strong" type="xs:string"/>
                <xs:element name="br"/>
            </xs:choice>
            </xs:complexType>
        </xs:element>
        </xs:choice>
    </xs:complexType>
    </xs:element>
</xs:schema>

Jelikož každé XML musí mít kořenový element, použili jsme <div/>. Mohli bychom si vymyslet i vlastní kořenovou značku a vůbec celý formát, ale podobnost s XHTML se nám hodí – uživatelé se nemusí učit novou syntaxi a my nemusíme dělat další konverzi při vypisování na stránku.

Podpora XSD v Netbeans

V Netbeans existuje pěkný plugin pro vizuální návrh XML schématu. Ve výchozí instalaci ho pravděpodobně nemáte dostupný, ale dá se to snadno napravit – stačí si přidat vývojářské úložiště zásuvných modulů  – jeho URL je:

http://updates.netbeans.org/netbeans/updates/6.8/uc/m1/dev/catalog.xml.gz

a doinstalovat si „XML Schema and WSDL“.

Validace v Javě

Kód, který se stará o kontrolu XML oproti schématu se nachází v metodě zkontroluj() třídy Komentare (v modulu nekurak.net-lib).

public static Document zkontroluj(String komentar) throws KomentarovaVyjimka {
    try {
    URL soubor = Komentare.class.getClassLoader().getResource("cz/frantovo/nekurak/util/komentář.xsd");
    SchemaFactory tovarnaSchemat = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
    Schema schema = tovarnaSchemat.newSchema(soubor);
    DocumentBuilderFactory tovarnaDB = DocumentBuilderFactory.newInstance();
    tovarnaDB.setSchema(schema);
    DocumentBuilder db = tovarnaDB.newDocumentBuilder();
    db.setErrorHandler(new ErrorHandler() {
        public void warning(SAXParseException e) throws SAXException {
        throw e;
        }
        public void error(SAXParseException e) throws SAXException {
        throw e;
        }
        public void fatalError(SAXParseException e) throws SAXException {
        throw e;
        }
    });
    Document dokument = db.parse(new ByteArrayInputStream(komentar.getBytes("UTF-8")));
    return dokument;
    } catch (Exception e) {
    throw new KomentarovaVyjimka("Neplatný komentář: " + komentar, e);
    }
}

Pomocí vlastního ErrorHandleru můžeme zjistit, v čem přesně dokument nevyhovuje a sdělit to uživali, aby věděl, co má opravit. V případě platného XML vrací metoda zkontroluj() DOM (který zatím k ničemu nevyužíváme) a v případě chyby vyhazuje výjimku – ta v sobě obsahuje informaci, které elementy jsou chybné, ale v ne příliš čitelné podobě.

Validace v Linuxu

Správnost XML dokumentů si můžeme kontrolovat i bez Javy a nějakých složitých IDE, stačí nám k tomu příkazová řádka a nástroj xmllint. V linuxových distribucích jako je Debian nebo Ubuntu si ho nainstalujeme pomocí:

$ aptitude install libxml2-utils

A kontrolu provádíme jednoduše příkazem:

xmllint --schema komentář.xsd komentář.xml

Pokud jsme nikde neudělali chybu, program nám odpoví výpisem XML souboru a hláškou komentář.xml validates. To se nám může hodit pro různé ladění nebo dávkové testování XML dokumentů na disku.

Validace při výstupu v JSP

Tak, jak jsme aplikaci vytvořili, teď závisí její bezpečnost na kvalitě dat v databázi. Pokud zajistíme, že se do ní bude zapisovat jen přes aplikaci (tzn. zkontrolované komentáře) nebo že do ní nikdo nezanese ručně chyby, můžeme aplikaci nechat tak, jak je. Pokud ale chceme vyšší bezpečnost, je lepší kontrolovat validitu komentářů i při jejich vypisování a nespoléhat se na kvalitu dat v databázi.

K tomu můžeme použít vlastní JSTL funkci nkfn:zkontrolujKomentar(). Pomocí tohoto kódu vypíšeme platné komentáře s formátováním a neplatné bez něj – escapované:

<c:out value="${k.komentar}" escapeXml="${!nkfn:zkontrolujKomentar(k.komentar)}" />

Další možností je, nevypsat chybné komentáře vůbec a zobrazit místo nich hlášku. Tento kód najdete v mercurialu v historii verzí souboru komentareVypis.tag. Jestli kontrolovat data jen na vstupu nebo i na výstupu, je z velké části kompromis mezi bezpečností a výkonem. S nastavením můžete experimentovat a vyzkoušet si, jestli se zapnutá validace vůbec na výkonu nějak viditelně projeví.

Závěr

Dnes jme do naší aplikace doplnili podporu komentářů a ukázali jsme si ještě jeden způsob, jak lze provázat aplikace – byť ne tak sofistikovaný jako webové služby, REST nebo jiné standardnější postupy. Také jsme nakousli téma XML a jeho validace v Javě. Jen připomínám, že aplikaci si můžete vyzkoušet na adrese nekuřák.net a jméno a heslo je: zdrojak.root.cz/hes­lo – pokud si nechcete zakládat vlastní účet.

Odkazy

  • Texy! – PHP knihovna pro snadné formátování textu.
  • JTexy – její port do jazyka Java.
  • XML schémata  – stránka Jiřího Koska o XML schématech.
  • Libxml2 – XML parser a sada nástrojů napsaná v C.
  • Relax NG – další způsob definice XML dokumentů.
  • Schematron  – totéž, ale trochu jinak.

František Kučera

Franta Kučera působí jako Java vývojář na volné noze. Programování je jeho koníčkem už od dětství. Kromě toho má rád Linux, relační SŘBD a XML.

Školení Google Analytics pro pokročilé

DW - Školení Google Analytics
  • Jak využít nové funkce Google Analytics
  • Vyhodnocování kampaní díky používání Multichannel funnels
  • Kde návštěvníci vašeho webu utíkají z objednávacího procesu.
  • Nebudete opakovat časté chyby při vyhodnocování dat o návštěvnosti.

Detailní informace o školení Google Analytics pro pokročilé »

Přehled názorů

PHP interface
Harvie .cz 9. 6. 2010 01:43
Nový
├ 
Re: PHP interface
tom 9. 6. 2010 09:36
Nový
└ 
Re: PHP interface
Franta Kučera 9. 6. 2010 15:48
Nový
 
├ 
Re: PHP interface
Franta Kučera 10. 6. 2010 14:50
Nový
 
└ 
Texy Quercus
snowracer 2. 8. 2010 16:42
Nový
java na web
lolek 9. 6. 2010 11:31
Nový
├ 
Re: java na web
jehovista 9. 6. 2010 11:35
Nový
│
└ 
Re: java na web
jerzy.burzek 9. 6. 2010 13:09
Nový
│
 
└ 
Re: java na web
Flasi 9. 6. 2010 14:08
Nový
│
 
 
├ 
Re: java na web
lolek 9. 6. 2010 14:52
Nový
│
 
 
│
└ 
Re: java na web
jehovista 9. 6. 2010 22:24
Nový
│
 
 
│
 
└ 
Re: java na web
Radek Miček 9. 6. 2010 23:28
Nový
│
 
 
│
 
 
└ 
Re: java na web
blizzboz 11. 6. 2010 01:48
Nový
│
 
 
└ 
Re: java na web
x 9. 6. 2010 19:09
Nový
│
 
 
 
├ 
Re: java na web
Přezdívka 9. 6. 2010 20:44
Nový
│
 
 
 
├ 
Re: java na web
Palo 9. 6. 2010 23:59
Nový
│
 
 
 
└ 
Větších webů v Javě...
Ondra 18. 6. 2010 04:13
Nový
└ 
Re: java na web
Radek Miček 9. 6. 2010 18:26
Nový
 
└ 
Re: java na web
dívka 9. 6. 2010 20:47
Nový
 
 
└ 
Re: java na web
Radek Miček 9. 6. 2010 23:12
Nový
 
 
 
└ 
Re: java na web
Franta Kučera 9. 6. 2010 23:21
Nový
 
 
 
 
└ 
Re: java na web
Radek Miček 9. 6. 2010 23:29
Nový
 
 
 
 
 
└ 
Re: java na web
Franta Kučera 10. 6. 2010 00:03
Nový
 
 
 
 
 
 
└ 
Re: java na web
Ondra Satai Nekola 16. 6. 2010 12:41
Nový
Prosba
KapitánRUM 9. 6. 2010 16:07
Nový
└ 
Re: Prosba
KapitánRUM 9. 6. 2010 16:08
Nový
chybí syntax coloring
lopata 9. 6. 2010 16:59
Nový
└ 
Re: chybí syntax coloring
Martin Malý 9. 6. 2010 17:02
Nový
JTexy je ve vývoji...
Ondra 16. 6. 2010 17:19
Nový
       

Tento text je již více než dva měsíce starý. Chcete-li na něj reagovat v diskusi, pravděpodobně vám již nikdo neodpoví. Pro řešení aktuálních problémů doporučujeme využít naše diskusní fórum.

Zasílat nově přidané příspěvky e-mailem