parent
							
								
									e15eec7fdd
								
							
						
					
					
						commit
						488a7d720b
					
				@ -0,0 +1,133 @@ | 
				
			||||
/* | 
				
			||||
 * Copyright 2004, 2005, 2006 Acegi Technology Pty Limited | 
				
			||||
 * | 
				
			||||
 * Licensed under the Apache License, Version 2.0 (the "License"); | 
				
			||||
 * you may not use this file except in compliance with the License. | 
				
			||||
 * You may obtain a copy of the License at | 
				
			||||
 * | 
				
			||||
 *      http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||
 * | 
				
			||||
 * Unless required by applicable law or agreed to in writing, software | 
				
			||||
 * distributed under the License is distributed on an "AS IS" BASIS, | 
				
			||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
				
			||||
 * See the License for the specific language governing permissions and | 
				
			||||
 * limitations under the License. | 
				
			||||
 */ | 
				
			||||
 | 
				
			||||
package org.libresonic.player.security; | 
				
			||||
 | 
				
			||||
import org.libresonic.player.Logger; | 
				
			||||
import org.libresonic.player.domain.User; | 
				
			||||
import org.libresonic.player.service.SecurityService; | 
				
			||||
import org.libresonic.player.service.SettingsService; | 
				
			||||
import org.springframework.beans.factory.annotation.Autowired; | 
				
			||||
import org.springframework.ldap.core.DirContextAdapter; | 
				
			||||
import org.springframework.ldap.core.DirContextOperations; | 
				
			||||
import org.springframework.security.authentication.BadCredentialsException; | 
				
			||||
import org.springframework.security.core.GrantedAuthority; | 
				
			||||
import org.springframework.security.core.userdetails.UserDetails; | 
				
			||||
import org.springframework.security.ldap.ppolicy.PasswordPolicyControl; | 
				
			||||
import org.springframework.security.ldap.ppolicy.PasswordPolicyResponseControl; | 
				
			||||
import org.springframework.security.ldap.userdetails.LdapUserDetailsImpl; | 
				
			||||
import org.springframework.security.ldap.userdetails.UserDetailsContextMapper; | 
				
			||||
import org.springframework.stereotype.Component; | 
				
			||||
 | 
				
			||||
import java.util.Collection; | 
				
			||||
 | 
				
			||||
@Component | 
				
			||||
public class LibresonicUserDetailsContextMapper implements UserDetailsContextMapper { | 
				
			||||
    // ~ Instance fields
 | 
				
			||||
    // ================================================================================================
 | 
				
			||||
 | 
				
			||||
    private final Logger logger = Logger.getLogger(LibresonicUserDetailsContextMapper.class); | 
				
			||||
    private String passwordAttributeName = "userPassword"; | 
				
			||||
 | 
				
			||||
    @Autowired | 
				
			||||
    SecurityService securityService; | 
				
			||||
 | 
				
			||||
    @Autowired | 
				
			||||
    SettingsService settingsService; | 
				
			||||
 | 
				
			||||
    // ~ Methods
 | 
				
			||||
    // ========================================================================================================
 | 
				
			||||
 | 
				
			||||
    public UserDetails mapUserFromContext(DirContextOperations ctx, String username, | 
				
			||||
                                          Collection<? extends GrantedAuthority> authorities) { | 
				
			||||
        String dn = ctx.getNameInNamespace(); | 
				
			||||
 | 
				
			||||
        logger.debug("Mapping user details from context with DN: " + dn); | 
				
			||||
 | 
				
			||||
        // User must be defined in Libresonic, unless auto-shadowing is enabled.
 | 
				
			||||
        User user = securityService.getUserByName(username, false); | 
				
			||||
        if (user == null && !settingsService.isLdapAutoShadowing()) { | 
				
			||||
            throw new BadCredentialsException("User does not exist."); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        if (user == null) { | 
				
			||||
            User newUser = new User(username, "", null, true, 0L, 0L, 0L); | 
				
			||||
            newUser.setStreamRole(true); | 
				
			||||
            newUser.setSettingsRole(true); | 
				
			||||
            securityService.createUser(newUser); | 
				
			||||
            logger.info("Created local user '" + username + "' for DN " + dn); | 
				
			||||
            user = securityService.getUserByName(username, false); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        // LDAP authentication must be enabled for the given user.
 | 
				
			||||
        if (!user.isLdapAuthenticated()) { | 
				
			||||
            throw new BadCredentialsException("LDAP authentication disabled for user."); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        LdapUserDetailsImpl.Essence essence = new LdapUserDetailsImpl.Essence(); | 
				
			||||
        essence.setDn(dn); | 
				
			||||
 | 
				
			||||
        Object passwordValue = ctx.getObjectAttribute(passwordAttributeName); | 
				
			||||
 | 
				
			||||
        if (passwordValue != null) { | 
				
			||||
            essence.setPassword(mapPassword(passwordValue)); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        essence.setUsername(user.getUsername()); | 
				
			||||
 | 
				
			||||
        // Add the supplied authorities
 | 
				
			||||
        for (GrantedAuthority authority : securityService.getGrantedAuthorities(user.getUsername())) { | 
				
			||||
            essence.addAuthority(authority); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        // Check for PPolicy data
 | 
				
			||||
 | 
				
			||||
        PasswordPolicyResponseControl ppolicy = (PasswordPolicyResponseControl) ctx | 
				
			||||
                .getObjectAttribute(PasswordPolicyControl.OID); | 
				
			||||
 | 
				
			||||
        if (ppolicy != null) { | 
				
			||||
            essence.setTimeBeforeExpiration(ppolicy.getTimeBeforeExpiration()); | 
				
			||||
            essence.setGraceLoginsRemaining(ppolicy.getGraceLoginsRemaining()); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        return essence.createUserDetails(); | 
				
			||||
 | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public void mapUserToContext(UserDetails user, DirContextAdapter ctx) { | 
				
			||||
        throw new UnsupportedOperationException( | 
				
			||||
                "LdapUserDetailsMapper only supports reading from a context. Please" | 
				
			||||
                        + "use a subclass if mapUserToContext() is required."); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * Extension point to allow customized creation of the user's password from the | 
				
			||||
     * attribute stored in the directory. | 
				
			||||
     * | 
				
			||||
     * @param passwordValue the value of the password attribute | 
				
			||||
     * @return a String representation of the password. | 
				
			||||
     */ | 
				
			||||
    protected String mapPassword(Object passwordValue) { | 
				
			||||
 | 
				
			||||
        if (!(passwordValue instanceof String)) { | 
				
			||||
            // Assume it's binary
 | 
				
			||||
            passwordValue = new String((byte[]) passwordValue); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        return (String) passwordValue; | 
				
			||||
 | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
					Loading…
					
					
				
		Reference in new issue