在JavaServer Faces应用程序中使用托管Bean进行身份验证

时间:2014-04-08 17:27:57

标签: jsf authentication servlets jsf-2

目标:当用户通过身份验证时,想要在会话中检索并存储用户相关信息(USER表中超过5列),这样我就可以在不同的时间点使用用户信息在本届会议期间。

方法:我选择在我的JavaServerFaces应用程序中使用托管Bean(LoginBean.java)进行身份验证。我将检索用户信息并将其存储在LoginBean.login()方法的会话中。

参考http://docs.oracle.com/javaee/6/tutorial/doc/glxce.html#glxef

Bean代码:

@ManagedBean
@SessionScoped
public class LoginBean {
    private String id;
    private String password;

    public LoginBean() {
        System.out.println("LoginBean() called .....");
    }

    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }

    public String login() {
        System.out.println("login() invoked .....");
        FacesContext facesContext = FacesContext.getCurrentInstance();
        HttpServletRequest request = (HttpServletRequest)facesContext.getExternalContext().getRequest();

        try {
            request.login(id, password);
        } catch (ServletException e) {
            facesContext.addMessage(null, new FacesMessage("Login failed."));
            return "error";
        }

        return "home";
    }

    public void logout() {
        System.out.println("logout() invoked .....");
        FacesContext facesContext = FacesContext.getCurrentInstance();
        HttpServletRequest request = (HttpServletRequest)facesContext.getExternalContext().getRequest();

        try {
            request.logout();
        } catch (ServletException e) {
            facesContext.addMessage(null, new FacesMessage("Logout failed."));
        }
    }
}

的web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
  <display-name>AuthenticationUsingLoginBean</display-name>
  <servlet>
    <servlet-name>Faces Servlet</servlet-name>
    <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>

  <servlet-mapping>
    <servlet-name>Faces Servlet</servlet-name>
    <url-pattern>*.xhtml</url-pattern>
  </servlet-mapping>

   <login-config>
        <auth-method>FORM</auth-method>
        <realm-name>jdbcRealm</realm-name>
        <form-login-config>
            <form-login-page>/login.xhtml</form-login-page>
            <form-error-page>/error.xhtml</form-error-page>
        </form-login-config>
    </login-config>

    <security-constraint>
        <web-resource-collection>       
            <web-resource-name>All resources are restricted</web-resource-name> 
            <url-pattern>/*</url-pattern>
        </web-resource-collection>          
        <auth-constraint>
            <role-name>admin</role-name>            
        </auth-constraint>
    </security-constraint>
</web-app>

login.xhtml

<?xml version="1.0" encoding="UTF-8"?>
<!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:f="http://java.sun.com/jsf/core" xmlns:ui="http://java.sun.com/jsf/facelets">

<h:head>
    <title>Form based authentication with login bean</title>
</h:head>

<h:body>
    <h:form>
        <h:outputLabel for="usernameInput">User ID:</h:outputLabel>
        <h:inputText id="usernameInput" value="#{loginBean.id}" required="true" />
        <h:message for="usernameInput"/>
        <br />
        <h:outputLabel for="passwordInput">Password:</h:outputLabel>
        <h:inputSecret id="passwordInput" value="#{loginBean.password}" required="true" />
        <h:message for="passwordInput" />
        <br />
        <h:commandButton value="Login" action="#{loginBean.login}" />
    </h:form>
</h:body>
</html>

问题 我已经启动了新的浏览器窗口并访问了主页(home.xhml)。 我被重定向到login.xhtml,这很好。 但是,点击Login用户界面上的login.xhtml按钮后,系统不会调用LoginBean.login()方法。

注意 login.xhtml应正确,因为当我在LoginBean.login()文件中注释<login-config>时,web.xml方法已成功调用。显然,我无法对其进行评论,因为身份验证无法按预期工作。

更新 我在tomcat的JDBCRealm文件中配置了必要的server.xml,并确保通过使用j_security_check实施基于样本表单的身份验证,它可以正常工作。

<Realm className="org.apache.catalina.realm.JDBCRealm"
            driverName="com.mysql.jdbc.Driver"
            connectionURL="jdbc:mysql://localhost/xyz"
            connectionName="root"
            connectionPassword="xxxxx"
            userTable="USER" userCredCol="PASSWORD"
            userRoleTable="USER_ROLE_MPNG" userNameCol="ID" roleNameCol="ROLE_NAME" />

使用的软件: Apache的Tomcat的7.0.47 JSF 2.1(Mojarra 2.1.6)

2 个答案:

答案 0 :(得分:1)

<h:commandButton value="Login" action="#{loginBean.login()}" />
登录后,请注意()。您正在调用一个方法而不是尝试使用LoginBean中的名称登录来获取/设置var。

答案 1 :(得分:0)

这不起作用的原因是因为您限制了web.xml中的所有资源。您可以看到您的登录页面和错误页面,但这并不意味着可以访问它周围的所有内容。

解决方案

为公共资源添加新的安全约束,如下所示:

<security-constraint>
    <web-resource-collection>
        <web-resource-name>Open Resources</web-resource-name>
        <url-pattern>/public/*</url-pattern>
    </web-resource-collection>
</security-constraint>

现在,在login.xhtmlerror.xhtml中创建一个新的子文件夹,并将其命名为public,如安全约束中所示。将您的login.xhtmlerror.xhtml移至新创建的文件夹中,并相应地调整web.xml中的登录配置。