我从JSF页面调用了一个Java doLogin()
方法,该方法从用户获取id(String netId
)和密码(String password
)。 doLogin()
使用netId
作为Active Directory登录中的主体来启动身份验证。之后,我想从保护我的应用程序的目录中获取除主体名称之外的其他属性。
我的安全性是在容器和配置中配置的。它有效,
HttpSession ses = FacesContext.getCurrentInstance().getExternalContext().getSession (false);
HttpServletRequest req = FacesContext.getCurrentInstance().getExternalContext().getRequest();
req.login(netID, password);
成功并且
req.getUserPrincipal().getName();
返回用户netID
。但是,我的应用仅使用netId
进行身份验证。访问另一个数据库的应用程序的其他部分需要其他属性(例如commonName
)。我想做像
usefulLDAPobj = *getLDAPSession from "somewhere" in the HTTP Session, the FacesContext or some other available object*
String cn = usefulLDAPobj.getAttributeFromProfile ("cn");
ses.setAttribute("username", cn);
从此开始使用用户名,存储在会话中,在我的Hibernate ORM中。
我知道简单的usefulLDAPobj.getAttributeFromProfile ("cn")
会更复杂,但如果能找到一个让我访问LDAP目录的起点,我可以填写。
由于容器设置了明显的LDAP连接,我觉得必须是我使用它的一种方式,而无需以编程方式手动构建LdapContext;这将要求代码知道Web服务器(JBoss EAP 6.2)已经知道的所有LDAP server / bind-DN / bind-password configuration
(来自<login-module>
中定义的standalone.xml
)。例如,getUserPrincipal()
和isUserInRole()
等方法需要访问我想要访问的同一个目录配置文件。
所以我的问题是:有没有办法从FacesContext或HTTPServletRequest获取LDAP连接或上下文,或者从HTTPServlet可以访问任何对象?
答案 0 :(得分:0)
从FacesConext获取LdapConext的最简单方法是什么?
根本没有办法,更不用说一个简单的方法了。 JSF不假设存在LDAP服务器,也不提供任何与LDAP相关的API。
由于容器设置了明显的LDAP连接
登录时。不是永久性的。如果有LDAP服务器的话。并且JSF不知道容器如何登录你。
我觉得必须有办法...
没有。
答案 1 :(得分:0)
我认为这个问题的一个有用的答案是没有办法直接从LDAPContext
获取FacesContext
,而是通过编写特定于容器的登录模块和{ {1}}类,您可以通过Principal
获得的HttpServletRequest
传递其他数据。
我会在此处提供我的解决方案的详细信息,因为即使它与FacesContext
没有直接关系,它也能解释我在问题正文中要求的内容,即从LDAP配置文件获取其他用户数据的方法,同时避免创建一个完整的单独FacesContext
。
我特别想要的是LDAPContext
,我可以解析CN
而无需进行额外搜索。如果我需要任何其他数据,我认为我可以使用下面DN
中的ctx
来获取该数据。
我想我的应用依赖于findUserDN()
这个解决方案,如果这是不可取的,我会搜索一个JBoss
- 独立的登录模块类来扩展(不知道是否会这样)简单,困难或不可能)。
这是我的解决方案:
在AdvancedADLoginModule中覆盖findUserDN(LdapContext ctx)
JBoss
extend Principal以提供displayName属性
package ca.mycompany.myapp.jboss;
import java.security.Principal;
import javax.naming.ldap.LdapContext;
import javax.security.auth.login.LoginException;
import org.jboss.security.negotiation.AdvancedADLoginModule;
public class NameFetchingADLoginModule extends AdvancedADLoginModule
@Override
protected String findUserDN(LdapContext ctx) throws LoginException
{
String lclUserDN = super.findUserDN(ctx);
Principal principal = getIdentity();
if (principal instanceof PrincipalWithDisplayName)
{
String displayName = lclUserDN.substring(3, lclUserDN.indexOf(','));
((PrincipalWithDisplayName) principal).setDisplayName (displayName);
}
return lclUserDN;
}
}
在doLogin()方法中使用新的登录模块和Principal
片段:
package ca.mycompany.myapp.jboss;
import java.io.Serializable;
import java.security.Principal;
public class PrincipalWithDisplayName implements Serializable, Principal
{
private static final long serialVersionUID = 1L;
private final String name;
// additional attribute provided by this subclass
private String displayName;
public PrincipalWithDisplayName(final String name) {
this.name = name;
}
// new and overriding getters and setters, equals() and hashCode() removed for brevity
}
String displayName = "";
HttpSession ses = FacesContext.getCurrentInstance().getExternalContext().getSession (false);
HttpServletRequest req = FacesContext.getCurrentInstance().getExternalContext().getRequest();
try {
req.login(userName, password); // this throws an exception if authentication fails
Principal lclUser = req.getUserPrincipal();
if (lclUser instanceof PrincipalWithDisplayName)
{
displayName = ((PrincipalWithDisplayName) lclUser).getDisplayName ();
}
// get Http Session and store username
//
HttpSession session = HttpUtil.getSession();
sess.setAttribute("username", displayName);
...
中配置JBoss EAP 6.2
以使用新类片段:
standalone.xml