首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Spring安全中的Ldap AD认证

Spring安全中的Ldap AD认证
EN

Stack Overflow用户
提问于 2022-08-04 14:02:13
回答 1查看 542关注 0票数 1

我在我的应用程序中有一个登录页面,在该页面中,我想根据Ldap AD验证输入的用户名/密码。我正在考虑创建一个绑定并获得一个上下文。如果bind成功,就意味着用户是经过身份验证的。在Java中,我实现了这样的目标:

代码语言:javascript
运行
复制
public class Test {
    public static void main(String[] args) {
        try {

            Hashtable<String, String> env = new Hashtable<String, String>();
            env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
            env.put(Context.PROVIDER_URL, "ldap://ldapserver:389");
            env.put(Context.SECURITY_AUTHENTICATION, "simple");
            env.put(Context.SECURITY_PRINCIPAL, "domain\\userId");  //coming from frontend login form
            env.put(Context.SECURITY_CREDENTIALS, password); // from login form

            LdapContext ctx = new InitialLdapContext(env, null);
            ctx.setRequestControls(null);
            NamingEnumeration<?> namingEnum = ctx.search("ou=users,ou=in,dc=global,dc=company,dc=org", "(objectclass=user)", getSimpleSearchControls());
            for (int i=0;i<1;i++) {
                SearchResult result = (SearchResult) namingEnum.next();
                Attributes attrs = result.getAttributes();
                NamingEnumeration<String> nam =attrs.getIDs();
                while(nam.hasMore()) {
                    System.out.println(nam.next());
                }
            }
            namingEnum.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    private static SearchControls getSimpleSearchControls() {
        SearchControls searchControls = new SearchControls();
        searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
        searchControls.setTimeLimit(30000);
        //String[] attrIDs = {"objectGUID"};
        //searchControls.setReturningAttributes(attrIDs);
        return searchControls;
    }
}

上面的代码非常适合我。我希望在使用spring安全性的spring引导应用程序中实现相同的功能。我尝试过多种建议的方法,但每次都会出错。

在这里,我想验证enter用户名/密码,我认为上下文绑定就足够了,所以不需要再次使用"sAMAccountName={0}“之类的东西搜索该用户,如果我错了,请纠正我。

更新

在尝试下面的代码时,我可以在日志中看到它获取用户详细信息,但在最后一段中给出了一些错误:

代码语言:javascript
运行
复制
      auth
        .ldapAuthentication()
        .userSearchFilter("(sAMAccountName={0})")
        .userDnPatterns()
        .userSearchBase("dc=global,dc=company,dc=org")
        .contextSource()
        .url("ldap://ldapserver")
        .port(389)
        .managerDn("domain\\userId")
        .managerPassword("******");

错误日志:

代码语言:javascript
运行
复制
2022-08-04 19:47:44.477 TRACE 33541 --- [nio-8080-exec-2] o.s.s.w.a.www.BasicAuthenticationFilter  : Found username 'userId' in Basic Authorization header 
2022-08-04 19:47:44.478 TRACE 33541 --- [nio-8080-exec-2] o.s.s.authentication.ProviderManager     : Authenticating request with LdapAuthenticationProvider (1/1) 
2022-08-04 19:47:44.478 DEBUG 33541 --- [nio-8080-exec-2] o.s.s.l.a.LdapAuthenticationProvider     : Processing authentication request for user: userId 
2022-08-04 19:47:44.479 DEBUG 33541 --- [nio-8080-exec-2] o.s.s.l.s.FilterBasedLdapUserSearch      : Searching for user 'userId', with user search [ searchFilter: '(sAMAccountName={0})', searchBase: 'dc=global,dc=company,dc=org', scope: subtree, searchTimeLimit: 0, derefLinkFlag: false ] 
2022-08-04 19:47:44.831 DEBUG 33541 --- [nio-8080-exec-2] o.s.l.c.support.AbstractContextSource    : Got Ldap context on server 'ldap://ldapserver' 
2022-08-04 19:47:45.241 DEBUG 33541 --- [nio-8080-exec-2] o.s.s.ldap.SpringSecurityLdapTemplate    : Searching for entry under DN '', base = 'dc=global,dc=company,dc=org', filter = '(sAMAccountName={0})' 
2022-08-04 19:47:45.252 DEBUG 33541 --- [nio-8080-exec-2] o.s.s.ldap.SpringSecurityLdapTemplate    : Found DN: CN=Kumar\, Rajesh,OU=Users,OU=IN,DC=global,DC=company,DC=org 
2022-08-04 19:47:45.253  INFO 33541 --- [nio-8080-exec-2] o.s.s.ldap.SpringSecurityLdapTemplate    : Ignoring PartialResultException 
2022-08-04 19:47:45.254 DEBUG 33541 --- [nio-8080-exec-2] o.s.s.l.a.BindAuthenticator              : Attempting to bind as cn=Kumar\, Rajesh,ou=Users,ou=IN,dc=global,dc=company,dc=org 
2022-08-04 19:47:45.254 DEBUG 33541 --- [nio-8080-exec-2] s.s.l.DefaultSpringSecurityContextSource : Removing pooling flag for user cn=Kumar\, Rajesh,ou=Users,ou=IN,dc=global,dc=company,dc=org 
2022-08-04 19:47:45.622 DEBUG 33541 --- [nio-8080-exec-2] o.s.l.c.support.AbstractContextSource    : Got Ldap context on server 'ldap://ldapserver' 
2022-08-04 19:47:45.623 DEBUG 33541 --- [nio-8080-exec-2] o.s.s.l.a.BindAuthenticator              : Retrieving attributes... 2022-08-04 19:47:45.625 DEBUG 33541 --- [nio-8080-exec-2] .s.s.l.u.DefaultLdapAuthoritiesPopulator : Getting authorities for user cn=Kumar\, Rajesh,ou=Users,ou=IN,dc=global,dc=company,dc=org 
2022-08-04 19:47:45.627 DEBUG 33541 --- [nio-8080-exec-2] .s.s.l.u.DefaultLdapAuthoritiesPopulator : Searching for roles for user 'userId', DN = 'cn=Kumar\, Rajesh,ou=Users,ou=IN,dc=global,dc= company,dc=org', with filter (uniqueMember={0}) in search base '' 
2022-08-04 19:47:45.628 DEBUG 33541 --- [nio-8080-exec-2] o.s.s.ldap.SpringSecurityLdapTemplate    : Using filter: (uniqueMember=cn=Kumar\5c, Rajesh,ou=Users,ou=IN,dc=global,dc= company,dc=org) 
2022-08-04 19:47:45.628 DEBUG 33541 --- [nio-8080-exec-2] o.s.ldap.core.LdapTemplate               : The returnObjFlag of supplied SearchControls is not set but a ContextMapper is used - setting flag to true 
2022-08-04 19:47:45.629 DEBUG 33541 --- [nio-8080-exec-2] o.s.l.c.support.AbstractContextSource    : Got Ldap context on server 'ldap://ldapserver' 
2022-08-04 19:47:45.837 TRACE 33541 --- [nio-8080-exec-2] o.s.s.w.header.writers.HstsHeaderWriter  : Not injecting HSTS header since it did not match request to [Is Secure] 
2022-08-04 19:47:45.838 DEBUG 33541 --- [nio-8080-exec-2] w.c.HttpSessionSecurityContextRepository : Did not store empty SecurityContext 
2022-08-04 19:47:45.838 DEBUG 33541 --- [nio-8080-exec-2] s.s.w.c.SecurityContextPersistenceFilter : Cleared SecurityContextHolder to complete request 
2022-08-04 19:47:45.839 TRACE 33541 --- [nio-8080-exec-2] o.s.b.w.s.f.OrderedRequestContextFilter  : Cleared thread-bound request context: org.apache.catalina.connector.RequestFacade@1c138f13 
2022-08-04 19:47:45.847 ERROR 33541 --- [nio-8080-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception
    
org.springframework.ldap.NameNotFoundException: [LDAP: error code 32 - 0000208D: NameErr: DSID-03100217, problem 2001 (NO_OBJECT), data 0, best match of:   '' ]; 
nested exception is javax.naming.NameNotFoundException: [LDAP: error code 32 - 0000208D: NameErr: DSID-03100217, problem 2001 (NO_OBJECT), data 0, best match of:   '' ]; remaining name ''     
at org.springframework.ldap.support.LdapUtils.convertLdapException(LdapUtils.java:183) ~[spring-ldap-core-2.3.4.RELEASE.jar:2.3.4.RELEASE]  
at org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:376) ~[spring-ldap-core-2.3.4.RELEASE.jar:2.3.4.RELEASE]     
at org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:328) ~[spring-ldap-core-2.3.4.RELEASE.jar:2.3.4.RELEASE]     
at org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:629) ~[spring-ldap-core-2.3.4.RELEASE.jar:2.3.4.RELEASE]     
at org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:570) ~[spring-ldap-core-2.3.4.RELEASE.jar:2.3.4.RELEASE]

