Проблема с сессиями на моем сайте после перехода с HTTP на HTTPS - PullRequest
0 голосов
/ 16 января 2020

У меня есть сайт, использующий Java Сервлет и JSP, работающий на сервере apache tomcat8, я также использую Springboot 5 в качестве фреймворка и Hibernate в качестве ORM для получения информации в базе данных.

На этом сайте я использую атрибуты сеанса для управления информацией аутентификации пользователей (вместо, например, файлов cookie). У меня также есть Springboot Filter, который перехватывает ВСЕ traffi c на моем сайте, чтобы контролировать доступность запрашиваемой страницы определенным пользователем или нет.

Подробно, я реализовал 3 уровня проверок, там являются "административными" страницами, доступными только администраторам, "зарегистрированными" страницами, доступными для всех зарегистрированных пользователей, и всеми остальными страницами, доступными для всех пользователей, которые посещают мой сайт.

Когда пользователь заходит на мой сайт, для каждого запроса, который он отправляет на сервер, фильтр Springboot перехватывает запрос и проверяет, доступна ли запрашиваемая страница этому пользователю, проверяя атрибуты сеанса и «уровень безопасности страницы» (извините за имя, но я не знаю, как называть это). Если у пользователя нет прав на вход, он перенаправляется на страницу входа. Код выглядит следующим образом:

LoginServlet : вызывается путем отправки стандартной формы входа в систему при входе в систему. jsp

public class loginServlet extends HttpServlet{

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
        String email = request.getParameter("email");
        String password = request.getParameter("password");

        /* Controls if User Exist in the Database based on username and password */

        if(/* userNotExist */){

            /*the attributes setted here is used in the login.jsp page to show 
            a login error message, or not in case the attributes are not setted*/

            request.getSession().setAttribute("login.successfull", "LOGIN.ERROR");
            request.getSession().setAttribute("logged", false);
            response.sendRedirect("login.jsp");
        }

        else { //user Exist
            //get the old session and invalidate if exist
            HttpSession oldSession = request.getSession(false);
            if (oldSession != null) {
                oldSession.invalidate();
            }

            //generate a new session
            HttpSession newSession = request.getSession(true);

            //setting session to expiry in 10 mins
            newSession.setMaxInactiveInterval(10*60);


            /*Setting Attributes for this Session*/
            newSession.setAttribute("login.successfull", "LOGIN.OK");
            newSession.setAttribute("logged", true);
            newSession.setAttribute("is.admin", workUser.getAdminVal());
            newSession.setAttribute("user.username", workUser.getUsername());
            newSession.setAttribute("user.email", workUser.getEmail());
            newSession.setAttribute("user.uid", workUser.getUid());

            /*Redirecting to survey page*/
            response.sendRedirect("survey.jsp");
        }

Когда пользователь выполняет вход в систему правильно, затем он перенаправляется на страницу опроса. jsp (страница доступна только зарегистрированным пользователям). Это перенаправление перехватывается authenticationFilter , который управляет атрибутами сеанса, которые были только что установлены в LoginServlet:

public class AuthenticationFilter implements Filter {

    private ServletContext context;

    public void init(FilterConfig fConfig) throws ServletException {
        this.context = fConfig.getServletContext();
        this.context.log("AuthenticationFilter initialized");
    }

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {


        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse res = (HttpServletResponse) response;

        HttpSession session = req.getSession(false);



        /* Retrieving page security level (checking a config.properties file) */

        /* Retrieving requested page URI */
        String requested_page = req.getRequestURI();

        if(/* Page is accessible without login*/) {
            //showing page clear, no login required
            chain.doFilter(request, response);

        }

        else if (/* Page is accessible by logged users*/ ){
            //login required
            //check if user logged
            if(!accessAuthorization(session, "logged")) {
                //user not logged
                this.context.log("Unauthorized access request");

                //redirect to the login page
                req.getSession().setAttribute("login.successfull", "LOGIN.REQUIRED");
                res.sendRedirect("login.jsp");

            }
            else {
                //session exist, user logged

                chain.doFilter(request, response);
            }

        }

        else if(/* Page accessible only by administrators*/) {
            //login required, admin required too
            if(!accessAuthorization(session, "admin")) {
                //session not exist or user not admin
                this.context.log("Unauthorized access request");

                //redirect to error page
                res.sendRedirect("error.jsp");

            }
            else { //user is logged and is admin, ok!

                chain.doFilter(request, response);
            }
        }
    }

Метод accessAuthorization , используемый в AuthenticationFilter проверяет, не является ли сеанс ненулевым, и оба атрибута logged и is.admin.

Хорошо, так что до вчерашнего дня все работало правильно, на HTTP-запросах. Этим утром я переключил свой домен на HTTPS. В частности, я настроил Let's Encrypt SSL Cert для Apache в Ubuntu 18.04, следуя онлайн-руководству.

Затем в своих настройках apache2 я включил 000-default-le-ssl.conf и отключено 000-default.conf . В 000-default-le-ssl.conf я добавил прокси в virtualHost для перенаправления всех запросов на порт 443 на стандартный порт 8080, на котором запущена служба tomcat:

<IfModule mod_ssl.c>
<VirtualHost *:443>
        # The ServerName directive sets the request scheme, hostname and port that
        # the server uses to identify itself. This is used when creating
        # redirection URLs. In the context of virtual hosts, the ServerName
        # specifies what hostname must appear in the request's Host: header to
        # match this virtual host. For the default virtual host (this file) this
        # value is not decisive as it is used as a last resort host regardless.
        # However, you must set it for any further virtual host explicitly.
        #ServerName www.example.com

        ServerAdmin ### myserver@admin
        DocumentRoot ### my/document/root

        # Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
        # error, crit, alert, emerg.
        # It is also possible to configure the loglevel for particular
        # modules, e.g.
        #LogLevel info ssl:warn

        ServerName ### my.server.name
        ServerAlias ### my.server.alias

        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined

        # For most configuration files from conf-available/, which are
        # enabled or disabled at a global level, it is possible to
        # include a line for only one particular virtual host. For example the
        # following line enables the CGI configuration for this host only
        # after it has been globally disabled with "a2disconf".
        #Include conf-available/serve-cgi-bin.conf


        SSLCertificateFile ### my/certificate/file/path
        SSLCertificateKeyFile ### my/private/key/file/path
        Include /etc/letsencrypt/options-ssl-apache.conf

        ProxyRequests Off
        ProxyPreserveHost On
        ProxyPass / http://my.site:8080/
        ProxyPassReverse / http://my.site:8080/

</VirtualHost>
</IfModule>

Я ничего не изменял в конфигурационных файлах Tomcat.

Каждый раз, когда я пытаюсь войти, мой loginServlet устанавливает новый сеанс (как всегда), но теперь, когда происходит перенаправление перехватывается фильтром, сеанс пуст. Похоже, что loginServlet больше не устанавливает сеансы, что делает недоступными страницы, которые требовали разрешения для зарегистрированных пользователей. Кстати, консоль Springboot не выдает никакой ошибки, и, очевидно, сеанс недействителен где-то на этапе перенаправления. Кто-нибудь может мне помочь?

...