Commit 907dd4bb authored by Misagh Moayyed's avatar Misagh Moayyed
Browse files

Merge branch 'master' into service-factories

Conflicts:
	cas-server-core/src/test/java/org/jasig/cas/TestUtils.java
	cas-server-support-openid/src/main/java/org/jasig/cas/support/openid/OpenIdProtocolConstants.java
	cas-server-support-openid/src/main/java/org/jasig/cas/support/openid/web/support/OpenIdArgumentExtractor.java
parents 436891a7 fe03f630
......@@ -511,7 +511,6 @@
<i class="fa fa-lg fa-question-circle form-tooltip-icon" data-toggle="tooltip" data-placement="top" title="<spring:message code="services.form.tooltip.attrRelease.principleAttRepo.cached.expiration" />"></i>
</label>
<div class="col-sm-8">
<%-- TODO: Shouldn't this be at least greater than 0? --%>
<input type="number" min="0" class="form-control" id="cachedExp" ng-model="serviceFormCtrl.serviceData.attrRelease.cachedExpiration" />
</div>
</div>
......
......@@ -201,16 +201,6 @@
<artifactId>httpclient</artifactId>
</dependency>
<dependency>
<groupId>javax.cache</groupId>
<artifactId>cache-api</artifactId>
</dependency>
<dependency>
<groupId>org.jsr107.ri</groupId>
<artifactId>cache-ri-impl</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
......
......@@ -34,6 +34,7 @@ public class RememberMeUsernamePasswordCredential extends UsernamePasswordCreden
private boolean rememberMe;
@Override
public final boolean isRememberMe() {
return this.rememberMe;
}
......@@ -64,6 +65,7 @@ public class RememberMeUsernamePasswordCredential extends UsernamePasswordCreden
return true;
}
@Override
public final void setRememberMe(final boolean rememberMe) {
this.rememberMe = rememberMe;
}
......
......@@ -124,10 +124,6 @@ public abstract class AbstractUsernamePasswordAuthenticationHandler extends
this.passwordPolicyConfiguration = passwordPolicyConfiguration;
}
/**
* {@inheritDoc}
* @return True if credential is a {@link UsernamePasswordCredential}, false otherwise.
*/
@Override
public boolean supports(final Credential credential) {
return credential instanceof UsernamePasswordCredential;
......
......@@ -21,7 +21,9 @@ package org.jasig.cas.authentication.principal;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.jasig.cas.authentication.principal.cache.AbstractPrincipalAttributesRepository;
import java.io.IOException;
import java.util.Map;
/**
......@@ -30,14 +32,23 @@ import java.util.Map;
* @author Misagh Moayyed
* @since 4.1
*/
public final class DefaultPrincipalAttributesRepository implements PrincipalAttributesRepository {
public final class DefaultPrincipalAttributesRepository extends AbstractPrincipalAttributesRepository {
private static final long serialVersionUID = -4535358847021241725L;
@Override
public Map<String, Object> getAttributes(final Principal p) {
protected void addPrincipalAttributes(final String id, final Map<String, Object> attributes) {
logger.debug("Using {}, no caching takes place for {} to add attributes.", id,
this.getClass().getSimpleName());
}
@Override
protected Map<String, Object> getPrincipalAttributes(final Principal p) {
logger.debug("{} will return the collection of attributes directly associated with the principal object",
this.getClass().getSimpleName());
return p.getAttributes();
}
@Override
public String toString() {
return new ToStringBuilder(this)
......@@ -65,4 +76,7 @@ public final class DefaultPrincipalAttributesRepository implements PrincipalAttr
return new HashCodeBuilder(13, 133)
.toHashCode();
}
@Override
public void close() throws IOException {}
}
/*
* Licensed to Apereo under one or more contributor license
* agreements. See the NOTICE file distributed with this work
* for additional information regarding copyright ownership.
* Apereo licenses this file to you 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 the following location:
*
* 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.jasig.cas.authentication.principal.cache;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import org.jasig.cas.authentication.principal.Principal;
import org.jasig.services.persondir.IPersonAttributeDao;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
/**
* Wrapper around an attribute repository where attributes cached for a configurable period
* based on google guava's caching library.
* @author Misagh Moayyed
* @since 4.2
*/
public final class CachingPrincipalAttributesRepository extends AbstractPrincipalAttributesRepository {
private static final long serialVersionUID = 6350244643948535906L;
private static final long DEFAULT_MAXIMUM_CACHE_SIZE = 1000;
private final transient Cache<String, Map<String, Object>> cache;
private final PrincipalAttributesCacheLoader cacheLoader =
new PrincipalAttributesCacheLoader();
/**
* Used for serialization only.
*/
private CachingPrincipalAttributesRepository() {
this.cache = null;
}
/**
* Instantiates a new caching attributes principal factory.
* Sets the default cache size to {@link #DEFAULT_MAXIMUM_CACHE_SIZE}.
* @param attributeRepository the attribute repository
* @param timeUnit the time unit
* @param expiryDuration the expiry duration
*/
public CachingPrincipalAttributesRepository(final IPersonAttributeDao attributeRepository,
final TimeUnit timeUnit,
final long expiryDuration) {
this(attributeRepository, DEFAULT_MAXIMUM_CACHE_SIZE, timeUnit, expiryDuration);
}
/**
* Instantiates a new caching attributes principal factory.
* @param attributeRepository the attribute repository
* @param maxCacheSize the max cache size
* @param timeUnit the time unit
* @param expiryDuration the expiry duration
*/
public CachingPrincipalAttributesRepository(final IPersonAttributeDao attributeRepository,
final long maxCacheSize,
final TimeUnit timeUnit,
final long expiryDuration) {
super(attributeRepository, expiryDuration, timeUnit);
this.cache = CacheBuilder.newBuilder().maximumSize(maxCacheSize)
.expireAfterWrite(expiryDuration, timeUnit).build(this.cacheLoader);
}
@Override
protected void addPrincipalAttributes(final String id, final Map<String, Object> attributes) {
this.cache.put(id, attributes);
logger.debug("Cached attributes for {}", id);
}
@Override
protected Map<String, Object> getPrincipalAttributes(final Principal p) {
try {
return this.cache.get(p.getId(), new Callable<Map<String, Object>>() {
@Override
public Map<String, Object> call() throws Exception {
logger.debug("No cached attributes could be found for {}", p.getId());
return new HashMap<>();
}
});
} catch (final Exception e) {
logger.error(e.getMessage(), e);
}
return null;
}
@Override
public void close() throws IOException {
this.cache.cleanUp();
}
private static class PrincipalAttributesCacheLoader extends CacheLoader<String, Map<String, Object>> {
@Override
public Map<String, Object> load(final String key) throws Exception {
return new HashMap<>();
}
}
}
......@@ -76,7 +76,7 @@ public final class DefaultTicketRegistryCleaner implements RegistryCleaner {
private LockingStrategy lock = new NoOpLockingStrategy();
@NotNull
private TicketRegistry ticketRegistry;
private final TicketRegistry ticketRegistry;
/**
* Instantiates a new Default ticket registry cleaner.
......@@ -151,9 +151,7 @@ public final class DefaultTicketRegistryCleaner implements RegistryCleaner {
* such as JPA, in a clustered CAS environment. Use JPA locking strategies
* for JPA-backed ticket registries in a clustered
* CAS environment.
* @deprecated As of 4.1. Consider using constructors instead.
*/
@Deprecated
public void setLock(final LockingStrategy strategy) {
this.lock = strategy;
}
......
......@@ -25,7 +25,6 @@ import org.jasig.cas.services.RegisteredServiceAccessStrategy;
import org.jasig.cas.services.RegisteredServiceProxyPolicy;
import org.jasig.cas.util.AbstractJacksonBackedJsonSerializer;
import javax.cache.expiry.Duration;
import java.net.URL;
import java.util.Map;
......@@ -52,26 +51,10 @@ public final class RegisteredServiceJsonSerializer extends AbstractJacksonBacked
final ObjectMapper mapper = super.initializeObjectMapper();
mapper.addMixIn(RegisteredServiceProxyPolicy.class, RegisteredServiceProxyPolicyMixin.class);
mapper.addMixIn(RegisteredServiceAccessStrategy.class, RegisteredServiceAuthorizationStrategyMixin.class);
mapper.addMixIn(Duration.class, DurationMixin.class);
return mapper;
}
private static class DurationMixin extends Duration {
private static final long serialVersionUID = 743505593336053306L;
@JsonIgnore
@Override
public boolean isEternal() {
return false;
}
@JsonIgnore
@Override
public boolean isZero() {
return false;
}
}
private static class RegisteredServiceProxyPolicyMixin implements RegisteredServiceProxyPolicy {
private static final long serialVersionUID = 4854597398304437341L;
......
/*
* Licensed to Apereo under one or more contributor license
* agreements. See the NOTICE file distributed with this work
* for additional information regarding copyright ownership.
* Apereo licenses this file to you 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 the following location:
*
* 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.jasig.cas.web;
import org.jasig.cas.authentication.AuthenticationHandler;
import org.jasig.cas.authentication.principal.PrincipalResolver;
import org.jasig.cas.services.RegisteredService;
import org.jasig.cas.services.ServicesManager;
import org.jasig.cas.util.UniqueTicketIdGenerator;
import org.jasig.cas.web.support.ArgumentExtractor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping;
import org.springframework.web.servlet.mvc.Controller;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.ServletRegistration;
import java.util.List;
import java.util.Map;
/**
* Parent class for all servlet context initializers
* that provides commons methods for retrieving beans
* from the context dynamically.
* @author Misagh Moayyed
* @since 4.2
*/
@Component
public abstract class AbstractServletContextInitializer implements ServletContextListener, ApplicationContextAware {
/** Default CAS Servlet name. **/
private static final String CAS_SERVLET_NAME = "cas";
protected final Logger logger = LoggerFactory.getLogger(this.getClass());
/** Application context. */
protected ApplicationContext applicationContext;
private final String contextInitializerName = getClass().getSimpleName();
/**
* Instantiates a new servlet context initializer.
*/
protected AbstractServletContextInitializer() {}
@Override
public final void contextInitialized(final ServletContextEvent sce) {
logger.info("Initializing {} context...", contextInitializerName);
initializeServletContext(sce);
logger.info("Initialized {} context...", contextInitializerName);
}
@Override
public final void contextDestroyed(final ServletContextEvent sce) {
logger.info("Destroying {} context...", contextInitializerName);
destroyServletContext(sce);
logger.info("Destroyed {} context...", contextInitializerName);
}
@Override
public final void setApplicationContext(final ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
try {
if (applicationContext.getParent() == null) {
logger.info("Initializing {} root application context", contextInitializerName);
initializeRootApplicationContext();
logger.info("Initialized {} root application context successfully", contextInitializerName);
} else {
logger.info("Initializing {} application context", contextInitializerName);
initializeServletApplicationContext();
logger.info("Initialized {} application context successfully", contextInitializerName);
}
} catch (final Exception e) {
logger.error(e.getMessage(), e);
}
}
/**
* Add authentication handler principal resolver.
*
* @param handler the handler
* @param resolver the resolver
*/
protected final void addAuthenticationHandlerPrincipalResolver(final AuthenticationHandler handler,
final PrincipalResolver resolver) {
final Map<AuthenticationHandler, PrincipalResolver> authenticationHandlersResolvers =
applicationContext.getBean("authenticationHandlersResolvers", Map.class);
authenticationHandlersResolvers.put(handler, resolver);
}
/**
* Gets cas servlet registration.
*
* @param sce the sce
* @return the cas servlet registration
*/
protected final ServletRegistration getCasServletRegistration(final ServletContextEvent sce) {
final ServletRegistration registration = sce.getServletContext().getServletRegistration(CAS_SERVLET_NAME);
return registration;
}
/**
* Add registered service to services manager.
*
* @param svc the svc
*/
protected final void addRegisteredServiceToServicesManager(final RegisteredService svc) {
final ServicesManager manager = this.applicationContext.getBean("servicesManager", ServicesManager.class);
}
/**
* Gets cas servlet handler mapping.
*
* @return the cas servlet handler mapping
*/
protected final SimpleUrlHandlerMapping getCasServletHandlerMapping() {
final SimpleUrlHandlerMapping handlerMappingC =
applicationContext.getBean("handlerMappingC", SimpleUrlHandlerMapping.class);
return handlerMappingC;
}
/**
* Add controller to cas servlet handler mapping.
*
* @param path the path
* @param controller the controller
*/
protected final void addControllerToCasServletHandlerMapping(final String path, final Controller controller) {
final SimpleUrlHandlerMapping handlerMappingC = getCasServletHandlerMapping();
final Map<String, Object> urlMap = (Map<String, Object>) handlerMappingC.getUrlMap();
urlMap.put(path, controller);
handlerMappingC.initApplicationContext();
}
/**
* Add controller to cas servlet handler mapping.
*
* @param path the path
* @param controller the controller
*/
protected final void addControllerToCasServletHandlerMapping(final String path, final String controller) {
addControllerToCasServletHandlerMapping(path, getController(controller));
}
/**
* Gets controller.
*
* @param id the id
* @return the controller
*/
protected final Controller getController(final String id) {
return applicationContext.getBean(id, Controller.class);
}
/**
* Add endpoint mapping to cas servlet.
*
* @param sce the sce
* @param mapping the mapping
*/
protected final void addEndpointMappingToCasServlet(final ServletContextEvent sce, final String mapping) {
final ServletRegistration registration = getCasServletRegistration(sce);
registration.addMapping(mapping);
logger.info("Added [{}] to {} servlet context", mapping, CAS_SERVLET_NAME);
}
/**
* Add argument extractor.
*
* @param ext the ext
*/
protected final void addArgumentExtractor(final ArgumentExtractor ext) {
final List<ArgumentExtractor> list = applicationContext.getBean("argumentExtractors", List.class);
list.add(ext);
}
/**
* Add service ticket unique id generator.
*
* @param serviceName the service name
* @param gen the gen
*/
protected final void addServiceTicketUniqueIdGenerator(final String serviceName, final UniqueTicketIdGenerator gen) {
final Map<String, UniqueTicketIdGenerator> map =
applicationContext.getBean("uniqueIdGeneratorsMap", Map.class);
map.put(serviceName, gen);
}
/**
* Initialize root application context.
*/
protected void initializeRootApplicationContext() {}
/**
* Initialize servlet application context.
*/
protected void initializeServletApplicationContext() {}
/**
* Initialize servlet context.
*
* @param event the event
*/
protected void initializeServletContext(final ServletContextEvent event) {}
/**
* Destroy servlet context.
*
* @param event the event
*/
protected void destroyServletContext(final ServletContextEvent event) {}
}
......@@ -29,6 +29,8 @@ import org.jasig.cas.ticket.ServiceTicket;
import org.jasig.cas.web.support.WebUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.util.StringUtils;
import org.springframework.webflow.action.AbstractAction;
import org.springframework.webflow.execution.Event;
......@@ -56,6 +58,8 @@ public abstract class AbstractNonInteractiveCredentialsAction extends AbstractAc
/** Instance of CentralAuthenticationService. */
@NotNull
@Autowired
@Qualifier("centralAuthenticationService")
private CentralAuthenticationService centralAuthenticationService;
/**
......
......@@ -28,11 +28,11 @@ import org.jasig.cas.authentication.DefaultHandlerResult;
import org.jasig.cas.authentication.HttpBasedServiceCredential;
import org.jasig.cas.authentication.UsernamePasswordCredential;
import org.jasig.cas.authentication.handler.support.SimpleTestUsernamePasswordAuthenticationHandler;
import org.jasig.cas.authentication.principal.CachingPrincipalAttributesRepository;
import org.jasig.cas.authentication.principal.DefaultPrincipalFactory;
import org.jasig.cas.authentication.principal.Principal;
import org.jasig.cas.authentication.principal.Service;
import org.jasig.cas.authentication.principal.WebApplicationServiceFactory;
import org.jasig.cas.authentication.principal.cache.CachingPrincipalAttributesRepository;
import org.jasig.cas.services.AbstractRegisteredService;
import org.jasig.cas.services.DefaultRegisteredServiceAccessStrategy;
import org.jasig.cas.services.LogoutType;
......@@ -62,6 +62,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
/**
* @author Scott Battaglia
......@@ -170,7 +171,7 @@ public final class TestUtils {
policy.setAuthorizedToReleaseProxyGrantingTicket(true);
final CachingPrincipalAttributesRepository repo =
new CachingPrincipalAttributesRepository(new StubPersonAttributeDao(), 10);
new CachingPrincipalAttributesRepository(new StubPersonAttributeDao(), TimeUnit.SECONDS , 10);
repo.setMergingStrategy(new NoncollidingAttributeAdder());
policy.setPrincipalAttributesRepository(repo);
policy.setAttributeFilter(new RegisteredServiceRegexAttributeFilter("https://.+"));
......