Session 如何设计一个无会话的JSF2.0Web应用程序?

Session 如何设计一个无会话的JSF2.0Web应用程序?,session,jsf-2,Session,Jsf 2,我正在一个JSF2.0网站上工作。该网站有两种用户类型:注册用户和注册用户。现在我想知道如何为这两种用户创建会话?对于注册用户,当我的用户登录时,应该有会话,当会话过期时,我将其重定向到您的会话已过期的页面。对于公共用户,根本不应该有会话。表示my public用户没有会话超时,并且他们从未收到您的会话已过期的消息。如何在JSF2.0中实现这种行为 我可以使用过滤器,还是有更好的方法?我还了解到JSF使用托管bean自动创建会话。我可以将这些会话用于我的任务吗 编辑: 我告诉你们我做了什么所以你

我正在一个JSF2.0网站上工作。该网站有两种用户类型:注册用户和注册用户。现在我想知道如何为这两种用户创建会话?对于注册用户,当我的用户登录时,应该有会话,当会话过期时,我将其重定向到您的会话已过期的页面。对于公共用户,根本不应该有会话。表示my public用户没有会话超时,并且他们从未收到您的会话已过期的消息。如何在JSF2.0中实现这种行为

我可以使用过滤器,还是有更好的方法?我还了解到JSF使用托管bean自动创建会话。我可以将这些会话用于我的任务吗

编辑: 我告诉你们我做了什么所以你们最好在这个场景中引导我

我所做的是在我的web应用程序中添加了一个过滤器,如下所示

<filter>
    <filter-name>SessionTimeoutFilter</filter-name>
    <filter-class>util.SessionTimeoutFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>SessionTimeoutFilter</filter-name>
    <url-pattern>*.xhtml</url-pattern>
</filter-mapping>
String isRegisteredUser = session.getAttribute("logedin").toString();

        if (isRegisteredUser.equalsIgnoreCase(("1"))) {

            Login login = (Login)session.getAttribute("login");

            Enumeration e = session.getAttributeNames();

           while (e.hasMoreElements()) {

                String attr = (String)e.nextElement();
                System.err.println("attr  = "+ attr);
                Object value = session.getAttribute(attr);
                System.err.println("value = "+ value);

           } //end of while

           long sessionCreationTime = session.getCreationTime();
            int sessionCreationTimeInSec = (int)(sessionCreationTime / 1000) % 60;
           int sessionCreationTimeInMinutes = (int)((sessionCreationTime / (1000*60)) % 60);

            long sessionLastAccessTime = session.getLastAccessedTime();
            int sessionLastAccessTimeInSec  = (int)(sessionLastAccessTime / 1000) % 60 ;
           int sessionLastAccessTimeInMinutes  = (int)((sessionLastAccessTime / (1000*60)) % 60 );

            int sessionMaxTime = session.getMaxInactiveInterval();
            int sessionMaxTimeInMinute = sessionMaxTime / 60 ;

            if ((sessionCreationTimeInMinutes - sessionLastAccessTimeInMinutes) - 1 > sessionMaxTimeInMinute) {

                System.out.println("Session is expiring in one minute");

           }

            System.out.println("");

            filterChain.doFilter(httpServletRequest, httpServletResponse);

        }
现在,若你们第一次输入我的网站的url,那个么这个过滤器就会调用。它变得

Login login = (Login)session.getAttribute("login");
空。因此,它只需移动到我的index.xhtml页面。现在我的index.html页面构造函数调用。这是我的密码

@ManagedBean
//////@RequestScoped
@SessionScoped
public class Login implements Serializable {

