当前位置: 首页 > 知识库问答 >
问题:

使用Spring Boot的LDAP身份验证

曾泳
2023-03-14

我已经创建了一个Restful应用编程接口。我在这里使用LDAP身份验证。我们公司有一个LDAP目录服务器,我在我的服务层中使用下面的方法作为实用程序

这是我的LDAP身份验证方法,我将此方法用作服务层中的实用程序。

    public Map<String, Object> authenticate(String user, String pass) {
    String returnedAtts[] = {"sn", "givenName", "name", "userPrincipalName", "displayName", "memberOf"};
    String searchFilter = "(&(objectClass=User)(sAMAccountName=" + user + "))";
    // Create the search controls
    SearchControls searchCtls = new SearchControls();
    searchCtls.setReturningAttributes(returnedAtts);
    // Specify the search scope
    searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);
    Hashtable<String, String> env = new Hashtable<String, String>();
    env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
    env.put(Context.PROVIDER_URL, ldapHost);
    env.put(Context.SECURITY_AUTHENTICATION, "simple");

    env.put(Context.SECURITY_PRINCIPAL, user + "@" + domain);
    env.put(Context.SECURITY_CREDENTIALS, pass);
    env.put(Context.SECURITY_PROTOCOL, "SSL");
    LdapContext ctxGC = null;
    NamingEnumeration<SearchResult> answer = null;
    Attributes attrs = null;
    SearchResult sr = null;
    NamingEnumeration<?> ne = null;
    Attribute attr = null;

    try {
        ctxGC = new InitialLdapContext(env, null);
        if (ctxGC != null) {
            answer = ctxGC.search(searchBase, searchFilter, searchCtls);
            if (answer != null) {
                while (answer.hasMoreElements()) {
                    sr = (SearchResult) answer.next();
                    attrs = sr.getAttributes();
                    if (attrs != null) {
                        amap = new HashMap<String, Object>();
                        ne = attrs.getAll();
                        attr = (Attribute) ne.next();
                        amap.put(attr.getID(), attr.get());
                        ne.close();
                    }
                    ctxGC.close();         // Close and clean up
                }
            } else {
                System.out.println("Answer from domen controller is null!");
            }
        } else {
            System.out.println("Login or Password is wrong! ");
        }

    } catch (NamingException ex) {
        System.out.println("Exception: "+ex.toString());
    } finally {
        System.out.println("");
    }
    return amap;
}

这是我的服务层类,我将实用程序类作为一种注入,可以用于身份验证方法。当我以swagger或postman用户名和密码发送请求时,给定来自请求的值,我会将它们保存到表的数据库中。但在坚持之前,身份验证方法会控制我的用户名和密码。如果密码或用户名不正确,我将向客户端返回错误响应,否则我将向客户端返回成功响应。在这两种情况下,我都会从请求中将给定的值插入表的数据库。

@Override
    public Optional<ResponseEntity<? extends ResponseDto>> login(String username, String password, String type) {

//Is there any method or feature that spring boot provides us instead of the method you see here?
        Map<String, Object> authenticate = this.controlDomainLogin.authenticate(username, password);
//Is there any method or feature that spring boot provides us instead of the method you see here?


        if (authenticate != null) {
            DomainLogin domainLogin = new DomainLogin();
            domainLogin.setUsername(username);
            domainLogin.setType(type);
            domainLogin.setLogDate(new Date());
            ResponseEntity<ResponseDto> responseDtoResponseEntity = new ResponseEntity<>(new SuccessResponseDto(SUCCESS_OPERATION.getMessage(), SUCCESS_OPERATION.getCode(), authenticate), HttpStatus.OK);
            domainLogin.setResponse(Objects.requireNonNull(responseDtoResponseEntity.getBody()).getMessage() + "," + responseDtoResponseEntity.getBody().getCode());
            this.domainLoginRepository.save(domainLogin);
            return Optional.of(responseDtoResponseEntity);
        } else {
            DomainLogin domainLogin = new DomainLogin();
            domainLogin.setUsername(username);
            domainLogin.setType(type);
            domainLogin.setLogDate(new Date());
            ResponseEntity<ResponseDto> responseDtoResponseEntity = new ResponseEntity<>(new ErrorResponseDto(WRONG_USERNAME.getMessage(), WRONG_USERNAME.getCode()), HttpStatus.NOT_FOUND);
            domainLogin.setResponse(Objects.requireNonNull(responseDtoResponseEntity.getBody()).getMessage() + "," + responseDtoResponseEntity.getBody().getCode());
            domainLogin.setException(Objects.requireNonNull(responseDtoResponseEntity.getBody()).getMessage() + "," + responseDtoResponseEntity.getBody().getCode());
            this.domainLoginRepository.save(domainLogin);
            return Optional.of(responseDtoResponseEntity);
        }
    }

