Package org.geoserver.security

Source Code of org.geoserver.security.HttpDigestUserDetailsServiceWrapper$DigestUserDetails

/* (c) 2014 Open Source Geospatial Foundation - all rights reserved
* (c) 2001 - 2013 OpenPlans
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geoserver.security;

import java.nio.charset.Charset;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.geoserver.security.impl.GeoServerRole;
import org.geoserver.security.impl.GeoServerUser;
import org.geoserver.security.impl.UserDetailsWrapper;
import org.geoserver.security.password.GeoServerMultiplexingPasswordEncoder;
import org.geoserver.security.password.UserDetailsPasswordWrapper;
import org.springframework.dao.DataAccessException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.codec.Hex;
import org.springframework.security.web.authentication.www.DigestAuthenticationFilter;

/**
* {@link UserDetailsService} implementation to be used for
* HTTP digest authentication
*
* {@link UserDetails} objects have their password alreay md5a1 encoded.
*
{@link DigestAuthenticationFilter#setPasswordAlreadyEncoded(boolean)} must
*  be called with a value of <code>true</code>
*
* @author christian
*
*/
public class HttpDigestUserDetailsServiceWrapper implements UserDetailsService {
   
    static public class DigestUserDetails extends UserDetailsWrapper {       
        private static final long serialVersionUID = 1L;

        private String password;
        private Collection<GrantedAuthority> roles;
       
        public DigestUserDetails(UserDetails details, String password, Collection<GrantedAuthority> roles) {
            super(details);
            this.password=password;
            this.roles=roles;
        }
       
        @Override
        public Collection<GrantedAuthority> getAuthorities() {
            return roles;
        }

        @Override
        public String getPassword() {
            return password;
        }

    }
   
    private GeoServerSecurityManager manager;
    protected GeoServerUserGroupService service;
    protected Charset charSet;
    protected final char[] delimArray= new char[] {':' };
    protected MessageDigest digest;
    protected GeoServerMultiplexingPasswordEncoder enc;
   
    public HttpDigestUserDetailsServiceWrapper(GeoServerUserGroupService service,Charset charSet) {
       this.service= service;
       this.charSet=charSet;
       manager = service.getSecurityManager();
       enc = new GeoServerMultiplexingPasswordEncoder(service.getSecurityManager(),service);                        
        try {
            digest = MessageDigest.getInstance("MD5");
        } catch (NoSuchAlgorithmException e) {
            throw new IllegalStateException("No MD5 algorithm available!");
        }
    }

   
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException,
            DataAccessException {
       
        if (GeoServerUser.ROOT_USERNAME.equals(username))
            return prepareForRootUser ();
       
        GeoServerUser user = (GeoServerUser) service.loadUserByUsername(username);           
        return prepareForUser(user);
    }

    UserDetails prepareForUser (GeoServerUser user) {
        char[] pw = null;
        try {           
            pw = enc.decodeToCharArray(user.getPassword());
        } catch (UnsupportedOperationException ex) {
            pw = user.getPassword().toCharArray();
        }   
            
        String a1 = encodePasswordInA1Format(user.getUsername(),
                    GeoServerSecurityManager.REALM, pw);
        manager.disposePassword(pw);   
        List<GrantedAuthority> roles = new ArrayList<GrantedAuthority>();
        roles.addAll(user.getAuthorities());
        roles.add(GeoServerRole.AUTHENTICATED_ROLE);               
        return new DigestUserDetails(user, a1,roles);
    }
   
    UserDetails prepareForRootUser () {
       
        char[] mpw = null;
        try {
            mpw= manager.getMasterPassword();
            String a1 = encodePasswordInA1Format(GeoServerUser.ROOT_USERNAME,
                    GeoServerSecurityManager.REALM, mpw);
           
            return new UserDetailsPasswordWrapper(
                    GeoServerUser.createRoot(), a1);
        }
        finally {
            if (mpw!=null)
                manager.disposePassword(mpw);
        }
    }
   
    String encodePasswordInA1Format(String username, String realm, char[] password) {
        char[] array = null;
        try {
            char[] usernameArray = username.toCharArray();
            char[] realmArray = realm.toCharArray();
           
            array = new char[usernameArray.length+realmArray.length+password.length+2];
            int pos=0;
           
            System.arraycopy(usernameArray, 0, array, pos, usernameArray.length);
            pos+=usernameArray.length;
           
            System.arraycopy(delimArray, 0, array, pos, 1);
            pos++;
   
            System.arraycopy(realmArray, 0, array, pos, realmArray.length);
            pos+=realmArray.length;
           
            System.arraycopy(delimArray, 0, array, pos, 1);
            pos++;
   
            System.arraycopy(password, 0, array, pos, password.length);
                       
            MessageDigest md=null;
            try {
                md = (MessageDigest) digest.clone(); // thread safe
            } catch (CloneNotSupportedException e) {
                throw new RuntimeException(e);
            }
            return new String(Hex.encode(md.digest(SecurityUtils.toBytes(array, charSet))));
           
        } finally {
            if (array!=null)
                manager.disposePassword(array);
        }                       
    }
   
}
TOP

Related Classes of org.geoserver.security.HttpDigestUserDetailsServiceWrapper$DigestUserDetails

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.