# JSF 2.0 Login



## duddits (31. Aug 2010)

Hallo zusammen,

ich habe folgendes Szenario:
Über ein Template (basic.xhtml und header.xhtml):

```
basic.xhtml:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
          "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
	  xmlns:h="http://java.sun.com/jsf/html"
      xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head>
  <title>Function Box</title>
  <h:outputStylesheet name="skin.css" library="theme" />
</h:head>

<h:body>

<div id="header">
    <ui:insert name="header">
    	  <ui:include src="/WEB-INF/template/Header.xhtml"/> 
    </ui:insert>
</div>


<div id="content">
  <ui:insert name="content">
  </ui:insert>
</div>

<div id="footer">
  <ui:insert name="footer">
		<ui:include src="/WEB-INF/template/Footer.xhtml"/>
  </ui:insert>
</div>

</h:body>

</html>
```


```
header.xhtml:

<html xmlns="http://www.w3.org/1999/xhtml"
	xmlns:f="http://java.sun.com/jsf/core"
	xmlns:h="http://java.sun.com/jsf/html"
	xmlns:p="http://primefaces.prime.com.tr/ui">
	
<h:head>
</h:head>
<h:body>
<h:form>
	<h:panelGrid columns="4" style="padding:4px; margin: 0 auto;">
	
		<h:graphicImage library="images" name="pic.png"
			style="width: 80%; height:80% "></h:graphicImage>
		<h:inputText value="#{funcBean.darst}"  "></h:inputText>
		<p:commandButton value="Run" action="run" />
		<h:outputLink value="login.jsf"><h:outputText value="Anmelden" /></h:outputLink>
		
		
	</h:panelGrid>
	</h:form>

</h:body>
</html>
```
welches in der Startseite (index.xhtml):

```
index.xhtml:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml"
	xmlns:ui="http://java.sun.com/jsf/facelets"
	xmlns:h="http://java.sun.com/jsf/html"
	xmlns:f="http://java.sun.com/jsf/core">

<ui:composition template="/WEB-INF/template/basic.xhtml">
	
	<ui:define name="content">
	    
	</ui:define>
</ui:composition>
</html>
```
integriert ist (da der Header je nach Situation - angemeldet oder abgemeldet - immer gleich aussehen soll).
Der Benutzer kommt auf die Startseite (index.xhtml) und hat hier ohne Anmeldung nur rudimentäre Funktionsmöglichkeiten.
Wählt er nun den <hutputLink> zur Login-Seite (login.xhtml) wird er zu dieser weitergeleitet:

```
login.xhtml:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml"
	xmlns:f="http://java.sun.com/jsf/core"
	xmlns:h="http://java.sun.com/jsf/html"
	xmlns:p="http://primefaces.prime.com.tr/ui">
	
<h:head>
<h:outputStylesheet name="skin.css" library="theme" />
<title>JESL - Login</title>
</h:head>
<h:body>
	<h:form>

	<p:panel id="panel" header="JESL - Login" style="margin-bottom:10px;">
		<p:messages />
		<h:panelGrid columns="3">
			<h:outputLabel for="username" value="Benutzername: " />
			<h:inputText id="username" value="#{loginBean.username}" required="true" label="Benutzername" />
			<p:message for="username" />
			
			<h:outputLabel for="password" value="Kennwort: " />
			<h:inputSecret id="password" value="#{loginBean.password}" required="true" label="Kennwort"/>
			<p:message for="password" />
		</h:panelGrid>
	

	<p:commandButton ajax="false" value="Anmelden" actionListener="#{loginBean.CheckValidUser}"  />
	<p:commandButton immediate="true" ajax="false" id="index" value="Zurück" action="/index.xhtml"/>
</p:panel>
	
</h:form>
</h:body>
</html>
```

Auf dieser Befinden sich 2 commandButtons. Der erste Button (<p:commandButton ... value="Anmelden">) ist für die Anmeldung gedacht und ruft die entsprechende Bean auf. Der zweite Button (<p:commandButton ... value="Zurück" >) führt den Benutzer ohne die Formularfelder zu beachten wieder zurück auf die Startseite (index.xhtml).

