Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>I suppose you want <a href="http://docs.oracle.com/javaee/6/tutorial/doc/gkbaa.html#bncbq" rel="noreferrer">form based authentication</a> using <a href="http://docs.oracle.com/javaee/6/tutorial/doc/gkbaa.html#bncbn" rel="noreferrer">deployment descriptors</a> and <code>j_security_check</code>. </p> <p>You can also do this in JSF by just using the same predefinied field names <code>j_username</code> and <code>j_password</code> as demonstrated in the tutorial. </p> <p>E.g.</p> <pre><code>&lt;form action="j_security_check" method="post"&gt; &lt;h:outputLabel for="j_username" value="Username" /&gt; &lt;h:inputText id="j_username" /&gt; &lt;br /&gt; &lt;h:outputLabel for="j_password" value="Password" /&gt; &lt;h:inputSecret id="j_password" /&gt; &lt;br /&gt; &lt;h:commandButton value="Login" /&gt; &lt;/form&gt; </code></pre> <p>You could do lazy loading in the <code>User</code> getter to check if the <code>User</code> is already logged in and if not, then check if the <code>Principal</code> is present in the request and if so, then get the <code>User</code> associated with <code>j_username</code>.</p> <pre><code>package com.stackoverflow.q2206911; import java.io.IOException; import java.security.Principal; import javax.faces.bean.ManagedBean; import javax.faces.bean.SessionScoped; import javax.faces.context.FacesContext; @ManagedBean @SessionScoped public class Auth { private User user; // The JPA entity. @EJB private UserService userService; public User getUser() { if (user == null) { Principal principal = FacesContext.getCurrentInstance().getExternalContext().getUserPrincipal(); if (principal != null) { user = userService.find(principal.getName()); // Find User by j_username. } } return user; } } </code></pre> <p>The <code>User</code> is obviously accessible in JSF EL by <code>#{auth.user}</code>.</p> <p>To logout do a <a href="http://java.sun.com/javaee/6/docs/api/javax/servlet/http/HttpServletRequest.html" rel="noreferrer"><code>HttpServletRequest#logout()</code></a> (and set <code>User</code> to null!). You can get a handle of the <code>HttpServletRequest</code> in JSF by <a href="http://java.sun.com/javaee/6/docs/api/javax/faces/context/ExternalContext.html#getRequest%28%29" rel="noreferrer"><code>ExternalContext#getRequest()</code></a>. You can also just invalidate the session altogether.</p> <pre><code>public String logout() { FacesContext.getCurrentInstance().getExternalContext().invalidateSession(); return "login?faces-redirect=true"; } </code></pre> <p>For the remnant (defining users, roles and constraints in deployment descriptor and realm), just follow the Java EE 6 tutorial and the servletcontainer documentation the usual way.</p> <hr> <p><strong>Update</strong>: you can also use the new Servlet 3.0 <a href="http://java.sun.com/javaee/6/docs/api/javax/servlet/http/HttpServletRequest.html#login%28java.lang.String,%20java.lang.String%29" rel="noreferrer"><code>HttpServletRequest#login()</code></a> to do a programmatic login instead of using <code>j_security_check</code> which may not per-se be reachable by a dispatcher in some servletcontainers. In this case you can use a fullworthy JSF form and a bean with <code>username</code> and <code>password</code> properties and a <code>login</code> method which look like this:</p> <pre class="lang-html prettyprint-override"><code>&lt;h:form&gt; &lt;h:outputLabel for="username" value="Username" /&gt; &lt;h:inputText id="username" value="#{auth.username}" required="true" /&gt; &lt;h:message for="username" /&gt; &lt;br /&gt; &lt;h:outputLabel for="password" value="Password" /&gt; &lt;h:inputSecret id="password" value="#{auth.password}" required="true" /&gt; &lt;h:message for="password" /&gt; &lt;br /&gt; &lt;h:commandButton value="Login" action="#{auth.login}" /&gt; &lt;h:messages globalOnly="true" /&gt; &lt;/h:form&gt; </code></pre> <p>And this view scoped managed bean which also remembers the initially requested page:</p> <pre class="lang-java prettyprint-override"><code>@ManagedBean @ViewScoped public class Auth { private String username; private String password; private String originalURL; @PostConstruct public void init() { ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext(); originalURL = (String) externalContext.getRequestMap().get(RequestDispatcher.FORWARD_REQUEST_URI); if (originalURL == null) { originalURL = externalContext.getRequestContextPath() + "/home.xhtml"; } else { String originalQuery = (String) externalContext.getRequestMap().get(RequestDispatcher.FORWARD_QUERY_STRING); if (originalQuery != null) { originalURL += "?" + originalQuery; } } } @EJB private UserService userService; public void login() throws IOException { FacesContext context = FacesContext.getCurrentInstance(); ExternalContext externalContext = context.getExternalContext(); HttpServletRequest request = (HttpServletRequest) externalContext.getRequest(); try { request.login(username, password); User user = userService.find(username, password); externalContext.getSessionMap().put("user", user); externalContext.redirect(originalURL); } catch (ServletException e) { // Handle unknown username/password in request.login(). context.addMessage(null, new FacesMessage("Unknown login")); } } public void logout() throws IOException { ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext(); externalContext.invalidateSession(); externalContext.redirect(externalContext.getRequestContextPath() + "/login.xhtml"); } // Getters/setters for username and password. } </code></pre> <p>This way the <code>User</code> is accessible in JSF EL by <code>#{user}</code>.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload