[英]Spring Security with Active Directory and Database roles
I'm trying to use Spring Security with Active Directory usernames and password. 我正在尝试将Spring Security与Active Directory用户名和密码一起使用。 Additionally, I have a database Roles table which has a relationship with a User table that contains the usernames of Active Directory (the User table is no related in anyway with Active Directory, it's completely independent I just put the usernames in that table so I can match it with the Roles) 此外,我有一个数据库Roles表,该表与包含Active Directory用户名的User表有关系(User表与Active Directory无关,它是完全独立的,我只是将用户名放在该表中,这样我就可以与角色匹配)
I'm following this example http://krams915.blogspot.com/2012/01/spring-security-31-implement_1244.html 我正在关注这个示例http://krams915.blogspot.com/2012/01/spring-security-31-implement_1244.html
The problem is that I fail to see where the password is used in the loadUserByUsername method of the CustomUserDetailsService class. 问题是我看不到CustomUserDetailsService类的loadUserByUsername方法中使用密码的位置。
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
try {
org.krams.domain.User domainUser = userRepository.findByUsername(username);
boolean enabled = true;
boolean accountNonExpired = true;
boolean credentialsNonExpired = true;
boolean accountNonLocked = true;
return new User(
domainUser.getUsername(),
domainUser.getPassword().toLowerCase(),
enabled,
accountNonExpired,
credentialsNonExpired,
accountNonLocked,
getAuthorities(domainUser.getRole().getRole()));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
For what I understand this line validates the username against the database userRepository.findByUsername(username);
据我了解,此行根据数据库userRepository.findByUsername(username);
验证用户userRepository.findByUsername(username);
But how can I use an lpad validation there? 但是,如何在其中使用lpad验证? Can I use something like the authentication implementes here http://www.javaxt.com/Tutorials/Windows/How_to_Authenticate_Users_with_Active_Directory 我可以在这里使用类似身份验证的工具吗? http://www.javaxt.com/Tutorials/Windows/How_to_Authenticate_Users_with_Active_Directory
UPDATE: 更新:
I'm trying to get it work with a CustomUserDetailsContextMapper 我正在尝试使其与CustomUserDetailsContextMapper一起使用
XML XML
<authentication-manager >
<authentication-provider ref="ldapActiveDirectoryAuthProvider" />
</authentication-manager>
<beans:bean id="ldapActiveDirectoryAuthProvider"
class="org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider">
<beans:constructor-arg value="domain" />
<beans:constructor-arg value="ldap://NAME/"/>
<beans:property name="userDetailsContextMapper" ref="tdrUserDetailsContextMapper"/>
<beans:property name="useAuthenticationRequestCredentials" value="true"/>
</beans:bean>
<beans:bean id="tdrUserDetailsContextMapper" class="com.test8.security8.service.CustomUserDetailsContextMapper"/>
Custom Class 自定义类
public class CustomUserDetailsContextMapper implements UserDetailsContextMapper, Serializable{
private static final long serialVersionUID = 3962976258168853984L;
@Override
public UserDetails mapUserFromContext(DirContextOperations ctx, String username, Collection<? extends GrantedAuthority> authority) {
String role="admin";
System.out.println("TEST");
if(username.equals("usuario"))role="admin";
else role="user";
List authList = getAuthorities(role);
return new User(username, "", true, true, true, true, authList);
}
private List getAuthorities(String role) {
List authList = new ArrayList();
authList.add(new SimpleGrantedAuthority("ROLE_USER"));
//you can also add different roles here
//for example, the user is also an admin of the site, then you can add ROLE_ADMIN
//so that he can view pages that are ROLE_ADMIN specific
if (role != null && role.trim().length() > 0) {
if (role.equals("admin")) {
authList.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
}
}
return authList;
}
@Override
public void mapUserToContext(UserDetails arg0, DirContextAdapter arg1) {
// TODO Auto-generated method stub
}
}
I think I'm almost there, I don´t get an error but it appears that it cannot map any user, The System.out.println("TEST")
; 我想我快要走了,但没有收到错误消息,但似乎无法映射任何用户, System.out.println("TEST")
; line is never executed. 行永远不会执行。 Could it be something related to the URL/Domain? 可能与URL /域名有关吗? I'm sure that the URL is correct because if I change it I get an error. 我确定网址正确无误,因为如果更改它,则会收到错误消息。
I ended up using a UserDetailsContextMapper as suggested by M. Deinum. 我最终按照M. Deinum的建议使用了UserDetailsContextMapper。 I also created customs SpringSecurityLdapTemplate and ActiveDirectoryLdapAuthenticationProvider. 我还创建了海关SpringSecurityLdapTemplate和ActiveDirectoryLdapAuthenticationProvider。
In my custom ActiveDirectoryLdapAuthenticationProvider I changed the following method: 在我的自定义ActiveDirectoryLdapAuthenticationProvider中,我更改了以下方法:
private LdapContext bindAsUser(String username, String password) {
// TODO. add DNS lookup based on domain
final String bindUrl = url;
Hashtable<String,String> env = new Hashtable<String,String>();
env.put(Context.SECURITY_AUTHENTICATION, "simple");
String bindPrincipal = createBindPrincipal(username);
env.put(Context.SECURITY_PRINCIPAL, bindPrincipal);
env.put(Context.PROVIDER_URL, bindUrl);
env.put(Context.SECURITY_CREDENTIALS, password);
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.REFERRAL, "follow");
try {
return new InitialLdapContext(env, null);
} catch (NamingException e) {
if ((e instanceof AuthenticationException) || (e instanceof OperationNotSupportedException)) {
handleBindException(bindPrincipal, e);
throw badCredentials();
} else {
throw LdapUtils.convertLdapException(e);
}
}
}
This was the important line for me: env.put(Context.REFERRAL, "follow"); 这对我来说很重要: env.put(Context.REFERRAL,“ follow”);
And in the SpringSecurityLdapTemplate custom class 并在SpringSecurityLdapTemplate自定义类中
public static DirContextOperations searchForSingleEntryInternal(DirContext ctx, SearchControls searchControls,
String base, String filter, Object[] params) throws NamingException {
final DistinguishedName ctxBaseDn = new DistinguishedName(ctx.getNameInNamespace());
final DistinguishedName searchBaseDn = new DistinguishedName(base);
final NamingEnumeration<SearchResult> resultsEnum = ctx.search(searchBaseDn, filter, params, buildControls(searchControls));
filter, searchControls);
if (logger.isDebugEnabled()) {
logger.debug("Searching for entry under DN '" + ctxBaseDn
+ "', base = '" + searchBaseDn + "', filter = '" + filter + "'");
}
Set<DirContextOperations> results = new HashSet<DirContextOperations>();
try {
while (resultsEnum.hasMore()) {
SearchResult searchResult = resultsEnum.next();
DirContextAdapter dca = new DirContextAdapter();
//dca=(DirContextAdapter) searchResult.getObject();
Assert.notNull(dca, "No object returned by search, DirContext is not correctly configured");
if (logger.isDebugEnabled()) {
logger.debug("Found DN: " + dca.getDn());
}
results.add(dca);
}
} catch (PartialResultException e) {
LdapUtils.closeEnumeration(resultsEnum);
logger.info("Ignoring PartialResultException");
}
if (results.size() == 0) {
throw new IncorrectResultSizeDataAccessException(1, 0);
}
if (results.size() > 1) {
throw new IncorrectResultSizeDataAccessException(1, results.size());
}
return results.iterator().next();
}
This worked for me, but it was a very particular scenario. 这对我有用,但这是一个非常特殊的场景。 Thanks to M. Deinum for pointing me in the right direction. 感谢Deinum M向我指出正确的方向。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.