    //Constructor
    public Login() {

        FacesContext facesContext = FacesContext.getCurrentInstance();
        ExternalContext externalContext = facesContext.getExternalContext();

        //getSession(false), which returns null if no session already exists for the current client.
        HttpSession session =(HttpSession)externalContext.getSession(false);

        if (session == null) {

            System.out.println();

        } else {

            session.setAttribute("logedin", 0);     //public user
            session.setMaxInactiveInterval(-1);     // no session time out

            Enumeration e = session.getAttributeNames();

            while (e.hasMoreElements()) {

                /**
                 * Here you also get "login" attr. Because when managed bean create the
                 * session, it sets you managedBean name in the session attribute.
                 */
                String attr = (String)e.nextElement();
                System.err.println("attr  = "+ attr);
                Object value = session.getAttribute(attr);
                System.err.println("value = "+ value);

            } //end of while

        }

    }//end of constructor

} //end of class Login
public String validUser() throws Exception {

    ArrayList2d<Object> mainarray = new ArrayList2d<Object>();
    mainarray.addRow();
    mainarray.add(userName);
    mainarray.add(password);

    busBeans.usermanagement.users um = new busBeans.usermanagement.users();
    ArrayList retrieveList = um.getValidUser(mainarray);    //database check of user existence

    if (Integer.parseInt(retrieveList.get(0).toString()) == 0) {

        ArrayList str = (ArrayList) retrieveList.get(1);

        FacesContext facesContext = FacesContext.getCurrentInstance();
        ExternalContext externalContext = facesContext.getExternalContext();

        //getSession(false), which returns null if no session already exists for the current client.
        HttpSession session =(HttpSession)externalContext.getSession(false);

        if (session == null) {

            System.out.println();

        } else {

            Enumeration e = session.getAttributeNames();

            while (e.hasMoreElements()) {

                String attr = (String)e.nextElement();
                System.err.println("attr  = "+ attr);
                Object value = session.getAttribute(attr);
                System.err.println("value = "+ value);

            } //end of while

        }

        logedin=true;
        session.setAttribute("logedin", 1);
        session.setAttribute("firstLastName", str.get(7).toString());
        session.setAttribute("getusercredentials", str);
        session.setAttribute("sessionUserId", str.get(0).toString());
        session.setAttribute("sessionRoleId",str.get(1).toString());
        firstLastName = session.getAttribute("firstLastName").toString();
        session.setMaxInactiveInterval(60);  //1 min
        ConnectionUtil.setRgihts(Integer.parseInt(str.get(0).toString()) , Integer.parseInt(str.get(1).toString()) ,Integer.parseInt(str.get(5).toString()));
        checkRgihts();
    }

} //end of validUser()
当用户第一次访问我的站点时,它并没有登录,所以我将LogeIn会话属性设置为0。现在假设用户输入凭证并按下登录按钮。首先,我的过滤器是invoke,但这次它将获得login属性,并进入我的doFilter else检查,然后进入我的validUser方法。这是我的密码

@ManagedBean
//////@RequestScoped
@SessionScoped
public class Login implements Serializable {

    //Constructor
    public Login() {

        FacesContext facesContext = FacesContext.getCurrentInstance();
        ExternalContext externalContext = facesContext.getExternalContext();

        //getSession(false), which returns null if no session already exists for the current client.
        HttpSession session =(HttpSession)externalContext.getSession(false);

        if (session == null) {

            System.out.println();

        } else {

            session.setAttribute("logedin", 0);     //public user
            session.setMaxInactiveInterval(-1);     // no session time out

            Enumeration e = session.getAttributeNames();

            while (e.hasMoreElements()) {

                /**
                 * Here you also get "login" attr. Because when managed bean create the
                 * session, it sets you managedBean name in the session attribute.
                 */
                String attr = (String)e.nextElement();
                System.err.println("attr  = "+ attr);
                Object value = session.getAttribute(attr);
                System.err.println("value = "+ value);

            } //end of while

        }

    }//end of constructor

} //end of class Login
public String validUser() throws Exception {

    ArrayList2d<Object> mainarray = new ArrayList2d<Object>();
    mainarray.addRow();
    mainarray.add(userName);
    mainarray.add(password);

    busBeans.usermanagement.users um = new busBeans.usermanagement.users();
    ArrayList retrieveList = um.getValidUser(mainarray);    //database check of user existence

    if (Integer.parseInt(retrieveList.get(0).toString()) == 0) {

        ArrayList str = (ArrayList) retrieveList.get(1);

        FacesContext facesContext = FacesContext.getCurrentInstance();
        ExternalContext externalContext = facesContext.getExternalContext();

        //getSession(false), which returns null if no session already exists for the current client.
        HttpSession session =(HttpSession)externalContext.getSession(false);

        if (session == null) {

            System.out.println();

        } else {

            Enumeration e = session.getAttributeNames();

            while (e.hasMoreElements()) {

                String attr = (String)e.nextElement();
                System.err.println("attr  = "+ attr);
                Object value = session.getAttribute(attr);
                System.err.println("value = "+ value);

            } //end of while

        }

        logedin=true;
        session.setAttribute("logedin", 1);
        session.setAttribute("firstLastName", str.get(7).toString());
        session.setAttribute("getusercredentials", str);
        session.setAttribute("sessionUserId", str.get(0).toString());
        session.setAttribute("sessionRoleId",str.get(1).toString());
        firstLastName = session.getAttribute("firstLastName").toString();
        session.setMaxInactiveInterval(60);  //1 min
        ConnectionUtil.setRgihts(Integer.parseInt(str.get(0).toString()) , Integer.parseInt(str.get(1).toString()) ,Integer.parseInt(str.get(5).toString()));
        checkRgihts();
    }

} //end of validUser()
但在会话到期时,如果这是一个注册用户,我还想将用户重定向到Redirer页面。如果这是一个公共用户,我不想重定向它,尽管会话已过期。我可以通过获取属性logedin来检查destroy方法,它是公共用户还是注册用户。但那个么,我怎样才能为注册用户重定向,或者不为公共用户做任何事情呢

如果我的筛选器在会话超时时以某种方式调用,并且我如何通过获取logedin属性1检查这是否是注册用户,并且会话超时已过期,因为对于公共用户,我设置了timeout-1,然后使用RequestDispatcher otherwoise do filterChain.doFilterrequest,response;重定向用户

这就是我实现的场景。我不知道我的方法是否正确?我不知道通过这种方法我将面临什么安全问题。就这样。。现在你们这些人指导我该怎么做


谢谢

我知道你的目标是什么,但我不认为不为未经身份验证的用户提供会话是最好的方法

假设一个未经身份验证的用户在Primefaces向导中导航,提供注册帐户的信息,例如选择用户名、提供密码、选择安全问题等

在收集和验证所有信息之前,您不会希望保留这些用户信息,因为用户可能改变了主意,决定不注册?现在,数据库中有一个不完整的用户记录需要清理

答案是,您需要将此信息存储在ViewScoped bean或会话中,直到未经身份验证的用户确认帐户创建,并最终将其持久化

我认为最好的方法是为用户提供一个独特的角色,其中一个角色未经身份验证。使用SpringSecurity3甚至Seam等组件,您应该能够通过会话中用户的角色来控制页面授权


例如,您可以阻止未经身份验证的用户在../app/*中输入页面,或阻止普通用户访问../admin/*中的页面。

我使用了类似的方法。首先是一个过滤器。这是我的过滤器

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
        throws IOException, ServletException {

    HttpServletRequest httpServletRequest = (HttpServletRequest) request;
    HttpServletResponse httpServletResponse = (HttpServletResponse) response;

    //Send request to server after each 1min
    // httpServletResponse.setIntHeader("Refresh", 60);

    //getSession(false), which returns null if no session already exists for the current client
    HttpSession session = httpServletRequest.getSession(false);

    if (session == null) {

        //session timeout check.
        if (httpServletRequest.getRequestedSessionId() != null && !httpServletRequest.isRequestedSessionIdValid()) {

            System.out.println("Session has expired");

            /**
             * getSession() (or, equivalently, getSession(true)) creates a new session if no
             * session already exists.
             */
            session = httpServletRequest.getSession(true);
            session.setAttribute("logedin", "0");    // public user

             //httpServletResponse.sendRedirect("http://www.google.com");
             httpServletResponse.sendRedirect(timeoutPage);

        } else {

            session = httpServletRequest.getSession(true);
            session.setAttribute("logedin", "0");

            filterChain.doFilter(httpServletRequest, httpServletResponse);

        }

    } else {

        String isRegisteredUser = session.getAttribute("logedin").toString();

        if (isRegisteredUser.equalsIgnoreCase(("1"))) {

            Login login = (Login)session.getAttribute("login");

            Enumeration e = session.getAttributeNames();



            System.out.println("");

            filterChain.doFilter(httpServletRequest, httpServletResponse);

        } else if (isRegisteredUser.equalsIgnoreCase(("0")))  {

             Enumeration e = session.getAttributeNames();

             filterChain.doFilter(httpServletRequest, httpServletResponse);

        } //end of else if (isRegisteredUser.equalsIgnoreCase(("0")))

    }

} //end of doFilter()
现在,当用户输入我的站点的url时,这个过滤器就会调用。第一次它得到会话null,然后检查会话超时。没有会话超时,因此它会创建会话。将logedin属性设置为零,表示这是公共用户并传递请求。这是我的方法

//constructor
public Login() {

    try {
        FacesContext facesContext = FacesContext.getCurrentInstance();
        ExternalContext externalContext = facesContext.getExternalContext();
        HttpServletRequest httpServletRequest = (HttpServletRequest)externalContext.getRequest();

        //getSession(false), which returns null if no session already exists for the current client.
        HttpSession session =(HttpSession)externalContext.getSession(false);

        if (session == null) {

            session = httpServletRequest.getSession(true);
            session.setAttribute("logedin", "0");
            session.setMaxInactiveInterval(-1);
            System.out.println();

            } else {

                session.setAttribute("logedin", "0");

                //No session timeout for public users
                session.setMaxInactiveInterval(-1);  

                Enumeration e = session.getAttributeNames();

            }

    } catch (Exception e) {
        System.out.println("Exception in session " + e.getMessage());
    }


} //end of constructor
第一次获取会话时,只需覆盖这些值,这样设置相同的属性就不会有任何危害。但在这里我只想问一件事,为公共用户设置没有会话超时可以吗?它会在某个时候损坏我的应用程序吗,比如我的服务器内存不足等等?如果是,那么我如何克服这一问题

现在假设我的用户正在登录。然后我的过滤器调用,这一次它将获得一个会话,因此它将进入我的isRegisterdUser检查并检查值。他得到0,只需传递请求,然后是我的有效用户方法调用

public String validUser() throws Exception {

    String returnString = null;

    ArrayList2d<Object> mainarray = new ArrayList2d<Object>();
    mainarray.addRow();
    mainarray.add(userName);
    mainarray.add(password);

    busBeans.usermanagement.users um = new busBeans.usermanagement.users();
    ArrayList retrieveList = um.getValidUser(mainarray);
    if (Integer.parseInt(retrieveList.get(0).toString()) == 0) {
        ArrayList str = (ArrayList) retrieveList.get(1);

        FacesContext facesContext = FacesContext.getCurrentInstance();
        ExternalContext externalContext = facesContext.getExternalContext();

        //getSession(false), which returns null if no session already exists for the current client.
        HttpSession session =(HttpSession)externalContext.getSession(false);


        if (session == null) {

            System.out.println();

        } else {

            Enumeration e = session.getAttributeNames();

        }

        System.out.println();

        logedin=true;

        //Set session attributes for login users
        session.setAttribute("logedin", 1);
        session.setAttribute("firstLastName", str.get(7).toString());
        session.setAttribute("getusercredentials", str);
        session.setAttribute("sessionUserId", str.get(0).toString());
        session.setAttribute("sessionRoleId",str.get(1).toString());
        session.setAttribute("registeredUser", "true");

        /**
         * set session timeout for login user
         * 1 min = 60 sec
         * 5 min = 60 * 5 sec = 300 sec
        */
        session.setMaxInactiveInterval(300);   //5min

        firstLastName = session.getAttribute("firstLastName").toString();

    }

    return returnString=null;

} //end of  validUser()
并通过公开来重定向用户。这就是我如何做到的。我也有一个想法,我在一段时间后刷新页面,我有sessionCreationTime、SessionAsAccessTime和sessionMaxTime。所以我可以做这样的工作

