gpt4 book ai didi

java - 在 Linux 上的 java 中针对远程 Activity 目录的身份验证

转载 作者:太空宇宙 更新时间:2023-11-04 11:02:37 24 4
gpt4 key购买 nike

我的场景与这个问题 How to authenticate users with a customer's (remote) active directory server 中描述的类似, 除了我们的 Web 应用程序是基于 Java 并在 CentOS Linux 下运行。

我一直在搜索和阅读大量内容,但似乎无法找到对我的场景有用的信息,原因如下:

  1. 虽然基于 Java 的应用程序有不同的解决方案来针对 AD 进行身份验证(Kerberos、NTLM、来自 Authenticating against Active Directory with Java on Linux 的 LDAP),但我认为它们不适用于我认为的远程 AD 身份验证阅读。
  2. 据说 Kerberos 是 Microsoft 推荐的用于 AD 身份验证的"new"机制。但是,它似乎需要 conf 文件或系统属性才能工作。我们的 Web 应用程序是基于 SaaS 的,因此相同的代码库将服务于多个客户,而且我没有看到让 Kerberos 很好地工作的好方法(即使它支持远程身份验证,我没有看到)。
  3. 产品 Jespa 使用基于 NTLMv2 的身份验证(同样,我没有看到它支持远程身份验证),这是“旧的”并且 Microsoft 不再推荐。此外,它还需要创建一个“计算机帐户”。
  4. Okta 有一个解决方案适用于我面临的远程场景。但是,它需要在客户的 AD 服务器上安装“AD 代理”,以处理“AD 代理”与我们 Web 应用程序中的 Java 库之间的所有 SAML 通信。对于我们的客户来说,在他们不是客户的基础设施中安装软件绝对是一个问题。

现在,根据我最近的阅读,组织的最佳安全实践是将 Active Directory 服务器隐藏在防火墙后面,并且不要将其暴露在 Internet 上。我想知道这是否意味着无论工具和库如何,都不会有远程 Active Directory 身份验证集成的“直接”路径,并且需要驻留在客户基础架构中的某种受信任的代理或代理来促进远程身份验证。

欢迎大家提出意见和建议!

最佳答案

我们可以通过 LDAP 协议(protocol)访问远程 AD。在我的场景中,我在远程服务器上配置了 LDAP。我已经安装了 Apache Active DS 来在我这边创建一个远程目录实例。因此,我可以在最后获得配置详细信息。为此,我们需要域名和绑定(bind)凭据。您可以下载Apache Directory for Linux从此链接创建新连接。参见 LDAP Connections to Active Directory Using Apache Directory Studio

Tomcat 的 LDAP 配置:

Sample JNDIRealm configuration for Tomcat 7 - Apache.org

在Tomcat conf 目录下的server.xml 文件中的Host 开始和Host 结束标记之间添加您想要的Realm 配置。例如,

<Host name="localhost"  appBase="webapps"
unpackWARs="true" autoDeploy="true">
<Realm className="org.apache.catalina.realm.JNDIRealm"
connectionName="cn=Manager,dc=mycompany,dc=com"
connectionPassword="secret"
connectionURL="ldap://localhost:389"
userPassword="userPassword"
userPattern="uid={0},ou=people,dc=mycompany,dc=com"
roleBase="ou=groups,dc=mycompany,dc=com"
roleName="cn"
roleSearch="(uniqueMember={0})"
/>
<!-- other stuffs -->
</Host>

不要忘记在 server.xml 文件中注释掉以下条目。

<Realm className="org.apache.catalina.realm.UserDatabaseRealm"
resourceName="UserDatabase"/>

完成此操作后,就可以配置您的 Web 应用程序,它将通过 Tomcat 服务器调用 LDAP 服务器。

Web 应用程序配置:

WebContent -> WEB-INF 目录下的 web.xml 文件中添加以下条目。

