views:

1896

answers:

2

I would like to see a simple Login Application, not as simple as this though.

What i would like to achive is an understanding on how JSF works, I've developed a lot of ASP.NET where you have the Code Behind and where you can just Check if a session was created upon Login.

A similar solution in JSF would be great.

This is basicly what I want to achieve:

  • Login page
  • IF OK
    • Create session and return "success"
  • IF FAIL
    • return "failure"

(The "success" and failure are mapped to faces-config.xml)

At the success-page I want to be Certian that the user is logged in, so one should Not be able to navigate to "success.jspx" if you have not got the correct session.

Suggestions on Tutorials / Blogs / etc on this topic?

+1  A: 

There is no inherent authentication functionality in core JSF beyond being able to use things like component rendered attributes geared towards role-based security.

By default, a JSF application relies on the same container-managed security mechanisms as the web component that contains it (JEE5 tutorial). 3rd party frameworks like Seam can provide alternatives.

If you want to add your own application security, a servlet filter is one of the simpler mechanisms.

This filter protects resources under the restricted directory as defined in web.xml:

  <filter>
    <filter-name>AuthenticationFilter</filter-name>
    <filter-class>restricted.AuthenticationFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>AuthenticationFilter</filter-name>
    <url-pattern>/restricted/*</url-pattern>
  </filter-mapping>

The filter class implementation:

public class AuthenticationFilter implements Filter {
  private FilterConfig config;

  public void doFilter(ServletRequest req, ServletResponse resp,
      FilterChain chain) throws IOException, ServletException {
    if (((HttpServletRequest) req).getSession().getAttribute(
        AuthenticationBean.AUTH_KEY) == null) {
      ((HttpServletResponse) resp).sendRedirect("../restricted_login.faces");
    } else {
      chain.doFilter(req, resp);
    }
  }

  public void init(FilterConfig config) throws ServletException {
    this.config = config;
  }

  public void destroy() {
    config = null;
  }
}

A login bean defined in faces-config.xml:

public class AuthenticationBean {
  public static final String AUTH_KEY = "app.user.name";

  private String name;
  public String getName() { return name; }
  public void setName(String name) { this.name = name; }

  public boolean isLoggedIn() {
    return FacesContext.getCurrentInstance().getExternalContext()
        .getSessionMap().get(AUTH_KEY) != null;
  }

  public String login() {
    FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put(
        AUTH_KEY, name);
    return "secret";
  }

  public String logout() {
    FacesContext.getCurrentInstance().getExternalContext().getSessionMap()
        .remove(AUTH_KEY);
    return null;
  }
}

The JSF login form in the restricted_login.jsp page:

  <f:view>
    <p><a href="restricted/secret.faces">try to go to secret
    page</a></p>
    <h:form>
    Username:
    <h:panelGroup rendered="#{not authenticationBean.loggedIn}">
        <h:inputText value="#{authenticationBean.name}" />
        <h:commandButton value="login"
          action="#{authenticationBean.login}" />
      </h:panelGroup>
      <h:commandButton value="logout"
        action="#{authenticationBean.logout}"
        rendered="#{authenticationBean.loggedIn}" />
    </h:form>
  </f:view>

(The redirect URL/mechanism was chosen for brevity rather than any sort of best practice; see the Servlet API for more options.)

McDowell
+1  A: 

If you're willing to try a bit more advanced approach then I suggest looking into spring-security+JSF. It works like a charm.

You can write your application as if it wasn't under security and then just configure which areas that should be protected using aspects.

Spring security: http://static.springsource.org/spring-security/site/

A Tutorial: http://ocpsoft.com/java/acegi-spring-security-jsf-login-page/

Tomas Forsman