簡體   English   中英

具有Active Directory和數據庫角色的Spring Security

[英]Spring Security with Active Directory and Database roles

我正在嘗試將Spring Security與Active Directory用戶名和密碼一起使用。 此外,我有一個數據庫Roles表,該表與包含Active Directory用戶名的User表有關系(User表與Active Directory無關,它是完全獨立的,我只是將用戶名放在該表中,這樣我就可以與角色匹配)

我正在關注這個示例http://krams915.blogspot.com/2012/01/spring-security-31-implement_1244.html

問題是我看不到CustomUserDetailsS​​ervice類的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);
        }
    }

據我了解,此行根據數據庫userRepository.findByUsername(username);驗證用戶userRepository.findByUsername(username);

但是,如何在其中使用lpad驗證? 我可以在這里使用類似身份驗證的工具嗎? http://www.javaxt.com/Tutorials/Windows/How_to_Authenticate_Users_with_Active_Directory

更新:

我正在嘗試使其與CustomUserDetailsContextMapper一起使用

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"/>

自定義類

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      
    }
}

我想我快要走了,但沒有收到錯誤消息,但似乎無法映射任何用戶, System.out.println("TEST") ; 行永遠不會執行。 可能與URL /域名有關嗎? 我確定網址正確無誤,因為如果更改它,則會收到錯誤消息。

我最終按照M. Deinum的建議使用了UserDetailsContextMapper。 我還創建了海關SpringSecurityLdapTemplate和ActiveDirectoryLdapAuthenticationProvider。

在我的自定義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);
        }
    }
} 

這對我來說很重要: env.put(Context.REFERRAL,“ follow”);

並在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();
}

這對我有用,但這是一個非常特殊的場景。 感謝Deinum M向我指出正確的方向。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM