Как разработать безсессионное веб-приложение JSF 2.0? - PullRequest
0 голосов
/ 02 декабря 2011

Я работаю над сайтом JSF 2.0. Сайт имеет два вида пользователей (публичный и зарегистрированный). Теперь я хочу знать, как я могу создать сеанс для обоих типов пользователей? Для зарегистрированных пользователей, когда мой пользователь является логином, для него должен быть сеанс, а когда сеанс истекает, я перенаправляю его на страницу, на которой истек срок вашего сеанса. Для публичных пользователей не должно быть никакого сеанса вообще. Означает, что у моих публичных пользователей нет времени ожидания сеанса, и у них никогда нет сообщений о том, что ваш сеанс истек. Как я могу реализовать это поведение в JSF 2.0.

Могу ли я использовать фильтр для него или есть лучший подход к нему? Я также читал, что JSF автоматически создает сеанс с использованием управляемых компонентов. Могу ли я использовать эти сеансы для своей задачи?

Edit:

Я расскажу вам, что я сделал, чтобы вы, люди, лучше направляли меня в этом сценарии

Что я сделал, я вставил фильтр в свое веб-приложение, как это

<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>

Вот мой код фильтра

public class SessionTimeoutFilter implements Filter {

    // This should be your default Home or Login page
    // "login.seam" if you use Jboss Seam otherwise "login.jsf"   
    // "login.xhtml" or whatever
    private String timeoutPage = "faces/SessionExpire.xhtml";
    private String welcomePage = "faces/index.xhtml";
    public static Boolean expirePage = false;
    private FilterConfig fc;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

        this.fc = filterConfig;

    }

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

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

        HttpSession session = httpServletRequest.getSession();

        /**
         * The session objects have a built-in data structure (a hash table) in which you can store
         * any number of keys and associated values. You use session.getAttribute("key") to look up
         * a previously stored value. The return type is Object, so you must do a typecast to
         * whatever more specific type of data was associated with that attribute name in the session.
         * The return value is null if there is no such attribute, so you need to check for null
         * before calling methods on objects associated with sessions.
         *
         * Note:
         *     JSF session scoped managed beans are under the covers stored as a HttpSession
         *     attribute with the managed bean name as key.
         */
        Login login = (Login)session.getAttribute("login");

        if (login == null) {  // No such object already in session

            filterChain.doFilter(request, response);

        } else {

            /**
             * If you use a RequestDispatcher, the target servlet/JSP receives the same
             * request/response objects as the original servlet/JSP. Therefore, you can pass
             * data between them using request.setAttribute(). With a sendRedirect(), it is a
             * new request from the client, and the only way to pass data is through the session or
             * with web parameters (url?name=value).
             */
            filterChain.doFilter(request, response);

        }

        System.out.println();

    } //end of doFilter()

    @Override
    public void destroy() {

    } //end of destroy()

Теперь, что произойдет, если вы впервые введете 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

когда пользователь впервые заходит на мой сайт, то это не логин, поэтому я установил атрибут сессии logedin 0. Теперь предположим, что пользователь вводит учетные данные и нажимает кнопку входа в систему. Сначала мой фильтр вызывается, но на этот раз он получает атрибут входа в систему и приходит к моей проверке doFilter () else, а затем приходит к методу My validUser (). Вот мой код

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()

Теперь я хочу спросить одну вещь. Я устанавливаю sessionTimeout, используя setMaxInterval. Это нормально или лучше делать в web.xml? Теперь, когда timeOut истекает, фильтр не запускается. Но предположим, что я также прикрепляю HttpSessionListener. Затем во время сеанса Out вызывается метод уничтожения. Я могу аннулировать сессию здесь. Вот так.

public class MySessionListener implements HttpSessionListener {

    // Constructor
    public MySessionListener() {

    } //end of constructor

    @Override
    public void sessionCreated(HttpSessionEvent event) {

        System.out.println("Current Session created : " + event.getSession().getCreationTime());
        System.out.println();


    } //end of sessionCreated()

