您可以在 User getter中进行延迟加载以检查 User 是否已经登录,如果没有,则检查请求中是否存在 Principal ,如果是,则获取与 j_username 关联的 User .
package com.stackoverflow.q2206911;
import java.io.IOException;
import java.security.Principal;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;
@ManagedBean
@SessionScoped
public class Auth {
private User user; // The JPA entity.
@EJB
private UserService userService;
public User getUser() {
if (user == null) {
Principal principal = FacesContext.getCurrentInstance().getExternalContext().getUserPrincipal();
if (principal != null) {
user = userService.find(principal.getName()); // Find User by j_username.
}
}
return user;
}
}
4 回答
在搜索Web并尝试了许多不同的方法之后,这就是我建议的Java EE 6身份验证:
设置安全领域:
就我而言,我有数据库中的用户 . 所以我按照这篇博客文章创建了一个JDBC领域,可以根据我的数据库表中的用户名和MD5哈希密码对用户进行身份验证:
http://blog.gamatam.com/2009/11/jdbc-realm-setup-with-glassfish-v3.html
注意:该帖子讨论了数据库中的用户和组表 . 我有一个User类,其UserType枚举属性通过javax.persistence注释映射到数据库 . 我使用userType列作为组列为用户和组配置了相同的表,并且它工作正常 .
使用表单身份验证:
仍然按照上面的博客文章,配置你的web.xml和sun-web.xml,但不使用BASIC身份验证,而是使用FORM(实际上,你使用哪一个并不重要,但我最终使用了FORM) . 使用标准HTML,而不是JSF .
然后使用BalusC的上述提示从数据库中初始化用户信息 . 他建议在托管bean中从faces上下文中获取主体 . 相反,我使用有状态会话bean来存储每个用户的会话信息,所以我注入了会话上下文:
使用主体,我可以检查用户名,并使用EJB实体管理器从数据库中获取用户信息并存储在我的
SessionInformation
EJB中 .退出:
我也四处寻找最佳退出方式 . 我发现最好的是使用Servlet:
虽然考虑到问题的日期,我的回答确实很晚,但我希望这有助于其他人来自Google,就像我一样 .
再见,
VítorSouza
问题HttpServletRequest.login does not set authentication state in session已在3.0.1中修复 . 将glassfish更新到最新版本,您就完成了 .
更新非常简单:
我想你想form based authentication使用deployment descriptors和
j_security_check
.您也可以在JSF中使用相同的预定义字段名称
j_username
和j_password
来完成此操作,如教程中所示 .例如 .
您可以在
User
getter中进行延迟加载以检查User
是否已经登录,如果没有,则检查请求中是否存在Principal
,如果是,则获取与j_username
关联的User
.User
显然可以通过#{auth.user}
在JSF EL中访问 .要注销,请执行HttpServletRequest#logout()(并将
User
设置为null!) . 您可以通过ExternalContext#getRequest()获取JSF中HttpServletRequest
的句柄 . 您也可以完全使会话无效 .对于残余(在部署描述符和领域中定义用户,角色和约束),只需按照常规方式遵循Java EE 6教程和servletcontainer文档 .
Update :您还可以使用新的Servlet 3.0 HttpServletRequest#login()进行编程登录,而不是使用
j_security_check
,某些servletcontainer中的调度程序可能无法访问这些内容 . 在这种情况下,您可以使用一个完整的JSF表单和一个带有username
和password
属性的bean以及一个如下所示的login
方法:这个视图作用域的托管bean也记得最初请求的页面:
这样
User
可以通过#{user}
在JSF EL中访问 .应该提到的是,可以完全将认证问题留给前端控制器,例如, Apache Web服务器并改为评估HttpServletRequest.getRemoteUser(),它是REMOTE_USER环境变量的JAVA表示 . 这也允许复杂的登录设计,例如Shibboleth身份验证 . 通过Web服务器过滤对servlet容器的请求对于 生产环境 环境来说是一个很好的设计,通常使用mod_jk来实现 .