<filter>
    <filter-name>SessionTimeoutFilter</filter-name>
    <filter-class>util.SessionTimeoutFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>SessionTimeoutFilter</filter-name>
    <url-pattern>*.xhtml</url-pattern>
</filter-mapping>
String isRegisteredUser = session.getAttribute("logedin").toString();

        if (isRegisteredUser.equalsIgnoreCase(("1"))) {

            Login login = (Login)session.getAttribute("login");

            Enumeration e = session.getAttributeNames();

           while (e.hasMoreElements()) {

                String attr = (String)e.nextElement();
                System.err.println("attr  = "+ attr);
                Object value = session.getAttribute(attr);
                System.err.println("value = "+ value);

           } //end of while

           long sessionCreationTime = session.getCreationTime();
            int sessionCreationTimeInSec = (int)(sessionCreationTime / 1000) % 60;
           int sessionCreationTimeInMinutes = (int)((sessionCreationTime / (1000*60)) % 60);

            long sessionLastAccessTime = session.getLastAccessedTime();
            int sessionLastAccessTimeInSec  = (int)(sessionLastAccessTime / 1000) % 60 ;
           int sessionLastAccessTimeInMinutes  = (int)((sessionLastAccessTime / (1000*60)) % 60 );

            int sessionMaxTime = session.getMaxInactiveInterval();
            int sessionMaxTimeInMinute = sessionMaxTime / 60 ;

            if ((sessionCreationTimeInMinutes - sessionLastAccessTimeInMinutes) - 1 > sessionMaxTimeInMinute) {

                System.out.println("Session is expiring in one minute");

           }

            System.out.println("");

            filterChain.doFilter(httpServletRequest, httpServletResponse);

        }
这里的想法是,如果您检查了会话超时的剩余时间,那么您可以在会话超时之前使会话无效。因为一旦你的会话过期,你会得到一个空的会话,然后你会 没有要检查的属性。但在一分钟之前,您就拥有了会话和所有会话属性,因此您可以做任何您想做的事情。我不知道这个想法有多可靠,它只是我脑海中浮现的一种方法

还假设用户正在登录,然后突然关闭浏览器。关闭浏览器关闭会话。现在,当您打开浏览器时,会收到一条消息,说明您的会话已过期。我想问你什么时候打开浏览器我能用这张支票吗

 if (httpServletRequest.getRequestedSessionId() != null && !httpServletRequest.isRequestedSessionIdValid()) {

     System.out.println("Session has expired");

     if (session.isNew()) {

          /**
            * getSession() (or, equivalently, getSession(true)) creates a new session if no
            * session already exists.
            */
           session = httpServletRequest.getSession(true);
           session.setAttribute("logedin", "0");    // public user

           filterChain.doFilter(httpServletRequest, httpServletResponse);

     } else {

             httpServletResponse.sendRedirect("http://www.google.com");


      }

}
我使用isNew check是因为我想这样做,如果用户第一次进入您的站点,比如打开他的浏览器,那么他没有看到重定向消息,尽管他的会话由于关闭浏览器而过期


谢谢

HHmm实际上我的网站场景是,我为所有用户提供了相同的页面,但是当您为登录用户登录时,页面上会显示一些选项。文件夹中没有页面。与注册用户一样,我的页面位于registeredUsers文件夹中,而对于未注册用户,我的页面位于unRegisteredUsers文件夹中。事实上,坦率地说,这是我第一次研究JavaEE和JSF2.0:。这就是为什么我也不知道JavaEE的良好实践:这仍然可以工作,您可以在托管bean中使用代码来隐藏或显示某些元素,具体取决于会话中用户对象的角色。我认为您的困惑在于您假定会话与经过身份验证的会话相同。不一定:我没有理解你…我假设会话与经过身份验证的会话相同是什么意思。现在我的问题是,如何在会话超时时将注册用户重定向到重定向页面,而不对公共用户执行任何操作。我也编辑了我的帖子。您可以看到我是如何完成会话的。@BalusC Hi抱歉,您是对的,我正在使用Majorra 2.0.2。当我的GlassFish容器运行时,它将初始化Majorra 2.0.2。无论如何,再次抱歉,那一次我不知道,并对你说我没有使用Majorra。