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