Sicherheit Varianten zur Realisierung Umsetzung in JSP
Transcription
Sicherheit Varianten zur Realisierung Umsetzung in JSP
Sicherheit Varianten zur Realisierung Vier Aufgaben • Authentifizierung: Nutzer erkennen; klassisch über Name und Passwort • Autorisierung: Nutzer darf nur bestimmte Aktionen durchführen, klassisch über Rechte‐Rollen‐System • Vertraulichkeit: kein weiterer Nutzer (außer BKA, CIA, ...) darf Informationen mitlesen • Unverfälschtheit: Inhalte werden zwischen Senden und Empfangen nicht verändert • letzten beiden Punkte typischerweise durch Verschlüsselung realisiert Komponentenbasierte Software‐ Entwicklung Prof. Dr. Stephan Kleuker 257 Umsetzung in JSP Komponentenbasierte Software‐ Entwicklung Prof. Dr. Stephan Kleuker 258 Applikationsbeispiel ‐ Überblick (1/2) Deployment Descriptor • Man kann Rollen definieren • Man kann Seiten (Servlet, JSP, HTML) Rollen zuordnen • Man kann Art der Übertragung festlegen Applikationsserver‐spezifisch: • Auswahl eines Informationssystems zur Authentifizierung (Nutzer, Passwort, zugehörige Rollen), z. B. im Server selbst, Datenbank, Anbindung LDAP • Zuordnung der Server‐Rollen zu den Rollen der JSP‐ Applikation (oder Zuordnung von Nutzern zu Rollen der JSP‐ Applikation) Komponentenbasierte Software‐ Entwicklung • direkt von Hand codieren (mit DB‐Anbindung für uns technisch kein Problem; Übertragung aber unsicher mit HHTP) – jeder Methodenaufruf beginnt mit Berechtigungsprüfung • deklarativ – Möglichkeit zur abgetrennten Authentifizierung – Seiten (Servlets, JSPs) können als schützenswert markiert werden (im Deployment Descriptor) – Zugang zu Seiten wird nur Nutzer in bestimmten Rollen gewährleistet • deklarativ (Variante) – Programmcode direkt mit erlaubten Rollen annotieren ([noch] nicht in JSP) Prof. Dr. Stephan Kleuker 259 1. Nutzer wählt Funktionalität 2. Nutzer muss sich authentifizieren 3. Prüfung ob Nutzer erlaubt und ob er benötigte Rechte hat 4a. falls ja, Zugang zur Funktionalität 4b. falls Nutzer unbekannt, ihn über Scheitern informieren 4c. falls Nutzer bekannt und zu wenig Rechte, ihn über fehlende Rechte informieren [oder wie 4b behandeln] • Hinweis: statt freien Zugriff auf Startseite kann auch diese schon geschützt werden • technische Probleme: – Nutzer kann mehrere Seiten für gleiche Applikation nutzen – Nutzer spielt mit „Back“‐Button Komponentenbasierte Software‐ Entwicklung Prof. Dr. Stephan Kleuker 260 Applikationsbeispiel ‐ Überblick (2/2) Architektur ‐ Ablaufplanung • Ansatz: kritische Ressource liegt in (logischen) Unterordner • gesamter Ordner kann später einer Rolle zugeordnet werden • erster Aufruf normal über HTTP Komponentenbasierte Software‐ Entwicklung Prof. Dr. Stephan Kleuker 261 Architektur ‐ Seitenumsetzung Komponentenbasierte Software‐ Entwicklung Prof. Dr. Stephan Kleuker Komponentenbasierte Software‐ Entwicklung Prof. Dr. Stephan Kleuker 262 Code im Detail (1/9) ‐ Servlet mit zugehöriger JSP 263 public class Geheim extends HttpServlet { protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); request.getSession(false).setAttribute("IN", 0); //später RequestDispatcher view = request.getRequestDispatcher("Geheiminfo.jsp"); view.forward(request, response); }... <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Premiuminformation</title> </head> <body> Geld stinkt<br><br> <a href="../index.jsp">zum Start </a> </body> Komponentenbasierte Software‐ Entwicklung Prof. Dr. Stephan Kleuker 264 Code im Detail (2/9) ‐ Servlet in web.xml Code im Detail (3/9) ‐ Rollendefinition in web.xml <servlet> <servlet-name>Geheim</servlet-name> <servlet-class>servlets.Geheim</servlet-class> </servlet> • Beliebig viele angebbar <security-role> <description>Die, die alles dürfen</description> <role-name>Boss</role-name> </security-role> <servlet-mapping> <servlet-name>Geheim</servlet-name> <url-pattern>/Premium/Geheim</url-pattern> </servlet-mapping> • Serverspezifisch (hier sun‐web.xml) direkte Zuordnung von Nutzern (alternativ über Datenbank, LDAP, ...) <security-role-mapping> <role-name>Boss</role-name> <principal-name>edna</principal-name> <principal-name>ella</principal-name> </security-role-mapping> • Entwicklung geschickter logischer Ordnerstruktur ist Architekturaufgabe Komponentenbasierte Software‐ Entwicklung Prof. Dr. Stephan Kleuker 265 Code im Detail (4/9) ‐ Sicherheitsregel in web.xml Prof. Dr. Stephan Kleuker Prof. Dr. Stephan Kleuker 266 Code im Detail (5/9) ‐ Art der Authorisierung <security-constraint> <display-name>Premiumzugriff</display-name <web-resource-collection> <web-resource-name>Premiumseiten</web-resource-name> <description/> Verzeichnisse <url-pattern>/Premium/*</url-pattern> (kommasepariert) <http-method>GET</http-method> HTTP‐Methoden <http-method>POST</http-method> (typisch alle) </web-resource-collection> erlaubte Rollen <auth-constraint> <description/> Art der Übertragung <role-name>Boss</role-name> (unverfälscht, </auth-constraint> vertraulich) <user-data-constraint> <description/> <transport-guarantee>CONFIDENTIAL</transport-guarantee> </user-data-constraint> </security-constraint> Komponentenbasierte Software‐ Entwicklung Komponentenbasierte Software‐ Entwicklung 267 <login-config> <auth-method>FORM</auth-method> <realm-name>file</realm-name> <form-login-config> <form-login-page>/login.html</form-login-page> <form-error-page>/loginError.html</form-error-page> </form-login-config> </login-config> • FORM: Nutzer erstellt eigenes Login‐Fenster (ohne <transport‐guarantee> direkt sichtbar) • BASIC: codiert mit base64 (nicht sehr sicher) • DIGEST: besser verschlüsselt, unterstützt nicht jeder Server • CLIENT‐CERT: Public Key Certificates (vor erstem Login benötigt, typisch für B2B) Komponentenbasierte Software‐ Entwicklung Prof. Dr. Stephan Kleuker 268 Code im Detail (6/9) ‐ Login‐Seite Code im Detail (7/9) ‐ Login‐Fehler‐Seite <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title></title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> </head> <body> <form name="POST" action="j_security_check"> Nutzer:<input type="text" name="j_username" value="" size="15" /><br> Passwort:<input type="text" name="j_password" value="" size="15" /><br> <input type="submit" value="Anmelden" /> </form> muss so heißen </body> </html> <!-- loginError.html --> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>Fehler</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> </head> <body> Passt nicht <br><br> <a href="/Authorisierung/login.html">noch'n Versuch</a> </body> </html> Komponentenbasierte Software‐ Entwicklung Komponentenbasierte Software‐ Entwicklung Prof. Dr. Stephan Kleuker 269 Code im Detail (8/9) ‐ erweiterte Fehlerbehandlung <error-page> <error-code>403</error-code> <location>/fehler.jsp</location> </error-page> <%@page contentType="text/html" pageEncoding="UTF-8" session="false" isErrorPage="true"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Fehler</title> </head> <body> <h3>Interner Fehler</h3> <a href="/Authorisierung/index.jsp">zum Start </a> <% request.getSession().invalidate();%> </body> </html> Prof. Dr. Stephan Kleuker 270 Code im Detail (9/9) ‐ Logout.java • Sonderseite für Nutzer, die sich anmelden dürfen, aber Ressource nicht nutzen dürfen Komponentenbasierte Software‐ Entwicklung Prof. Dr. Stephan Kleuker 271 public class Logout extends HttpServlet { protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); try { if (request.getSession(false) != null) { request.getSession().removeAttribute("IN"); request.getSession().invalidate(); } } finally { RequestDispatcher view = request.getRequestDispatcher("LoggedOut.jsp"); view.forward(request, response); } } <title>Logged Out</title> <body> <a href="index.jsp">zum Start </a> </body> Komponentenbasierte Software‐ Entwicklung Prof. Dr. Stephan Kleuker 272 Code im Detail (10/10) – index.jsp Ablaufmöglichkeiten (1/6) ‐ Klick auf Premium <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <%@page contentType="text/html" pageEncoding="UTF-8"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Start</title> </head> <body> <form name="m" action="Premium/Geheim"> <input type="submit" value="Premium" name="mb" /> </form> <c:if test="${IN!=null}"> <form name="l" action="Logout"> <input type="submit" value="Ausloggen" name="wb" /> </form> </c:if> </body> </html> Komponentenbasierte Software‐ Entwicklung Prof. Dr. Stephan Kleuker 273 Ablaufmöglichkeiten (2/6) ‐ unser Anmeldefenster Komponentenbasierte Software‐ Entwicklung Prof. Dr. Stephan Kleuker 274 Ablaufmöglichkeiten (3/6) ‐ unbekannter Nutzer • Umschaltung auf HTTPS Komponentenbasierte Software‐ Entwicklung Prof. Dr. Stephan Kleuker 275 Komponentenbasierte Software‐ Entwicklung Prof. Dr. Stephan Kleuker 276 Ablaufmöglichkeiten (4/6) ‐ unberechtigter Nutzer Komponentenbasierte Software‐ Entwicklung Prof. Dr. Stephan Kleuker Ablaufmöglichkeiten (5/6) ‐ berechtigter Nutzer 277 Ablaufmöglichkeiten (6/6) ‐ ausgeloggter Nutzer Komponentenbasierte Software‐ Entwicklung Prof. Dr. Stephan Kleuker 278 Sicherer Datenverkehr • Übertragungsart wählen, dann anmelden Komponentenbasierte Software‐ Entwicklung Prof. Dr. Stephan Kleuker 279 Komponentenbasierte Software‐ Entwicklung Prof. Dr. Stephan Kleuker 280 Session‐Kontrolle Projektstruktur • Generell Session mit invalidate() beenden • Um keine kurzzeitige Übernahme oder Rücksprünge mir „Zurück“‐Knopf zu erlauben kann Hilfs‐Session‐Attribut genutzt werden • Beim erfolgreichen Einloggen Attribut setzen • Bei Logout vor invalidate löschen • gepackt als WAR‐Datei • man beachte: Servlet Geheim.class nur logisch dem auch physikalisch vorhandenem Pfad /Premium zugeordnet • Attribut wird im Beispiel auch zur Einblendung des „Abmelden“‐Knopfs genutzt • vorgegebene Struktur noch vereinfachbar, aber skaliert auch für größere Projekte Komponentenbasierte Software‐ Entwicklung Prof. Dr. Stephan Kleuker 281 <auth‐constraint> Komponentenbasierte Software‐ Entwicklung Prof. Dr. Stephan Kleuker 282 Abfrage der Rollen im Servlet • Erlaubnis für bestimmte Rollen • generell nur in Ausnahmen nutzen (Rollen‐Logik aus Programmlogik heraushalten) • Beispiel im Servlet <auth-constraint> <role-name>Admin</role-name> <role-name>Member</role-name> </auth-constraint> String[] rollen= {"Leader","Worker","Hippie","Boss"}; for(int i=0;i<rollen.length;i++) System.out.println(rollen[i] +" : "+request.isUserInRole(rollen[i])); • Erlaubnis für alle; entweder kein Constraint angeben oder <auth-constraint> <role-name>*</role-name> </auth-constraint> • Erlaubnis für niemanden von außerhalb (forward geht!) <auth-constraint/> • Rechte können mehrfach in security‐constraints stehen – <auth-constraint/>: garantiert kein Zugriff – sonst oder‐Verknüpfung (eine Nennung reicht) Komponentenbasierte Software‐ Entwicklung Prof. Dr. Stephan Kleuker 283 Komponentenbasierte Software‐ Entwicklung Prof. Dr. Stephan Kleuker 284 Datenbankanbindung Ansätze • Servlets (und JSP) können einfach JPA nutzen • Grundidee: Container stellt Verbindung zur DB her und übernimmt Transaktionssteuerung (container managed persistence) • (bisher: em.begin() und em.commit(); Nutzer alleine für Transaktionen verantwortlich, user managed persistence) • im Servlet @PersistenceUnit private EntityManagerFactory emf; @Resource private UserTransaction utx; • Container nutzt Dependency Injection – zur Laufzeit wird ein zur angegebenen Schnittstelle passendes Objekt an Programm übergeben – verwandt: Exemplarvariablen haben als Typen Schnittstellen; konkrete Klassen werden mit set... injiziert Komponentenbasierte Software‐ Entwicklung Prof. Dr. Stephan Kleuker 285 Beispielapplikation „klassisch“ (1/7) Prof. Dr. Stephan Kleuker Komponentenbasierte Software‐ Entwicklung Prof. Dr. Stephan Kleuker 286 Beispielapplikation „klassisch“ (2/7) ‐ Modul @Entity public class Modul implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.AUTO) private int id; private int nr; private String name; public Modul(){} public Modul(int nr, String name) { this.nr = nr; this.name = name; } public int getId() { return id;} public void setId(int id) { this.id = id;} public String getName() { return name;} public void setName(String name) { this.name = name;} public int getNr() {return nr;} public void setNr(int nr) { this.nr = nr;} ...} • Verwaltung einer Liste mit Modulen (Nummer und Name) Komponentenbasierte Software‐ Entwicklung • schlechte Idee: EntityManager‐Objekt in einem scope (z. B. session) weitergeben; da Objekt nicht Thread‐sicher • schlechte Idee: JSP nutzt direkt EntityManager‐Objekt; besser: – Servlet rechnet – Servlet legt Ergebnis in request – Servlet leitet an JSP weiter – JSP arbeit Ergebnis aus request ab • gute Idee: Servlet reicht EntityManagerFactory an Persistenz‐Schicht weiter 287 Komponentenbasierte Software‐ Entwicklung Prof. Dr. Stephan Kleuker 288 Beispielapplikation „klassisch“ (3/7) ‐ Start Beispielapplikation „klassisch“ (4/7) ‐ Anzeige.jsp <%-- index.jsp --%> <%@page contentType="text/html" pageEncoding="UTF-8"%> <html> <head></head> <body> <jsp:forward page="Anzeige" /> </body> </html> public class Anzeige extends HttpServlet { protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { List<Modul> module = (List<Modul>) request.getSession().getAttribute("module"); if (module == null) { module = new ArrayList<Modul>(); request.getSession().setAttribute("module", module); } request.getRequestDispatcher("/Anzeige.jsp") .forward(request, response); } Komponentenbasierte Software‐ Entwicklung Prof. Dr. Stephan Kleuker 289 <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <%@page contentType="text/html" pageEncoding="UTF-8"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Module</title> </head> <body> <a href="/JSPJPABeispiel2/Erweiterung/Eintrag.jsp"> Modul hinzufügen</a> <h3>Modulübersicht</h3> <ul> <c:forEach var="m" items="${module}"> <li>${m.nr}: <c:out value="${m.name}"/> </li> </c:forEach> </ul> </body> Komponentenbasierte Software‐ Prof. Dr. 290 </html> Entwicklung Beispielapplikation „klassisch“ (5/7) ‐ Eintrag.jsp Stephan Kleuker Beispielapplikation „klassisch“ (6/7) ‐ Eintragen <%@page contentType="text/html" pageEncoding="UTF-8"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Neues Modul</title> </head> <body> <form name="neu" action="NeuesModul" method="POST"> Modulnummer: <input type="text" name="nr" value="" size="5" /><br> Modulname: <input type="text" name="name" value="" size="20" /><br> <input type="submit" value="Eintragen" /> </form> <a href="../index.jsp">Zurück</a> </body> </html> public class NeuesModul extends HttpServlet { protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); List<Modul> module = (List<Modul>) request.getSession().getAttribute("module"); Modul m = new Modul( Integer.parseInt(request.getParameter("nr")), request.getParameter("name")); module.add(m); request.getRequestDispatcher("/Anzeige.jsp") .forward(request, response); } Komponentenbasierte Software‐ Entwicklung Komponentenbasierte Software‐ Entwicklung Prof. Dr. Stephan Kleuker 291 Prof. Dr. Stephan Kleuker 292 Beispielapplikation „klassisch“ (7/7) ‐ Beispielablauf Komponentenbasierte Software‐ Entwicklung Prof. Dr. Stephan Kleuker Beispielapplikation mit DB (1/6) – Automat 293 Beispielapplikation mit DB (2/6) – Start, Anzeige List<Modul> module = (List<Modul>) request.getSession().getAttribute("module"); if (module == null) { module = new ArrayList<Modul>(); request.getSession().setAttribute("module", module); } Prof. Dr. Stephan Kleuker Prof. Dr. Stephan Kleuker 294 Beispielapplikation mit DB (3/6) – Eintragen 1/2 public class Anzeige extends HttpServlet { @PersistenceUnit private EntityManagerFactory emf; protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { EntityManager em = emf.createEntityManager(); request.setAttribute("module", em .createQuery("select m from Modul m").getResultList()); request.getRequestDispatcher("/Anzeige.jsp") .forward(request, response); } Komponentenbasierte Software‐ Entwicklung Komponentenbasierte Software‐ Entwicklung 295 public class NeuesModul extends HttpServlet { @PersistenceUnit private EntityManagerFactory emf; @Resource private UserTransaction utx; protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); try { utx.begin(); EntityManager em = emf.createEntityManager(); Modul m = new Modul( Integer.parseInt(request.getParameter("nr")), request.getParameter("name")); em.persist(m); utx.commit(); request.getRequestDispatcher("/index.jsp") .forward(request, response); } // nächste Folie catch (RollbackException ex) { Komponentenbasierte Software‐ Entwicklung Prof. Dr. Stephan Kleuker 296 Beispielapplikation mit DB (4/6) – Eintragen 2/2 } catch (RollbackException ex) { Logger.getLogger("NeuesModul".log(Level.SEVERE, } catch (HeuristicMixedException ex) { Logger.getLogger("NeuesModul".log(Level.SEVERE, } catch (HeuristicRollbackException ex) { Logger.getLogger("NeuesModul".log(Level.SEVERE, } catch (SecurityException ex) { Logger.getLogger("NeuesModul".log(Level.SEVERE, } catch (IllegalStateException ex) { Logger.getLogger("NeuesModul".log(Level.SEVERE, } catch (NotSupportedException ex) { Logger.getLogger("NeuesModul".log(Level.SEVERE, } catch (SystemException ex) { Logger.getLogger("NeuesModul".log(Level.SEVERE, } Komponentenbasierte Software‐ Entwicklung Beispielapplikation mit DB (5/6) – Realisierung null, ex); null, ex); null, ex); null, ex); null, ex); null, ex); null, ex); Prof. Dr. Stephan Kleuker 297 Beispielapplikation mit DB (6/6) – persistence.xml • JSPJPA2 ist eine vom Nutzer im Server angemeldete Data Source, die über JNDI gefunden wird <?xml version="1.0" encoding="UTF-8"?> <persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"> <persistence-unit name="JSPJPABeispiel2PU" transaction-type="JTA"> <provider>org.hibernate.ejb.HibernatePersistence</provider> <jta-data-source>JSPJPA2</jta-data-source> <exclude-unlisted-classes>false</exclude-unlisted-classes> <properties> <property name="hibernate.hbm2ddl.auto" value="update"/> </properties> </persistence-unit> </persistence> Komponentenbasierte Software‐ Entwicklung Prof. Dr. Stephan Kleuker 299 Komponentenbasierte Software‐ Entwicklung Prof. Dr. Stephan Kleuker 298