ejb 关于角色和身份验证的安全问题

Posted

技术标签:

【中文标题】ejb 关于角色和身份验证的安全问题【英文标题】:ejb Security questions regarding Roles and Authentication 【发布时间】:2011-11-05 08:48:19 【问题描述】:

如果有人可以帮助我解决以下问题,我将不胜感激:

    @RolesAllowed 和@DeclareRoles 注释有什么区别? 我开发了一个登录功能,用于根据数据库中的信息检查用户名和密码。但是,我想问一下如何将角色分配给经过身份验证的用户以与上述注释一起使用。

【问题讨论】:

【参考方案1】:

@RolesAllowed 和@DeclareRoles 注解有什么区别?

@RolesAllowed注解用于指定实际允许访问业务方法的角色列表。 EJB 在运行时的行为会受到此注解的影响,因为 EJB 容器会主动验证调用者是否存在于允许的角色中。此外,此注解可以在TYPEs 和METHODs 上定义,允许您定义在类或方法级别允许的角色列表。您可以在单个方法级别覆盖类的所有方法允许的角色列表。

另一方面,@DeclareRoles 注释仅用于声明角色列表;它相当于ejb-jar.xml 文件中的security-role-ref 元素。 EJB 容器不需要了解这些角色就可以对 EJB 的业务方法执行访问控制检查;相反,bean 提供者/开发者可以在isCallerInRole 测试中使用这些角色来确保程序安全。

EJB 3.1 规范对@DeclareRoles 注释进行了如下说明:

17.2.5.3 从 Bean 引用的安全角色声明 代码

Bean Provider 负责使用 DeclareRoles 注解 或部署描述符的 security-role-ref 元素 声明企业 bean 代码中使用的所有安全角色名称。 DeclareRoles 注释是在 bean 类上指定的,它 用于声明可以通过调用 isCallerInRole 进行测试的角色 从带注释的类的方法中。声明安全 角色允许 Bean Provider、Application Assembler 或 Deployer 将代码中使用的这些安全角色名称链接到安全角色 为组装的应用程序定义。在没有这个链接的情况下 步骤,将假定代码中使用的任何安全角色名称 对应同名的安全角色。

您问题的第二部分指出:

我开发了一个登录功能,可以根据数据库中的信息检查用户名和密码。但是,我想问一下如何将角色分配给经过身份验证的用户以与上述注释一起使用。

在这种情况下,需要注意的一般要点是,我的首选方法是不使用程序安全性,除非您的用例确实需要它。在大多数情况下,如果可以通过声明式安全实现要求,则最好使用它,因为程序安全性要求您跟踪isCallerInRole 方法调用,并且没有这样的调用可能会导致安全漏洞。无论哪种方式,在您的情况下,您都需要您的容器首先将数据库中的组和主体识别为可能用于访问控制检查的角色。

简单地说,EJB 客户端(Java SE 应用程序、servlet 或另一个 EJB)必须首先根据容器的安全机制验证自己,以建立调用者的Principal。因此,声明式或程序式安全性的成功使用依赖于成功的身份验证过程。在您的情况下,您需要配置容器以识别数据库中的组和用户,并将它们转换为 Principal 对象,这些对象可用于以声明性或编程方式实施访问控制。大多数容器为此目的支持一种或多种 JAAS 登录模块;例如,Glassfish 3.1 允许使用 JDBCRealm 进行此操作,而 JBoss 6.0 使用 DatabaseServerLoginModule 支持此操作。因此,您需要确定您的容器是否支持这样的登录模块,并将其配置为使用您的数据库。

请注意,在某些情况下,容器提供的登录模块可能无法满足您的需求。在这种情况下,您需要编写自己的登录模块(如果需要,还需要针对容器的接口)。

此外,您还需要将应用程序使用的角色映射到 JAAS 领域中的用户和组。例如,如果您的数据库被 JAAS 领域使用:

