请求中带有凭据的JSF登录

请求中带有凭据的JSF登录,jsf,login,jsf-2,servlet-filters,Jsf,Login,Jsf 2,Servlet Filters,我正在用JSF2.0开发一个web应用程序。我通过托管bean(LoginHandler)实现了登录,并检查用户是否使用过滤器登录 现在,我通过发送一个以用户名和密码为参数的请求,得到了能够登录到应用程序的请求。哪种方法最好 我试着使用f:metadata和preRenderView事件,但是过滤器似乎是更好的解决方案?我还尝试在登录页面的url上编写HTTPFilter,但问题是我需要将用户数据存储在托管bean中,并且当我第一次访问应用程序时,我没有一个会话可以从中获取托管bean Otpi

我正在用JSF2.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>
如前所述,选项2的问题是,在我第一次访问应用程序时,会话没有设置(即,我需要尝试登录两次,第二次一切正常)

谢谢

EDIT1:更新了注释和说明,以更好地反映类LoginHandler的角色

  • 关于何时使用,我会建议你阅读 这是一个伟大的答案。在通过HTTP GET请求发送数据时,切勿使用
    f:viewParam
    处理用户输入

  • 还建议不要将
    servlet
    JSF
    应用程序一起使用 会话范围bean是
    HTTPSessions
    的属性,您将发现 关于原因的解释

  • 最后,有四种方法可以注册一个系统,甚至是在 JSF应用程序。 在问题中使用
    f:event
    标记 通过使用
    @ListnerFor(systemEventClass=typeOfEvent.class)
    ,通过调用
    subscribeToEvent
    方法,最后注册一个系统事件
    faces config.xml
    文件中的listner

     <application>
        <system-event-listener>
          <system-event-listener-class>listenerClass</system-event-listener-class>
          <system-event-class>eventClass</system-event-class>
         </system-event-listener>
    </application>
    
    您的bean方法接受
    组件系统事件

    public void singleSignOn(ComponentSystemEvent event) {
         if (!login) {
              //do JSF stuff here when validating credentials fails or passes
             //eg. perform navigation
    
            }
    }
    
    注意:这个问题有一个答案,它解决了如何用jsf实现过滤器

    对于其他材料,我建议您继续

  • 关于何时使用,我会建议你阅读 这是一个伟大的答案。在通过HTTP GET请求发送数据时,切勿使用
    f:viewParam
    处理用户输入

  • 还建议不要将
    servlet
    JSF
    应用程序一起使用 会话范围bean是
    HTTPSessions
    的属性,您将发现 关于原因的解释

  • 最后,有四种方法可以注册一个系统,甚至是在 JSF应用程序。 在问题中使用
    f:event
    标记 通过使用
    @ListnerFor(systemEventClass=typeOfEvent.class)
    ,通过调用
    subscribeToEvent
    方法,最后注册一个系统事件
    faces config.xml
    文件中的listner

     <application>
        <system-event-listener>
          <system-event-listener-class>listenerClass</system-event-listener-class>
          <system-event-class>eventClass</system-event-class>
         </system-event-listener>
    </application>
    
    您的bean方法接受
    组件系统事件

    public void singleSignOn(ComponentSystemEvent event) {
         if (!login) {
              //do JSF stuff here when validating credentials fails or passes
             //eg. perform navigation
    
            }
    }
    
    注意:这个问题有一个答案,它解决了如何用jsf实现过滤器


    对于其他材料,我建议您继续。

    我参加了
    预渲染视图
    活动:

    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和LoginHandler.login是绑定到登录页面上的
    h:form
    的相同bean/方法

    我使用了
    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和LoginHandler.login是绑定到登录页面上的
    h:form
    的同一bean/方法,选项2确实更常见。解决方案:不要检查loginHandler(className表示“服务”,服务无论如何不应该存储在会话中)。但更好的解决办法是不要创造本土产品。如果您对此已经有疑问,您肯定会(无意中)引入安全漏洞。最好使用一些现有的框架,如PicketLink、Shiro甚至SpringSecurity(如果您已经使用spring)。@Kukeltje感谢您的回答。我会坚持我目前的框架,但会考虑在第二个时刻升级为Spring。我的类LoginHandler是JSF应用程序中的一个sessionscoped bean,它从登录EJB调用逻辑,并保存有关当前登录用户的信息。这是我的第一个jsf/EJB应用程序,我还不熟悉最佳实践。我需要在过滤器中使用LoginHandler,以便让用户登录到应用程序中,有办法吗?编辑:更新了问题,明确了我使用LoginHandler的目的是为了将服务和保存状态的bean结合在一起?这不是一个好的设计。将它们拆分为一个LoginService(请求范围或甚至静态方法或..)和一个LoggedInUser(会话范围)。选择2确实更常见。解决方案:不要检查loginHandler(className表示“服务”,服务无论如何不应该存储在会话中)。但更好的解决办法是不要创造本土产品。如果您对此已经有疑问,您肯定会(无意中)引入安全漏洞。最好使用一些现有的框架,如PicketLink、Shiro甚至SpringSecurity(如果您已经使用spring)。@Kukeltje感谢您的回答。我会坚持我目前的框架,但会考虑在第二个时刻升级为Spring。我的类LoginHandler是JSF应用程序中的一个sessionscoped bean,它从登录EJB调用逻辑,并保存有关当前登录用户的信息。这是我的第一个jsf/EJB应用程序,我还不熟悉最佳实践。我需要在过滤器中使用LoginHandler,以便让用户登录到应用程序中,有办法吗?编辑:更新了问题,明确了我使用LoginHandler的目的是为了将服务和保存状态的bean结合在一起?这不是一个好的设计。