请有人引导我将这段普通的java代码迁移到spring安全性中。

问候

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-08-05 16:57:48

我们可以在跟踪日志中看到以下消息:

代码语言:javascript
运行
复制
DefaultLdapAuthoritiesPopulator : Searching for roles for user 'userId', DN = 'cn=Kumar\, Rajesh,ou=Users,ou=IN,dc=global,dc= company,dc=org', with filter (uniqueMember={0}) in search base ''

文件上说:

成功验证用户之后,LdapAuthenticationProvider将尝试通过调用配置的LdapAuthoritiesPopulator为用户加载一组权限。

默认实现是试图通过搜索用户所属组的目录来加载权限,但由于没有指定组搜索基,因此无法加载权限。

代码语言:javascript
运行
复制
  auth
    .ldapAuthentication()
    .userSearchFilter("(sAMAccountName={0})")
    .userSearchBase("dc=global,dc=company,dc=org")
    .groupSearchBase("dc=global,dc=company,dc=org")  // <- here
    .contextSource()
    .url("ldap://ldapserver")
    .port(389)
    .managerDn("domain\\userId")
    .managerPassword("******");

通常,这些组在目录树中的ou=Roles组件下引用。例如,考虑到在“工作”代码:ou=roles,ou=in,dc=global,dc=company,dc=org中定义的用户搜索基础,但是一个更大的基础(只有dc)应该是可以的。

值得注意的是,您可以直接在ldap url中设置全局基,并为需要dn的参数定义相对dn (使用有效的全局基集,使groupSearchBase为空不会引发错误),例如:

代码语言:javascript
运行
复制
    .userSearchBase("ou=users,ou=in")
    .groupSearchBase("ou=roles,ou=in")

有:

代码语言:javascript
运行
复制
    .url("ldap://ldapserver:389/dc=global,dc=company,dc=org")

另外,请注意,在使用userDnPatterns()时不需要userSearchFilter(),请使用其中一种或另一种。

@见Security文档:装载当局

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73237295

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档