包含用户U1U2U3U4U5,以及 包含组G1G2G3,分别包含U1U2U3, 并且您的 EJB 允许角色 R1R2R3(通过 @RolesAllowed 注释定义)的用户访问它的方法,

然后您需要将角色映射到 JAAS 领域中的主体(用户和组)。即使角色名称与主体名称相同,也必须进行映射; Glassfish simplifies this by supporting the default principal to role mapping 将类似命名的主体(用户或组)直接映射到角色。此外,映射过程是特定于容器的,正如您可能猜到的那样,此映射是在特定于容器的部署描述符中执行的,而不是在 EJB 部署描述符 (ejb-jar.xml) 中执行的。

要完成答案,您需要为创建的每个用户分配一个角色。为简单起见,您可以创建所有用户可能属于的单个用户组。当用户根据 JAAS 领域对自己进行身份验证时,Principal 对象将包含该组。然后可以将 JAAS 领域中的组映射到 EJB 角色,并且可以在 @RolesAllowed 注释中指定角色名称。 EJB 容器将阻止数据库中不属于该组的任何用户访问带注释的方法。

【讨论】:

这是一个非常好的和彻底的答案。一项补充;在 Java EE 6+ 中,不再严格需要“针对容器的接口编写代码”。现在通过 JASPIC SPI 有 Java EE 标准化接口。【参考方案2】:

也许我的回答可能不正确并且可能不完整。但是可以在这个参考中找到 http://openejb.apache.org/3.0/security-annotations.html

声明角色 只能在班级级别使用 通过 isCallerInRole(roleName) 引用角色时,您需要更新 @DeclareRoles。

基本思路

默认情况下,业务接口的所有方法都可以访问、记录 在与否

注解在 bean 类上,而不是在业务接口上

安全注释可以应用于整个班级和/或个人 方法

使用的任何安全角色的名称必须通过以下方式声明 @DeclareRoles

@RolesAllowed 可用于类级别和方法级别来限制访问级别。

一个例子 混合类和方法级别的限制 安全注解可以同时在类级别和方法级别使用。这些规则不会叠加,因此标记 'submitPatch' 会覆盖默认的“committers”。

@Stateless
@DeclareRoles("committer", "contributor")
@RolesAllowed("committer")
public class OpenSourceProjectBean implements Project 

    public String svnCommit(String s) 
        return s;
    

    public String svnCheckout(String s) 
        return s;
    

    @RolesAllowed("contributor")
    public String submitPatch(String s) 
        return s;
    

编辑:

这里是SQLLoginModule 的代码 sn-p。您可以使用此模块作为登录模块。这样就可以遵循JAAS标准了。

在 commit 中,它会调用这个来添加主体。

subject.getPrincipals().addAll(allPrincipals);

您也可以在此处查看更多详细信息http://openejb.apache.org/3.0/security.html。

它列出了您可以选择的其他选项。

【讨论】:

感谢您的回答。你有什么想法我可以解决我的第二个问题吗? =) 嗯...我还有一个小问题。用户通过 web servlet 登录后,是否可以在他的会话 cookie 中记录这个人的角色?它会类似于“session.setAttribute(“role”, somethinghere)”吗?我的意思是我如何记录他的角色,这样他就可以访问方法而不必一次又一次地登录。 可以,但这是另一个问题。您可以选择将其保存在 cookie 或会话中。

以上是关于ejb 关于角色和身份验证的安全问题的主要内容,如果未能解决你的问题,请参考以下文章

EJB 身份验证和授权

使用spring boot(安全)和keycloak启用角色身份验证?

CloudKit 服务器到服务器身份验证 + 安全角色

关于我的 Web 应用程序的身份验证和角色的说明和同行评审

glassfish jdbcrealm身份验证中的受限页面未触发登录

Symfony 2.1.7 - 用户通过身份验证后更新安全令牌设置特定角色