我将 Java EE 6 与所有参考实现一起使用。对某些页面(例如下面的所有内容)进行了一些安全限制/secure/*
。这是粗粒度的安全性。例如,如果两个用户都具有相同的角色,但同一页面的某些内容应该只对用户“John”可见怎么办?或者应该向“约翰”显示一个完全不同的页面?我有很多问题没有得到解答,所以如果有人能提供一些链接/解释或涵盖这个问题的书籍,那就太好了。我需要更细粒度的安全控制。
4 回答
您希望的细粒度安全功能不仅存在,Oracle 甚至还有一篇有用的博客文章详细介绍了该主题,并附有示例代码。
而且因为简单地链接文档并运行对我来说是简洁和不礼貌的,所以接下来是一些关于如何根据我的理解结合在一起的讨论。
第0个问题:粗粒度、声明式安全
声明式安全性的最大问题是它迫使您在设计时迭代地定义所有用户角色。这是非常不可取的,原因有两个:首先,它无法正确地将您的安全模型从您的实现中抽象出来(未能充分地为您的应用程序提供面向未来的证明,并为信息泄露漏洞打开大门),其次,它将您的用户角色束缚在应用程序的直接设计,通常无法在需要或必要时提供细粒度的权限或ACL 。
实际上,这是一个抽象不足的问题。您正在使用的系统可以立即满足您当前的需求,但由于角色变得更加复杂并且代码库的复杂性不断增加,您无法期望在应用程序的生命周期内可以使用或维护该系统。
使用托管 Bean 的细粒度安全性
这里的一阶解决方案是使用一个抽象模型,该模型允许您在每个 JSF 方法调用的上下文中独立定义用户角色,允许您根据需要将它们换入或换出。作为奖励,这允许您定义更细粒度的权限,因为这样的方案允许您定义每个方法而不是每个视图、每个端点或每个 bean 的权限。如果角色改变?您只需要在一个位置更新您的权限模型,而不是去每个这些 bean 并换出它们的用户定义。
前面链接的文章比我愿意在这里介绍的要详细得多,所以我强烈建议阅读博客文章。但是这里的要点是,要正确执行此操作,您应该同时提供身份验证堆栈和详细说明权限角色的注释层,并且这两者只应在您明确且有意连接两者的地方相遇。
定义细粒度的方法调用和有意义的安全策略留给读者作为练习,但如果您在这方面有任何疑问,请随时在评论或一组后续问题中提出,如这些问题本质上对广大受众有用。
改进
可以想象,此解决方案不足以满足您的需求。例如,如果您希望使用LDAP或Kerberos对用户进行身份验证以提供用户和角色的统一表示,那么这仅提供了部分解决方案来满足您的需求。该领域中存在一些重要的 资源,但这留给读者作为练习。
这里的最终结论是,在完美的世界中,这就是您的应用程序安全性应该被定义的方式。您的需求可能会有所不同,对于小规模的东西,简单的声明式安全性可能足以满足您的需求。毕竟,这就是它继续存在的原因。
但是,对于必须安全、正确地满足大量用户需求的大型应用程序,这是正确的方法。它需要更多的知识和开销,但如果你从正确开始,它将为你节省大量的时间、精力和挫败感。
与往常一样,祝您的申请好运。
最简单的方法是
<h:panelGroup rendered="#{request.userPrincipal.name == 'user1'}">
<p>Content for user 1</p>
</h:panelGroup>
<h:panelGroup rendered="#{request.userPrincipal.name == 'user2'}">
<p>Content for user 2</p>
</h:panelGroup>
显示同一页面的多个版本与安全性无关(不同版本!=链接隐藏),限制访问和需要额外授权,如果您不介意,我会回答。
您可以在 JAAS 页面上了解这两者(身份验证、授权)。它也是我认为最好的框架。掌握它需要一些时间,但在那之后,它就很容易了,你甚至会意识到它根本不是重量级的——你不必被迫使用每一个功能。(就像 EJB 一样)
JAAS 甚至可以使用 ldap 或 windows 帐户登录您,甚至支持多个身份验证步骤 - 您可以实现 pass+sms 登录。当然,即使使用acegi也可以做到这一点(这并不容易)
由于您已经提到过 JSF,所以 JAAS 比 acegi 更适合,您可以使用@RolesAllowed注释任何支持 bean,如果用户会话不满足要求,则会抛出 SecurityException。这适用于 servlet 和 bean(ejb,支持),不适用于 jsps(但无论如何它没有多大意义)
您可以在此处阅读有关@RolesAllowed 的信息,但如果您已经在考虑它,请不要错过JBoss Seam Security - 它建立在安全注释和 JAAS 之上,而且使用起来也很容易上瘾。值得一读。
顺便说一句:我不是嫖客,只是发现了一个有趣的问题,所以......随时为赏金而战:)
通常这种内容会保存在会话变量中。因此,您不必考虑登录的是什么用户。