Das Problem ist, wie ich den Benutzer mittels des Beans als Angemeldet zur index.xhtml zurücksende und dies auch so anzeige. Den login bzw. die ganze Seite soll in JSF 2.0 realisiert werden.

Hier die noch nicht fertiggestellte Bean:

```
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.validation.constraints.*;

@ManagedBean
@SessionScoped
public class loginBean {
	
	@Size(min=2, max=30) @Pattern(regexp = "[\\s\\w-,!\\.]*", message = "must match a-z,A-Z,0-9 or !,-_.")
	private String username;
	@Size(min=2, max=20) @Pattern(regexp = "[\\s\\w-,!\\.]*", message = "must match a-z,A-Z,0-9 or !,-_.")
    private String password;
    private String message;


    public String getMessage() {
		return message;
	}


	public void setMessage(String message) {
		this.message = message;
	}


	public String getUsername ()
    {
        return username;
    }


    public void setUsername (final String username)
    {
        this.username = username;
    }


    public String getPassword ()
    {
        return password;
    }


    public void setPassword (final String password)
    {
        this.password = password;
    }
    
    /*
    public void checkPW(){
    	
    } */
    
    public String CheckValidUser(){
		if(username.equals("testuser") && password.equals("testpw")){
			return "/index.xhtml";
		}
		else{
			this.setMessage("Sie haben einen falschen Benutzernamen oder ein falsches Kennwort eingegeben");
			return "";
		}
	}
    

    

}
```

Ziel soll es sein, das bei falscher Kennwort- oder Benutzer-Eingabe der Benutzer eine Fehlermeldung auf der Lohin-Seite (login.xhtml) erhält. Ist der login erfolgreich, so soll dieser zur Startseite (index.xhtml) weitergeleitet werden und in dieser sollen nun weitere Funktionalitäten sichtbar sein, solange bis sich dieser wieder abmeldet.


Da ich noch was neu im Bereich J2EE sowie JSF bin, bin ich mir nicht ganz sicher wie ich das (am besten) realisieren soll 
Bzw. wie kann ich dafür sorgen das nach erfolgreicher Anmeldung in der login.xhtml ich nach der Weiterleitung (wie?) einige Komponenten sichtbar werden?



Vielen Dank schon mal für Eure Unterstützung 


Viele Grüße, Daniel


----------



## megaflop (31. Aug 2010)

Also ich habe das wie folgt realisiert:

Bau in deine loginBean noch 2 boolean Attribute ein, eines das anzeigt, ob der benutzer angemeldet ist oder nicht (loggedOn) und eines, das anzeigt ob eine Anmeldung fehlgeschlagen ist(loginFailed). Inklusive Getter und Setter.

In deiner Login-Methode setzt du dann entsprechend loggedOn auf true, wenns erfolgreich war, oder loginFailed auf true, wenns fehlgeschlagen ist.

In deinen JSF-Seiten kannst du dann wie folgt arbeiten:


```
<c:if test="#{loginBean.loggedOn}">
    <!-- Geschützte inhalte -->
</c:if>
```

Wenn der login gescheitert ist, kannst du die Meldung auf der Login-Seite wie folgt anzeigen lassen:


```
<c:if test="#{loginBean.loginFailed}">
   Login falsch.
</c:if>
```

Damit die Meldung dann nicht die ganze zeit angezeigt wird, setzt du in der Getter-Methode von loginFailed dieses feld wieder auf false.

Grüße,
  megaflop


----------



## duddits (1. Sep 2010)

Hi megaflop,

erst mal vielen Dank für Deine schnelle Hilfe 