<security-constraint>
<web-resource-collection>
<web-resource-name>Logging Area</web-resource-name>
<description>
Authentication Required.
</description>
<url-pattern>/*</url-pattern>
<http-method>GET</http-method>
<http-method>POST</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>*</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<role-name>*</role-name>
</security-role>
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>Authentication Required.</realm-name>
</login-config>

这是基本配置。但是,您可以使用 LDAP 映射特定用户或组。看看Mapping Roles to Users and Groups - J2EE Tutorial .您还可以通过在 web-resource-collection 标签下为其添加 url pattern 来仅向特定文件夹添加安全性

<url-pattern>/Admin/*</url-pattern> // Restrict access to Admin folder
<url-pattern>/Employee/*</url-pattern> // Restrict access to Employee folder

所有配置都已完成。现在,当您运行应用程序时,它会要求您提供登录凭证。输入并点击提交后,它将在 LDAP 服务器中搜索该用户。

Tomcat LDAP Authentication Window

在服务器上,要访问用户名,请使用以下代码片段:-

Principal principal = request.getUserPrincipal();
String userName = principal.getName();

LDAP 用户管理器 (JBOSS) 示例:

public LdapContext getLdapContext() {
// Set up environment for creating initial context
Hashtable<String, Object> env = new Hashtable<String, Object>(11);

env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
// e.g., ldap://IP address of remote m/c:10389/dc=sevenseas,dc=com
env.put(Context.PROVIDER_URL, LDAP_PROVIDER_URL + Constant.FORWARD_SLASH + LDAP_DOMAIN);

// Authenticate as User and password
env.put(Context.SECURITY_AUTHENTICATION, "simple");
// e.g., "uid=admin,ou=system"
env.put(Context.SECURITY_PRINCIPAL, LDAP_ADMIN);
env.put(Context.SECURITY_CREDENTIALS, LDAP_DEFAULT_PASSWORD);

try {
// Create initial context
ldapContext = new InitialLdapContext(env, null);
if (ldapContext == null) {
LogManager.fatal("Invalid LDAP system properties. Please contact your administrator.",
LDAPUserManager.class.getName());
}
System.out.println("Organization : " + ldapContext.getNameInNamespace());
} catch (Exception e) {
StringWriter stack = new StringWriter();
e.printStackTrace(new PrintWriter(stack));
LogManager.fatal(stack.toString(), LDAPUserManager.class.getName());
}
return ldapContext;
}

这将使用环境参数构造初始上下文以连接 LDAP 服务器。

现在,要从 AD 中获取用户数据,请使用以下代码:

try {
SearchControls constraints = new SearchControls();
constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);
String[] attrIDs = { "cn", "sn", "givenName", "uid", "mail", "userPassword" };

constraints.setReturningAttributes(attrIDs);

// Search for user in LDAP server by emailId
NamingEnumeration<SearchResult> answer = ldapContext.search(LDAP_GROUP, "mail=" + emailId, constraints);
if (answer.hasMore()) {
LogManager.info("User with email id '" + emailId + "' found.", LDAPUserManager.class.getName());

Attributes attrs = answer.next().getAttributes();

userDTO = new UserDTO();

// Store user details temporarily
Attribute firstNameAttr = attrs.get("givenName");
String firstName = "";
if (firstNameAttr == null) {
userDTO.setFirstName(firstName);
} else {
firstName = firstNameAttr.get().toString();
if (firstName == null) {
userDTO.setFirstName("");
}
userDTO.setFirstName(firstName);
}

Attribute lastNameAttr = attrs.get("sn");
String lastName = "";
if (lastNameAttr == null) {
userDTO.setLastName(lastName);
} else {
lastName = lastNameAttr.get().toString();
if (lastName == null) {
userDTO.setLastName("");
}
userDTO.setLastName(lastName);
}

return userDTO;
} else {
LogManager.fatal("Invalid User.", LDAPUserManager.class.getName());
return userDTO;
}
} catch (Exception e) {
StringWriter stack = new StringWriter();
e.printStackTrace(new PrintWriter(stack));
LogManager.fatal(stack.toString(), LDAPUserManager.class.getName());
}

希望对你有帮助

关于java - 在 Linux 上的 java 中针对远程 Activity 目录的身份验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26389358/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com