我花了一整天的时间在谷歌上搜索并查看这里的各种问题,试图提出实现身份验证和授权的最佳解决方案。我现在已经提出了部分解决方案,但我希望有人可以填补空白。我知道下面有很多文字,但请多多包涵:O)
背景
我继承了一个部分完成的 CRM 应用程序,该应用程序目前使用 JSF 2.0、JavaEE 6、JPA 和 PostgreSQL 数据库。不幸的是,最初以无限智慧开始构建这个网络应用程序的人决定最好将身份验证/授权留到最后——我现在必须把它放进去。
应用程序基本上分为三层——视图、托管 bean 和 DAO。这意味着托管 bean 特别“胖”,因为它们包含所有业务逻辑、验证和导航逻辑。
身份验证/授权要求
- 基于表单的身份验证,针对存储在 PostgreSQL 数据库中的凭据进行验证。
- 唯一可以公开访问的页面(匿名用户)将是登录页面。
- 我需要根据用户角色阻止访问应用程序的某些区域。例如,只有具有“管理员”角色的用户才能访问创建/编辑用户页面。
- 我还需要能够限制对页面某些区域的访问。例如,具有“销售代表”角色的用户应该能够查看客户详细信息,但只有当用户具有“客户服务”角色时才应显示保存/编辑按钮。
我在哪里
我计划做的第一件事是遵循这个使用 JAAS 和 Servlet 3.0 登录示例的用户身份验证和授权。我相信这将满足我的前 3 个要求。
为了在页面上显示/隐藏保存按钮等,我可以使用此 SO answer中描述的技术。这将部分解决需求 4,但是我认为我仍然需要保护操作方法和/或托管 bean 本身。例如,我希望能够在客户 bean 上的 save() 方法中添加注释或其他内容,以确保只有具有“客户服务”角色的用户才能调用它——这就是我开始遇到问题的地方.
我想一种选择是做类似于我提议在视图中做的事情,并使用 facesContext 检查当前用户是否“在角色中”。我对此并不热衷,因为它只会弄乱我的代码,而宁愿使用注释。但是,如果我确实沿着这条路线走,我将如何返回 http 403 状态?
javax.annotation.security.* 注释似乎非常适合以声明方式定义对应用程序区域的访问,但据我了解,它们只能添加到 EJB 中。这意味着我需要将我的所有业务逻辑从它当前所在的托管 bean 中移到新的 EJB 中。我认为这将具有将业务逻辑分离到它自己的一组类(委托、服务或您选择调用它们的任何内容)中的额外好处。这将是一个相当大的重构,但是不会因为缺少单元测试或集成测试而有所帮助。我不确定访问控制的责任是否应该在这个新的服务级别上——我认为它应该在托管 bean 上。
其他选择
在我的研究中,我发现很多人提到了 Spring 和 Seam 等框架。我对 Seam 的经验有限,我认为它非常适合这个项目,据我回忆,我相信它解决了我遇到的授权问题,但我认为现在介绍它为时已晚.
我也看到很多地方都提到了Shiro。看了10 分钟的教程,这似乎很合适,尤其是与Deluan Quintao 的 taglib结合使用,但我一直找不到任何教程或示例来说明如何将其与 JSF Web 应用程序集成。
我经常出人意料地遇到的另一种选择是实施自定义解决方案 - 这对我来说似乎很疯狂!
概括
总而言之,我真的很想得到一些指导,说明我在实现身份验证和授权方面是否走在正确的道路上,以及我如何填补保护单个方法和/或托管 bean 的缺失部分(或者至少是他们委托给的代码)和/或我如何手动返回 HTTP 状态 403。