Java EE、JSF 以基于表单的编程方式登录不会重定向到生产环境中的用户主页

问题描述

我正在开发一个具有多个不同用户配置文件/角色的项目。安全性是基于领域的,并且使用了表单身份验证。当用户成功登录时,必须根据用户的角色将其重定向到他/她的主页。

所有这些都在我的开发环境中完美运行。我将 Netbeans IDE 与 Payara 5 应用服务器运行时一起使用。

为了将测试版投入生产,我使用了一台安装了 Payara 5 完整版的 Ubuntu 机器。在那之后(服务器配置,领域,jdbc 连接,...)我意识到当用户成功登录并被重定向到他/她的主页时,登录表单再次出现并且用户无法访问他的主页。

这是我的 web.xml 文件的摘录:

        <servlet>
            <servlet-name>Faces Servlet</servlet-name>
            <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
            <load-on-startup>1</load-on-startup>
        </servlet>    
        <servlet-mapping>
            <servlet-name>Faces Servlet</servlet-name>
            <url-pattern>*.xhtml</url-pattern>
        </servlet-mapping>    
        <welcome-file-list>
            <welcome-file>index.xhtml</welcome-file>
        </welcome-file-list>
       <login-config>
            <auth-method>FORM</auth-method>
            <realm-name>MyRealmName</realm-name>
            <form-login-config>
                <form-login-page>/authentication/login.xhtml</form-login-page>
                <form-error-page>/authentication/error.xhtml</form-error-page>
            </form-login-config>
        </login-config>
        <security-constraint>
        <web-resource-collection>
            <web-resource-name>Admin portal</web-resource-name>
            <url-pattern>/subfolder/*</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <role-name>role_admin</role-name>
        </auth-constraint>
    </security-constraint>    
    <session-config>
        <session-timeout>
            5
        </session-timeout>
    </session-config>

为了将组名与角色名映射,我使用了这个文件“glassfish-web.xml”

<glassfish-web-app>   
    <context-root>/WebAppDeplo</context-root>    
    <security-role-mapping>
        <role-name>role_admin</role-name>
        <group-name>ADMINISTRATOR</group-name>
    </security-role-mapping>  
</glassfish-web-app>

最后是login()方法代码

private static String HOME = "/subfolder/index.xhtml?faces-redirect=true";

// ...

public void login() throws IOException {
        ExternalContext externalContext
                = FacesContext.getCurrentInstance().getExternalContext();
        HttpServletRequest request = (HttpServletRequest) externalContext.getRequest();
        
        log.debug("[bean] - login()");
        
        try{
            request.login(this.userName,this.password);
            // Authentication OK
            String url = extractcontextpath() + HOME;
            log.debug("[bean] - login() - login OK - redirecting to: " + url);
            externalContext.redirect(url);
        }catch (servletexception e){
            // Authentication Failed
            log.debug("[bean] - login() - Authentication Failed!");
            String loginErrorMessage = e.getLocalizedMessage();
            FacesContext.getCurrentInstance()
                    .addMessage(null,new FacesMessage(loginErrorMessage));
        }
    }

    private String extractcontextpath() {
        ExternalContext externalContext
                = FacesContext.getCurrentInstance().getExternalContext();
        return externalContext.getRequestcontextpath();
    }

几个想法:

a) 在 web.xml 上使用 BASIC 身份验证。它工作正常!不幸的是,需要以编程方式登录,因为必须记录不同的用户角色并将其重定向到基于角色的主页。

b) 身份验证机制工作正常,因为如果输入了错误登录信息,则会抛出 servletexception。当提供了正确的用户时,日志文件中会打印调试消息“[bean] - login() - login OK...”。在日志文件中没有看到其他错误

c) 我已经尝试了几个静态变量 HOME 的值:“/subfolder”、“/subforlder/index”、...所有这些选项在开发环境中都可以正常工作,但在生产环境中却没有。

d) 我已经尝试过 Payara 5.201 和 Payara 5 5.2021.3 以避免特定版本的服务器错误

e) 令我不安的是,在开发环境中,这东西运行良好! :-(

我很感激你能提出的关于这个问题的任何想法。

解决方法

我会自动回答我的问题,因为我想我已经找到了解决这个问题的重要线索。 我意识到在访问生产部署时,不会在浏览器中创建会话 cookie。 因此,我在 web.xml 中找到了一个允许自定义会话 cookie 名称的参数。 键入此参数身份验证(基于表单,并重定向到用户主页)工作正常。 这是受影响的 web.xml 片段:

    <session-config>
        <session-timeout>5</session-timeout>
         <cookie-config>
            <name>MY_JSESSIONID</name>
        </cookie-config>
    </session-config>