我需要使用对象列表进行访问控制。获取该列表的查询非常复杂和冗长,因此当用户使用服务器进行身份验证时,我希望将其缓存在用户对象中。 我决定尝试使用UserDetailService和WebSecurityConfig的自定义实现来解决这个问题:
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
...
@Override
public void init(AuthenticationManagerBuilder auth) throws Exception {
String ldapURI = "ldap://" + ldaHost + ":" + ldapPort + "/" + ldapBasis;
DefaultSpringSecurityContextSource contextSource = new DefaultSpringSecurityContextSource(ldapURI);
contextSource.setUserDn(ldapUser);
contextSource.setPassword(ldapPassword);
contextSource.afterPropertiesSet();
LdapAuthenticationProviderConfigurer<AuthenticationManagerBuilder> ldapAuthenticationProviderConfigurer = auth
.ldapAuthentication().userDetailsContextMapper(new LdapUserDetailsContextMapper());
ldapAuthenticationProviderConfigurer
.userSearchFilter("(&(criteria={0}))")
.userSearchBase("ou=usersearchbase").contextSource(contextSource);
}
}
ContextMapper用数据填充用户对象:
public class LdapUserDetailsContextMapper implements UserDetailsContextMapper {
private final org.slf4j.Logger log = LoggerFactory.getLogger(this.getClass());
private DataService dataService;
public UserDetails mapUserFromContext(DirContextOperations ctx, String username,
Collection<? extends GrantedAuthority> authorities) {
AppUser user = new AppUser();
user.setUsername(ctx.getStringAttribute("uid"));
user.setName(ctx.getStringAttribute("cn"));
user.setSurname(ctx.getStringAttribute("sn"));
user.setMail(ctx.getStringAttribute("mail"));
user.setRoleUser();
user.setManaged(dataService.getManagedData(user.getMail()));
return user;
}
问题在于我看不到将DataService注入此进程的方法 - ContextMapper和@Configure类都不是托管bean,这使得@Autowired成为不可能。我想避免使用LoadTimeWeaving,因为使用它会使部署非常困难 - 我还有其他选择吗?
我发现了这两个类似的问题:Why is my Spring @Autowired field null?在Controller类中有相同的问题,可以将其转换为托管bean;其他两个提到的解决方案对我来说都没有用(dataService总是为null)和 Spring Boot, @Autowire into an unmanaged class using @Configurable and load time weaving再次推荐LoadTimeWeaving。
我还发现了一些明显的解决方案,提到在init方法中使用@Autowired,但是我也无法使用它(尝试使用注入的dataService调用ContextMapper构造函数)
答案 0 :(得分:1)
让它成为一个Spring托管bean。
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
...
@Override
public void init(AuthenticationManagerBuilder auth) throws Exception {
String ldapURI = "ldap://" + ldaHost + ":" + ldapPort + "/" + ldapBasis;
DefaultSpringSecurityContextSource contextSource = new DefaultSpringSecurityContextSource(ldapURI);
contextSource.setUserDn(ldapUser);
contextSource.setPassword(ldapPassword);
contextSource.afterPropertiesSet();
LdapAuthenticationProviderConfigurer<AuthenticationManagerBuilder> ldapAuthenticationProviderConfigurer = auth
.ldapAuthentication().userDetailsContextMapper(userDetailsContextMapper());
ldapAuthenticationProviderConfigurer
.userSearchFilter("(&(criteria={0}))")
.userSearchBase("ou=usersearchbase").contextSource(contextSource);
}
@Bean
public LdapUserDetailsContextMapper userDetailsContextMapper() {
return new LdapUserDetailsContextMapper();
}
}
使用LdapUserDetailsContextMapper
在@Autowired
内注释您的字段。