我设法配置了OAuth2和ldap授权。通过实现LdapUserDetails创建自定义LdapUser,并通过实现UserDetailsContextMapper创建CustomUserDetailsContextMapper。
最终,通过Active Directory用户名和密码进行授权时,我获得了访问令牌。
但是问题是,我无法从SecurityContextHolder.getContext()。getAuthentication()中获取我当前登录的用户
无法将java.lang.String强制转换为LdapUser
在我的安全性下面进行配置:
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(adAuthenticationProvider())
.ldapAuthentication()
.userSearchBase("ldap.searchbase").userSearchFilter("ldap.filter").groupSearchFilter("ldap.groupsearch")
.contextSource(contextSource())
.userDetailsContextMapper(userDetailsContextMapper())
.passwordCompare()
.passwordEncoder(new LdapShaPasswordEncoder())
.passwordAttribute("userPassword");
}
@Bean
public DefaultSpringSecurityContextSource contextSource() {
return new DefaultSpringSecurityContextSource(Arrays.asList("ldap.url"), "dc=smth,dc=com");
}
@Bean
public ActiveDirectoryLdapAuthenticationProvider adAuthenticationProvider() {
ActiveDirectoryLdapAuthenticationProvider provider = new ActiveDirectoryLdapAuthenticationProvider("smth.com","ldap.url");
provider.setConvertSubErrorCodesToExceptions(true);
provider.setUseAuthenticationRequestCredentials(true);
provider.setUserDetailsContextMapper(userDetailsContextMapper());
return provider;
}
@Bean
public UserDetailsContextMapper userDetailsContextMapper() {
return new CustomUserDetailsContextMapper();
}
自定义LdapUser:
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.ldap.userdetails.LdapUserDetails;
import java.util.Collection;
public class LdapUser implements LdapUserDetails
{
private String commonName;
private LdapUserDetails ldapUserDetails;
public LdapUser(LdapUserDetails ldapUserDetails) {
this.ldapUserDetails = ldapUserDetails;
}
@Override
public String getDn() {
return ldapUserDetails.getDn();
}
@Override
public void eraseCredentials() {
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return ldapUserDetails.getAuthorities();
}
@Override
public String getPassword() {
return ldapUserDetails.getPassword();
}
@Override
public String getUsername() {
return ldapUserDetails.getUsername();
}
@Override
public boolean isAccountNonExpired() {
return ldapUserDetails.isAccountNonExpired();
}
@Override
public boolean isAccountNonLocked() {
return ldapUserDetails.isAccountNonLocked();
}
@Override
public boolean isCredentialsNonExpired() {
return ldapUserDetails.isCredentialsNonExpired();
}
@Override
public boolean isEnabled() {
return ldapUserDetails.isEnabled();
}
}
CustomUserDetailsContextMapper:
我可以成功打印出上下文属性,并且看到这是我登录的用户
@Configuration
public class CustomUserDetailsContextMapper extends LdapUserDetailsMapper implements UserDetailsContextMapper {
private LdapUser ldapUser = null;
private String commonName;
private Boolean isCity;
@Override
public LdapUserDetails mapUserFromContext(DirContextOperations ctx, String username, Collection<? extends GrantedAuthority> authorities) {
Attributes attributes = ctx.getAttributes();
LdapUserDetails ldapUserDetails = (LdapUserDetails) super.mapUserFromContext(ctx,username,authorities);
return new LdapUser(ldapUserDetails);
}
@Override
public void mapUserToContext(UserDetails user, DirContextAdapter ctx) {
}
}
现在这就是我想要获取自定义LdapUser的方式:
public LdapUser getCurrentLdapUser() {
org.springframework.security.core.context.SecurityContext securityContext = SecurityContextHolder
.getContext();
Authentication authentication = securityContext.getAuthentication();
LdapUser user = null;
if (authentication != null) {
user = ((LdapUser) authentication.getPrincipal());
}
return user;
}
调用此函数后,出现转换错误。当我尝试获取主体名称时,它会返回-anonymousUser。我不知道为什么它不返回我LdapUser
最佳答案
好的,我知道了。错过了基本的东西。
由于我没有配置资源服务器(ResourceServerConfigurerAdapter),因此每个登录的Active Directory用户都被视为匿名用户。这就是为什么安全上下文返回String用户而不是我的自定义Ldap用户。
如果有人需要,这是一个ResourceServerConfig示例:
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
private static final String RESOURCE_ID = "resource_id";
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources
.resourceId(RESOURCE_ID)
.stateless(false);
}
@Override
public void configure(HttpSecurity http) throws Exception {
http
.anonymous().disable()
.authorizeRequests()
.antMatchers("/api/**").hasAnyAuthority("Authority_1","Authority_2")
.and().exceptionHandling().authenticationEntryPoint(new UnauthorizedHandler())
.and().exceptionHandling().accessDeniedHandler(accessDeniedHandler());
}
@Bean
public AccessDeniedHandler accessDeniedHandler() {
return new CustomAccessDeniedHandler();
}
}