我發現很少有Spring XML配置示例用於使用LDAP登錄並使用自定義方法而不是通過LDAP配置登錄用戶的權限。 不幸的是,我找不到任何帶有註釋的Spring Boot示例。使用LDAP身份驗證的自定義權限
在我們的例子中,有一箇中央LDAP存儲庫,其中存儲了用戶的用戶名和密碼,但用戶組不存儲在那裏。
我很欣賞任何示例或參考。 預先感謝您。
我發現很少有Spring XML配置示例用於使用LDAP登錄並使用自定義方法而不是通過LDAP配置登錄用戶的權限。 不幸的是,我找不到任何帶有註釋的Spring Boot示例。使用LDAP身份驗證的自定義權限
在我們的例子中,有一箇中央LDAP存儲庫,其中存儲了用戶的用戶名和密碼,但用戶組不存儲在那裏。
我很欣賞任何示例或參考。 預先感謝您。
下面你可以找到我們的項目最終落實。 基本流程爲:
a)在認證過程中檢查用戶標識和角色。如果用戶未定義或不具有應用程序的角色,則不要對用戶進行身份驗證。
b)如果用戶通過數據庫檢查,繼續ldap身份驗證。
c)合併來自數據庫的角色與ldap,以便在應用程序中使用。
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter implements InitializingBean {
...
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.authenticationProvider(this.ldapAndDatabaseAuthenticationProvider());
}
@Bean(name="ldapAuthenticationProvider")
public AuthenticationProvider ldapAndDatabaseAuthenticationProvider(){
LdapUserDetailsMapper userDetailsMapper = new LdapUserDetailsMapper();
userDetailsMapper.setRoleAttributes(new String[]{"groupMembership"});
LdapAndDatabaseAuthenticationProvider provider =
new LdapAndDatabaseAuthenticationProvider(this.ldapAuthenticator(), this.ldapAuthoritiesPopulator());
provider.setUserDetailsContextMapper(userDetailsMapper);
return provider;
}
@Bean(name = "ldapAuthoritiesPopulator")
public LdapAndDatabaseAuthoritiesPopulator ldapAuthoritiesPopulator(){
return new LdapAndDatabaseAuthoritiesPopulator(this.contextSource(), "");
}
@Bean(name = "ldapAuthenticator")
public LdapAuthenticator ldapAuthenticator() {
BindAuthenticator authenticator = new BindAuthenticator( this.contextSource());
authenticator.setUserDnPatterns(new String[]{"cn={0},ou=prod,o=COMP"});
return authenticator;
}
@Bean(name = "contextSource")
public DefaultSpringSecurityContextSource contextSource() {
DefaultSpringSecurityContextSource contextSource =
new DefaultSpringSecurityContextSource(ldapUrl);
return contextSource;
}
以下是如何實現其他角色populator(LdapAndDatabaseAuthoritiesPopulator)。
public class LdapAndDatabaseAuthoritiesPopulator extends DefaultLdapAuthoritiesPopulator{
public LdapAndDatabaseAuthoritiesPopulator(ContextSource contextSource, String groupSearchBase) {
super(contextSource, groupSearchBase);
}
protected Set<GrantedAuthority> getAdditionalRoles(DirContextOperations user,
String username) {
Set<GrantedAuthority> mappedAuthorities = new HashSet<GrantedAuthority>();
/* Add additional roles from other sources for this user*/
/* below add is just an example of how to add a role */
mappedAuthorities.add(
new GrantedAuthority() {
private static final long serialVersionUID = 3618700057662135367L;
@Override
public String getAuthority() {
return "ROLE_MYAPP_USER"; //this is just a temporary role we are adding as example. get the roles from database.
}
@Override
public String toString(){
return this.getAuthority();
}
});
for (GrantedAuthority granted : mappedAuthorities) {
log.debug("Authority : {}", granted.getAuthority().toString());
}
return mappedAuthorities;
}
}
下面是自定義LDAP身份驗證提供者(LdapAndDatabaseAuthenticationProvider)如何實現的,以檢查用戶是否已要求在數據庫中定義訪問應用程序的作用。如果用戶不在數據庫中或缺少角色,身份驗證將拋出Account DisabledException。
franDays還建議使用「自定義驗證提供程序」。我想給他一個信貸。
public class LdapAndDatabaseAuthenticationProvider extends LdapAuthenticationProvider{
public LdapAndDatabaseAuthenticationProvider(LdapAuthenticator authenticator, LdapAuthoritiesPopulator authoritiesPopulator) {
super(authenticator, authoritiesPopulator);
}
@Override
protected DirContextOperations doAuthentication(
UsernamePasswordAuthenticationToken authentication) {
log.debug("Checking if user <{}> is defined at database to use this application.", authentication.getName());
// Here is the part we need to check in the database if user has required role to log into the application.
// After check if user has the role, do nothing, otherwise throw exception like below example.
boolean canUserAuthenticate = isActiveUserExist(authentication.getName());
log.debug("canUserAuthenticate: {}", canUserAuthenticate);
if (!canUserAuthenticate)
throw new DisabledException("User does not have access to Application!");
return super.doAuthentication(authentication);
}
private boolean isActiveUserExist(String userId) {
// Do your logic here are return boolean value...
}
你可以實現你自己的AuthenticationProvider。身份驗證方法將查詢LdapTemplate,並在成功嘗試後從隨處存儲的任何位置查詢組。它可能如下所示:
public class CustomAuthenticationProvider implements AuthenticationProvider {
private LdapTemplate ldapTemplate;
private UserRepository userRepository;
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String username = (String) authentication.getPrincipal();
boolean success = ldapTemplate.authenticate(...);
if (!success) {
throw new BadCredentialsException("Wrong username or password");
}
User user = userRepository.findByUsername(username);
if (user == null) {
throw new BadCredentialsException("Username not known by the application");
}
return new CustomAuthentication(username, user.getRoles());
}
}
我省略了LdapTemplate的初始化,因爲它取決於您的案例的具體情況。對於您要返回的Authentication對象,您需要實現一個類並允許通過傳遞用戶名和密碼來構建實例。
如果您需要關於如何註冊使用Java配置您的身份驗證提供者的指導,這篇文章可能會有所幫助:Custom Authentication provider with Spring Security and Java Config
在我的應用程序中,角色和角色都擁有權限。在這種情況下,我應該在mappedAuthorities方法中指定什麼(角色名稱或權限名稱) –