    @Override
    public void sessionDestroyed(HttpSessionEvent event) {

        // get the destroying session...
        HttpSession session = event.getSession();

        if (session != null) {

            session.invalidate();

        }

        System.out.println();

    } //end of sessionDestroyed()

} //end of class MySessionListener

Но по истечении сеанса я также хочу перенаправить пользователя на страницу перенаправления, если это зарегистрированный пользователь. Если это публичный пользователь, я не хочу его перенаправлять, хотя сессия истекла. Я могу проверить метод уничтожения, получив атрибут logedin, что он является публичным или зарегистрированным пользователем. Но тогда как я могу перенаправить для зарегистрированного пользователя или ничего не делать для публичного пользователя.

Если каким-то образом мой фильтр вызывается по истечении времени сеанса, и каким-то образом я могу проверить, что если это зарегистрированный пользователь, получив атрибут logedin 1 и время сеанса истекло, потому что для общедоступного пользователя я установил тайм-аут -1, затем перенаправьте пользователя , используя RequestDispatcher, также выполните filterChain.doFilter (запрос, ответ);.

Так что это сценарий, который я реализовал. Я не знаю, правильны ли мои подходы или нет? Я не знаю, с какими проблемами безопасности я столкнусь при таком подходе. Вот и все .. Теперь вы, люди, направляете меня, что мне делать .....

Спасибо

Ответы [ 2 ]

0 голосов
/ 09 декабря 2011

Я использовал кое-что как это.Сначала есть фильтр.Вот мой фильтр

@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 моего сайта, этот фильтр запускается.В первый раз он получает нулевую сессию, а затем проверяет время ожидания сессии.нет времени ожидания сеанса, поэтому он создает сеанс.Установите для атрибута logedin значение 0, это означает, что это публичный пользователь, и передайте запрос.Вот мой метод

//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()

Я переопределяю значение атрибута logedin на 1, так что теперь пользователь становится действительным пользователем.Теперь, если действительный пользователь делает запрос, тогда мой фильтр вызывает, он получит сеанс, так что он приходит к моей проверке isRegisterdUser, на этот раз он получает значение 1, поэтому просто передайте запрос. Теперь, когда время сеанса истекло, и пользователь делает любой запрос, тогда мой фильтрвызвать и на этот раз он входит внутрь проверки

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

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

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

        } else {

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

            filterChain.doFilter(httpServletRequest, httpServletResponse);

        }

и перенаправить пользователя, сделав его публичным.Так вот как это я делаю.Я также получил идею, что через некоторое время я обновляю страницу, у меня есть sessionCreationTime, sessionLastAccessTime и sessionMaxTime.так что я могу сделать такую ​​работу

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 (), потому что я хочу сделать это, если пользователь заходит на ваш сайт впервые, например, открывает свой браузер, затемон не видел сообщения о перенаправлении, хотя его сеанс истек из-за закрытия браузера.

Спасибо

0 голосов
/ 02 декабря 2011

Я понимаю, какова ваша цель, но я не думаю, что отсутствие сессии для неаутентифицированных пользователей является особенно лучшим подходом.

Рассмотрим пользователя без аутентификации, который перемещается по мастеру Primefaces, поскольку он предоставляет информациюзарегистрируйте учетную запись (например, выберите имя пользователя, введите пароль, выберите вопросы безопасности и т. д.)

Вы не захотите сохранять эту информацию пользователя, пока она не будет собрана и проверена,потому что, возможно, пользователь изменил свое мнение и решает не регистрироваться?Теперь у вас есть неполная запись пользователя в вашей базе данных, которую необходимо очистить.

Ответ заключается в том, что вам нужно хранить эту информацию в компоненте ViewScoped или в сеансе, пока не прошедший проверку подлинности пользователь не подтвердит создание учетной записи, где оннаконец-то можно настаивать.

Я считаю, что лучшим подходом для вас было бы дать вам User уникальный Role с одной ролью Unauthenticated.Используя такие компоненты, как Spring Security 3 или даже Seam, вы сможете контролировать Авторизацию страниц через Role из User в Session.

Например, вы можете запретить неаутентифицированным пользователям входить на страницы в * 1016.* или обычным пользователям доступ к страницам в ../admin/*

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...