package org.apereo.cas.services;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.http.client.utils.URIBuilder;
import org.apereo.cas.util.http.HttpClient;
import org.apereo.cas.util.spring.ApplicationContextProvider;
import org.apereo.cas.util.http.HttpMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;
import java.net.URL;
import java.util.Map;
/**
* This is {@link RemoteEndpointServiceAccessStrategy} that reaches out
* to a remote endpoint, passing the CAS principal id to determine if access is allowed.
* If the status code returned in the final response is not accepted by the policy here,
* access shall be denied.
*
* @author Misagh Moayyed
* @since 5.0.0
*/
public class RemoteEndpointServiceAccessStrategy extends DefaultRegisteredServiceAccessStrategy {
private static final long serialVersionUID = -1108201604115278440L;
private static final Logger LOGGER = LoggerFactory.getLogger(RemoteEndpointServiceAccessStrategy.class);
private String endpointUrl;
private String acceptableResponseCodes;
@Override
public boolean doPrincipalAttributesAllowServiceAccess(final String principal,
final Map<String, Object> principalAttributes) {
try {
if (super.doPrincipalAttributesAllowServiceAccess(principal, principalAttributes)) {
final HttpClient client = ApplicationContextProvider.getApplicationContext()
.getBean("noRedirectHttpClient", HttpClient.class);
final URIBuilder builder = new URIBuilder(this.endpointUrl);
builder.addParameter("username", principal);
final URL url = builder.build().toURL();
final HttpMessage message = client.sendMessageToEndPoint(url);
LOGGER.debug("Message received from [{}] is [{}]", url, message);
return message != null && StringUtils.commaDelimitedListToSet(this.acceptableResponseCodes)
.contains(String.valueOf(message.getResponseCode()));
}
} catch (final Exception e) {
LOGGER.error(e.getMessage(), e);
}
return false;
}
public String getEndpointUrl() {
return endpointUrl;
}
public void setEndpointUrl(final String endpointUrl) {
this.endpointUrl = endpointUrl;
}
public String getAcceptableResponseCodes() {
return acceptableResponseCodes;
}
public void setAcceptableResponseCodes(final String acceptableResponseCodes) {
this.acceptableResponseCodes = acceptableResponseCodes;
}
@Override
public boolean equals(final Object obj) {
if (obj == null) {
return false;
}
if (obj == this) {
return true;
}
if (obj.getClass() != getClass()) {
return false;
}
final RemoteEndpointServiceAccessStrategy rhs = (RemoteEndpointServiceAccessStrategy) obj;
return new EqualsBuilder()
.appendSuper(super.equals(obj))
.append(this.endpointUrl, rhs.endpointUrl)
.append(this.acceptableResponseCodes, rhs.acceptableResponseCodes)
.isEquals();
}
@Override
public int hashCode() {
return new HashCodeBuilder()
.appendSuper(super.hashCode())
.append(endpointUrl)
.append(acceptableResponseCodes)
.toHashCode();
}
@Override
public String toString() {
return new ToStringBuilder(this)
.appendSuper(super.toString())
.append("endpointUrl", endpointUrl)
.append("acceptableResponseCodes", acceptableResponseCodes)
.toString();
}
}