现在我不需要使用这种方法,相反,Spring引导本身是否有类似的方法或任何特征,就像我上面展示的方法一样?我的意思是我不应该使用这种方法,相反,是否有Spring引导给我们的东西做同样的事情?

同样的操作将被重复,但不同的是,我将删除我用java编写的方法,并使用spring boot的LDAP身份验证方法。

如果是我在下面展示的类,当我运行项目时,spring默认提供的登录页面会出现,当我在那里输入用户名和密码时,它会成功执行验证过程,如果失败,它会给出以下警告。

ctiveDirectoryLdapAuthenticationProvider : Active Directory authentication failed: Supplied password was invalid


import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider;

import java.util.Arrays;

import org.springframework.beans.factory.annotation.Value;

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Value("${ad.domain}")
    private String AD_DOMAIN;

    @Value("${ad.url}")
    private String AD_URL;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                .anyRequest().fullyAuthenticated()
                .and()
                .formLogin();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder authManagerBuilder) throws Exception {
        authManagerBuilder.authenticationProvider(activeDirectoryLdapAuthenticationProvider()).userDetailsService(userDetailsService());
    }

    @Bean
    public AuthenticationManager authenticationManager() {
        return new ProviderManager(Arrays.asList(activeDirectoryLdapAuthenticationProvider()));
    }
    @Bean
    public AuthenticationProvider activeDirectoryLdapAuthenticationProvider() {
        ActiveDirectoryLdapAuthenticationProvider provider = new ActiveDirectoryLdapAuthenticationProvider(AD_DOMAIN, AD_URL);
        provider.setConvertSubErrorCodesToExceptions(true);
        provider.setUseAuthenticationRequestCredentials(true);

        return provider;
    }
}

共有1个答案

吴飞语
2023-03-14

您可以通过Spring数据Ldap实现这一点。只需将Java类映射到Ldap条目,就可以在Ldap上执行CRUD操作。

创建一个从Spring Security扩展UserDetail的LdapUserService。

然后在Spring Security配置中使用此LdapUserService。

现在,您可以执行身份验证、授权以及CRUD操作。

 类似资料:
  • 我正在编写一个程序,用于验证通过HTTP POST发送的用户名和密码,并根据ldap进行验证,无论验证是否成功,都将响应发送回用户。 我的Websecurity配置器实现 我的测试服务器.ldif

  • 我有一个asp。net(C#)设置为使用LDAP进行身份验证。一切正常,我可以和我们目录中的任何用户一起登录。问题是,我需要将某些页面限制为特定组中的人。我正在使用登录查看帐户文件夹的方法。 我的网站设计很简单,它有三个页面,一个供所有人查看(账户文件夹之外),另外两个需要身份验证。我希望一个组可以访问两个网页,另一个组只能访问其中一个网页。 我试过: 但不管我的用户不在该组中。我有一个LDAP浏

  • 我正在使用SpringBoot开发具有微服务架构的Rest Backend。为了保护endpoint,我使用了JWT令牌机制。我正在使用Zuul API网关。 如果请求需要权限(来自JWT的角色),它将被转发到正确的微服务。Zuul api网关的“WebSecurityConfigrerAdapter”如下。 这样,我必须在这个类中编写每个请求授权部分。因此,我希望使用方法级安全性,即“Enabl

  • 我使用Presto Cli测试ldap,下面是以下命令: 它不要求密码,我能够连接到Presto集群,并能够运行查询。为什么LDAP身份验证对此没有任何帮助?

  • 我正在尝试使用passport ldapauth npm验证openLDAP用户名和密码。在执行下面的代码时,我总是收到错误消息:“缺少凭据”。请帮助我我的代码有什么问题。 有关更多详细信息,请参阅此badRequestMessage flash消息以查找缺少的用户名/密码(默认值:“缺少凭据”)

  • 我正在尝试在ms access 2010中使用用户名和密码进行ldap身份验证。我似乎无法理解这一点,并在网上尝试了不同的代码,但似乎都不起作用。有人能帮忙吗? 以下是我从这里学到的 我收到的错误是 “错误:服务器无法运行。-2147217865” 更改为ip地址立即获取以下错误 ,但它可能来自其他地方在我的代码.我将如何检查,如果ldap是成功的?