【发布时间】:2022-01-20 16:53:55
【问题描述】:
我创建了一个 Restful API。我在这里使用 LDAP 身份验证。我们公司有一个 LDAP 目录服务器,我在我的service layer 中使用下面的方法as utility。
这是我的 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 或邮递员用户名和密码发送请求时,给定来自请求的值,我将它们保存到表的数据库中。但在坚持之前,身份验证方法会控制我的用户名和密码。如果密码或用户名不正确,我会向客户端返回错误响应,否则我会向客户端返回成功响应。在这两种情况下,我都会从请求中将给定值插入到表的数据库中。
@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 boot 本身有没有类似的方法或任何特性,就像我上面展示的方法一样?我的意思是我不应该使用这种方法,相反,spring boot 给我们的东西可以做同样的事情吗?
同样的操作会重复,但不同的是我会删除我用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;
}
}
【问题讨论】:
标签: java spring-boot api authentication ldap