# <security-constraint> Probleme



## freez (5. Feb 2009)

Hallo,

ich würde gern alle JSF Seiten unter /user/ nur berechtigten Personen zukommen lassen. Nun kann ich das schön mit den Realms unter Tomcat 6 lösen. Die Datenbank wäre auch schon dafür vorbereitet. Also ich hätte einen JDBC Realm und alle Seiten unter /user/* wären nur per login Seite erreichbar.

Nun habe ich 3 Probleme mit dieser Geschichte:
1. Wenn ich eine Seite unter /user/* aufrufe komme ich automatisch auf die login Seite. Aber ich möchte auf der Startseite (/index.faces) dieses Login Formular anbieten. Aber wenn ich mich da anmelde (ohne eine Seite unter /user/ aufgerufen zu haben), habe ich keine Möglichkeit gefunden um auf /user/index.faces umzuleiten.

2. Ich benötige den Usernamen in meinen Beans, um userabhängige Daten in der Datenbank abzulegen. Wie komme ich an den angemeldeten Usernamen?

3. Ich möchte bei Registrierung eines Users sein Passwort "versalzen" und als MD5 Hash ablegen. Nun kann ich problemlos diesen User mit dem versalzenen Password anlegen, aber wie mache ich es dem Realm klar, dass er zu dem eingegebenen Passwort das Salz anhängen muss um sauber zu authentisieren?

Ich habe nun auch eine Idee, wie ich es lösen könnte. Nämlich ohne Realm. Ich mache die Überprüfung der Usernamen und Password in einer Bean und leite auf /user/index.faces bzw /error.faces per navigation rule weiter. Dann wäre das Problem mit dem Salz und dem Usernamen in der Bean gelöst. Nur wie mache ich dem Tomcat klar, dass dieser User nun die Seiten unter /user/ sehen darf?

Vielleicht hat ja jemand auch eine ganz andere Idee.


----------



## freez (6. Feb 2009)

So, zu dem Usernamen innerhalb der Bean habe ich was gefunden:


```
FacesContext fc = FacesContext.getCurrentInstance();
HttpServletRequest req = (HttpServletRequest) fc.getExternalContext().getRequest();
String userName = req.getUserPrincipal().getName();
```

Den Codeschnipsel habe ich noch nicht getestet, deswegen ohne Gewähr.

Punkt 1 und 3 sind noch offen.

Muss ich vielleicht einen eigenen Realm erstellen? Kann ich von einem Realm bei erfolgreicher Authentisierung auch auf eine Seite weiterleiten?


----------



## freez (6. Feb 2009)

OK, ich glaube, ich habe eine mögliche Lösung ohne großen Aufwand geschaffen:

Also, eine genz normale Konfiguration über <security-constraint>:

```
<security-constraint>
		<web-resource-collection>
			<web-resource-name>user</web-resource-name>
			<url-pattern>/user/*</url-pattern>
		</web-resource-collection>
		<auth-constraint>
			<role-name>customer</role-name>
		</auth-constraint>
	</security-constraint>
	<login-config>
	<auth-method>FORM</auth-method>
	<form-login-config>
			<form-login-page>/login.html</form-login-page>
			<form-error-page>/error.html</form-error-page>
		</form-login-config>
	</login-config>
	<security-role>
		<role-name>customer</role-name>
	</security-role>
	<security-role>
		<role-name>deaktiviert</role-name>
	</security-role>
```

ich habe eine Session Bean die mir die Login Informationen speichert:


```
public class LoginBean {
	private String userName = "";
	private String password = "";
	private String saltedPassword = "";
	public String getUserName() {
		return userName;
	}
	public void setUserName(String userName) {
		this.userName = userName;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public String getSaltedPassword() {
		this.saltedPassword = userName + password;
		return saltedPassword;
	}
	public void setSaltedPassword(String saltedPassword) {
		this.saltedPassword = saltedPassword;
	}
}
```

in der index.faces habe ich folgendes Formular, welches die LoginBean betankt:

```
<a4j:form styleClass="formTable">
							<table class="loginTable" cellpadding="0" cellspacing="3">
								<tr>
									<td class="bezeichnung">
										E-Mail Adresse:
									</td>
									<td>
										<h:inputText value="#{loginBean.userName}" />
									</td>
									<td class="bezeichnung">
										Passwort:
									</td>
									<td>
										<h:inputSecret value="#{loginBean.password}" />
									</td>
									<td>
										<a4j:commandButton action="toUserBase" value="Login" />
									</td>
								</tr>
							</table>


						</a4j:form>
```


Eine Navigation Rule in der faces-config.xml verweist auf mit dem Klick auf den Button auf die /user/index.faces. Da die geschützt ist, wird die login.faces aufgerufen. Diese Seite enthält ein unsichtbares Formular mit 2 Hidden Felder, welche den Usernamen und das "versalzene" Password beinhaltet. Beim Laden der Seite wird das Formular automatisch abgeschickt, was die Anmeldung vornimmt. Bei Erfolg, wird auf die /user/index.faces geleitet und beim Fehler auf die /error.faces

login.faces:

```
<body onload="document.loginForm.submit()">
		<form name="loginForm" method="post" action="j_security_check">
			<input name="j_username" type="hidden" value="#{loginBean.userName}" />
			<input name="j_password" type="hidden" value="#{loginBean.saltedPassword}" />
		</form>			
	</body>
```

Nun habe ich 2 Möglichkeiten an den Usernamen zu kommen. Einmal durch die LoginBean und dann durch den UserPrincipal.getName()


----------

