JSF在请求中使用凭据登录

时间:2017-06-29 10:42:28

标签: jsf login jsf-2 servlet-filters

我正在使用JSF 2.0开发一个Web应用程序。我通过托管bean(LoginHandler)实现了登录,并检查用户是否使用过滤器登录。

现在,通过发送带有用户名和密码作为参数的请求,我得到了能够登录应用程序的请求。哪种方法最好?

我尝试使用f:metadata和preRenderView事件,但似乎过滤器是更好的解决方案吗?我也尝试在登录页面的url上编写HTTPFilter,但问题是我需要将用户数据存储在我的托管bean中,当我第一次访问应用程序时,我没有从中获取管理bean的会话。

Otpion 1:f:managedbean LoginHandler中的元数据和操作: 登录页面:

<f:metadata>
    <f:viewParam name="username" value="#{loginManager.username}"/>
    <f:viewParam name="password" value="#{loginManager.password}"/>
    <f:event type="preRenderView" listener="#{loginManager.singleSignOn}"/>            
</f:metadata>

LoginHandler中的singleSignOn方法检查是否设置了用户名和密码。如果是这种情况,它的作用与提交登录表单相同(它使用相同的方法),如果登录成功,则转发到欢迎页面。否则返回null(显示登录页面)

Otpion 2:过滤器

public void doFilter(ServletRequest req, ServletResponse res,
        FilterChain chain) throws IOException, ServletException {
    HttpServletRequest request = (HttpServletRequest) req;
    HttpServletResponse response = (HttpServletResponse) res;
    HttpSession session = request.getSession(false);

    String username = request.getParameter("username");
    String password = request.getParameter("password");

    LoginHandler loginHandler = null;
    if (session != null) {
        loginHandler = (LoginHandler) session.getAttribute("loginHandler");

        if (loginHandler != null && username != null && password != null) {
            boolean loginOk = false;
            //do logic using methods and objects in loginHandler and set loginOk if login is successful
            loginOk = loginHandler.login(username, password);
            if (loginOk) {
                // login OK
                response.sendRedirect(request.getContextPath() + WELCOME_PAGE_URL);
            }
        }
    }

    chain.doFilter(request, response);
}

如上所述,选项2的问题是我第一次访问应用程序时没有设置会话(即,我需要尝试登录两次 - 第二次一切正常)

由于

EDIT1:更新了评论和说明,以更好地反映类LoginHandler的作用

2 个答案:

答案 0 :(得分:3)

  1. 关于何时使用 f:param & f:metadata ,我建议您阅读 这个答案作为一个伟大的答案提供了这样的。由于数据是通过f:viewParam请求发送的,因此永远不要使用HTTP GET来处理用户输入。

  2. 还建议不要将servletsJSF申请一起使用 会话范围的bean是HTTPSessions的属性,你会发现 解释为什么here

  3. 最后有四种方法可以在一个系统中注册一个系统甚至列表器 JSF应用程序。     使用您在问题中使用的f:event标记 提供,通过注释类 @ListnerFor(systemEventClass = typeOfEvent.class),通过拨打电话 subscribeToEvent方法,最后注册一个系统事件 faces-config.xml文件中的列表器如此

     <application>
        <system-event-listener>
          <system-event-listener-class>listenerClass</system-event-listener-class>
          <system-event-class>eventClass</system-event-class>
         </system-event-listener>
    </application>
    
  4. 在您使用f:event标记的情况下(正如您在问题中所做的那样),您应该确保将其括在f:view标记中

        <f:view>
          <f:event type="preRenderView" listener="#{loginManager.singleSignOn}"/>  
            ......
             <f:viewParam name="username" value="#{loginManager.username}"/>
             <f:viewParam name="password" value="#{loginManager.password}"/>
            ......
        </f:view>
    

    并且你的bean方法接受ComponentSystemEvent如此

    public void singleSignOn(ComponentSystemEvent event) {
         if (!login) {
              //do JSF stuff here when validating credentials fails or passes
             //eg. perform navigation
    
            }
    }
    

    注意:这个问题的答案解决了如何使用jsf实现过滤器,use it as head start

    对于其他材料,我建议您继续Basic steps for starting session in jsf

答案 1 :(得分:0)

我参加了prerenderview活动:

singleSignOn.xhtml:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html">
<f:metadata>
    <f:viewParam name="userName" value="#{loginCredentials.userName}" />
    <f:viewParam name="password" value="#{loginCredentials.password}" />
    <f:event type="preRenderView" listener="#{loginHandler.singleSignOn}" />
</f:metadata>
<h:head>
    <title>singleSignOn</title>    
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</h:head>    
<h:body />      
</html>

LoginCredentials是一个请求范围的POJO,其字段为userName和password。

LoginHandler中的singleSignOn()(部分):

public void singleSignOn(ComponentSystemEvent event) {
    if (loginCredentials.getUserName() != null
            && loginCredentials.getPassword() != null) {
        login();
    } else {
        // error handling (i did output on syserr)
    }
}

LoginCredentials和LoginHandler.login是绑定到登录页面上h:form的相同bean /方法