package org.apereo.cas.services; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder; import org.apereo.cas.authentication.principal.Principal; import org.apereo.cas.authentication.principal.Service; import org.apereo.cas.util.spring.ApplicationContextProvider; import org.apereo.services.persondir.util.CaseCanonicalizationMode; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.ApplicationContext; import javax.persistence.PostLoad; import java.util.Locale; /** * This is {@link BaseRegisteredServiceUsernameAttributeProvider}. * * @author Misagh Moayyed * @since 5.1.0 */ public abstract class BaseRegisteredServiceUsernameAttributeProvider implements RegisteredServiceUsernameAttributeProvider { private static final long serialVersionUID = -8381275200333399951L; private static final Logger LOGGER = LoggerFactory.getLogger(BaseRegisteredServiceUsernameAttributeProvider.class); private String canonicalizationMode = CaseCanonicalizationMode.NONE.name(); private boolean encryptUsername; public BaseRegisteredServiceUsernameAttributeProvider() { setCanonicalizationMode(CaseCanonicalizationMode.NONE.name()); } public BaseRegisteredServiceUsernameAttributeProvider(final String canonicalizationMode) { this.canonicalizationMode = canonicalizationMode; } @Override public final String resolveUsername(final Principal principal, final Service service, final RegisteredService registeredService) { final String username = resolveUsernameInternal(principal, service); if (canonicalizationMode == null) { canonicalizationMode = CaseCanonicalizationMode.NONE.name(); } final String uid = CaseCanonicalizationMode.valueOf(canonicalizationMode).canonicalize(username.trim(), Locale.getDefault()); LOGGER.debug("Resolved username for [{}] is [{}]", service.getId(), uid); if (!this.encryptUsername) { return uid; } final String encryptedId = encryptResolvedUsername(principal, service, registeredService, uid); if (StringUtils.isBlank(encryptedId)) { throw new IllegalArgumentException("Could not encrypt username " + uid + " for service " + service); } return encryptedId; } /** * Encrypt resolved username. * * @param principal the principal * @param service the service * @param registeredService the registered service * @param username the username * @return the encrypted username or null */ protected String encryptResolvedUsername(final Principal principal, final Service service, final RegisteredService registeredService, final String username) { final ApplicationContext applicationContext = ApplicationContextProvider.getApplicationContext(); final RegisteredServiceCipherExecutor cipher = applicationContext.getBean("registeredServiceCipherExecutor", RegisteredServiceCipherExecutor.class); return cipher.encode(username, registeredService); } /** * Initializes the registered service with default values * for fields that are unspecified. Only triggered by JPA. */ @PostLoad public void initialize() { setCanonicalizationMode(CaseCanonicalizationMode.NONE.name()); } /** * Resolve username internal string. * * @param principal the principal * @param service the service * @return the string */ protected abstract String resolveUsernameInternal(Principal principal, Service service); public String getCanonicalizationMode() { return canonicalizationMode; } public void setCanonicalizationMode(final String canonicalizationMode) { this.canonicalizationMode = canonicalizationMode; } public boolean isEncryptUsername() { return encryptUsername; } public void setEncryptUsername(final boolean encryptUsername) { this.encryptUsername = encryptUsername; } @Override public boolean equals(final Object obj) { if (obj == null) { return false; } if (obj == this) { return true; } if (obj.getClass() != getClass()) { return false; } final BaseRegisteredServiceUsernameAttributeProvider rhs = (BaseRegisteredServiceUsernameAttributeProvider) obj; return new EqualsBuilder() .append(this.canonicalizationMode, rhs.canonicalizationMode) .append(this.encryptUsername, rhs.encryptUsername) .isEquals(); } @Override public int hashCode() { return new HashCodeBuilder() .append(canonicalizationMode) .append(encryptUsername) .toHashCode(); } }