【问题标题】:how to obtain JSF app username from stateless session bean如何从无状态会话 bean 获取 JSF 应用程序用户名
【发布时间】:2026-01-25 19:45:01
【问题描述】:

在我们的应用程序中,我们使用 JSF 和 EJB 3.0 (EclipseLink 2.0)。我们需要对无状态会话 bean 中的每个连接使用 Oracle 代理授权。为此,我们需要获取数据库用户名以通过代理连接。 DB 用户名由 JSF 认证的用户名通过规则构造而成。

这是一篇关于主题http://blogs.oracle.com/olaf/2010/04/using_oracle_proxy_authenticat.html的文章

因此,当经过身份验证的用户调用 JSF 托管 bean 方法时,该方法又调用某个会话 bean 方法,他的用户名必须以某种方式传递给会话 bean。

目前我有两个不太好的解决方案: - 在每个会话 bean 方法中传递用户名作为参数(不是很整洁,但会起作用); - 上篇文章的解决方案:使用会话bean的类成员变量来存储用户名(不是线程安全的,有潜在危险)

附:我找到了使用线程局部变量的解决方案:_http://www.adam-bien.com/roller/abien/entry/how_to_pass_context_with 它工作正常,但仍然存在问题。我需要在每次调用 ejb 会话 bean 之前将当前用户名放在每个 jsf 会话托管 bean 中,因为它必须在同一个线程中。

【问题讨论】:

    标签: java jpa proxy


    【解决方案1】:

    如果您的用户已通过容器身份验证,您可以使用注入的 javax.ejb.SessionContext 实例访问 ejb 中的用户名,如下所示:

    @Resource
    private SessionContext context;
    
    private String getCurrentUsername() {
        return context.getCallerPrincipal().getName();
    }
    

    编辑: 如果身份验证是通过 login-config 和 security-constraint 元素在 web.xml 中配置的,则此方法有效。如果您自己进行身份验证,则可以使用覆盖 getUserPrincipal、getRemoteUser 和 isUserInRole(在 glassfish 中测试)的 ServletFilter 和 HttpServletRequestWrapper。

    如果您在 jsf bean 中处理身份验证,那么这可能不起作用,因为 ejb 已经初始化并注入。但是,您也可以创建一个会话范围的 ejb,它只保存用户名并将这个 bean 注入到您的无状态 bean 中。

    【讨论】:

    • 非常感谢,乔恩。在我看来,您的解决方案非常简洁。附言你能告诉我 SessionContext 什么时候不包含当前的 web 层用户名吗?