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