All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cn.home1.cloud.config.server.security.ApplicationConfigSecurity Maven / Gradle / Ivy

The newest version!
package cn.home1.cloud.config.server.security;

import static cn.home1.cloud.config.server.util.Consts.DOT_ENV;
import static cn.home1.cloud.config.server.util.Consts.PRIVILEGE_ENV_PROFILE_;
import static java.util.stream.Collectors.toSet;
import static org.apache.commons.lang3.StringUtils.isNotEmpty;

import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;

import java.util.Collection;
import java.util.Optional;
import java.util.regex.Pattern;

/**
 * Determine whether let user go further by login user and repository name in URL.
 */
@Slf4j
public class ApplicationConfigSecurity {

    private static final Pattern PATTERN_COMMA = Pattern.compile(",");

    @Autowired
    @Setter
    private PrivilegedUserProperties privilegedUserProperties;

    /**
     * Allow admin user, allow user that name matches repository name
     *
     * @param pathApplication application (repository) name extracted from path
     * @param pathProfiles    profiles extracted from path
     * @return allow access
     */
    public boolean checkAuthentication(final String pathApplication, final String pathProfiles) {
        final boolean result;

        final Collection envProfiles = PATTERN_COMMA.splitAsStream(pathProfiles)
            .filter(profile -> profile.endsWith(DOT_ENV))
            .collect(toSet());

        final Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        final String authName = auth != null ? auth.getName() : null;

        if (envProfiles.size() <= 1) {
            if (isNotEmpty(authName) && auth.isAuthenticated()) {
                final String adminName = this.privilegedUserProperties.getAdminName();
                if (adminName.equals(authName)) {
                    result = true;
                } else {
                    final boolean applicationMatch = pathApplication != null && pathApplication.equals(authName);
                    final boolean isRequestValid = this.isRequestValid(auth, envProfiles);
                    result = applicationMatch && isRequestValid;
                }
            } else {
                result = false;
            }
        } else {
            result = false;
            log.info("Illegal to access multiple environment profiles ({}) in one request", envProfiles);
        }

        log.debug("'{}' {} privilege to access '{}'", authName, result ? "has" : "has no", pathApplication);
        return result;
    }

    boolean isRequestValid(final Authentication auth, final Collection envProfiles) {
        final boolean result;

        final Optional privilege = auth.getAuthorities().stream()
            .map(GrantedAuthority::getAuthority)
            .filter(authority -> authority.startsWith(PRIVILEGE_ENV_PROFILE_))
            .map(p -> p.replace(PRIVILEGE_ENV_PROFILE_, ""))
            .findFirst(); // one environment profile privilege at most, may be none.

        if (privilege.isPresent() && privilege.get().equals("*")) {
            result = true; // wildcard privilege can access any environment profile
        } else {
            result = privilege
                .map(p -> envProfiles.isEmpty() || envProfiles.contains(p)) // access no or matched environment profile only
                .orElseGet(envProfiles::isEmpty); // can not access any environment profile
        }

        return result;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy