java 如何在 Spring Security 中从 LDAP 获取其他用户属性?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/37728277/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to get additional user attributes from LDAP in Spring Security?
提问by Alex
I'm currently trying to develop a Spring Boot application whose purpose it will be to manage user entries in our LDAP directory.
我目前正在尝试开发一个 Spring Boot 应用程序,其目的是管理 LDAP 目录中的用户条目。
LDAP login already works; so does the lookup of groups a user is member of.
LDAP 登录已经有效;查找用户所属的组也是如此。
Additionally, I'd like to populate the Spring Security Principal
object with some more LDAP attributes of that user. I've read several posts on SO and also the official Spring documentation, but simply cannot get this to work.
此外,我想Principal
用该用户的更多 LDAP 属性填充 Spring Security对象。我已经阅读了几篇关于 SO 的文章以及官方的 Spring 文档,但根本无法让它发挥作用。
Here is my current code:
Class AuthenticationConfiguration
这是我当前的代码:Class AuthenticationConfiguration
@Configuration
class AuthenticationConfiguration extends GlobalAuthenticationConfigurerAdapter {
private String ldapUrl = "ldap://127.0.0.1:10389/dc=corp,dc=org";
private String bindUser = "cn=spring,ou=users,dc=corp,dc=org";
private String bindPW = "<password>";
private String groupSearchBase = "ou=groups";
private String groupSearchFilter = "(member={0})";
private String userDnPattern = "uid={0},ou=users";
private Log log = LogFactory.getLog(this.getClass());
@Override
public void init(AuthenticationManagerBuilder auth) throws Exception {
DefaultSpringSecurityContextSource contextSource = new DefaultSpringSecurityContextSource(ldapUrl);
contextSource.setUserDn(bindUser);
contextSource.setPassword(bindPW);
contextSource.afterPropertiesSet();
log.info(contextSource.getReadOnlyContext().getAttributes("uid=testuser,ou=users")); // returns all LDAP attributes from that user
DefaultLdapAuthoritiesPopulator populator = new DefaultLdapAuthoritiesPopulator(contextSource, groupSearchBase);
populator.setGroupSearchFilter(groupSearchFilter);
populator.setSearchSubtree(true);
populator.setIgnorePartialResultException(true);
auth
.ldapAuthentication()
.ldapAuthoritiesPopulator(populator)
.contextSource(contextSource)
.userDetailsContextMapper(userDetailsContextMapper())
.userDnPatterns(userDnPattern)
;
}
@Bean
public UserDetailsContextMapper userDetailsContextMapper() {
return new CustomUserDetailsContextMapper();
}
}
As you can see, I'm using the userDetailsContextMapper() method to return an instance of my CustomUserDetailsContextMapper
:
如您所见,我使用 userDetailsContextMapper() 方法返回 my 的一个实例CustomUserDetailsContextMapper
:
@Configuration
public class CustomUserDetailsContextMapper extends LdapUserDetailsMapper implements UserDetailsContextMapper {
private Log log = LogFactory.getLog(this.getClass());
@Override
public LdapUserDetails mapUserFromContext(DirContextOperations ctx, String username, Collection<? extends GrantedAuthority> authorities) {
LdapUserDetailsImpl details = (LdapUserDetailsImpl) super.mapUserFromContext(ctx, username, authorities);
log.info("DN from ctx: " + ctx.getDn()); // return correct DN
log.info("Attributes size: " + ctx.getAttributes().size()); // always returns 0
return new CustomUserDetails(details);
}
@Override
public void mapUserToContext(UserDetails user, DirContextAdapter ctx) {
// default
}
}
Now, when you look at that first log statement in AuthenticationConfiguration
, Spring will actually print the whole user object to stdout, correctly showing all LDAP attributes from the user:
{displayname=displayName: Test User, givenname=givenName: Test, objectclass=objectClass: posixAccount, top [...]}
现在,当您查看 中的第一条日志语句时AuthenticationConfiguration
,Spring 实际上会将整个用户对象打印到标准输出,正确显示用户的所有 LDAP 属性:
{displayname=displayName: Test User, givenname=givenName: Test, objectclass=objectClass: posixAccount, top [...]}
However, the log statements in my CustomUserDetailsContextMapper
class do not. Although the first one correctly displays the DN of the logged in user, the second one just display 0, i.e. ctx does not seem to contain any attributes from the current user.
但是,我CustomUserDetailsContextMapper
班级中的日志语句没有。虽然第一个正确显示了登录用户的 DN,但第二个只显示 0,即 ctx 似乎不包含来自当前用户的任何属性。
I also tried directly querying for attributes via ctx.getAttribute("attribute")
, ctx.getStringAttribute("attribute")
or ctx.getObjectAttribute("attribute")
, to no avail.
我还尝试通过ctx.getAttribute("attribute")
,ctx.getStringAttribute("attribute")
或直接查询属性ctx.getObjectAttribute("attribute")
,但无济于事。
How can I access LDAP attributes from within the mapUserFromContext
method?
如何从mapUserFromContext
方法中访问 LDAP 属性?
I'm really out of ideas, so any help would be greatly appreciated :-)
我真的没有想法,所以任何帮助将不胜感激:-)
采纳答案by Alex
Solved it. The problem was not in the application code, but in the LDAP configuration.
解决了。问题不在于应用程序代码,而在于 LDAP 配置。
Because I was using the default BindAuthenticator, Spring Security tried to bind to LDAP with the user specified in the login form. Unfortunately, all users under ou=users only had a search
permission in the LDAP configuration. Changing search
to read
(see point 8.2.3 http://www.openldap.org/doc/admin24/access-control.html) solved this issue for me.
因为我使用的是默认的 BindAuthenticator,所以 Spring Security 尝试使用登录表单中指定的用户绑定到 LDAP。不幸的是,ou=users 下的所有用户都只有search
在 LDAP 配置中的权限。更改search
为read
(参见第 8.2.3 点http://www.openldap.org/doc/admin24/access-control.html)为我解决了这个问题。
Note that the login/bind itself was still successful (because the auth
permission is a subset of search
), but any retrieval of attributes failed, as this required the read
permission.
请注意,登录/绑定本身仍然成功(因为auth
权限是 的子集search
),但任何属性检索都失败了,因为这需要read
权限。
回答by qwert_ukg
In advance for @mpm example:
提前为@mpm 示例:
Hope it will be helpful for somebody. Here is my decorator for UserDetails
希望它会对某人有所帮助。这是我的装饰器UserDetails
public class CustomUserDetails implements LdapUserDetails {
private String iin;
private String colvirId;
private LdapUserDetails details;
public CustomUserDetails(LdapUserDetails details) {
this.details = details;
}
public String getIin() {
return iin;
}
public void setIin(String iin) {
this.iin = iin;
}
public String getColvirId() {
return colvirId;
}
public void setColvirId(String colvirId) {
this.colvirId = colvirId;
}
@Override
public String getDn() {
return details.getDn();
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return details.getAuthorities();
}
@Override
public String getPassword() {
return details.getPassword();
}
@Override
public String getUsername() {
return details.getUsername();
}
@Override
public boolean isAccountNonExpired() {
return details.isAccountNonExpired();
}
@Override
public boolean isAccountNonLocked() {
return details.isAccountNonLocked();
}
@Override
public boolean isCredentialsNonExpired() {
return details.isCredentialsNonExpired();
}
@Override
public boolean isEnabled() {
return details.isEnabled();
}
}