Ich glaube, das es mittels des c-Tags möglich wäre, habe allerdings beim recherchieren erfahren das in JSF 2.0 es besser ist mittels des Attributes rendered gelöst werden sollte, damit die Logik im Bean bleibt (Falls ich mich da irre, lasse ich mich gerne verbessern .
Jetzt bin ich auf der Suche nach Informationen, wie das mittels des rendered-Attributes funktioniert. Hat vll. jmd. einen guten Link parat?

*Nachtrag*
Ich habe versucht erstmal die Situation mittels dem Anzeigen des Anmelde/Abmelde Linkes darzustellen, allerdings ist dort irgendwo der Wurm drinnen -.-

```
<h:outputLink value="login.jsf" rendered="#{loginBean.loggedOn == false}"><h:outputText value="Anmelden" /></h:outputLink>
		<h:commandLink id="abmelden" rendered="#{loginBean.loggedOn}" action="#{loginBean.setLoggedOn(false)}"><h:outputText value="Abmelden" /></h:commandLink>
```

Vielen Dank nochmals  und viele Grüße,
Daniel


----------



## duddits (1. Sep 2010)

Ok, mittlerweile klappt der wechseln von Angemeldet zu Abgemeldet wunderbar. Die Änderung sieht wie folgt aus:

```
<h:outputLink value="login.jsf" rendered="#{loginBean.loggedOn == false}"><h:outputText value="Anmelden" /></h:outputLink>
<h:outputLink id="abmelden" rendered="#{loginBean.loggedOn}" value="#{loginBean.loggedOn}"><h:outputText value="Abmelden" /><f:attribute name="loggedOn" value="false"/></h:outputLink>
```

Allerdings wenn ich jetzt auf den Abmelde-Link klicke, wird versucht eine neue Seite aufzurufen:
http://localhost:8080/FunB/true?loggedOn=false

Doch an sich, sollte nur der Wert der Eigenschaft _loggedOn_ im Bean "loginBean" von true auf false gesetzt werden, so das der Anmelde-Link wieder zu sehen ist -.-

Hat einer von euch einen Tipp? 


*Nachtrag*
Habe es jetzt wie folgt lösen können:

Der zweite Link ist nun ein commandLink, welches in der Bean fürs Abmelden loggedOn auf false setzt und die gleiche Seit nochmals laden lässt:

```
<h:outputLink value="login.jsf" rendered="#{loginBean.loggedOn == false}" ><h:outputText value="Anmelden" /></h:outputLink>
<h:commandLink id="abmelden" rendered="#{loginBean.loggedOn}" immediate="true" action="#{loginBean.Abmelden}"><h:outputText value="Abmelden" /></h:commandLink>
```


Besten Dank, Daniel


----------



## duddits (1. Sep 2010)

Als Problem bleibt einzig bestehen, das die Fehlermeldung für ein falsch eingegebenes Kennwort und/oder Benutzer nur auf der Konsole ausgegeben wird.
Hier der Auszug aus dem Facelet:
[XML]<h:form>

	<panel id="panel" header="Login" style="margin-bottom:10px;">
		<p:message for="login" />
		<hanelGrid columns="3">
			<hutputLabel for="username" value="Benutzername: " />
			<h:inputText id="username" value="#{loginBean.username}" required="true" label="Benutzername" />
			<p:message for="username" />

			<hutputLabel for="password" value="Kennwort: " />
			<h:inputSecret id="password" value="#{loginBean.password}" required="true" label="Kennwort"/>
			<p:message for="password" />
		</hanelGrid>


	<p:commandButton id="login" value="Anmelden" ajax="false" action="#{loginBean.CheckValidUser}"  />
	<p:commandButton id="index" immediate="true" ajax="false"  value="Zurück" action="/index.xhtml"/>
</panel>

</h:form>[/XML]

```
...
String msgText = "Sie haben einen falschen Benutzernamen oder ein falsches Kennwort eingegeben";
			FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_ERROR, msgText, null);
			throw new ValidatorException(msg);
```

Irgendwie will sich mir der Fehler hieran nicht erschließen, da es scheinbar nach einigen Dokumentationen so richtig ist....


*Nachtrag*
Ok, auch dieses letzte Problem habe ich lösen können. Hier die Änderung an der Bean:

```
String msgText = "Sie haben einen falschen Benutzernamen oder ein falsches Kennwort eingegeben";
FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_WARN, msgText, null);
FacesContext facesContext = FacesContext.getCurrentInstance();
facesContext.addMessage(UIComponent.getCurrentComponent(facesContext).getClientId(), msg);
```

Danke an alle die sich mit meinem Problem auseinander gesetzt haben.


----------

