Compare commits
83 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 82d140ffb1 | |||
| 1563491322 | |||
| b688bb69ee | |||
| 36f008643d | |||
| cbdf77e991 | |||
| 399e921d14 | |||
| c458311d2d | |||
| d6f408e8bf | |||
| 1739628e6a | |||
| 8e68fa1334 | |||
| 82cd72768d | |||
| 161710cc87 | |||
| dc1b652512 | |||
| ed9411c660 | |||
| e58f982351 | |||
| 072b73354f | |||
| 443231d1e8 | |||
| 45674a16ea | |||
| a1b124def5 | |||
| f6abc24ed6 | |||
| 1a9b7e1b6f | |||
| 8b5c70951d | |||
| c891ab45ec | |||
| 657a69b906 | |||
| 3b8fbe8bee | |||
| 4ad85cdfdf | |||
| 845c50a1c3 | |||
| 25d222208d | |||
| 9b0c21dfef | |||
| 8301bd6276 | |||
| 1872d94aa1 | |||
| 46611872db | |||
| b6cbdde0cb | |||
| 71e1702224 | |||
| 80ccd2b285 | |||
| 02c1f02f2a | |||
| 21a664b2eb | |||
| 9a2d0c2cb5 | |||
| 73b62497a3 | |||
| 09aba3906c | |||
| 57cfff6f5c | |||
| b7b6b2bac7 | |||
| 8602ae3863 | |||
| 8737fe3acb | |||
| 27faad3402 | |||
| aaa7bd90b2 | |||
| 295e0ded18 | |||
| 304f12fb63 | |||
| 8cbe232fbf | |||
| 5ac106808e | |||
| 8c605516b3 | |||
| e6e168f127 | |||
| 6d6c2d31ef | |||
| 8f6aecac9b | |||
| 0760bb947b | |||
| 9d2e2ca11d | |||
| 6354c7e052 | |||
| 42cdaa0ce2 | |||
| eda60b72b1 | |||
| 0d198d42ae | |||
| f000aaa7e8 | |||
| 634e340d80 | |||
| 4c8e9e2d7e | |||
| e518adbef1 | |||
| 59b69f6f48 | |||
| b8e50c0933 | |||
| 677576ea8b | |||
| 91153df78d | |||
| 1b0ac9c785 | |||
| 8c9159f273 | |||
| 4c8b0faa88 | |||
| 5a5b62e2cb | |||
| 6ac8588144 | |||
| 5690f1c581 | |||
| 87cf27ab7c | |||
| 41e06152b3 | |||
| a7e21318bf | |||
| bc6aae132b | |||
| b46ae6ac62 | |||
| 317da55cd0 | |||
| 9e751e22c8 | |||
| 4d65b35827 | |||
| 9831980bc2 |
+6
-10
@@ -1,20 +1,16 @@
|
||||
target/
|
||||
*/src/META-INF/
|
||||
.classpath
|
||||
.springBeans
|
||||
.project
|
||||
.DS_Store
|
||||
.settings/
|
||||
.idea/
|
||||
out/
|
||||
bin/
|
||||
intellij/
|
||||
build/
|
||||
*.log
|
||||
*.log.*
|
||||
*.iml
|
||||
out/
|
||||
intellij/
|
||||
*.ipr
|
||||
*.iws
|
||||
*.log
|
||||
*.log.1
|
||||
.DS_Store
|
||||
*.iml
|
||||
.gradle/
|
||||
gradle.properties
|
||||
atlassian-ide-plugin.xml
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
dependencies {
|
||||
compile project(':spring-security-core'),
|
||||
'aopalliance:aopalliance:1.0',
|
||||
"net.sf.ehcache:ehcache:$ehcacheVersion",
|
||||
"org.springframework:spring-aop:$springVersion",
|
||||
"org.springframework:spring-context:$springVersion",
|
||||
@@ -12,6 +11,4 @@ dependencies {
|
||||
testCompile "org.springframework:spring-beans:$springVersion",
|
||||
"org.springframework:spring-context-support:$springVersion",
|
||||
"org.springframework:spring-test:$springVersion"
|
||||
|
||||
testRuntime "hsqldb:hsqldb:$hsqlVersion"
|
||||
}
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
<?xml version="1.0"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<parent>
|
||||
<artifactId>spring-security-parent</artifactId>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<version>3.0.4.RELEASE</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-acl</artifactId>
|
||||
<name>Spring Security - ACL module</name>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<classifier>tests</classifier>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context-support</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-jdbc</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.sf.ehcache</groupId>
|
||||
<artifactId>ehcache</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>hsqldb</groupId>
|
||||
<artifactId>hsqldb</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>postgresql</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
<version>8.3-603.jdbc3</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>com.springsource.bundlor</groupId>
|
||||
<artifactId>com.springsource.bundlor.maven</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
@@ -20,7 +20,6 @@ import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.security.access.AuthorizationServiceException;
|
||||
@@ -146,10 +145,14 @@ public class AclEntryVoter extends AbstractAclVoter {
|
||||
}
|
||||
|
||||
public boolean supports(ConfigAttribute attribute) {
|
||||
return (attribute.getAttribute() != null) && attribute.getAttribute().equals(getProcessConfigAttribute());
|
||||
if ((attribute.getAttribute() != null) && attribute.getAttribute().equals(getProcessConfigAttribute())) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public int vote(Authentication authentication, MethodInvocation object, Collection<ConfigAttribute> attributes) {
|
||||
public int vote(Authentication authentication, Object object, Collection<ConfigAttribute> attributes) {
|
||||
|
||||
for(ConfigAttribute attr : attributes) {
|
||||
|
||||
@@ -174,7 +177,7 @@ public class AclEntryVoter extends AbstractAclVoter {
|
||||
try {
|
||||
Class<?> clazz = domainObject.getClass();
|
||||
Method method = clazz.getMethod(internalMethod, new Class[0]);
|
||||
domainObject = method.invoke(domainObject);
|
||||
domainObject = method.invoke(domainObject, new Object[0]);
|
||||
} catch (NoSuchMethodException nsme) {
|
||||
throw new AuthorizationServiceException("Object of class '" + domainObject.getClass()
|
||||
+ "' does not provide the requested internalMethod: " + internalMethod);
|
||||
|
||||
@@ -1,66 +0,0 @@
|
||||
package org.springframework.security.acls;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.security.access.PermissionCacheOptimizer;
|
||||
import org.springframework.security.acls.domain.ObjectIdentityRetrievalStrategyImpl;
|
||||
import org.springframework.security.acls.domain.SidRetrievalStrategyImpl;
|
||||
import org.springframework.security.acls.model.AclService;
|
||||
import org.springframework.security.acls.model.ObjectIdentity;
|
||||
import org.springframework.security.acls.model.ObjectIdentityRetrievalStrategy;
|
||||
import org.springframework.security.acls.model.Sid;
|
||||
import org.springframework.security.acls.model.SidRetrievalStrategy;
|
||||
import org.springframework.security.core.Authentication;
|
||||
|
||||
/**
|
||||
* Batch loads ACLs for collections of objects to allow optimised filtering.
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @since 3.1
|
||||
*/
|
||||
public class AclPermissionCacheOptimizer implements PermissionCacheOptimizer {
|
||||
private final Log logger = LogFactory.getLog(getClass());
|
||||
private final AclService aclService;
|
||||
private SidRetrievalStrategy sidRetrievalStrategy = new SidRetrievalStrategyImpl();
|
||||
private ObjectIdentityRetrievalStrategy oidRetrievalStrategy = new ObjectIdentityRetrievalStrategyImpl();
|
||||
|
||||
public AclPermissionCacheOptimizer(AclService aclService) {
|
||||
this.aclService = aclService;
|
||||
}
|
||||
|
||||
public void cachePermissionsFor(Authentication authentication, Collection<?> objects) {
|
||||
if (objects.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<ObjectIdentity> oidsToCache = new ArrayList<ObjectIdentity>(objects.size());
|
||||
|
||||
for (Object domainObject : objects) {
|
||||
if (domainObject == null) {
|
||||
continue;
|
||||
}
|
||||
ObjectIdentity oid = oidRetrievalStrategy.getObjectIdentity(domainObject);
|
||||
oidsToCache.add(oid);
|
||||
}
|
||||
|
||||
List<Sid> sids = sidRetrievalStrategy.getSids(authentication);
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Eagerly loading Acls for " + oidsToCache.size() + " objects");
|
||||
}
|
||||
|
||||
aclService.readAclsById(oidsToCache, sids);
|
||||
}
|
||||
|
||||
public void setObjectIdentityRetrievalStrategy(ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy) {
|
||||
this.oidRetrievalStrategy = objectIdentityRetrievalStrategy;
|
||||
}
|
||||
|
||||
public void setSidRetrievalStrategy(SidRetrievalStrategy sidRetrievalStrategy) {
|
||||
this.sidRetrievalStrategy = sidRetrievalStrategy;
|
||||
}
|
||||
}
|
||||
@@ -34,7 +34,7 @@ public class AclPermissionEvaluator implements PermissionEvaluator {
|
||||
|
||||
private final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private final AclService aclService;
|
||||
private AclService aclService;
|
||||
private ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy = new ObjectIdentityRetrievalStrategyImpl();
|
||||
private ObjectIdentityGenerator objectIdentityGenerator = new ObjectIdentityRetrievalStrategyImpl();
|
||||
private SidRetrievalStrategy sidRetrievalStrategy = new SidRetrievalStrategyImpl();
|
||||
@@ -70,30 +70,24 @@ public class AclPermissionEvaluator implements PermissionEvaluator {
|
||||
List<Sid> sids = sidRetrievalStrategy.getSids(authentication);
|
||||
List<Permission> requiredPermission = resolvePermission(permission);
|
||||
|
||||
final boolean debug = logger.isDebugEnabled();
|
||||
|
||||
if (debug) {
|
||||
logger.debug("Checking permission '" + permission + "' for object '" + oid + "'");
|
||||
}
|
||||
|
||||
try {
|
||||
// Lookup only ACLs for SIDs we're interested in
|
||||
Acl acl = aclService.readAclById(oid, sids);
|
||||
|
||||
if (acl.isGranted(requiredPermission, sids, false)) {
|
||||
if (debug) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Access is granted");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (debug) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Returning false - ACLs returned, but insufficient permissions for this principal");
|
||||
}
|
||||
|
||||
} catch (NotFoundException nfe) {
|
||||
if (debug) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Returning false - no ACLs apply for this principal");
|
||||
}
|
||||
}
|
||||
@@ -117,7 +111,7 @@ public class AclPermissionEvaluator implements PermissionEvaluator {
|
||||
|
||||
if (permission instanceof String) {
|
||||
String permString = (String)permission;
|
||||
Permission p;
|
||||
Permission p = null;
|
||||
|
||||
try {
|
||||
p = permissionFactory.buildFromName(permString);
|
||||
|
||||
+5
-3
@@ -43,12 +43,12 @@ import org.springframework.util.Assert;
|
||||
public abstract class AbstractAclProvider implements AfterInvocationProvider {
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
protected final AclService aclService;
|
||||
protected AclService aclService;
|
||||
protected Class<?> processDomainObjectClass = Object.class;
|
||||
protected ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy = new ObjectIdentityRetrievalStrategyImpl();
|
||||
protected SidRetrievalStrategy sidRetrievalStrategy = new SidRetrievalStrategyImpl();
|
||||
protected String processConfigAttribute;
|
||||
protected final List<Permission> requirePermission;
|
||||
protected List<Permission> requirePermission = Arrays.asList(BasePermission.READ);
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
@@ -78,9 +78,11 @@ public abstract class AbstractAclProvider implements AfterInvocationProvider {
|
||||
// Obtain the SIDs applicable to the principal
|
||||
List<Sid> sids = sidRetrievalStrategy.getSids(authentication);
|
||||
|
||||
Acl acl = null;
|
||||
|
||||
try {
|
||||
// Lookup only ACLs for SIDs we're interested in
|
||||
Acl acl = aclService.readAclById(objectIdentity, sids);
|
||||
acl = aclService.readAclById(objectIdentity, sids);
|
||||
|
||||
return acl.isGranted(requirePermission, sids, false);
|
||||
} catch (NotFoundException ignore) {
|
||||
|
||||
+3
-1
@@ -75,7 +75,9 @@ public class AclEntryAfterInvocationCollectionFilteringProvider extends Abstract
|
||||
Object returnedObject) throws AccessDeniedException {
|
||||
|
||||
if (returnedObject == null) {
|
||||
logger.debug("Return object is null, skipping");
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Return object is null, skipping");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
+8
-4
@@ -65,7 +65,7 @@ public class AclEntryAfterInvocationProvider extends AbstractAclProvider impleme
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
public AclEntryAfterInvocationProvider(AclService aclService, List<Permission> requirePermission) {
|
||||
this(aclService, "AFTER_ACL_READ", requirePermission);
|
||||
super(aclService, "AFTER_ACL_READ", requirePermission);
|
||||
}
|
||||
|
||||
public AclEntryAfterInvocationProvider(AclService aclService, String processConfigAttribute,
|
||||
@@ -81,13 +81,17 @@ public class AclEntryAfterInvocationProvider extends AbstractAclProvider impleme
|
||||
if (returnedObject == null) {
|
||||
// AclManager interface contract prohibits nulls
|
||||
// As they have permission to null/nothing, grant access
|
||||
logger.debug("Return object is null, skipping");
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Return object is null, skipping");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!getProcessDomainObjectClass().isAssignableFrom(returnedObject.getClass())) {
|
||||
logger.debug("Return object is not applicable for this provider, skipping");
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Return object is not applicable for this provider, skipping");
|
||||
}
|
||||
|
||||
return returnedObject;
|
||||
}
|
||||
@@ -104,7 +108,7 @@ public class AclEntryAfterInvocationProvider extends AbstractAclProvider impleme
|
||||
|
||||
logger.debug("Denying access");
|
||||
|
||||
throw new AccessDeniedException(messages.getMessage("AclEntryAfterInvocationProvider.noPermission",
|
||||
throw new AccessDeniedException(messages.getMessage("BasicAclEntryAfterInvocationProvider.noPermission",
|
||||
new Object[] {authentication.getName(), returnedObject},
|
||||
"Authentication {0} has NO permissions to the domain object {1}"));
|
||||
}
|
||||
|
||||
+1
-1
@@ -95,7 +95,7 @@ class ArrayFilterer<T> implements Filterer<T> {
|
||||
}
|
||||
|
||||
public T next() {
|
||||
if (!hasNext()) {
|
||||
if (hasNext() == false) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
return list[index++];
|
||||
|
||||
+8
-3
@@ -37,9 +37,12 @@ class CollectionFilterer<T> implements Filterer<T> {
|
||||
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private final Collection<T> collection;
|
||||
private Collection<T> collection;
|
||||
|
||||
private final Set<T> removeList;
|
||||
// collectionIter offers significant performance optimisations (as
|
||||
// per security-developer mailing list conversation 19/5/05)
|
||||
private Iterator<T> collectionIter;
|
||||
private Set<T> removeList;
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
@@ -85,7 +88,9 @@ class CollectionFilterer<T> implements Filterer<T> {
|
||||
* @see org.springframework.security.acls.afterinvocation.Filterer#iterator()
|
||||
*/
|
||||
public Iterator<T> iterator() {
|
||||
return collection.iterator();
|
||||
collectionIter = collection.iterator();
|
||||
|
||||
return collectionIter;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,7 +12,7 @@ public abstract class AbstractPermission implements Permission {
|
||||
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
protected final char code;
|
||||
protected char code;
|
||||
protected int mask;
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
+4
-4
@@ -33,13 +33,13 @@ import java.io.Serializable;
|
||||
public class AccessControlEntryImpl implements AccessControlEntry, AuditableAccessControlEntry {
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private final Acl acl;
|
||||
private Acl acl;
|
||||
private Permission permission;
|
||||
private final Serializable id;
|
||||
private final Sid sid;
|
||||
private Serializable id;
|
||||
private Sid sid;
|
||||
private boolean auditFailure = false;
|
||||
private boolean auditSuccess = false;
|
||||
private final boolean granting;
|
||||
private boolean granting;
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
|
||||
+10
-17
@@ -41,9 +41,9 @@ import org.springframework.util.Assert;
|
||||
public class AclAuthorizationStrategyImpl implements AclAuthorizationStrategy {
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private final GrantedAuthority gaGeneralChanges;
|
||||
private final GrantedAuthority gaModifyAuditing;
|
||||
private final GrantedAuthority gaTakeOwnership;
|
||||
private GrantedAuthority gaGeneralChanges;
|
||||
private GrantedAuthority gaModifyAuditing;
|
||||
private GrantedAuthority gaTakeOwnership;
|
||||
private SidRetrievalStrategy sidRetrievalStrategy = new SidRetrievalStrategyImpl();
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
@@ -52,23 +52,16 @@ public class AclAuthorizationStrategyImpl implements AclAuthorizationStrategy {
|
||||
* Constructor. The only mandatory parameter relates to the system-wide {@link GrantedAuthority} instances that
|
||||
* can be held to always permit ACL changes.
|
||||
*
|
||||
* @param auths the <code>GrantedAuthority</code>s that have
|
||||
* @param auths an array of <code>GrantedAuthority</code>s that have
|
||||
* special permissions (index 0 is the authority needed to change
|
||||
* ownership, index 1 is the authority needed to modify auditing details,
|
||||
* index 2 is the authority needed to change other ACL and ACE details) (required)
|
||||
* <p>
|
||||
* Alternatively, a single value can be supplied for all three permissions.
|
||||
*/
|
||||
public AclAuthorizationStrategyImpl(GrantedAuthority... auths) {
|
||||
Assert.isTrue(auths != null && (auths.length == 3 || auths.length == 1),
|
||||
"One or three GrantedAuthority instances required");
|
||||
if (auths.length == 3) {
|
||||
gaTakeOwnership = auths[0];
|
||||
gaModifyAuditing = auths[1];
|
||||
gaGeneralChanges = auths[2];
|
||||
} else {
|
||||
gaTakeOwnership = gaModifyAuditing = gaGeneralChanges = auths[0];
|
||||
}
|
||||
public AclAuthorizationStrategyImpl(GrantedAuthority[] auths) {
|
||||
Assert.isTrue(auths != null && auths.length == 3, "GrantedAuthority[] with three elements required");
|
||||
this.gaTakeOwnership = auths[0];
|
||||
this.gaModifyAuditing = auths[1];
|
||||
this.gaGeneralChanges = auths[2];
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
@@ -91,7 +84,7 @@ public class AclAuthorizationStrategyImpl implements AclAuthorizationStrategy {
|
||||
}
|
||||
|
||||
// Not authorized by ACL ownership; try via adminstrative permissions
|
||||
GrantedAuthority requiredAuthority;
|
||||
GrantedAuthority requiredAuthority = null;
|
||||
|
||||
if (changeType == CHANGE_AUDITING) {
|
||||
requiredAuthority = this.gaModifyAuditing;
|
||||
|
||||
@@ -26,7 +26,6 @@ import org.springframework.security.acls.model.NotFoundException;
|
||||
import org.springframework.security.acls.model.ObjectIdentity;
|
||||
import org.springframework.security.acls.model.OwnershipAcl;
|
||||
import org.springframework.security.acls.model.Permission;
|
||||
import org.springframework.security.acls.model.PermissionGrantingStrategy;
|
||||
import org.springframework.security.acls.model.Sid;
|
||||
import org.springframework.security.acls.model.UnloadedSidException;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -42,8 +41,8 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
|
||||
|
||||
private Acl parentAcl;
|
||||
private transient AclAuthorizationStrategy aclAuthorizationStrategy;
|
||||
private transient PermissionGrantingStrategy permissionGrantingStrategy;
|
||||
private final List<AccessControlEntry> aces = new ArrayList<AccessControlEntry>();
|
||||
private transient AuditLogger auditLogger;
|
||||
private List<AccessControlEntry> aces = new ArrayList<AccessControlEntry>();
|
||||
private ObjectIdentity objectIdentity;
|
||||
private Serializable id;
|
||||
private Sid owner; // OwnershipAcl
|
||||
@@ -70,48 +69,39 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
|
||||
this.objectIdentity = objectIdentity;
|
||||
this.id = id;
|
||||
this.aclAuthorizationStrategy = aclAuthorizationStrategy;
|
||||
this.permissionGrantingStrategy = new DefaultPermissionGrantingStrategy(auditLogger);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use the version which takes a {@code PermissionGrantingStrategy} argument instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public AclImpl(ObjectIdentity objectIdentity, Serializable id, AclAuthorizationStrategy aclAuthorizationStrategy,
|
||||
AuditLogger auditLogger, Acl parentAcl, List<Sid> loadedSids, boolean entriesInheriting, Sid owner) {
|
||||
this(objectIdentity, id, aclAuthorizationStrategy, new DefaultPermissionGrantingStrategy(auditLogger),
|
||||
parentAcl, loadedSids, entriesInheriting, owner);
|
||||
this.auditLogger = auditLogger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Full constructor, which should be used by persistence tools that do not
|
||||
* provide field-level access features.
|
||||
*
|
||||
* @param objectIdentity the object identity this ACL relates to
|
||||
* @param id the primary key assigned to this ACL
|
||||
* @param aclAuthorizationStrategy authorization strategy
|
||||
* @param grantingStrategy the {@code PermissionGrantingStrategy} which will be used by the {@code isGranted()} method
|
||||
* @param parentAcl the parent (may be may be {@code null})
|
||||
* @param loadedSids the loaded SIDs if only a subset were loaded (may be {@code null})
|
||||
* @param objectIdentity the object identity this ACL relates to (required)
|
||||
* @param id the primary key assigned to this ACL (required)
|
||||
* @param aclAuthorizationStrategy authorization strategy (required)
|
||||
* @param auditLogger audit logger (required)
|
||||
* @param parentAcl the parent (may be <code>null</code>)
|
||||
* @param loadedSids the loaded SIDs if only a subset were loaded (may be
|
||||
* <code>null</code>)
|
||||
* @param entriesInheriting if ACEs from the parent should inherit into
|
||||
* this ACL
|
||||
* @param owner the owner (required)
|
||||
*/
|
||||
public AclImpl(ObjectIdentity objectIdentity, Serializable id, AclAuthorizationStrategy aclAuthorizationStrategy,
|
||||
PermissionGrantingStrategy grantingStrategy, Acl parentAcl, List<Sid> loadedSids, boolean entriesInheriting, Sid owner) {
|
||||
AuditLogger auditLogger, Acl parentAcl, List<Sid> loadedSids, boolean entriesInheriting, Sid owner) {
|
||||
Assert.notNull(objectIdentity, "Object Identity required");
|
||||
Assert.notNull(id, "Id required");
|
||||
Assert.notNull(aclAuthorizationStrategy, "AclAuthorizationStrategy required");
|
||||
Assert.notNull(owner, "Owner required");
|
||||
|
||||
Assert.notNull(auditLogger, "AuditLogger required");
|
||||
this.objectIdentity = objectIdentity;
|
||||
this.id = id;
|
||||
this.aclAuthorizationStrategy = aclAuthorizationStrategy;
|
||||
this.auditLogger = auditLogger;
|
||||
this.parentAcl = parentAcl; // may be null
|
||||
this.loadedSids = loadedSids; // may be null
|
||||
this.entriesInheriting = entriesInheriting;
|
||||
this.owner = owner;
|
||||
this.permissionGrantingStrategy = grantingStrategy;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -178,11 +168,35 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegates to the {@link PermissionGrantingStrategy}.
|
||||
* Determines authorization. The order of the <code>permission</code> and <code>sid</code> arguments is
|
||||
* <em>extremely important</em>! The method will iterate through each of the <code>permission</code>s in the order
|
||||
* specified. For each iteration, all of the <code>sid</code>s will be considered, again in the order they are
|
||||
* presented. A search will then be performed for the first {@link AccessControlEntry} object that directly
|
||||
* matches that <code>permission:sid</code> combination. When the <em>first full match</em> is found (ie an ACE
|
||||
* that has the SID currently being searched for and the exact permission bit mask being search for), the grant or
|
||||
* deny flag for that ACE will prevail. If the ACE specifies to grant access, the method will return
|
||||
* <code>true</code>. If the ACE specifies to deny access, the loop will stop and the next <code>permission</code>
|
||||
* iteration will be performed. If each permission indicates to deny access, the first deny ACE found will be
|
||||
* considered the reason for the failure (as it was the first match found, and is therefore the one most logically
|
||||
* requiring changes - although not always). If absolutely no matching ACE was found at all for any permission,
|
||||
* the parent ACL will be tried (provided that there is a parent and {@link #isEntriesInheriting()} is
|
||||
* <code>true</code>. The parent ACL will also scan its parent and so on. If ultimately no matching ACE is found,
|
||||
* a <code>NotFoundException</code> will be thrown and the caller will need to decide how to handle the permission
|
||||
* check. Similarly, if any of the SID arguments presented to the method were not loaded by the ACL,
|
||||
* <code>UnloadedSidException</code> will be thrown.
|
||||
*
|
||||
* @param permission the exact permissions to scan for (order is important)
|
||||
* @param sids the exact SIDs to scan for (order is important)
|
||||
* @param administrativeMode if <code>true</code> denotes the query is for administrative purposes and no auditing
|
||||
* will be undertaken
|
||||
*
|
||||
* @return <code>true</code> if one of the permissions has been granted, <code>false</code> if one of the
|
||||
* permissions has been specifically revoked
|
||||
*
|
||||
* @throws NotFoundException if an exact ACE for one of the permission bit masks and SID combination could not be
|
||||
* found
|
||||
* @throws UnloadedSidException if the passed SIDs are unknown to this ACL because the ACL was only loaded for a
|
||||
* subset of SIDs
|
||||
* @see DefaultPermissionGrantingStrategy
|
||||
*/
|
||||
public boolean isGranted(List<Permission> permission, List<Sid> sids, boolean administrativeMode)
|
||||
throws NotFoundException, UnloadedSidException {
|
||||
@@ -193,7 +207,64 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
|
||||
throw new UnloadedSidException("ACL was not loaded for one or more SID");
|
||||
}
|
||||
|
||||
return permissionGrantingStrategy.isGranted(this, permission, sids, administrativeMode);
|
||||
AccessControlEntry firstRejection = null;
|
||||
|
||||
for (Permission p : permission) {
|
||||
for (Sid sid: sids) {
|
||||
// Attempt to find exact match for this permission mask and SID
|
||||
boolean scanNextSid = true;
|
||||
|
||||
for (AccessControlEntry ace : aces ) {
|
||||
|
||||
if ((ace.getPermission().getMask() == p.getMask()) && ace.getSid().equals(sid)) {
|
||||
// Found a matching ACE, so its authorization decision will prevail
|
||||
if (ace.isGranting()) {
|
||||
// Success
|
||||
if (!administrativeMode) {
|
||||
auditLogger.logIfNeeded(true, ace);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Failure for this permission, so stop search
|
||||
// We will see if they have a different permission
|
||||
// (this permission is 100% rejected for this SID)
|
||||
if (firstRejection == null) {
|
||||
// Store first rejection for auditing reasons
|
||||
firstRejection = ace;
|
||||
}
|
||||
|
||||
scanNextSid = false; // helps break the loop
|
||||
|
||||
break; // exit aces loop
|
||||
}
|
||||
}
|
||||
|
||||
if (!scanNextSid) {
|
||||
break; // exit SID for loop (now try next permission)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (firstRejection != null) {
|
||||
// We found an ACE to reject the request at this point, as no
|
||||
// other ACEs were found that granted a different permission
|
||||
if (!administrativeMode) {
|
||||
auditLogger.logIfNeeded(false, firstRejection);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// No matches have been found so far
|
||||
if (isEntriesInheriting() && (parentAcl != null)) {
|
||||
// We have a parent, so let them try to find a matching ACE
|
||||
return parentAcl.isGranted(permission, sids, false);
|
||||
} else {
|
||||
// We either have no parent, or we're the uppermost parent
|
||||
throw new NotFoundException("Unable to locate a matching ACE for passed permissions and SIDs");
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isSidLoaded(List<Sid> sids) {
|
||||
@@ -249,6 +320,39 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
|
||||
return parentAcl;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("AclImpl[");
|
||||
sb.append("id: ").append(this.id).append("; ");
|
||||
sb.append("objectIdentity: ").append(this.objectIdentity).append("; ");
|
||||
sb.append("owner: ").append(this.owner).append("; ");
|
||||
|
||||
int count = 0;
|
||||
|
||||
for (AccessControlEntry ace : aces) {
|
||||
count++;
|
||||
|
||||
if (count == 1) {
|
||||
sb.append("\r\n");
|
||||
}
|
||||
|
||||
sb.append(ace).append("\r\n");
|
||||
}
|
||||
|
||||
if (count == 0) {
|
||||
sb.append("no ACEs; ");
|
||||
}
|
||||
|
||||
sb.append("inheriting: ").append(this.entriesInheriting).append("; ");
|
||||
sb.append("parent: ").append((this.parentAcl == null) ? "Null" : this.parentAcl.getObjectIdentity().toString());
|
||||
sb.append("; ");
|
||||
sb.append("aclAuthorizationStrategy: ").append(this.aclAuthorizationStrategy).append("; ");
|
||||
sb.append("auditLogger: ").append(this.auditLogger);
|
||||
sb.append("]");
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public void updateAce(int aceIndex, Permission permission)
|
||||
throws NotFoundException {
|
||||
aclAuthorizationStrategy.securityCheck(this, AclAuthorizationStrategy.CHANGE_GENERAL);
|
||||
@@ -275,15 +379,15 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
|
||||
if (obj instanceof AclImpl) {
|
||||
AclImpl rhs = (AclImpl) obj;
|
||||
if (this.aces.equals(rhs.aces)) {
|
||||
if ((this.parentAcl == null && rhs.parentAcl == null) || (this.parentAcl !=null && this.parentAcl.equals(rhs.parentAcl))) {
|
||||
if ((this.objectIdentity == null && rhs.objectIdentity == null) || (this.objectIdentity != null && this.objectIdentity.equals(rhs.objectIdentity))) {
|
||||
if ((this.id == null && rhs.id == null) || (this.id != null && this.id.equals(rhs.id))) {
|
||||
if ((this.owner == null && rhs.owner == null) || (this.owner != null && this.owner.equals(rhs.owner))) {
|
||||
if ((this.parentAcl == null && rhs.parentAcl == null) || (this.parentAcl.equals(rhs.parentAcl))) {
|
||||
if ((this.objectIdentity == null && rhs.objectIdentity == null) || (this.objectIdentity.equals(rhs.objectIdentity))) {
|
||||
if ((this.id == null && rhs.id == null) || (this.id.equals(rhs.id))) {
|
||||
if ((this.owner == null && rhs.owner == null) || this.owner.equals(rhs.owner)) {
|
||||
if (this.entriesInheriting == rhs.entriesInheriting) {
|
||||
if ((this.loadedSids == null && rhs.loadedSids == null)) {
|
||||
return true;
|
||||
}
|
||||
if (this.loadedSids != null && (this.loadedSids.size() == rhs.loadedSids.size())) {
|
||||
if (this.loadedSids.size() == rhs.loadedSids.size()) {
|
||||
for (int i = 0; i < this.loadedSids.size(); i++) {
|
||||
if (!this.loadedSids.get(i).equals(rhs.loadedSids.get(i))) {
|
||||
return false;
|
||||
@@ -301,37 +405,4 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
|
||||
return false;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("AclImpl[");
|
||||
sb.append("id: ").append(this.id).append("; ");
|
||||
sb.append("objectIdentity: ").append(this.objectIdentity).append("; ");
|
||||
sb.append("owner: ").append(this.owner).append("; ");
|
||||
|
||||
int count = 0;
|
||||
|
||||
for (AccessControlEntry ace : aces) {
|
||||
count++;
|
||||
|
||||
if (count == 1) {
|
||||
sb.append("\n");
|
||||
}
|
||||
|
||||
sb.append(ace).append("\n");
|
||||
}
|
||||
|
||||
if (count == 0) {
|
||||
sb.append("no ACEs; ");
|
||||
}
|
||||
|
||||
sb.append("inheriting: ").append(this.entriesInheriting).append("; ");
|
||||
sb.append("parent: ").append((this.parentAcl == null) ? "Null" : this.parentAcl.getObjectIdentity().toString());
|
||||
sb.append("; ");
|
||||
sb.append("aclAuthorizationStrategy: ").append(this.aclAuthorizationStrategy).append("; ");
|
||||
sb.append("permissionGrantingStrategy: ").append(this.permissionGrantingStrategy);
|
||||
sb.append("]");
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+6
-7
@@ -64,19 +64,18 @@ public class DefaultPermissionFactory implements PermissionFactory {
|
||||
|
||||
Field[] fields = clazz.getFields();
|
||||
|
||||
for (Field field : fields) {
|
||||
for (int i = 0; i < fields.length; i++) {
|
||||
try {
|
||||
Object fieldValue = field.get(null);
|
||||
Object fieldValue = fields[i].get(null);
|
||||
|
||||
if (Permission.class.isAssignableFrom(fieldValue.getClass())) {
|
||||
// Found a Permission static field
|
||||
Permission perm = (Permission) fieldValue;
|
||||
String permissionName = field.getName();
|
||||
String permissionName = fields[i].getName();
|
||||
|
||||
registerPermission(perm, permissionName);
|
||||
}
|
||||
} catch (Exception ignore) {
|
||||
}
|
||||
} catch (Exception ignore) {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,7 +83,7 @@ public class DefaultPermissionFactory implements PermissionFactory {
|
||||
Assert.notNull(perm, "Permission required");
|
||||
Assert.hasText(permissionName, "Permission name required");
|
||||
|
||||
Integer mask = Integer.valueOf(perm.getMask());
|
||||
Integer mask = new Integer(perm.getMask());
|
||||
|
||||
// Ensure no existing Permission uses this integer or code
|
||||
Assert.isTrue(!registeredPermissionsByInteger.containsKey(mask), "An existing Permission already provides mask " + mask);
|
||||
@@ -98,7 +97,7 @@ public class DefaultPermissionFactory implements PermissionFactory {
|
||||
public Permission buildFromMask(int mask) {
|
||||
if (registeredPermissionsByInteger.containsKey(Integer.valueOf(mask))) {
|
||||
// The requested mask has an exact match against a statically-defined Permission, so return it
|
||||
return registeredPermissionsByInteger.get(Integer.valueOf(mask));
|
||||
return registeredPermissionsByInteger.get(new Integer(mask));
|
||||
}
|
||||
|
||||
// To get this far, we have to use a CumulativePermission
|
||||
|
||||
-119
@@ -1,119 +0,0 @@
|
||||
package org.springframework.security.acls.domain;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.security.acls.model.AccessControlEntry;
|
||||
import org.springframework.security.acls.model.Acl;
|
||||
import org.springframework.security.acls.model.NotFoundException;
|
||||
import org.springframework.security.acls.model.Permission;
|
||||
import org.springframework.security.acls.model.PermissionGrantingStrategy;
|
||||
import org.springframework.security.acls.model.Sid;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
public class DefaultPermissionGrantingStrategy implements PermissionGrantingStrategy {
|
||||
|
||||
private final transient AuditLogger auditLogger;
|
||||
|
||||
/**
|
||||
* Creates an instance with the logger which will be used to record granting and denial of requested permissions.
|
||||
*/
|
||||
public DefaultPermissionGrantingStrategy(AuditLogger auditLogger) {
|
||||
Assert.notNull(auditLogger, "auditLogger cannot be null");
|
||||
this.auditLogger = auditLogger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines authorization. The order of the <code>permission</code> and <code>sid</code> arguments is
|
||||
* <em>extremely important</em>! The method will iterate through each of the <code>permission</code>s in the order
|
||||
* specified. For each iteration, all of the <code>sid</code>s will be considered, again in the order they are
|
||||
* presented. A search will then be performed for the first {@link AccessControlEntry} object that directly
|
||||
* matches that <code>permission:sid</code> combination. When the <em>first full match</em> is found (ie an ACE
|
||||
* that has the SID currently being searched for and the exact permission bit mask being search for), the grant or
|
||||
* deny flag for that ACE will prevail. If the ACE specifies to grant access, the method will return
|
||||
* <code>true</code>. If the ACE specifies to deny access, the loop will stop and the next <code>permission</code>
|
||||
* iteration will be performed. If each permission indicates to deny access, the first deny ACE found will be
|
||||
* considered the reason for the failure (as it was the first match found, and is therefore the one most logically
|
||||
* requiring changes - although not always). If absolutely no matching ACE was found at all for any permission,
|
||||
* the parent ACL will be tried (provided that there is a parent and {@link Acl#isEntriesInheriting()} is
|
||||
* <code>true</code>. The parent ACL will also scan its parent and so on. If ultimately no matching ACE is found,
|
||||
* a <code>NotFoundException</code> will be thrown and the caller will need to decide how to handle the permission
|
||||
* check. Similarly, if any of the SID arguments presented to the method were not loaded by the ACL,
|
||||
* <code>UnloadedSidException</code> will be thrown.
|
||||
*
|
||||
* @param permission the exact permissions to scan for (order is important)
|
||||
* @param sids the exact SIDs to scan for (order is important)
|
||||
* @param administrativeMode if <code>true</code> denotes the query is for administrative purposes and no auditing
|
||||
* will be undertaken
|
||||
*
|
||||
* @return <code>true</code> if one of the permissions has been granted, <code>false</code> if one of the
|
||||
* permissions has been specifically revoked
|
||||
*
|
||||
* @throws NotFoundException if an exact ACE for one of the permission bit masks and SID combination could not be
|
||||
* found
|
||||
*/
|
||||
public boolean isGranted(Acl acl, List<Permission> permission, List<Sid> sids, boolean administrativeMode)
|
||||
throws NotFoundException {
|
||||
|
||||
final List<AccessControlEntry> aces = acl.getEntries();
|
||||
|
||||
AccessControlEntry firstRejection = null;
|
||||
|
||||
for (Permission p : permission) {
|
||||
for (Sid sid: sids) {
|
||||
// Attempt to find exact match for this permission mask and SID
|
||||
boolean scanNextSid = true;
|
||||
|
||||
for (AccessControlEntry ace : aces ) {
|
||||
|
||||
if ((ace.getPermission().getMask() == p.getMask()) && ace.getSid().equals(sid)) {
|
||||
// Found a matching ACE, so its authorization decision will prevail
|
||||
if (ace.isGranting()) {
|
||||
// Success
|
||||
if (!administrativeMode) {
|
||||
auditLogger.logIfNeeded(true, ace);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Failure for this permission, so stop search
|
||||
// We will see if they have a different permission
|
||||
// (this permission is 100% rejected for this SID)
|
||||
if (firstRejection == null) {
|
||||
// Store first rejection for auditing reasons
|
||||
firstRejection = ace;
|
||||
}
|
||||
|
||||
scanNextSid = false; // helps break the loop
|
||||
|
||||
break; // exit aces loop
|
||||
}
|
||||
}
|
||||
|
||||
if (!scanNextSid) {
|
||||
break; // exit SID for loop (now try next permission)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (firstRejection != null) {
|
||||
// We found an ACE to reject the request at this point, as no
|
||||
// other ACEs were found that granted a different permission
|
||||
if (!administrativeMode) {
|
||||
auditLogger.logIfNeeded(false, firstRejection);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// No matches have been found so far
|
||||
if (acl.isEntriesInheriting() && (acl.getParentAcl() != null)) {
|
||||
// We have a parent, so let them try to find a matching ACE
|
||||
return acl.getParentAcl().isGranted(permission, sids, false);
|
||||
} else {
|
||||
// We either have no parent, or we're the uppermost parent
|
||||
throw new NotFoundException("Unable to locate a matching ACE for passed permissions and SIDs");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+7
-21
@@ -23,48 +23,34 @@ import net.sf.ehcache.Element;
|
||||
import org.springframework.security.acls.model.AclCache;
|
||||
import org.springframework.security.acls.model.MutableAcl;
|
||||
import org.springframework.security.acls.model.ObjectIdentity;
|
||||
import org.springframework.security.acls.model.PermissionGrantingStrategy;
|
||||
import org.springframework.security.util.FieldUtils;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
|
||||
/**
|
||||
* Simple implementation of {@link AclCache} that delegates to EH-CACHE.
|
||||
*
|
||||
* <p>
|
||||
* Designed to handle the transient fields in {@link AclImpl}. Note that this implementation assumes all
|
||||
* {@link AclImpl} instances share the same {@link PermissionGrantingStrategy} and {@link AclAuthorizationStrategy}
|
||||
* instances.
|
||||
* {@link AclImpl} instances share the same {@link AuditLogger} and {@link AclAuthorizationStrategy} instance.
|
||||
* </p>
|
||||
*
|
||||
* @author Ben Alex
|
||||
*/
|
||||
public class EhCacheBasedAclCache implements AclCache {
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private final Ehcache cache;
|
||||
private PermissionGrantingStrategy permissionGrantingStrategy;
|
||||
private Ehcache cache;
|
||||
private AuditLogger auditLogger;
|
||||
private AclAuthorizationStrategy aclAuthorizationStrategy;
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
/**
|
||||
* @deprecated use the second constructor which injects the strategy objects. See SEC-1498.
|
||||
*/
|
||||
@Deprecated
|
||||
public EhCacheBasedAclCache(Ehcache cache) {
|
||||
Assert.notNull(cache, "Cache required");
|
||||
this.cache = cache;
|
||||
}
|
||||
|
||||
public EhCacheBasedAclCache(Ehcache cache, PermissionGrantingStrategy permissionGrantingStrategy,
|
||||
AclAuthorizationStrategy aclAuthorizationStrategy) {
|
||||
Assert.notNull(cache, "Cache required");
|
||||
Assert.notNull(permissionGrantingStrategy, "PermissionGrantingStrategy required");
|
||||
Assert.notNull(aclAuthorizationStrategy, "AclAuthorizationStrategy required");
|
||||
this.cache = cache;
|
||||
this.permissionGrantingStrategy = permissionGrantingStrategy;
|
||||
this.aclAuthorizationStrategy = aclAuthorizationStrategy;
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public void evictFromCache(Serializable pk) {
|
||||
@@ -129,7 +115,7 @@ public class EhCacheBasedAclCache implements AclCache {
|
||||
if (this.aclAuthorizationStrategy == null) {
|
||||
if (acl instanceof AclImpl) {
|
||||
this.aclAuthorizationStrategy = (AclAuthorizationStrategy) FieldUtils.getProtectedFieldValue("aclAuthorizationStrategy", acl);
|
||||
this.permissionGrantingStrategy = (PermissionGrantingStrategy) FieldUtils.getProtectedFieldValue("permissionGrantingStrategy", acl);
|
||||
this.auditLogger = (AuditLogger) FieldUtils.getProtectedFieldValue("auditLogger", acl);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,7 +130,7 @@ public class EhCacheBasedAclCache implements AclCache {
|
||||
private MutableAcl initializeTransientFields(MutableAcl value) {
|
||||
if (value instanceof AclImpl) {
|
||||
FieldUtils.setProtectedFieldValue("aclAuthorizationStrategy", value, this.aclAuthorizationStrategy);
|
||||
FieldUtils.setProtectedFieldValue("permissionGrantingStrategy", value, this.permissionGrantingStrategy);
|
||||
FieldUtils.setProtectedFieldValue("auditLogger", value, this.auditLogger);
|
||||
}
|
||||
|
||||
if (value.getParentAcl() != null) {
|
||||
|
||||
@@ -30,7 +30,7 @@ import org.springframework.util.Assert;
|
||||
public class GrantedAuthoritySid implements Sid {
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private final String grantedAuthority;
|
||||
private String grantedAuthority;
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@ public class ObjectIdentityImpl implements ObjectIdentity {
|
||||
|
||||
try {
|
||||
Method method = typeClass.getMethod("getId", new Class[] {});
|
||||
result = method.invoke(object);
|
||||
result = method.invoke(object, new Object[] {});
|
||||
} catch (Exception e) {
|
||||
throw new IdentityUnavailableException("Could not extract identity from object " + object, e);
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ import org.springframework.util.Assert;
|
||||
public class PrincipalSid implements Sid {
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private final String principal;
|
||||
private String principal;
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
|
||||
+1
-1
@@ -51,7 +51,7 @@ public class SidRetrievalStrategyImpl implements SidRetrievalStrategy {
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public List<Sid> getSids(Authentication authentication) {
|
||||
Collection<? extends GrantedAuthority> authorities = roleHierarchy.getReachableGrantedAuthorities(authentication.getAuthorities());
|
||||
Collection<GrantedAuthority> authorities = roleHierarchy.getReachableGrantedAuthorities(authentication.getAuthorities());
|
||||
List<Sid> sids = new ArrayList<Sid>(authorities.size() + 1);
|
||||
|
||||
sids.add(new PrincipalSid(authentication));
|
||||
|
||||
@@ -29,6 +29,7 @@ import java.util.Set;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.core.PreparedStatementSetter;
|
||||
import org.springframework.jdbc.core.ResultSetExtractor;
|
||||
@@ -37,7 +38,6 @@ import org.springframework.security.acls.domain.AclAuthorizationStrategy;
|
||||
import org.springframework.security.acls.domain.AclImpl;
|
||||
import org.springframework.security.acls.domain.AuditLogger;
|
||||
import org.springframework.security.acls.domain.DefaultPermissionFactory;
|
||||
import org.springframework.security.acls.domain.DefaultPermissionGrantingStrategy;
|
||||
import org.springframework.security.acls.domain.GrantedAuthoritySid;
|
||||
import org.springframework.security.acls.domain.ObjectIdentityImpl;
|
||||
import org.springframework.security.acls.domain.PermissionFactory;
|
||||
@@ -49,7 +49,6 @@ import org.springframework.security.acls.model.MutableAcl;
|
||||
import org.springframework.security.acls.model.NotFoundException;
|
||||
import org.springframework.security.acls.model.ObjectIdentity;
|
||||
import org.springframework.security.acls.model.Permission;
|
||||
import org.springframework.security.acls.model.PermissionGrantingStrategy;
|
||||
import org.springframework.security.acls.model.Sid;
|
||||
import org.springframework.security.acls.model.UnloadedSidException;
|
||||
import org.springframework.security.util.FieldUtils;
|
||||
@@ -107,11 +106,11 @@ public final class BasicLookupStrategy implements LookupStrategy {
|
||||
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private final AclAuthorizationStrategy aclAuthorizationStrategy;
|
||||
private AclAuthorizationStrategy aclAuthorizationStrategy;
|
||||
private PermissionFactory permissionFactory = new DefaultPermissionFactory();
|
||||
private final AclCache aclCache;
|
||||
private final PermissionGrantingStrategy grantingStrategy;
|
||||
private final JdbcTemplate jdbcTemplate;
|
||||
private AclCache aclCache;
|
||||
private AuditLogger auditLogger;
|
||||
private JdbcTemplate jdbcTemplate;
|
||||
private int batchSize = 50;
|
||||
|
||||
private final Field fieldAces = FieldUtils.getField(AclImpl.class, "aces");
|
||||
@@ -131,28 +130,19 @@ public final class BasicLookupStrategy implements LookupStrategy {
|
||||
* @param dataSource to access the database
|
||||
* @param aclCache the cache where fully-loaded elements can be stored
|
||||
* @param aclAuthorizationStrategy authorization strategy (required)
|
||||
*
|
||||
* @deprecated Use the version which takes a {@code PermissionGrantingStrategy} argument instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public BasicLookupStrategy(DataSource dataSource, AclCache aclCache,
|
||||
AclAuthorizationStrategy aclAuthorizationStrategy, AuditLogger auditLogger) {
|
||||
this(dataSource, aclCache, aclAuthorizationStrategy, new DefaultPermissionGrantingStrategy(auditLogger));
|
||||
}
|
||||
|
||||
public BasicLookupStrategy(DataSource dataSource, AclCache aclCache,
|
||||
AclAuthorizationStrategy aclAuthorizationStrategy, PermissionGrantingStrategy grantingStrategy) {
|
||||
AclAuthorizationStrategy aclAuthorizationStrategy, AuditLogger auditLogger) {
|
||||
Assert.notNull(dataSource, "DataSource required");
|
||||
Assert.notNull(aclCache, "AclCache required");
|
||||
Assert.notNull(aclAuthorizationStrategy, "AclAuthorizationStrategy required");
|
||||
Assert.notNull(grantingStrategy, "grantingStrategy required");
|
||||
Assert.notNull(auditLogger, "AuditLogger required");
|
||||
jdbcTemplate = new JdbcTemplate(dataSource);
|
||||
this.aclCache = aclCache;
|
||||
this.aclAuthorizationStrategy = aclAuthorizationStrategy;
|
||||
this.grantingStrategy = grantingStrategy;
|
||||
this.auditLogger = auditLogger;
|
||||
fieldAces.setAccessible(true);
|
||||
fieldAcl.setAccessible(true);
|
||||
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
@@ -405,7 +395,7 @@ public final class BasicLookupStrategy implements LookupStrategy {
|
||||
|
||||
// Now we have the parent (if there is one), create the true AclImpl
|
||||
AclImpl result = new AclImpl(inputAcl.getObjectIdentity(), (Long) inputAcl.getId(), aclAuthorizationStrategy,
|
||||
grantingStrategy, parent, null, inputAcl.isEntriesInheriting(), inputAcl.getOwner());
|
||||
auditLogger, parent, null, inputAcl.isEntriesInheriting(), inputAcl.getOwner());
|
||||
|
||||
// Copy the "aces" from the input to the destination
|
||||
|
||||
@@ -476,8 +466,8 @@ public final class BasicLookupStrategy implements LookupStrategy {
|
||||
//~ Inner Classes ==================================================================================================
|
||||
|
||||
private class ProcessResultSet implements ResultSetExtractor<Set<Long>> {
|
||||
private final Map<Serializable, Acl> acls;
|
||||
private final List<Sid> sids;
|
||||
private Map<Serializable, Acl> acls;
|
||||
private List<Sid> sids;
|
||||
|
||||
public ProcessResultSet(Map<Serializable, Acl> acls, List<Sid> sids) {
|
||||
Assert.notNull(acls, "ACLs cannot be null");
|
||||
@@ -494,8 +484,9 @@ public final class BasicLookupStrategy implements LookupStrategy {
|
||||
* @param rs The {@link ResultSet} to be processed
|
||||
* @return a list of parent IDs remaining to be looked up (may be empty, but never <tt>null</tt>)
|
||||
* @throws SQLException
|
||||
* @throws DataAccessException
|
||||
*/
|
||||
public Set<Long> extractData(ResultSet rs) throws SQLException {
|
||||
public Set<Long> extractData(ResultSet rs) throws SQLException, DataAccessException {
|
||||
Set<Long> parentIdsToLookup = new HashSet<Long>(); // Set of parent_id Longs
|
||||
|
||||
while (rs.next()) {
|
||||
@@ -564,7 +555,7 @@ public final class BasicLookupStrategy implements LookupStrategy {
|
||||
owner = new GrantedAuthoritySid(rs.getString("acl_sid"));
|
||||
}
|
||||
|
||||
acl = new AclImpl(objectIdentity, id, aclAuthorizationStrategy, grantingStrategy, parentAcl, null,
|
||||
acl = new AclImpl(objectIdentity, id, aclAuthorizationStrategy, auditLogger, parentAcl, null,
|
||||
entriesInheriting, owner);
|
||||
|
||||
acls.put(id, acl);
|
||||
@@ -603,7 +594,7 @@ public final class BasicLookupStrategy implements LookupStrategy {
|
||||
}
|
||||
|
||||
private class StubAclParent implements Acl {
|
||||
private final Long id;
|
||||
private Long id;
|
||||
|
||||
public StubAclParent(Long id) {
|
||||
this.id = id;
|
||||
|
||||
@@ -56,8 +56,8 @@ public class JdbcAclService implements AclService {
|
||||
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
protected final JdbcTemplate jdbcTemplate;
|
||||
private final LookupStrategy lookupStrategy;
|
||||
protected JdbcTemplate jdbcTemplate;
|
||||
private LookupStrategy lookupStrategy;
|
||||
private String findChildrenSql = DEFAULT_SELECT_ACL_WITH_PARENT_SQL;
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
@@ -109,9 +109,10 @@ public class JdbcAclService implements AclService {
|
||||
Map<ObjectIdentity, Acl> result = lookupStrategy.readAclsById(objects, sids);
|
||||
|
||||
// Check every requested object identity was found (throw NotFoundException if needed)
|
||||
for (ObjectIdentity oid : objects) {
|
||||
if (!result.containsKey(oid)) {
|
||||
throw new NotFoundException("Unable to find ACL information for object identity '" + oid + "'");
|
||||
for (int i = 0; i < objects.size(); i++) {
|
||||
if (!result.containsKey(objects.get(i))) {
|
||||
throw new NotFoundException("Unable to find ACL information for object identity '"
|
||||
+ objects.get(i) + "'");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+13
-11
@@ -61,7 +61,7 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private boolean foreignKeysInDatabase = true;
|
||||
private final AclCache aclCache;
|
||||
private AclCache aclCache;
|
||||
private String deleteEntryByObjectIdentityForeignKey = "delete from acl_entry where acl_object_identity=?";
|
||||
private String deleteObjectIdentityByPrimaryKey = "delete from acl_object_identity where id=?";
|
||||
private String classIdentityQuery = "call identity()";
|
||||
@@ -194,7 +194,7 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
|
||||
protected Long createOrRetrieveSidPrimaryKey(Sid sid, boolean allowCreate) {
|
||||
Assert.notNull(sid, "Sid required");
|
||||
|
||||
String sidName;
|
||||
String sidName = null;
|
||||
boolean sidIsPrincipal = true;
|
||||
|
||||
if (sid instanceof PrincipalSid) {
|
||||
@@ -214,7 +214,7 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
|
||||
}
|
||||
|
||||
if (allowCreate) {
|
||||
jdbcTemplate.update(insertSid, Boolean.valueOf(sidIsPrincipal), sidName);
|
||||
jdbcTemplate.update(insertSid, new Object[] {Boolean.valueOf(sidIsPrincipal), sidName});
|
||||
Assert.isTrue(TransactionSynchronizationManager.isSynchronizationActive(), "Transaction must be running");
|
||||
return new Long(jdbcTemplate.queryForLong(sidIdentityQuery));
|
||||
}
|
||||
@@ -229,8 +229,8 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
|
||||
if (deleteChildren) {
|
||||
List<ObjectIdentity> children = findChildren(objectIdentity);
|
||||
if (children != null) {
|
||||
for (ObjectIdentity child : children) {
|
||||
deleteAcl(child, true);
|
||||
for (int i = 0; i < children.size(); i++) {
|
||||
deleteAcl(children.get(i), true);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -263,7 +263,8 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
|
||||
* @param oidPrimaryKey the rows in acl_entry to delete
|
||||
*/
|
||||
protected void deleteEntries(Long oidPrimaryKey) {
|
||||
jdbcTemplate.update(deleteEntryByObjectIdentityForeignKey, oidPrimaryKey);
|
||||
jdbcTemplate.update(deleteEntryByObjectIdentityForeignKey,
|
||||
new Object[] {oidPrimaryKey});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -276,7 +277,7 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
|
||||
*/
|
||||
protected void deleteObjectIdentity(Long oidPrimaryKey) {
|
||||
// Delete the acl_object_identity row
|
||||
jdbcTemplate.update(deleteObjectIdentityByPrimaryKey, oidPrimaryKey);
|
||||
jdbcTemplate.update(deleteObjectIdentityByPrimaryKey, new Object[] {oidPrimaryKey});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -290,7 +291,8 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
|
||||
*/
|
||||
protected Long retrieveObjectIdentityPrimaryKey(ObjectIdentity oid) {
|
||||
try {
|
||||
return new Long(jdbcTemplate.queryForLong(selectObjectIdentityPrimaryKey, oid.getType(), oid.getIdentifier()));
|
||||
return new Long(jdbcTemplate.queryForLong(selectObjectIdentityPrimaryKey,
|
||||
new Object[] {oid.getType(), oid.getIdentifier()}));
|
||||
} catch (DataAccessException notFound) {
|
||||
return null;
|
||||
}
|
||||
@@ -324,8 +326,8 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
|
||||
Assert.notNull(objectIdentity, "ObjectIdentity required");
|
||||
List<ObjectIdentity> children = findChildren(objectIdentity);
|
||||
if (children != null) {
|
||||
for (ObjectIdentity child : children) {
|
||||
clearCacheIncludingChildren(child);
|
||||
for (int i = 0; i < children.size(); i++) {
|
||||
clearCacheIncludingChildren(children.get(i));
|
||||
}
|
||||
}
|
||||
aclCache.evictFromCache(objectIdentity);
|
||||
@@ -354,7 +356,7 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
|
||||
|
||||
Long ownerSid = createOrRetrieveSidPrimaryKey(acl.getOwner(), true);
|
||||
int count = jdbcTemplate.update(updateObjectIdentity,
|
||||
parentId, ownerSid, Boolean.valueOf(acl.isEntriesInheriting()), acl.getId());
|
||||
new Object[] {parentId, ownerSid, new Boolean(acl.isEntriesInheriting()), acl.getId()});
|
||||
|
||||
if (count != 1) {
|
||||
throw new NotFoundException("Unable to locate ACL to update");
|
||||
|
||||
-20
@@ -1,20 +0,0 @@
|
||||
package org.springframework.security.acls.model;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Allow customization of the logic for determining whether a permission or permissions are granted to a particular
|
||||
* sid or sids by an {@link Acl}.
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @since 3.0.2
|
||||
*/
|
||||
public interface PermissionGrantingStrategy {
|
||||
|
||||
/**
|
||||
* Returns true if the the supplied strategy decides that the supplied {@code Acl} grants access
|
||||
* based on the supplied list of permissions and sids.
|
||||
*/
|
||||
boolean isGranted(Acl acl, List<Permission> permission, List<Sid> sids, boolean administrativeMode);
|
||||
|
||||
}
|
||||
-56
@@ -1,56 +0,0 @@
|
||||
package org.springframework.security.acls;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.security.acls.domain.ObjectIdentityImpl;
|
||||
import org.springframework.security.acls.model.AclService;
|
||||
import org.springframework.security.acls.model.ObjectIdentity;
|
||||
import org.springframework.security.acls.model.ObjectIdentityRetrievalStrategy;
|
||||
import org.springframework.security.acls.model.SidRetrievalStrategy;
|
||||
import org.springframework.security.core.Authentication;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Luke Taylor
|
||||
*/
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public class AclPermissionCacheOptimizerTests {
|
||||
|
||||
@Test
|
||||
public void eagerlyLoadsRequiredAcls() throws Exception {
|
||||
AclService service = mock(AclService.class);
|
||||
AclPermissionCacheOptimizer pco = new AclPermissionCacheOptimizer(service);
|
||||
ObjectIdentityRetrievalStrategy oidStrat = mock(ObjectIdentityRetrievalStrategy.class);
|
||||
SidRetrievalStrategy sidStrat = mock(SidRetrievalStrategy.class);
|
||||
pco.setObjectIdentityRetrievalStrategy(oidStrat);
|
||||
pco.setSidRetrievalStrategy(sidStrat);
|
||||
Object[] dos = {new Object(), null, new Object()};
|
||||
ObjectIdentity[] oids = {new ObjectIdentityImpl("A", "1"), new ObjectIdentityImpl("A", "2")};
|
||||
when(oidStrat.getObjectIdentity(dos[0])).thenReturn(oids[0]);
|
||||
when(oidStrat.getObjectIdentity(dos[2])).thenReturn(oids[1]);
|
||||
|
||||
pco.cachePermissionsFor(mock(Authentication.class), Arrays.asList(dos));
|
||||
|
||||
// AclService should be invoked with the list of required Oids
|
||||
verify(service).readAclsById(eq(Arrays.asList(oids)), any(List.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ignoresEmptyCollection() {
|
||||
AclService service = mock(AclService.class);
|
||||
AclPermissionCacheOptimizer pco = new AclPermissionCacheOptimizer(service);
|
||||
ObjectIdentityRetrievalStrategy oids = mock(ObjectIdentityRetrievalStrategy.class);
|
||||
SidRetrievalStrategy sids = mock(SidRetrievalStrategy.class);
|
||||
pco.setObjectIdentityRetrievalStrategy(oids);
|
||||
pco.setSidRetrievalStrategy(sids);
|
||||
|
||||
pco.cachePermissionsFor(mock(Authentication.class), Collections.emptyList());
|
||||
|
||||
verifyZeroInteractions(service, sids, oids);
|
||||
}
|
||||
|
||||
}
|
||||
-64
@@ -1,64 +0,0 @@
|
||||
package org.springframework.security.acls.afterinvocation;
|
||||
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.anyBoolean;
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.security.access.ConfigAttribute;
|
||||
import org.springframework.security.access.SecurityConfig;
|
||||
import org.springframework.security.acls.model.*;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.SpringSecurityMessageSource;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Luke Taylor
|
||||
*/
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public class AclEntryAfterInvocationCollectionFilteringProviderTests {
|
||||
@Test
|
||||
public void objectsAreRemovedIfPermissionDenied() throws Exception {
|
||||
AclService service = mock(AclService.class);
|
||||
Acl acl = mock(Acl.class);
|
||||
when(acl.isGranted(any(List.class), any(List.class), anyBoolean())).thenReturn(false);
|
||||
when(service.readAclById(any(ObjectIdentity.class), any(List.class))).thenReturn(acl);
|
||||
AclEntryAfterInvocationCollectionFilteringProvider provider = new AclEntryAfterInvocationCollectionFilteringProvider(service, Arrays.asList(mock(Permission.class)));
|
||||
provider.setObjectIdentityRetrievalStrategy(mock(ObjectIdentityRetrievalStrategy.class));
|
||||
provider.setProcessDomainObjectClass(Object.class);
|
||||
provider.setSidRetrievalStrategy(mock(SidRetrievalStrategy.class));
|
||||
|
||||
Object returned = provider.decide(mock(Authentication.class), new Object(), SecurityConfig.createList("AFTER_ACL_COLLECTION_READ"), new ArrayList(Arrays.asList(new Object(), new Object())));
|
||||
assertTrue(returned instanceof List);
|
||||
assertTrue(((List)returned).isEmpty());
|
||||
returned = provider.decide(mock(Authentication.class), new Object(), SecurityConfig.createList("UNSUPPORTED", "AFTER_ACL_COLLECTION_READ"), new Object[] {new Object(), new Object()});
|
||||
assertTrue(returned instanceof Object[]);
|
||||
assertTrue(((Object[])returned).length == 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void accessIsGrantedIfNoAttributesDefined() throws Exception {
|
||||
AclEntryAfterInvocationCollectionFilteringProvider provider = new AclEntryAfterInvocationCollectionFilteringProvider(mock(AclService.class), Arrays.asList(mock(Permission.class)));
|
||||
Object returned = new Object();
|
||||
|
||||
assertSame(returned, provider.decide(mock(Authentication.class), new Object(), Collections.<ConfigAttribute>emptyList(), returned));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nullReturnObjectIsIgnored() throws Exception {
|
||||
AclService service = mock(AclService.class);
|
||||
AclEntryAfterInvocationCollectionFilteringProvider provider = new AclEntryAfterInvocationCollectionFilteringProvider(service, Arrays.asList(mock(Permission.class)));
|
||||
|
||||
assertNull(provider.decide(mock(Authentication.class), new Object(), SecurityConfig.createList("AFTER_ACL_COLLECTION_READ"), null));
|
||||
verify(service, never()).readAclById(any(ObjectIdentity.class), any(List.class));
|
||||
}
|
||||
|
||||
}
|
||||
-101
@@ -1,101 +0,0 @@
|
||||
package org.springframework.security.acls.afterinvocation;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.security.access.ConfigAttribute;
|
||||
import org.springframework.security.access.SecurityConfig;
|
||||
import org.springframework.security.acls.model.*;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.SpringSecurityMessageSource;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Luke Taylor
|
||||
*/
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public class AclEntryAfterInvocationProviderTests {
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void rejectsMissingPermissions() throws Exception {
|
||||
try {
|
||||
new AclEntryAfterInvocationProvider(mock(AclService.class), null);
|
||||
fail("Exception expected");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
}
|
||||
new AclEntryAfterInvocationProvider(mock(AclService.class), Collections.<Permission>emptyList());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void accessIsAllowedIfPermissionIsGranted() {
|
||||
AclService service = mock(AclService.class);
|
||||
Acl acl = mock(Acl.class);
|
||||
when(acl.isGranted(any(List.class), any(List.class), anyBoolean())).thenReturn(true);
|
||||
when(service.readAclById(any(ObjectIdentity.class), any(List.class))).thenReturn(acl);
|
||||
AclEntryAfterInvocationProvider provider = new AclEntryAfterInvocationProvider(service, Arrays.asList(mock(Permission.class)));
|
||||
provider.setMessageSource(new SpringSecurityMessageSource());
|
||||
provider.setObjectIdentityRetrievalStrategy(mock(ObjectIdentityRetrievalStrategy.class));
|
||||
provider.setProcessDomainObjectClass(Object.class);
|
||||
provider.setSidRetrievalStrategy(mock(SidRetrievalStrategy.class));
|
||||
Object returned = new Object();
|
||||
|
||||
assertSame(returned, provider.decide(mock(Authentication.class), new Object(), SecurityConfig.createList("AFTER_ACL_READ"), returned));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void accessIsGrantedIfNoAttributesDefined() throws Exception {
|
||||
AclEntryAfterInvocationProvider provider = new AclEntryAfterInvocationProvider(mock(AclService.class), Arrays.asList(mock(Permission.class)));
|
||||
Object returned = new Object();
|
||||
|
||||
assertSame(returned, provider.decide(mock(Authentication.class), new Object(), Collections.<ConfigAttribute>emptyList(), returned));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void accessIsGrantedIfObjectTypeNotSupported() throws Exception {
|
||||
AclEntryAfterInvocationProvider provider = new AclEntryAfterInvocationProvider(mock(AclService.class), Arrays.asList(mock(Permission.class)));
|
||||
provider.setProcessDomainObjectClass(String.class);
|
||||
// Not a String
|
||||
Object returned = new Object();
|
||||
|
||||
assertSame(returned, provider.decide(mock(Authentication.class), new Object(), SecurityConfig.createList("AFTER_ACL_READ"), returned));
|
||||
}
|
||||
|
||||
|
||||
@Test(expected= AccessDeniedException.class)
|
||||
public void accessIsDeniedIfPermissionIsNotGranted() {
|
||||
AclService service = mock(AclService.class);
|
||||
Acl acl = mock(Acl.class);
|
||||
when(acl.isGranted(any(List.class), any(List.class), anyBoolean())).thenReturn(false);
|
||||
// Try a second time with no permissions found
|
||||
when(acl.isGranted(any(List.class), any(List.class), anyBoolean())).thenThrow(new NotFoundException(""));
|
||||
when(service.readAclById(any(ObjectIdentity.class), any(List.class))).thenReturn(acl);
|
||||
AclEntryAfterInvocationProvider provider = new AclEntryAfterInvocationProvider(service, Arrays.asList(mock(Permission.class)));
|
||||
provider.setProcessConfigAttribute("MY_ATTRIBUTE");
|
||||
provider.setMessageSource(new SpringSecurityMessageSource());
|
||||
provider.setObjectIdentityRetrievalStrategy(mock(ObjectIdentityRetrievalStrategy.class));
|
||||
provider.setProcessDomainObjectClass(Object.class);
|
||||
provider.setSidRetrievalStrategy(mock(SidRetrievalStrategy.class));
|
||||
try {
|
||||
provider.decide(mock(Authentication.class), new Object(), SecurityConfig.createList("UNSUPPORTED", "MY_ATTRIBUTE"), new Object());
|
||||
fail();
|
||||
} catch (AccessDeniedException expected) {
|
||||
}
|
||||
// Second scenario with no acls found
|
||||
provider.decide(mock(Authentication.class), new Object(), SecurityConfig.createList("UNSUPPORTED", "MY_ATTRIBUTE"), new Object());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nullReturnObjectIsIgnored() throws Exception {
|
||||
AclService service = mock(AclService.class);
|
||||
AclEntryAfterInvocationProvider provider = new AclEntryAfterInvocationProvider(service, Arrays.asList(mock(Permission.class)));
|
||||
|
||||
assertNull(provider.decide(mock(Authentication.class), new Object(), SecurityConfig.createList("AFTER_ACL_COLLECTION_READ"), null));
|
||||
verify(service, never()).readAclById(any(ObjectIdentity.class), any(List.class));
|
||||
}
|
||||
}
|
||||
+22
-18
@@ -1,8 +1,10 @@
|
||||
package org.springframework.security.acls.domain;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import org.jmock.Expectations;
|
||||
import org.jmock.Mockery;
|
||||
import org.jmock.integration.junit4.JUnit4Mockery;
|
||||
import org.junit.Test;
|
||||
import org.springframework.security.acls.model.AccessControlEntry;
|
||||
import org.springframework.security.acls.model.Acl;
|
||||
@@ -16,6 +18,7 @@ import org.springframework.security.acls.model.Sid;
|
||||
* @author Andrei Stefan
|
||||
*/
|
||||
public class AccessControlImplEntryTests {
|
||||
Mockery jmock = new JUnit4Mockery();
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
@@ -32,7 +35,7 @@ public class AccessControlImplEntryTests {
|
||||
|
||||
// Check Sid field is present
|
||||
try {
|
||||
new AccessControlEntryImpl(null, mock(Acl.class), null,
|
||||
new AccessControlEntryImpl(null, jmock.mock(Acl.class), null,
|
||||
BasePermission.ADMINISTRATION, true, true, true);
|
||||
fail("It should have thrown IllegalArgumentException");
|
||||
}
|
||||
@@ -41,7 +44,7 @@ public class AccessControlImplEntryTests {
|
||||
|
||||
// Check Permission field is present
|
||||
try {
|
||||
new AccessControlEntryImpl(null, mock(Acl.class), new PrincipalSid("johndoe"), null,
|
||||
new AccessControlEntryImpl(null, jmock.mock(Acl.class), new PrincipalSid("johndoe"), null,
|
||||
true, true, true);
|
||||
fail("It should have thrown IllegalArgumentException");
|
||||
}
|
||||
@@ -51,11 +54,11 @@ public class AccessControlImplEntryTests {
|
||||
|
||||
@Test
|
||||
public void testAccessControlEntryImplGetters() {
|
||||
Acl mockAcl = mock(Acl.class);
|
||||
Acl mockAcl = jmock.mock(Acl.class);
|
||||
Sid sid = new PrincipalSid("johndoe");
|
||||
|
||||
// Create a sample entry
|
||||
AccessControlEntry ace = new AccessControlEntryImpl(Long.valueOf(1), mockAcl, sid, BasePermission.ADMINISTRATION,
|
||||
AccessControlEntry ace = new AccessControlEntryImpl(new Long(1), mockAcl, sid, BasePermission.ADMINISTRATION,
|
||||
true, true, true);
|
||||
|
||||
// and check every get() method
|
||||
@@ -70,31 +73,32 @@ public class AccessControlImplEntryTests {
|
||||
|
||||
@Test
|
||||
public void testEquals() {
|
||||
final Acl mockAcl = mock(Acl.class);
|
||||
final ObjectIdentity oid = mock(ObjectIdentity.class);
|
||||
|
||||
when(mockAcl.getObjectIdentity()).thenReturn(oid);
|
||||
final Acl mockAcl = jmock.mock(Acl.class);
|
||||
final ObjectIdentity oid = jmock.mock(ObjectIdentity.class);
|
||||
jmock.checking(new Expectations() {{
|
||||
allowing(mockAcl).getObjectIdentity(); will(returnValue(oid));
|
||||
}});
|
||||
Sid sid = new PrincipalSid("johndoe");
|
||||
|
||||
AccessControlEntry ace = new AccessControlEntryImpl(Long.valueOf(1), mockAcl, sid, BasePermission.ADMINISTRATION,
|
||||
AccessControlEntry ace = new AccessControlEntryImpl(new Long(1), mockAcl, sid, BasePermission.ADMINISTRATION,
|
||||
true, true, true);
|
||||
|
||||
assertFalse(ace.equals(null));
|
||||
assertFalse(ace.equals(Long.valueOf(100)));
|
||||
assertFalse(ace.equals(new Long(100)));
|
||||
assertTrue(ace.equals(ace));
|
||||
assertTrue(ace.equals(new AccessControlEntryImpl(Long.valueOf(1), mockAcl, sid,
|
||||
assertTrue(ace.equals(new AccessControlEntryImpl(new Long(1), mockAcl, sid,
|
||||
BasePermission.ADMINISTRATION, true, true, true)));
|
||||
assertFalse(ace.equals(new AccessControlEntryImpl(Long.valueOf(2), mockAcl, sid,
|
||||
assertFalse(ace.equals(new AccessControlEntryImpl(new Long(2), mockAcl, sid,
|
||||
BasePermission.ADMINISTRATION, true, true, true)));
|
||||
assertFalse(ace.equals(new AccessControlEntryImpl(Long.valueOf(1), mockAcl, new PrincipalSid("scott"),
|
||||
assertFalse(ace.equals(new AccessControlEntryImpl(new Long(1), mockAcl, new PrincipalSid("scott"),
|
||||
BasePermission.ADMINISTRATION, true, true, true)));
|
||||
assertFalse(ace.equals(new AccessControlEntryImpl(Long.valueOf(1), mockAcl, sid, BasePermission.WRITE, true,
|
||||
assertFalse(ace.equals(new AccessControlEntryImpl(new Long(1), mockAcl, sid, BasePermission.WRITE, true,
|
||||
true, true)));
|
||||
assertFalse(ace.equals(new AccessControlEntryImpl(Long.valueOf(1), mockAcl, sid,
|
||||
assertFalse(ace.equals(new AccessControlEntryImpl(new Long(1), mockAcl, sid,
|
||||
BasePermission.ADMINISTRATION, false, true, true)));
|
||||
assertFalse(ace.equals(new AccessControlEntryImpl(Long.valueOf(1), mockAcl, sid,
|
||||
assertFalse(ace.equals(new AccessControlEntryImpl(new Long(1), mockAcl, sid,
|
||||
BasePermission.ADMINISTRATION, true, false, true)));
|
||||
assertFalse(ace.equals(new AccessControlEntryImpl(Long.valueOf(1), mockAcl, sid,
|
||||
assertFalse(ace.equals(new AccessControlEntryImpl(new Long(1), mockAcl, sid,
|
||||
BasePermission.ADMINISTRATION, true, true, false)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,37 @@
|
||||
package org.springframework.security.acls.domain;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import org.junit.*;
|
||||
import org.springframework.security.acls.model.*;
|
||||
import org.springframework.security.authentication.TestingAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.util.FieldUtils;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jmock.Mockery;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.security.acls.model.AccessControlEntry;
|
||||
import org.springframework.security.acls.model.Acl;
|
||||
import org.springframework.security.acls.model.AlreadyExistsException;
|
||||
import org.springframework.security.acls.model.AuditableAccessControlEntry;
|
||||
import org.springframework.security.acls.model.AuditableAcl;
|
||||
import org.springframework.security.acls.model.ChildrenExistException;
|
||||
import org.springframework.security.acls.model.MutableAcl;
|
||||
import org.springframework.security.acls.model.MutableAclService;
|
||||
import org.springframework.security.acls.model.NotFoundException;
|
||||
import org.springframework.security.acls.model.ObjectIdentity;
|
||||
import org.springframework.security.acls.model.OwnershipAcl;
|
||||
import org.springframework.security.acls.model.Permission;
|
||||
import org.springframework.security.acls.model.Sid;
|
||||
import org.springframework.security.authentication.TestingAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.GrantedAuthorityImpl;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.util.FieldUtils;
|
||||
|
||||
|
||||
/**
|
||||
@@ -30,8 +49,8 @@ public class AclImplTests {
|
||||
private static final List<Sid> BEN = Arrays.asList((Sid)new PrincipalSid("ben"));
|
||||
|
||||
Authentication auth = new TestingAuthenticationToken("joe", "ignored", "ROLE_ADMINISTRATOR");
|
||||
AclAuthorizationStrategy authzStrategy;
|
||||
PermissionGrantingStrategy pgs;
|
||||
Mockery jmockCtx = new Mockery();
|
||||
AclAuthorizationStrategy mockAuthzStrategy;
|
||||
AuditLogger mockAuditLogger;
|
||||
ObjectIdentity objectIdentity = new ObjectIdentityImpl(TARGET_CLASS, 100);
|
||||
|
||||
@@ -40,9 +59,8 @@ public class AclImplTests {
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||
authzStrategy = mock(AclAuthorizationStrategy.class);
|
||||
mockAuditLogger = mock(AuditLogger.class);
|
||||
pgs = new DefaultPermissionGrantingStrategy(mockAuditLogger);
|
||||
mockAuthzStrategy = mock(AclAuthorizationStrategy.class);
|
||||
mockAuditLogger = mock(AuditLogger.class);;
|
||||
auth.setAuthenticated(true);
|
||||
}
|
||||
|
||||
@@ -54,26 +72,25 @@ public class AclImplTests {
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void constructorsRejectNullObjectIdentity() throws Exception {
|
||||
try {
|
||||
new AclImpl(null, 1, authzStrategy, pgs, null, null, true, new PrincipalSid("joe"));
|
||||
new AclImpl(null, 1, mockAuthzStrategy, mockAuditLogger, null, null, true, new PrincipalSid("joe"));
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
}
|
||||
new AclImpl(null, 1, authzStrategy, mockAuditLogger);
|
||||
new AclImpl(null, 1, mockAuthzStrategy, mockAuditLogger);
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void constructorsRejectNullId() throws Exception {
|
||||
try {
|
||||
new AclImpl(objectIdentity, null, authzStrategy, pgs, null, null, true, new PrincipalSid("joe"));
|
||||
new AclImpl(objectIdentity, null, mockAuthzStrategy, mockAuditLogger, null, null, true, new PrincipalSid("joe"));
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
}
|
||||
new AclImpl(objectIdentity, null, authzStrategy, mockAuditLogger);
|
||||
new AclImpl(objectIdentity, null, mockAuthzStrategy, mockAuditLogger);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void constructorsRejectNullAclAuthzStrategy() throws Exception {
|
||||
try {
|
||||
@@ -85,9 +102,20 @@ public class AclImplTests {
|
||||
new AclImpl(objectIdentity, 1, null, mockAuditLogger);
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void constructorsRejectNullAuditLogger() throws Exception {
|
||||
try {
|
||||
new AclImpl(objectIdentity, 1, mockAuthzStrategy, null, null, null, true, new PrincipalSid("joe"));
|
||||
fail("It should have thrown IllegalArgumentException");
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
}
|
||||
new AclImpl(objectIdentity, 1, mockAuthzStrategy, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void insertAceRejectsNullParameters() throws Exception {
|
||||
MutableAcl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null, true, new PrincipalSid(
|
||||
MutableAcl acl = new AclImpl(objectIdentity, 1, mockAuthzStrategy, mockAuditLogger, null, null, true, new PrincipalSid(
|
||||
"joe"));
|
||||
try {
|
||||
acl.insertAce(0, null, new GrantedAuthoritySid("ROLE_IGNORED"), true);
|
||||
@@ -105,7 +133,7 @@ public class AclImplTests {
|
||||
|
||||
@Test
|
||||
public void insertAceAddsElementAtCorrectIndex() throws Exception {
|
||||
MutableAcl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null, true, new PrincipalSid("joe"));
|
||||
MutableAcl acl = new AclImpl(objectIdentity, 1, mockAuthzStrategy, mockAuditLogger, null, null, true, new PrincipalSid("joe"));
|
||||
MockAclService service = new MockAclService();
|
||||
|
||||
// Insert one permission
|
||||
@@ -141,7 +169,7 @@ public class AclImplTests {
|
||||
|
||||
@Test(expected=NotFoundException.class)
|
||||
public void insertAceFailsForNonExistentElement() throws Exception {
|
||||
MutableAcl acl = new AclImpl(objectIdentity,1, authzStrategy, pgs, null, null, true, new PrincipalSid(
|
||||
MutableAcl acl = new AclImpl(objectIdentity,1, mockAuthzStrategy, mockAuditLogger, null, null, true, new PrincipalSid(
|
||||
"joe"));
|
||||
MockAclService service = new MockAclService();
|
||||
|
||||
@@ -154,7 +182,8 @@ public class AclImplTests {
|
||||
|
||||
@Test
|
||||
public void deleteAceKeepsInitialOrdering() throws Exception {
|
||||
MutableAcl acl = new AclImpl(objectIdentity,1, authzStrategy, pgs, null, null, true, new PrincipalSid("joe"));
|
||||
MutableAcl acl = new AclImpl(objectIdentity,1, mockAuthzStrategy, mockAuditLogger, null, null, true, new PrincipalSid(
|
||||
"joe"));
|
||||
MockAclService service = new MockAclService();
|
||||
|
||||
// Add several permissions
|
||||
@@ -185,10 +214,11 @@ public class AclImplTests {
|
||||
|
||||
@Test
|
||||
public void deleteAceFailsForNonExistentElement() throws Exception {
|
||||
AclAuthorizationStrategyImpl strategy = new AclAuthorizationStrategyImpl(
|
||||
new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority("ROLE_AUDITING"),
|
||||
new SimpleGrantedAuthority("ROLE_GENERAL"));
|
||||
MutableAcl acl = new AclImpl(objectIdentity, (1), strategy, pgs, null, null, true, new PrincipalSid(
|
||||
AclAuthorizationStrategyImpl strategy = new AclAuthorizationStrategyImpl(new GrantedAuthority[] {
|
||||
new GrantedAuthorityImpl("ROLE_OWNERSHIP"), new GrantedAuthorityImpl("ROLE_AUDITING"),
|
||||
new GrantedAuthorityImpl("ROLE_GENERAL") });
|
||||
AuditLogger auditLogger = new ConsoleAuditLogger();
|
||||
MutableAcl acl = new AclImpl(objectIdentity, (1), strategy, auditLogger, null, null, true, new PrincipalSid(
|
||||
"joe"));
|
||||
try {
|
||||
acl.deleteAce(99);
|
||||
@@ -200,7 +230,8 @@ public class AclImplTests {
|
||||
|
||||
@Test
|
||||
public void isGrantingRejectsEmptyParameters() throws Exception {
|
||||
MutableAcl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null, true, new PrincipalSid("joe"));
|
||||
MutableAcl acl = new AclImpl(objectIdentity, 1, mockAuthzStrategy, mockAuditLogger, null, null, true, new PrincipalSid(
|
||||
"joe"));
|
||||
Sid ben = new PrincipalSid("ben");
|
||||
try {
|
||||
acl.isGranted(new ArrayList<Permission>(0), Arrays.asList(ben) , false);
|
||||
@@ -224,7 +255,8 @@ public class AclImplTests {
|
||||
ObjectIdentity rootOid = new ObjectIdentityImpl(TARGET_CLASS, 100);
|
||||
|
||||
// Create an ACL which owner is not the authenticated principal
|
||||
MutableAcl rootAcl = new AclImpl(rootOid, 1, authzStrategy, pgs, null, null, false, new PrincipalSid("joe"));
|
||||
MutableAcl rootAcl = new AclImpl(rootOid, 1, mockAuthzStrategy, mockAuditLogger, null, null, false, new PrincipalSid(
|
||||
"joe"));
|
||||
|
||||
// Grant some permissions
|
||||
rootAcl.insertAce(0, BasePermission.READ, new PrincipalSid("ben"), false);
|
||||
@@ -267,12 +299,16 @@ public class AclImplTests {
|
||||
ObjectIdentity childOid2 = new ObjectIdentityImpl(TARGET_CLASS, 104);
|
||||
|
||||
// Create ACLs
|
||||
PrincipalSid joe = new PrincipalSid("joe");
|
||||
MutableAcl grandParentAcl = new AclImpl(grandParentOid, 1, authzStrategy, pgs, null, null, false, joe);
|
||||
MutableAcl parentAcl1 = new AclImpl(parentOid1, 2, authzStrategy, pgs, null, null, true, joe);
|
||||
MutableAcl parentAcl2 = new AclImpl(parentOid2, 3, authzStrategy, pgs, null, null, true, joe);
|
||||
MutableAcl childAcl1 = new AclImpl(childOid1, 4, authzStrategy, pgs, null, null, true, joe);
|
||||
MutableAcl childAcl2 = new AclImpl(childOid2, 4, authzStrategy, pgs, null, null, false, joe);
|
||||
MutableAcl grandParentAcl = new AclImpl(grandParentOid, 1, mockAuthzStrategy, mockAuditLogger, null, null, false,
|
||||
new PrincipalSid("joe"));
|
||||
MutableAcl parentAcl1 = new AclImpl(parentOid1, 2, mockAuthzStrategy, mockAuditLogger, null, null, true,
|
||||
new PrincipalSid("joe"));
|
||||
MutableAcl parentAcl2 = new AclImpl(parentOid2, 3, mockAuthzStrategy, mockAuditLogger, null, null, true,
|
||||
new PrincipalSid("joe"));
|
||||
MutableAcl childAcl1 = new AclImpl(childOid1, 4, mockAuthzStrategy, mockAuditLogger, null, null, true,
|
||||
new PrincipalSid("joe"));
|
||||
MutableAcl childAcl2 = new AclImpl(childOid2, 4, mockAuthzStrategy, mockAuditLogger, null, null, false,
|
||||
new PrincipalSid("joe"));
|
||||
|
||||
// Create hierarchies
|
||||
childAcl2.setParent(childAcl1);
|
||||
@@ -330,7 +366,8 @@ public class AclImplTests {
|
||||
Authentication auth = new TestingAuthenticationToken("ben", "ignored","ROLE_GENERAL");
|
||||
auth.setAuthenticated(true);
|
||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||
MutableAcl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null, false, new PrincipalSid("joe"));
|
||||
MutableAcl acl = new AclImpl(objectIdentity, 1, mockAuthzStrategy, mockAuditLogger, null, null, false, new PrincipalSid(
|
||||
"joe"));
|
||||
MockAclService service = new MockAclService();
|
||||
|
||||
acl.insertAce(0, BasePermission.READ, new GrantedAuthoritySid("ROLE_USER_READ"), true);
|
||||
@@ -347,7 +384,7 @@ public class AclImplTests {
|
||||
acl.updateAce(1, BasePermission.DELETE);
|
||||
acl.updateAce(2, BasePermission.READ);
|
||||
|
||||
// Check the change was successfully made
|
||||
// Check the change was successfuly made
|
||||
assertEquals(acl.getEntries().get(0).getPermission(), BasePermission.CREATE);
|
||||
assertEquals(acl.getEntries().get(1).getPermission(), BasePermission.DELETE);
|
||||
assertEquals(acl.getEntries().get(2).getPermission(), BasePermission.READ);
|
||||
@@ -358,7 +395,8 @@ public class AclImplTests {
|
||||
Authentication auth = new TestingAuthenticationToken("ben", "ignored", "ROLE_AUDITING", "ROLE_GENERAL");
|
||||
auth.setAuthenticated(true);
|
||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||
MutableAcl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null, false, new PrincipalSid("joe"));
|
||||
MutableAcl acl = new AclImpl(objectIdentity, 1, mockAuthzStrategy, mockAuditLogger, null, null, false, new PrincipalSid(
|
||||
"joe"));
|
||||
MockAclService service = new MockAclService();
|
||||
|
||||
acl.insertAce(0, BasePermission.READ, new GrantedAuthoritySid("ROLE_USER_READ"), true);
|
||||
@@ -383,13 +421,16 @@ public class AclImplTests {
|
||||
|
||||
@Test
|
||||
public void gettersAndSettersAreConsistent() throws Exception {
|
||||
Authentication auth = new TestingAuthenticationToken("ben", "ignored", "ROLE_GENERAL");
|
||||
Authentication auth = new TestingAuthenticationToken("ben", "ignored", new GrantedAuthority[] {
|
||||
new GrantedAuthorityImpl("ROLE_GENERAL") });
|
||||
auth.setAuthenticated(true);
|
||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||
ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, (100));
|
||||
ObjectIdentity identity2 = new ObjectIdentityImpl(TARGET_CLASS, (101));
|
||||
MutableAcl acl = new AclImpl(identity, 1, authzStrategy, pgs, null, null, true, new PrincipalSid("joe"));
|
||||
MutableAcl parentAcl = new AclImpl(identity2, 2, authzStrategy, pgs, null, null, true, new PrincipalSid("joe"));
|
||||
MutableAcl acl = new AclImpl(identity, 1, mockAuthzStrategy, mockAuditLogger, null, null, true,
|
||||
new PrincipalSid("joe"));
|
||||
MutableAcl parentAcl = new AclImpl(identity2, 2, mockAuthzStrategy, mockAuditLogger, null, null, true,
|
||||
new PrincipalSid("joe"));
|
||||
MockAclService service = new MockAclService();
|
||||
acl.insertAce(0, BasePermission.READ, new GrantedAuthoritySid("ROLE_USER_READ"), true);
|
||||
acl.insertAce(1, BasePermission.WRITE, new GrantedAuthoritySid("ROLE_USER_READ"), true);
|
||||
@@ -408,14 +449,14 @@ public class AclImplTests {
|
||||
acl.setEntriesInheriting(false);
|
||||
assertFalse(acl.isEntriesInheriting());
|
||||
|
||||
acl.setOwner(new PrincipalSid("ben"));
|
||||
((OwnershipAcl) acl).setOwner(new PrincipalSid("ben"));
|
||||
assertEquals(acl.getOwner(), new PrincipalSid("ben"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSidLoadedBehavesAsExpected() throws Exception {
|
||||
List<Sid> loadedSids = Arrays.asList(new PrincipalSid("ben"), new GrantedAuthoritySid("ROLE_IGNORED"));
|
||||
MutableAcl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, loadedSids, true,
|
||||
MutableAcl acl = new AclImpl(objectIdentity, 1, mockAuthzStrategy, mockAuditLogger, null, loadedSids, true,
|
||||
new PrincipalSid("joe"));
|
||||
|
||||
assertTrue(acl.isSidLoaded(loadedSids));
|
||||
@@ -431,19 +472,22 @@ public class AclImplTests {
|
||||
|
||||
@Test(expected=NotFoundException.class)
|
||||
public void insertAceRaisesNotFoundExceptionForIndexLessThanZero() throws Exception {
|
||||
AclImpl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null, true, new PrincipalSid("joe"));
|
||||
AclImpl acl = new AclImpl(objectIdentity, 1, mockAuthzStrategy, mockAuditLogger, null, null, true,
|
||||
new PrincipalSid("joe"));
|
||||
acl.insertAce(-1, mock(Permission.class), mock(Sid.class), true);
|
||||
}
|
||||
|
||||
@Test(expected=NotFoundException.class)
|
||||
public void deleteAceRaisesNotFoundExceptionForIndexLessThanZero() throws Exception {
|
||||
AclImpl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null, true, new PrincipalSid("joe"));
|
||||
AclImpl acl = new AclImpl(objectIdentity, 1, mockAuthzStrategy, mockAuditLogger, null, null, true,
|
||||
new PrincipalSid("joe"));
|
||||
acl.deleteAce(-1);
|
||||
}
|
||||
|
||||
@Test(expected=NotFoundException.class)
|
||||
public void insertAceRaisesNotFoundExceptionForIndexGreaterThanSize() throws Exception {
|
||||
AclImpl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null, true, new PrincipalSid("joe"));
|
||||
AclImpl acl = new AclImpl(objectIdentity, 1, mockAuthzStrategy, mockAuditLogger, null, null, true,
|
||||
new PrincipalSid("joe"));
|
||||
// Insert at zero, OK.
|
||||
acl.insertAce(0, mock(Permission.class), mock(Sid.class), true);
|
||||
// Size is now 1
|
||||
@@ -453,22 +497,13 @@ public class AclImplTests {
|
||||
// SEC-1151
|
||||
@Test(expected=NotFoundException.class)
|
||||
public void deleteAceRaisesNotFoundExceptionForIndexEqualToSize() throws Exception {
|
||||
AclImpl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null, true, new PrincipalSid("joe"));
|
||||
AclImpl acl = new AclImpl(objectIdentity, 1, mockAuthzStrategy, mockAuditLogger, null, null, true,
|
||||
new PrincipalSid("joe"));
|
||||
acl.insertAce(0, mock(Permission.class), mock(Sid.class), true);
|
||||
// Size is now 1
|
||||
acl.deleteAce(1);
|
||||
}
|
||||
|
||||
// SEC-1795
|
||||
@Test
|
||||
public void changingParentIsSuccessful() throws Exception {
|
||||
AclImpl parentAcl = new AclImpl(objectIdentity, 1L, authzStrategy, mockAuditLogger);
|
||||
AclImpl childAcl = new AclImpl(objectIdentity, 2L, authzStrategy, mockAuditLogger);
|
||||
AclImpl changeParentAcl = new AclImpl(objectIdentity, 3L, authzStrategy, mockAuditLogger);
|
||||
|
||||
childAcl.setParent(parentAcl);
|
||||
childAcl.setParent(changeParentAcl);
|
||||
}
|
||||
|
||||
//~ Inner Classes ==================================================================================================
|
||||
|
||||
|
||||
+60
-59
@@ -1,8 +1,8 @@
|
||||
package org.springframework.security.acls.domain;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import junit.framework.Assert;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.junit.*;
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.security.acls.model.Acl;
|
||||
import org.springframework.security.acls.model.MutableAcl;
|
||||
@@ -10,7 +10,8 @@ import org.springframework.security.acls.model.NotFoundException;
|
||||
import org.springframework.security.acls.model.ObjectIdentity;
|
||||
import org.springframework.security.authentication.TestingAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.GrantedAuthorityImpl;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
|
||||
/**
|
||||
@@ -19,31 +20,28 @@ import org.springframework.security.core.context.SecurityContextHolder;
|
||||
*
|
||||
* @author Andrei Stefan
|
||||
*/
|
||||
public class AclImplementationSecurityCheckTests {
|
||||
public class AclImplementationSecurityCheckTests extends TestCase {
|
||||
private static final String TARGET_CLASS = "org.springframework.security.acls.TargetObject";
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
protected void setUp() throws Exception {
|
||||
SecurityContextHolder.clearContext();
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
protected void tearDown() throws Exception {
|
||||
SecurityContextHolder.clearContext();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSecurityCheckNoACEs() throws Exception {
|
||||
Authentication auth = new TestingAuthenticationToken("user", "password","ROLE_GENERAL","ROLE_AUDITING","ROLE_OWNERSHIP");
|
||||
auth.setAuthenticated(true);
|
||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||
|
||||
ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, new Long(100));
|
||||
AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl(
|
||||
new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority("ROLE_AUDITING"),
|
||||
new SimpleGrantedAuthority("ROLE_GENERAL"));
|
||||
AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl(new GrantedAuthority[] {
|
||||
new GrantedAuthorityImpl("ROLE_OWNERSHIP"), new GrantedAuthorityImpl("ROLE_AUDITING"),
|
||||
new GrantedAuthorityImpl("ROLE_GENERAL") });
|
||||
|
||||
Acl acl = new AclImpl(identity, new Long(1), aclAuthorizationStrategy, new ConsoleAuditLogger());
|
||||
|
||||
@@ -52,43 +50,43 @@ public class AclImplementationSecurityCheckTests {
|
||||
aclAuthorizationStrategy.securityCheck(acl, AclAuthorizationStrategy.CHANGE_OWNERSHIP);
|
||||
|
||||
// Create another authorization strategy
|
||||
AclAuthorizationStrategy aclAuthorizationStrategy2 = new AclAuthorizationStrategyImpl(
|
||||
new SimpleGrantedAuthority("ROLE_ONE"), new SimpleGrantedAuthority("ROLE_TWO"),
|
||||
new SimpleGrantedAuthority("ROLE_THREE"));
|
||||
AclAuthorizationStrategy aclAuthorizationStrategy2 = new AclAuthorizationStrategyImpl(new GrantedAuthority[] {
|
||||
new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO"),
|
||||
new GrantedAuthorityImpl("ROLE_THREE") });
|
||||
Acl acl2 = new AclImpl(identity, new Long(1), aclAuthorizationStrategy2, new ConsoleAuditLogger());
|
||||
// Check access in case the principal has no authorization rights
|
||||
try {
|
||||
aclAuthorizationStrategy2.securityCheck(acl2, AclAuthorizationStrategy.CHANGE_GENERAL);
|
||||
fail("It should have thrown NotFoundException");
|
||||
Assert.fail("It should have thrown NotFoundException");
|
||||
}
|
||||
catch (NotFoundException expected) {
|
||||
}
|
||||
try {
|
||||
aclAuthorizationStrategy2.securityCheck(acl2, AclAuthorizationStrategy.CHANGE_AUDITING);
|
||||
fail("It should have thrown NotFoundException");
|
||||
Assert.fail("It should have thrown NotFoundException");
|
||||
}
|
||||
catch (NotFoundException expected) {
|
||||
}
|
||||
try {
|
||||
aclAuthorizationStrategy2.securityCheck(acl2, AclAuthorizationStrategy.CHANGE_OWNERSHIP);
|
||||
fail("It should have thrown NotFoundException");
|
||||
Assert.fail("It should have thrown NotFoundException");
|
||||
}
|
||||
catch (NotFoundException expected) {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSecurityCheckWithMultipleACEs() throws Exception {
|
||||
// Create a simple authentication with ROLE_GENERAL
|
||||
Authentication auth = new TestingAuthenticationToken("user", "password", "ROLE_GENERAL");
|
||||
Authentication auth = new TestingAuthenticationToken("user", "password",
|
||||
new GrantedAuthority[] { new GrantedAuthorityImpl("ROLE_GENERAL") });
|
||||
auth.setAuthenticated(true);
|
||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||
|
||||
ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, new Long(100));
|
||||
// Authorization strategy will require a different role for each access
|
||||
AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl(
|
||||
new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority("ROLE_AUDITING"),
|
||||
new SimpleGrantedAuthority("ROLE_GENERAL"));
|
||||
AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl(new GrantedAuthority[] {
|
||||
new GrantedAuthorityImpl("ROLE_OWNERSHIP"), new GrantedAuthorityImpl("ROLE_AUDITING"),
|
||||
new GrantedAuthorityImpl("ROLE_GENERAL") });
|
||||
|
||||
// Let's give the principal the ADMINISTRATION permission, without
|
||||
// granting access
|
||||
@@ -103,13 +101,13 @@ public class AclImplementationSecurityCheckTests {
|
||||
// nor granting access
|
||||
try {
|
||||
aclAuthorizationStrategy.securityCheck(aclFirstDeny, AclAuthorizationStrategy.CHANGE_AUDITING);
|
||||
fail("It should have thrown AccessDeniedException");
|
||||
Assert.fail("It should have thrown AccessDeniedException");
|
||||
}
|
||||
catch (AccessDeniedException expected) {
|
||||
}
|
||||
try {
|
||||
aclAuthorizationStrategy.securityCheck(aclFirstDeny, AclAuthorizationStrategy.CHANGE_OWNERSHIP);
|
||||
fail("It should have thrown AccessDeniedException");
|
||||
Assert.fail("It should have thrown AccessDeniedException");
|
||||
}
|
||||
catch (AccessDeniedException expected) {
|
||||
}
|
||||
@@ -120,7 +118,7 @@ public class AclImplementationSecurityCheckTests {
|
||||
// (false) will deny this access
|
||||
try {
|
||||
aclAuthorizationStrategy.securityCheck(aclFirstDeny, AclAuthorizationStrategy.CHANGE_AUDITING);
|
||||
fail("It should have thrown AccessDeniedException");
|
||||
Assert.fail("It should have thrown AccessDeniedException");
|
||||
}
|
||||
catch (AccessDeniedException expected) {
|
||||
}
|
||||
@@ -140,58 +138,58 @@ public class AclImplementationSecurityCheckTests {
|
||||
aclFirstAllow.insertAce(1, BasePermission.ADMINISTRATION, new PrincipalSid(auth), false);
|
||||
try {
|
||||
aclAuthorizationStrategy.securityCheck(aclFirstAllow, AclAuthorizationStrategy.CHANGE_AUDITING);
|
||||
assertTrue(true);
|
||||
Assert.assertTrue(true);
|
||||
}
|
||||
catch (AccessDeniedException notExpected) {
|
||||
fail("It shouldn't have thrown AccessDeniedException");
|
||||
Assert.fail("It shouldn't have thrown AccessDeniedException");
|
||||
}
|
||||
|
||||
// Create an ACL with no ACE
|
||||
MutableAcl aclNoACE = new AclImpl(identity, new Long(1), aclAuthorizationStrategy, new ConsoleAuditLogger());
|
||||
try {
|
||||
aclAuthorizationStrategy.securityCheck(aclNoACE, AclAuthorizationStrategy.CHANGE_AUDITING);
|
||||
fail("It should have thrown NotFoundException");
|
||||
Assert.fail("It should have thrown NotFoundException");
|
||||
}
|
||||
catch (NotFoundException expected) {
|
||||
assertTrue(true);
|
||||
Assert.assertTrue(true);
|
||||
}
|
||||
// and still grant access for CHANGE_GENERAL
|
||||
try {
|
||||
aclAuthorizationStrategy.securityCheck(aclNoACE, AclAuthorizationStrategy.CHANGE_GENERAL);
|
||||
assertTrue(true);
|
||||
Assert.assertTrue(true);
|
||||
}
|
||||
catch (NotFoundException expected) {
|
||||
fail("It shouldn't have thrown NotFoundException");
|
||||
Assert.fail("It shouldn't have thrown NotFoundException");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSecurityCheckWithInheritableACEs() throws Exception {
|
||||
// Create a simple authentication with ROLE_GENERAL
|
||||
Authentication auth = new TestingAuthenticationToken("user", "password", "ROLE_GENERAL");
|
||||
Authentication auth = new TestingAuthenticationToken("user", "password",
|
||||
new GrantedAuthority[] { new GrantedAuthorityImpl("ROLE_GENERAL") });
|
||||
auth.setAuthenticated(true);
|
||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||
|
||||
ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, 100);
|
||||
ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, new Long(100));
|
||||
// Authorization strategy will require a different role for each access
|
||||
AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl(
|
||||
new SimpleGrantedAuthority("ROLE_ONE"), new SimpleGrantedAuthority("ROLE_TWO"),
|
||||
new SimpleGrantedAuthority("ROLE_GENERAL"));
|
||||
AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl(new GrantedAuthority[] {
|
||||
new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO"),
|
||||
new GrantedAuthorityImpl("ROLE_GENERAL") });
|
||||
|
||||
// Let's give the principal an ADMINISTRATION permission, with granting
|
||||
// access
|
||||
MutableAcl parentAcl = new AclImpl(identity, 1, aclAuthorizationStrategy, new ConsoleAuditLogger());
|
||||
MutableAcl parentAcl = new AclImpl(identity, new Long(1), aclAuthorizationStrategy, new ConsoleAuditLogger());
|
||||
parentAcl.insertAce(0, BasePermission.ADMINISTRATION, new PrincipalSid(auth), true);
|
||||
MutableAcl childAcl = new AclImpl(identity, 2, aclAuthorizationStrategy, new ConsoleAuditLogger());
|
||||
MutableAcl childAcl = new AclImpl(identity, new Long(2), aclAuthorizationStrategy, new ConsoleAuditLogger());
|
||||
|
||||
// Check against the 'child' acl, which doesn't offer any authorization
|
||||
// rights on CHANGE_OWNERSHIP
|
||||
try {
|
||||
aclAuthorizationStrategy.securityCheck(childAcl, AclAuthorizationStrategy.CHANGE_OWNERSHIP);
|
||||
fail("It should have thrown NotFoundException");
|
||||
Assert.fail("It should have thrown NotFoundException");
|
||||
}
|
||||
catch (NotFoundException expected) {
|
||||
assertTrue(true);
|
||||
Assert.assertTrue(true);
|
||||
}
|
||||
|
||||
// Link the child with its parent and test again against the
|
||||
@@ -200,60 +198,63 @@ public class AclImplementationSecurityCheckTests {
|
||||
childAcl.setEntriesInheriting(true);
|
||||
try {
|
||||
aclAuthorizationStrategy.securityCheck(childAcl, AclAuthorizationStrategy.CHANGE_OWNERSHIP);
|
||||
assertTrue(true);
|
||||
Assert.assertTrue(true);
|
||||
}
|
||||
catch (NotFoundException expected) {
|
||||
fail("It shouldn't have thrown NotFoundException");
|
||||
Assert.fail("It shouldn't have thrown NotFoundException");
|
||||
}
|
||||
|
||||
// Create a root parent and link it to the middle parent
|
||||
MutableAcl rootParentAcl = new AclImpl(identity, 1, aclAuthorizationStrategy,
|
||||
MutableAcl rootParentAcl = new AclImpl(identity, new Long(1), aclAuthorizationStrategy,
|
||||
new ConsoleAuditLogger());
|
||||
parentAcl = new AclImpl(identity, 1, aclAuthorizationStrategy, new ConsoleAuditLogger());
|
||||
parentAcl = new AclImpl(identity, new Long(1), aclAuthorizationStrategy, new ConsoleAuditLogger());
|
||||
rootParentAcl.insertAce(0, BasePermission.ADMINISTRATION, new PrincipalSid(auth), true);
|
||||
parentAcl.setEntriesInheriting(true);
|
||||
parentAcl.setParent(rootParentAcl);
|
||||
childAcl.setParent(parentAcl);
|
||||
try {
|
||||
aclAuthorizationStrategy.securityCheck(childAcl, AclAuthorizationStrategy.CHANGE_OWNERSHIP);
|
||||
assertTrue(true);
|
||||
Assert.assertTrue(true);
|
||||
}
|
||||
catch (NotFoundException expected) {
|
||||
fail("It shouldn't have thrown NotFoundException");
|
||||
Assert.fail("It shouldn't have thrown NotFoundException");
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Test
|
||||
public void testSecurityCheckPrincipalOwner() throws Exception {
|
||||
Authentication auth = new TestingAuthenticationToken("user", "password", "ROLE_ONE");
|
||||
Authentication auth = new TestingAuthenticationToken("user", "password", new GrantedAuthority[] {
|
||||
new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_ONE"),
|
||||
new GrantedAuthorityImpl("ROLE_ONE") });
|
||||
auth.setAuthenticated(true);
|
||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||
|
||||
ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, 100);
|
||||
AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl(
|
||||
new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority("ROLE_AUDITING"),
|
||||
new SimpleGrantedAuthority("ROLE_GENERAL"));
|
||||
ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, new Long(100));
|
||||
AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl(new GrantedAuthority[] {
|
||||
new GrantedAuthorityImpl("ROLE_OWNERSHIP"), new GrantedAuthorityImpl("ROLE_AUDITING"),
|
||||
new GrantedAuthorityImpl("ROLE_GENERAL") });
|
||||
|
||||
Acl acl = new AclImpl(identity, 1, aclAuthorizationStrategy, new ConsoleAuditLogger(), null, null,
|
||||
Acl acl = new AclImpl(identity, new Long(1), aclAuthorizationStrategy, new ConsoleAuditLogger(), null, null,
|
||||
false, new PrincipalSid(auth));
|
||||
try {
|
||||
aclAuthorizationStrategy.securityCheck(acl, AclAuthorizationStrategy.CHANGE_GENERAL);
|
||||
Assert.assertTrue(true);
|
||||
}
|
||||
catch (AccessDeniedException notExpected) {
|
||||
fail("It shouldn't have thrown AccessDeniedException");
|
||||
Assert.fail("It shouldn't have thrown AccessDeniedException");
|
||||
}
|
||||
try {
|
||||
aclAuthorizationStrategy.securityCheck(acl, AclAuthorizationStrategy.CHANGE_AUDITING);
|
||||
fail("It shouldn't have thrown AccessDeniedException");
|
||||
Assert.fail("It shouldn't have thrown AccessDeniedException");
|
||||
}
|
||||
catch (NotFoundException expected) {
|
||||
Assert.assertTrue(true);
|
||||
}
|
||||
try {
|
||||
aclAuthorizationStrategy.securityCheck(acl, AclAuthorizationStrategy.CHANGE_OWNERSHIP);
|
||||
Assert.assertTrue(true);
|
||||
}
|
||||
catch (AccessDeniedException notExpected) {
|
||||
fail("It shouldn't have thrown AccessDeniedException");
|
||||
Assert.fail("It shouldn't have thrown AccessDeniedException");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
package org.springframework.security.acls.domain;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.PrintStream;
|
||||
|
||||
import org.jmock.Expectations;
|
||||
import org.jmock.Mockery;
|
||||
import org.jmock.integration.junit4.JUnit4Mockery;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -19,17 +21,29 @@ import org.springframework.security.acls.model.AuditableAccessControlEntry;
|
||||
*/
|
||||
public class AuditLoggerTests {
|
||||
//~ Instance fields ================================================================================================
|
||||
private Mockery jmock = new JUnit4Mockery();
|
||||
private PrintStream console;
|
||||
private ByteArrayOutputStream bytes = new ByteArrayOutputStream();
|
||||
private ConsoleAuditLogger logger;
|
||||
private AuditableAccessControlEntry ace;
|
||||
private Expectations aceRequiresAudit;
|
||||
private Expectations aceDoesntRequireAudit;
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
logger = new ConsoleAuditLogger();
|
||||
ace = mock(AuditableAccessControlEntry.class);
|
||||
ace = jmock.mock(AuditableAccessControlEntry.class);
|
||||
aceRequiresAudit = new Expectations() {{
|
||||
allowing(ace).isAuditSuccess(); will(returnValue(true));
|
||||
allowing(ace).isAuditFailure(); will(returnValue(true));
|
||||
}};
|
||||
aceDoesntRequireAudit = new Expectations() {{
|
||||
allowing(ace).isAuditSuccess(); will(returnValue(false));
|
||||
allowing(ace).isAuditFailure(); will(returnValue(false));
|
||||
}};
|
||||
|
||||
console = System.out;
|
||||
System.setOut(new PrintStream(bytes));
|
||||
}
|
||||
@@ -42,36 +56,35 @@ public class AuditLoggerTests {
|
||||
|
||||
@Test
|
||||
public void nonAuditableAceIsIgnored() {
|
||||
AccessControlEntry ace = mock(AccessControlEntry.class);
|
||||
AccessControlEntry ace = jmock.mock(AccessControlEntry.class);
|
||||
logger.logIfNeeded(true, ace);
|
||||
assertEquals(0, bytes.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void successIsNotLoggedIfAceDoesntRequireSuccessAudit() throws Exception {
|
||||
when(ace.isAuditSuccess()).thenReturn(false);
|
||||
jmock.checking(aceDoesntRequireAudit);
|
||||
logger.logIfNeeded(true, ace);
|
||||
assertEquals(0, bytes.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void successIsLoggedIfAceRequiresSuccessAudit() throws Exception {
|
||||
when(ace.isAuditSuccess()).thenReturn(true);
|
||||
|
||||
jmock.checking(aceRequiresAudit);
|
||||
logger.logIfNeeded(true, ace);
|
||||
assertTrue(bytes.toString().startsWith("GRANTED due to ACE"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void failureIsntLoggedIfAceDoesntRequireFailureAudit() throws Exception {
|
||||
when(ace.isAuditFailure()).thenReturn(false);
|
||||
jmock.checking(aceDoesntRequireAudit);
|
||||
logger.logIfNeeded(false, ace);
|
||||
assertEquals(0, bytes.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void failureIsLoggedIfAceRequiresFailureAudit() throws Exception {
|
||||
when(ace.isAuditFailure()).thenReturn(true);
|
||||
jmock.checking(aceRequiresAudit);
|
||||
logger.logIfNeeded(false, ace);
|
||||
assertTrue(bytes.toString().startsWith("DENIED due to ACE"));
|
||||
}
|
||||
|
||||
+1
-1
@@ -140,7 +140,7 @@ public class ObjectIdentityImplTests {
|
||||
@Test
|
||||
public void longAndIntegerIdsWithSameValueAreEqualAndHaveSameHashcode() {
|
||||
ObjectIdentity obj = new ObjectIdentityImpl(Object.class, new Long(5));
|
||||
ObjectIdentity obj2 = new ObjectIdentityImpl(Object.class, Integer.valueOf(5));
|
||||
ObjectIdentity obj2 = new ObjectIdentityImpl(Object.class, new Integer(5));
|
||||
|
||||
assertEquals(obj, obj2);
|
||||
assertEquals(obj.hashCode(), obj2.hashCode());
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@ public class ObjectIdentityRetrievalStrategyImplTests extends TestCase {
|
||||
|
||||
public void testObjectIdentityCreation() throws Exception {
|
||||
MockIdDomainObject domain = new MockIdDomainObject();
|
||||
domain.setId(Integer.valueOf(1));
|
||||
domain.setId(new Integer(1));
|
||||
|
||||
ObjectIdentityRetrievalStrategy retStrategy = new ObjectIdentityRetrievalStrategyImpl();
|
||||
ObjectIdentity identity = retStrategy.getObjectIdentity(domain);
|
||||
|
||||
+41
-33
@@ -1,10 +1,19 @@
|
||||
package org.springframework.security.acls.jdbc;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import junit.framework.Assert;
|
||||
import net.sf.ehcache.Cache;
|
||||
import net.sf.ehcache.CacheManager;
|
||||
import net.sf.ehcache.Ehcache;
|
||||
import org.junit.*;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
@@ -14,7 +23,6 @@ import org.springframework.security.acls.domain.AclAuthorizationStrategyImpl;
|
||||
import org.springframework.security.acls.domain.BasePermission;
|
||||
import org.springframework.security.acls.domain.ConsoleAuditLogger;
|
||||
import org.springframework.security.acls.domain.DefaultPermissionFactory;
|
||||
import org.springframework.security.acls.domain.DefaultPermissionGrantingStrategy;
|
||||
import org.springframework.security.acls.domain.EhCacheBasedAclCache;
|
||||
import org.springframework.security.acls.domain.ObjectIdentityImpl;
|
||||
import org.springframework.security.acls.domain.PrincipalSid;
|
||||
@@ -25,11 +33,10 @@ import org.springframework.security.acls.model.NotFoundException;
|
||||
import org.springframework.security.acls.model.ObjectIdentity;
|
||||
import org.springframework.security.acls.model.Permission;
|
||||
import org.springframework.security.acls.model.Sid;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.GrantedAuthorityImpl;
|
||||
import org.springframework.util.FileCopyUtils;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Tests {@link BasicLookupStrategy}
|
||||
*
|
||||
@@ -93,9 +100,10 @@ public class BasicLookupStrategyTests {
|
||||
@Before
|
||||
public void initializeBeans() {
|
||||
EhCacheBasedAclCache cache = new EhCacheBasedAclCache(getCache());
|
||||
AclAuthorizationStrategy authorizationStrategy = new AclAuthorizationStrategyImpl(new SimpleGrantedAuthority("ROLE_ADMINISTRATOR"));
|
||||
strategy = new BasicLookupStrategy(dataSource, cache, authorizationStrategy,
|
||||
new DefaultPermissionGrantingStrategy(new ConsoleAuditLogger()));
|
||||
AclAuthorizationStrategy authorizationStrategy = new AclAuthorizationStrategyImpl(new GrantedAuthority[] {
|
||||
new GrantedAuthorityImpl("ROLE_ADMINISTRATOR"), new GrantedAuthorityImpl("ROLE_ADMINISTRATOR"),
|
||||
new GrantedAuthorityImpl("ROLE_ADMINISTRATOR") });
|
||||
strategy = new BasicLookupStrategy(dataSource, cache, authorizationStrategy, new ConsoleAuditLogger());
|
||||
strategy.setPermissionFactory(new DefaultPermissionFactory());
|
||||
}
|
||||
|
||||
@@ -120,7 +128,7 @@ public class BasicLookupStrategyTests {
|
||||
ObjectIdentity topParentOid = new ObjectIdentityImpl(TARGET_CLASS, new Long(100));
|
||||
ObjectIdentity middleParentOid = new ObjectIdentityImpl(TARGET_CLASS, new Long(101));
|
||||
// Deliberately use an integer for the child, to reproduce bug report in SEC-819
|
||||
ObjectIdentity childOid = new ObjectIdentityImpl(TARGET_CLASS, Integer.valueOf(102));
|
||||
ObjectIdentity childOid = new ObjectIdentityImpl(TARGET_CLASS, new Integer(102));
|
||||
|
||||
Map<ObjectIdentity, Acl> map = this.strategy.readAclsById(Arrays.asList(topParentOid, middleParentOid, childOid), null);
|
||||
checkEntries(topParentOid, middleParentOid, childOid, map);
|
||||
@@ -128,7 +136,7 @@ public class BasicLookupStrategyTests {
|
||||
|
||||
@Test
|
||||
public void testAclsRetrievalFromCacheOnly() throws Exception {
|
||||
ObjectIdentity topParentOid = new ObjectIdentityImpl(TARGET_CLASS, Integer.valueOf(100));
|
||||
ObjectIdentity topParentOid = new ObjectIdentityImpl(TARGET_CLASS, new Integer(100));
|
||||
ObjectIdentity middleParentOid = new ObjectIdentityImpl(TARGET_CLASS, new Long(101));
|
||||
ObjectIdentity childOid = new ObjectIdentityImpl(TARGET_CLASS, new Long(102));
|
||||
|
||||
@@ -145,11 +153,11 @@ public class BasicLookupStrategyTests {
|
||||
@Test
|
||||
public void testAclsRetrievalWithCustomBatchSize() throws Exception {
|
||||
ObjectIdentity topParentOid = new ObjectIdentityImpl(TARGET_CLASS, new Long(100));
|
||||
ObjectIdentity middleParentOid = new ObjectIdentityImpl(TARGET_CLASS, Integer.valueOf(101));
|
||||
ObjectIdentity middleParentOid = new ObjectIdentityImpl(TARGET_CLASS, new Integer(101));
|
||||
ObjectIdentity childOid = new ObjectIdentityImpl(TARGET_CLASS, new Long(102));
|
||||
|
||||
// Set a batch size to allow multiple database queries in order to retrieve all acls
|
||||
this.strategy.setBatchSize(1);
|
||||
((BasicLookupStrategy) this.strategy).setBatchSize(1);
|
||||
Map<ObjectIdentity, Acl> map = this.strategy.readAclsById(Arrays.asList(topParentOid, middleParentOid, childOid), null);
|
||||
checkEntries(topParentOid, middleParentOid, childOid, map);
|
||||
}
|
||||
@@ -184,36 +192,36 @@ public class BasicLookupStrategyTests {
|
||||
|
||||
// Check each entry
|
||||
Assert.assertTrue(topParent.isEntriesInheriting());
|
||||
Assert.assertEquals(topParent.getId(), Long.valueOf(1));
|
||||
Assert.assertEquals(topParent.getId(), new Long(1));
|
||||
Assert.assertEquals(topParent.getOwner(), new PrincipalSid("ben"));
|
||||
Assert.assertEquals(topParent.getEntries().get(0).getId(), Long.valueOf(1));
|
||||
Assert.assertEquals(topParent.getEntries().get(0).getId(), new Long(1));
|
||||
Assert.assertEquals(topParent.getEntries().get(0).getPermission(), BasePermission.READ);
|
||||
Assert.assertEquals(topParent.getEntries().get(0).getSid(), new PrincipalSid("ben"));
|
||||
Assert.assertFalse(((AuditableAccessControlEntry) topParent.getEntries().get(0)).isAuditFailure());
|
||||
Assert.assertFalse(((AuditableAccessControlEntry) topParent.getEntries().get(0)).isAuditSuccess());
|
||||
Assert.assertTrue((topParent.getEntries().get(0)).isGranting());
|
||||
Assert.assertTrue(((AuditableAccessControlEntry) topParent.getEntries().get(0)).isGranting());
|
||||
|
||||
Assert.assertEquals(topParent.getEntries().get(1).getId(), Long.valueOf(2));
|
||||
Assert.assertEquals(topParent.getEntries().get(1).getId(), new Long(2));
|
||||
Assert.assertEquals(topParent.getEntries().get(1).getPermission(), BasePermission.WRITE);
|
||||
Assert.assertEquals(topParent.getEntries().get(1).getSid(), new PrincipalSid("ben"));
|
||||
Assert.assertFalse(((AuditableAccessControlEntry) topParent.getEntries().get(1)).isAuditFailure());
|
||||
Assert.assertFalse(((AuditableAccessControlEntry) topParent.getEntries().get(1)).isAuditSuccess());
|
||||
Assert.assertFalse(topParent.getEntries().get(1).isGranting());
|
||||
Assert.assertFalse(((AuditableAccessControlEntry) topParent.getEntries().get(1)).isGranting());
|
||||
|
||||
Assert.assertTrue(middleParent.isEntriesInheriting());
|
||||
Assert.assertEquals(middleParent.getId(), Long.valueOf(2));
|
||||
Assert.assertEquals(middleParent.getId(), new Long(2));
|
||||
Assert.assertEquals(middleParent.getOwner(), new PrincipalSid("ben"));
|
||||
Assert.assertEquals(middleParent.getEntries().get(0).getId(), Long.valueOf(3));
|
||||
Assert.assertEquals(middleParent.getEntries().get(0).getId(), new Long(3));
|
||||
Assert.assertEquals(middleParent.getEntries().get(0).getPermission(), BasePermission.DELETE);
|
||||
Assert.assertEquals(middleParent.getEntries().get(0).getSid(), new PrincipalSid("ben"));
|
||||
Assert.assertFalse(((AuditableAccessControlEntry) middleParent.getEntries().get(0)).isAuditFailure());
|
||||
Assert.assertFalse(((AuditableAccessControlEntry) middleParent.getEntries().get(0)).isAuditSuccess());
|
||||
Assert.assertTrue(middleParent.getEntries().get(0).isGranting());
|
||||
Assert.assertTrue(((AuditableAccessControlEntry) middleParent.getEntries().get(0)).isGranting());
|
||||
|
||||
Assert.assertTrue(child.isEntriesInheriting());
|
||||
Assert.assertEquals(child.getId(), Long.valueOf(3));
|
||||
Assert.assertEquals(child.getId(), new Long(3));
|
||||
Assert.assertEquals(child.getOwner(), new PrincipalSid("ben"));
|
||||
Assert.assertEquals(child.getEntries().get(0).getId(), Long.valueOf(4));
|
||||
Assert.assertEquals(child.getEntries().get(0).getId(), new Long(4));
|
||||
Assert.assertEquals(child.getEntries().get(0).getPermission(), BasePermission.DELETE);
|
||||
Assert.assertEquals(child.getEntries().get(0).getSid(), new PrincipalSid("ben"));
|
||||
Assert.assertFalse(((AuditableAccessControlEntry) child.getEntries().get(0)).isAuditFailure());
|
||||
@@ -226,21 +234,21 @@ public class BasicLookupStrategyTests {
|
||||
String query = "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (4,2,103,1,1,1);";
|
||||
jdbcTemplate.execute(query);
|
||||
|
||||
ObjectIdentity topParentOid = new ObjectIdentityImpl(TARGET_CLASS, Long.valueOf(100));
|
||||
ObjectIdentity middleParentOid = new ObjectIdentityImpl(TARGET_CLASS, Long.valueOf(101));
|
||||
ObjectIdentity childOid = new ObjectIdentityImpl(TARGET_CLASS, Long.valueOf(102));
|
||||
ObjectIdentity middleParent2Oid = new ObjectIdentityImpl(TARGET_CLASS, Long.valueOf(103));
|
||||
ObjectIdentity topParentOid = new ObjectIdentityImpl(TARGET_CLASS, new Long(100));
|
||||
ObjectIdentity middleParentOid = new ObjectIdentityImpl(TARGET_CLASS, new Integer(101));
|
||||
ObjectIdentity childOid = new ObjectIdentityImpl(TARGET_CLASS, new Long(102));
|
||||
ObjectIdentity middleParent2Oid = new ObjectIdentityImpl(TARGET_CLASS, new Long(103));
|
||||
|
||||
// Retrieve the child
|
||||
Map<ObjectIdentity, Acl> map = this.strategy.readAclsById(Arrays.asList(childOid), null);
|
||||
|
||||
// Check that the child and all its parents were retrieved
|
||||
Assert.assertNotNull(map.get(childOid));
|
||||
Assert.assertEquals(childOid, map.get(childOid).getObjectIdentity());
|
||||
Assert.assertEquals(childOid, ((Acl) map.get(childOid)).getObjectIdentity());
|
||||
Assert.assertNotNull(map.get(middleParentOid));
|
||||
Assert.assertEquals(middleParentOid, map.get(middleParentOid).getObjectIdentity());
|
||||
Assert.assertEquals(middleParentOid, ((Acl) map.get(middleParentOid)).getObjectIdentity());
|
||||
Assert.assertNotNull(map.get(topParentOid));
|
||||
Assert.assertEquals(topParentOid, map.get(topParentOid).getObjectIdentity());
|
||||
Assert.assertEquals(topParentOid, ((Acl) map.get(topParentOid)).getObjectIdentity());
|
||||
|
||||
// The second parent shouldn't have been retrieved
|
||||
Assert.assertNull(map.get(middleParent2Oid));
|
||||
@@ -260,8 +268,8 @@ public class BasicLookupStrategyTests {
|
||||
|
||||
ObjectIdentity grandParentOid = new ObjectIdentityImpl(TARGET_CLASS, new Long(104));
|
||||
ObjectIdentity parent1Oid = new ObjectIdentityImpl(TARGET_CLASS, new Long(105));
|
||||
ObjectIdentity parent2Oid = new ObjectIdentityImpl(TARGET_CLASS, Integer.valueOf(106));
|
||||
ObjectIdentity childOid = new ObjectIdentityImpl(TARGET_CLASS, Integer.valueOf(107));
|
||||
ObjectIdentity parent2Oid = new ObjectIdentityImpl(TARGET_CLASS, new Integer(106));
|
||||
ObjectIdentity childOid = new ObjectIdentityImpl(TARGET_CLASS, new Integer(107));
|
||||
|
||||
// First lookup only child, thus populating the cache with grandParent, parent1 and child
|
||||
List<Permission> checkPermission = Arrays.asList(BasePermission.READ);
|
||||
@@ -271,7 +279,7 @@ public class BasicLookupStrategyTests {
|
||||
strategy.setBatchSize(6);
|
||||
Map<ObjectIdentity, Acl> foundAcls = strategy.readAclsById(childOids, sids);
|
||||
|
||||
Acl foundChildAcl = foundAcls.get(childOid);
|
||||
Acl foundChildAcl = (Acl) foundAcls.get(childOid);
|
||||
Assert.assertNotNull(foundChildAcl);
|
||||
Assert.assertTrue(foundChildAcl.isGranted(checkPermission, sids, false));
|
||||
|
||||
@@ -285,7 +293,7 @@ public class BasicLookupStrategyTests {
|
||||
Assert.fail("It shouldn't have thrown NotFoundException");
|
||||
}
|
||||
|
||||
Acl foundParent2Acl = foundAcls.get(parent2Oid);
|
||||
Acl foundParent2Acl = (Acl) foundAcls.get(parent2Oid);
|
||||
Assert.assertNotNull(foundParent2Acl);
|
||||
Assert.assertTrue(foundParent2Acl.isGranted(checkPermission, sids, false));
|
||||
}
|
||||
|
||||
+45
-39
@@ -2,10 +2,22 @@ package org.springframework.security.acls.jdbc;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.Serializable;
|
||||
import java.util.Map;
|
||||
|
||||
import net.sf.ehcache.Cache;
|
||||
import net.sf.ehcache.CacheManager;
|
||||
import net.sf.ehcache.Ehcache;
|
||||
import org.junit.*;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.springframework.security.acls.domain.AclAuthorizationStrategy;
|
||||
import org.springframework.security.acls.domain.AclAuthorizationStrategyImpl;
|
||||
import org.springframework.security.acls.domain.AclImpl;
|
||||
@@ -16,18 +28,11 @@ import org.springframework.security.acls.model.MutableAcl;
|
||||
import org.springframework.security.acls.model.ObjectIdentity;
|
||||
import org.springframework.security.authentication.TestingAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.GrantedAuthorityImpl;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.util.FieldUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Tests {@link EhCacheBasedAclCache}
|
||||
*
|
||||
@@ -122,11 +127,11 @@ public class EhCacheBasedAclCacheTests {
|
||||
// SEC-527
|
||||
@Test
|
||||
public void testDiskSerializationOfMutableAclObjectInstance() throws Exception {
|
||||
ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, Long.valueOf(100));
|
||||
AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl(
|
||||
new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority("ROLE_AUDITING"),
|
||||
new SimpleGrantedAuthority("ROLE_GENERAL"));
|
||||
MutableAcl acl = new AclImpl(identity, Long.valueOf(1), aclAuthorizationStrategy, new ConsoleAuditLogger());
|
||||
ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, new Long(100));
|
||||
AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl(new GrantedAuthority[] {
|
||||
new GrantedAuthorityImpl("ROLE_OWNERSHIP"), new GrantedAuthorityImpl("ROLE_AUDITING"),
|
||||
new GrantedAuthorityImpl("ROLE_GENERAL") });
|
||||
MutableAcl acl = new AclImpl(identity, new Long(1), aclAuthorizationStrategy, new ConsoleAuditLogger());
|
||||
|
||||
// Serialization test
|
||||
File file = File.createTempFile("SEC_TEST", ".object");
|
||||
@@ -145,7 +150,7 @@ public class EhCacheBasedAclCacheTests {
|
||||
Object retrieved1 = FieldUtils.getProtectedFieldValue("aclAuthorizationStrategy", retrieved);
|
||||
assertEquals(null, retrieved1);
|
||||
|
||||
Object retrieved2 = FieldUtils.getProtectedFieldValue("permissionGrantingStrategy", retrieved);
|
||||
Object retrieved2 = FieldUtils.getProtectedFieldValue("auditLogger", retrieved);
|
||||
assertEquals(null, retrieved2);
|
||||
}
|
||||
|
||||
@@ -154,11 +159,11 @@ public class EhCacheBasedAclCacheTests {
|
||||
Ehcache cache = getCache();
|
||||
EhCacheBasedAclCache myCache = new EhCacheBasedAclCache(cache);
|
||||
|
||||
ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, Long.valueOf(100));
|
||||
AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl(
|
||||
new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority("ROLE_AUDITING"),
|
||||
new SimpleGrantedAuthority("ROLE_GENERAL"));
|
||||
MutableAcl acl = new AclImpl(identity, Long.valueOf(1), aclAuthorizationStrategy, new ConsoleAuditLogger());
|
||||
ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, new Long(100));
|
||||
AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl(new GrantedAuthority[] {
|
||||
new GrantedAuthorityImpl("ROLE_OWNERSHIP"), new GrantedAuthorityImpl("ROLE_AUDITING"),
|
||||
new GrantedAuthorityImpl("ROLE_GENERAL") });
|
||||
MutableAcl acl = new AclImpl(identity, new Long(1), aclAuthorizationStrategy, new ConsoleAuditLogger());
|
||||
|
||||
assertEquals(0, cache.getDiskStoreSize());
|
||||
myCache.putInCache(acl);
|
||||
@@ -168,29 +173,29 @@ public class EhCacheBasedAclCacheTests {
|
||||
assertFalse(cache.isElementInMemory(acl.getObjectIdentity()));
|
||||
|
||||
// Check we can get from cache the same objects we put in
|
||||
assertEquals(myCache.getFromCache(Long.valueOf(1)), acl);
|
||||
assertEquals(myCache.getFromCache(new Long(1)), acl);
|
||||
assertEquals(myCache.getFromCache(identity), acl);
|
||||
|
||||
// Put another object in cache
|
||||
ObjectIdentity identity2 = new ObjectIdentityImpl(TARGET_CLASS, Long.valueOf(101));
|
||||
MutableAcl acl2 = new AclImpl(identity2, Long.valueOf(2), aclAuthorizationStrategy, new ConsoleAuditLogger());
|
||||
ObjectIdentity identity2 = new ObjectIdentityImpl(TARGET_CLASS, new Long(101));
|
||||
MutableAcl acl2 = new AclImpl(identity2, new Long(2), aclAuthorizationStrategy, new ConsoleAuditLogger());
|
||||
|
||||
myCache.putInCache(acl2);
|
||||
assertEquals(cache.getSize(), 4);
|
||||
assertEquals(4, cache.getDiskStoreSize());
|
||||
|
||||
// Try to evict an entry that doesn't exist
|
||||
myCache.evictFromCache(Long.valueOf(3));
|
||||
myCache.evictFromCache(new ObjectIdentityImpl(TARGET_CLASS, Long.valueOf(102)));
|
||||
myCache.evictFromCache(new Long(3));
|
||||
myCache.evictFromCache(new ObjectIdentityImpl(TARGET_CLASS, new Long(102)));
|
||||
assertEquals(cache.getSize(), 4);
|
||||
assertEquals(4, cache.getDiskStoreSize());
|
||||
|
||||
myCache.evictFromCache(Long.valueOf(1));
|
||||
myCache.evictFromCache(new Long(1));
|
||||
assertEquals(cache.getSize(), 2);
|
||||
assertEquals(2, cache.getDiskStoreSize());
|
||||
|
||||
// Check the second object inserted
|
||||
assertEquals(myCache.getFromCache(Long.valueOf(2)), acl2);
|
||||
assertEquals(myCache.getFromCache(new Long(2)), acl2);
|
||||
assertEquals(myCache.getFromCache(identity2), acl2);
|
||||
|
||||
myCache.evictFromCache(identity2);
|
||||
@@ -203,17 +208,18 @@ public class EhCacheBasedAclCacheTests {
|
||||
Ehcache cache = getCache();
|
||||
EhCacheBasedAclCache myCache = new EhCacheBasedAclCache(cache);
|
||||
|
||||
Authentication auth = new TestingAuthenticationToken("user", "password", "ROLE_GENERAL");
|
||||
Authentication auth = new TestingAuthenticationToken("user", "password", new GrantedAuthority[] {
|
||||
new GrantedAuthorityImpl("ROLE_GENERAL") });
|
||||
auth.setAuthenticated(true);
|
||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||
|
||||
ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, Long.valueOf(1));
|
||||
ObjectIdentity identityParent = new ObjectIdentityImpl(TARGET_CLASS, Long.valueOf(2));
|
||||
AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl(
|
||||
new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority("ROLE_AUDITING"),
|
||||
new SimpleGrantedAuthority("ROLE_GENERAL"));
|
||||
MutableAcl acl = new AclImpl(identity, Long.valueOf(1), aclAuthorizationStrategy, new ConsoleAuditLogger());
|
||||
MutableAcl parentAcl = new AclImpl(identityParent, Long.valueOf(2), aclAuthorizationStrategy, new ConsoleAuditLogger());
|
||||
ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, new Long(1));
|
||||
ObjectIdentity identityParent = new ObjectIdentityImpl(TARGET_CLASS, new Long(2));
|
||||
AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl(new GrantedAuthority[] {
|
||||
new GrantedAuthorityImpl("ROLE_OWNERSHIP"), new GrantedAuthorityImpl("ROLE_AUDITING"),
|
||||
new GrantedAuthorityImpl("ROLE_GENERAL") });
|
||||
MutableAcl acl = new AclImpl(identity, new Long(1), aclAuthorizationStrategy, new ConsoleAuditLogger());
|
||||
MutableAcl parentAcl = new AclImpl(identityParent, new Long(2), aclAuthorizationStrategy, new ConsoleAuditLogger());
|
||||
|
||||
acl.setParent(parentAcl);
|
||||
|
||||
@@ -234,17 +240,17 @@ public class EhCacheBasedAclCacheTests {
|
||||
}
|
||||
|
||||
// Check we can get from cache the same objects we put in
|
||||
AclImpl aclFromCache = (AclImpl) myCache.getFromCache(Long.valueOf(1));
|
||||
AclImpl aclFromCache = (AclImpl) myCache.getFromCache(new Long(1));
|
||||
// For the checks on transient fields, we need to be sure that the object is being loaded from the cache,
|
||||
// not from the ehcache spool or elsewhere...
|
||||
assertFalse(acl == aclFromCache);
|
||||
assertEquals(acl, aclFromCache);
|
||||
// SEC-951 check transient fields are set on parent
|
||||
assertNotNull(FieldUtils.getFieldValue(aclFromCache.getParentAcl(), "aclAuthorizationStrategy"));
|
||||
assertNotNull(FieldUtils.getFieldValue(aclFromCache.getParentAcl(), "permissionGrantingStrategy"));
|
||||
assertNotNull(FieldUtils.getFieldValue(aclFromCache.getParentAcl(), "auditLogger"));
|
||||
assertEquals(acl, myCache.getFromCache(identity));
|
||||
assertNotNull(FieldUtils.getFieldValue(aclFromCache, "aclAuthorizationStrategy"));
|
||||
AclImpl parentAclFromCache = (AclImpl) myCache.getFromCache(Long.valueOf(2));
|
||||
AclImpl parentAclFromCache = (AclImpl) myCache.getFromCache(new Long(2));
|
||||
assertEquals(parentAcl, parentAclFromCache);
|
||||
assertNotNull(FieldUtils.getFieldValue(parentAclFromCache, "aclAuthorizationStrategy"));
|
||||
assertEquals(parentAcl, myCache.getFromCache(identityParent));
|
||||
|
||||
+2
-3
@@ -4,7 +4,6 @@ import static org.junit.Assert.*;
|
||||
import static org.mockito.Matchers.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
@@ -54,8 +53,8 @@ public class SidRetrievalStrategyTests {
|
||||
@Test
|
||||
public void roleHierarchyIsUsedWhenSet() throws Exception {
|
||||
RoleHierarchy rh = mock(RoleHierarchy.class);
|
||||
List rhAuthorities = AuthorityUtils.createAuthorityList("D");
|
||||
when(rh.getReachableGrantedAuthorities(anyCollection())).thenReturn(rhAuthorities);
|
||||
List<GrantedAuthority> rhAuthorities = AuthorityUtils.createAuthorityList("D");
|
||||
when(rh.getReachableGrantedAuthorities(anyList())).thenReturn(rhAuthorities);
|
||||
SidRetrievalStrategy strat = new SidRetrievalStrategyImpl(rh);
|
||||
|
||||
List<Sid> sids = strat.getSids(authentication);
|
||||
|
||||
@@ -2,13 +2,14 @@ package org.springframework.security.acls.sid;
|
||||
|
||||
import junit.framework.Assert;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.security.acls.domain.GrantedAuthoritySid;
|
||||
import org.springframework.security.acls.domain.PrincipalSid;
|
||||
import org.springframework.security.acls.model.Sid;
|
||||
import org.springframework.security.authentication.TestingAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.authority.GrantedAuthorityImpl;
|
||||
|
||||
public class SidTests extends TestCase {
|
||||
|
||||
@@ -108,7 +109,7 @@ public class SidTests extends TestCase {
|
||||
}
|
||||
|
||||
try {
|
||||
GrantedAuthority ga = new SimpleGrantedAuthority(null);
|
||||
GrantedAuthority ga = new GrantedAuthorityImpl(null);
|
||||
new GrantedAuthoritySid(ga);
|
||||
Assert.fail("It should have thrown IllegalArgumentException");
|
||||
}
|
||||
@@ -117,7 +118,7 @@ public class SidTests extends TestCase {
|
||||
}
|
||||
|
||||
try {
|
||||
GrantedAuthority ga = new SimpleGrantedAuthority("ROLE_TEST");
|
||||
GrantedAuthority ga = new GrantedAuthorityImpl("ROLE_TEST");
|
||||
new GrantedAuthoritySid(ga);
|
||||
Assert.assertTrue(true);
|
||||
}
|
||||
@@ -141,15 +142,15 @@ public class SidTests extends TestCase {
|
||||
}
|
||||
|
||||
public void testGrantedAuthoritySidEquals() throws Exception {
|
||||
GrantedAuthority ga = new SimpleGrantedAuthority("ROLE_TEST");
|
||||
GrantedAuthority ga = new GrantedAuthorityImpl("ROLE_TEST");
|
||||
Sid gaSid = new GrantedAuthoritySid(ga);
|
||||
|
||||
Assert.assertFalse(gaSid.equals(null));
|
||||
Assert.assertFalse(gaSid.equals("DIFFERENT_TYPE_OBJECT"));
|
||||
Assert.assertTrue(gaSid.equals(gaSid));
|
||||
Assert.assertTrue(gaSid.equals(new GrantedAuthoritySid(ga)));
|
||||
Assert.assertTrue(gaSid.equals(new GrantedAuthoritySid(new SimpleGrantedAuthority("ROLE_TEST"))));
|
||||
Assert.assertFalse(gaSid.equals(new GrantedAuthoritySid(new SimpleGrantedAuthority("ROLE_NOT_EQUAL"))));
|
||||
Assert.assertTrue(gaSid.equals(new GrantedAuthoritySid(new GrantedAuthorityImpl("ROLE_TEST"))));
|
||||
Assert.assertFalse(gaSid.equals(new GrantedAuthoritySid(new GrantedAuthorityImpl("ROLE_NOT_EQUAL"))));
|
||||
Assert.assertTrue(gaSid.equals(new GrantedAuthoritySid("ROLE_TEST")));
|
||||
Assert.assertFalse(gaSid.equals(new GrantedAuthoritySid("ROLE_NOT_EQUAL")));
|
||||
}
|
||||
@@ -158,26 +159,26 @@ public class SidTests extends TestCase {
|
||||
Authentication authentication = new TestingAuthenticationToken("johndoe", "password");
|
||||
Sid principalSid = new PrincipalSid(authentication);
|
||||
|
||||
Assert.assertTrue(principalSid.hashCode() == "johndoe".hashCode());
|
||||
Assert.assertTrue(principalSid.hashCode() == new String("johndoe").hashCode());
|
||||
Assert.assertTrue(principalSid.hashCode() == new PrincipalSid("johndoe").hashCode());
|
||||
Assert.assertTrue(principalSid.hashCode() != new PrincipalSid("scott").hashCode());
|
||||
Assert.assertTrue(principalSid.hashCode() != new PrincipalSid(new TestingAuthenticationToken("scott", "password")).hashCode());
|
||||
}
|
||||
|
||||
public void testGrantedAuthoritySidHashCode() throws Exception {
|
||||
GrantedAuthority ga = new SimpleGrantedAuthority("ROLE_TEST");
|
||||
GrantedAuthority ga = new GrantedAuthorityImpl("ROLE_TEST");
|
||||
Sid gaSid = new GrantedAuthoritySid(ga);
|
||||
|
||||
Assert.assertTrue(gaSid.hashCode() == "ROLE_TEST".hashCode());
|
||||
Assert.assertTrue(gaSid.hashCode() == new String("ROLE_TEST").hashCode());
|
||||
Assert.assertTrue(gaSid.hashCode() == new GrantedAuthoritySid("ROLE_TEST").hashCode());
|
||||
Assert.assertTrue(gaSid.hashCode() != new GrantedAuthoritySid("ROLE_TEST_2").hashCode());
|
||||
Assert.assertTrue(gaSid.hashCode() != new GrantedAuthoritySid(new SimpleGrantedAuthority("ROLE_TEST_2")).hashCode());
|
||||
Assert.assertTrue(gaSid.hashCode() != new GrantedAuthoritySid(new GrantedAuthorityImpl("ROLE_TEST_2")).hashCode());
|
||||
}
|
||||
|
||||
public void testGetters() throws Exception {
|
||||
Authentication authentication = new TestingAuthenticationToken("johndoe", "password");
|
||||
PrincipalSid principalSid = new PrincipalSid(authentication);
|
||||
GrantedAuthority ga = new SimpleGrantedAuthority("ROLE_TEST");
|
||||
GrantedAuthority ga = new GrantedAuthorityImpl("ROLE_TEST");
|
||||
GrantedAuthoritySid gaSid = new GrantedAuthoritySid(ga);
|
||||
|
||||
Assert.assertTrue("johndoe".equals(principalSid.getPrincipal()));
|
||||
|
||||
@@ -36,13 +36,13 @@
|
||||
<bean id="aclAuthorizationStrategy" class="org.springframework.security.acls.domain.AclAuthorizationStrategyImpl">
|
||||
<constructor-arg>
|
||||
<list>
|
||||
<bean class="org.springframework.security.core.authority.SimpleGrantedAuthority">
|
||||
<bean class="org.springframework.security.core.authority.GrantedAuthorityImpl">
|
||||
<constructor-arg value="ROLE_ADMINISTRATOR"/>
|
||||
</bean>
|
||||
<bean class="org.springframework.security.core.authority.SimpleGrantedAuthority">
|
||||
<bean class="org.springframework.security.core.authority.GrantedAuthorityImpl">
|
||||
<constructor-arg value="ROLE_ADMINISTRATOR"/>
|
||||
</bean>
|
||||
<bean class="org.springframework.security.core.authority.SimpleGrantedAuthority">
|
||||
<bean class="org.springframework.security.core.authority.GrantedAuthorityImpl">
|
||||
<constructor-arg value="ROLE_ADMINISTRATOR"/>
|
||||
</bean>
|
||||
</list>
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
<configuration>
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<logger name="org.springframework.security" level="${sec.log.level}:-WARN"/>
|
||||
|
||||
<root level="${root.level}:-WARN">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</root>
|
||||
|
||||
</configuration>
|
||||
+12
-13
@@ -5,19 +5,18 @@ Bundle-Name: Spring Security Acls
|
||||
Bundle-Vendor: SpringSource
|
||||
Bundle-Version: ${version}
|
||||
Bundle-ManifestVersion: 2
|
||||
Ignored-Existing-Headers:
|
||||
Ignored-Existing-Headers:
|
||||
Import-Package,
|
||||
Export-Package
|
||||
Import-Template:
|
||||
org.aopalliance.*;version="${aopAllianceRange}",
|
||||
org.apache.commons.logging.*;version="${cloggingRange}",
|
||||
org.springframework.security.core.*;version="${secRange}",
|
||||
org.springframework.security.access.*;version="${secRange}",
|
||||
org.springframework.security.util.*;version="${secRange}",
|
||||
org.springframework.context.*;version="${secRange}";resolution:=optional,
|
||||
org.springframework.dao.*;version="${springRange}";resolution:=optional,
|
||||
org.springframework.jdbc.core.*;version="${springRange}";resolution:=optional,
|
||||
org.springframework.transaction.support.*;version="${springRange}";resolution:=optional,
|
||||
org.springframework.util.*;version="${springRange}";resolution:=optional,
|
||||
net.sf.ehcache.*;version="${ehcacheRange}";resolution:=optional,
|
||||
Import-Template:
|
||||
org.apache.commons.logging.*;version="[1.0.4, 2.0.0)",
|
||||
org.springframework.security.core.*;version="[${version}, 3.1.0)",
|
||||
org.springframework.security.access.*;version="[${version}, 3.1.0)",
|
||||
org.springframework.security.util.*;version="[${version}, 3.1.0)",
|
||||
org.springframework.context.*;version="[${spring.version}, 3.1.0)";resolution:=optional,
|
||||
org.springframework.dao.*;version="[${spring.version}, 3.1.0)";resolution:=optional,
|
||||
org.springframework.jdbc.core.*;version="[${spring.version}, 3.1.0)";resolution:=optional,
|
||||
org.springframework.transaction.support.*;version="[${spring.version}, 3.1.0)";resolution:=optional,
|
||||
org.springframework.util.*;version="[${spring.version}, 3.1.0)";resolution:=optional,
|
||||
net.sf.ehcache.*;version="[1.4.1, 2.0.0)";resolution:=optional,
|
||||
javax.sql.*;version="0";resolution:=optional
|
||||
|
||||
@@ -3,6 +3,4 @@ dependencies {
|
||||
compile project(':spring-security-core'),
|
||||
"org.springframework:spring-beans:$springVersion",
|
||||
"org.springframework:spring-context:$springVersion"
|
||||
|
||||
testCompile 'aopalliance:aopalliance:1.0'
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-parent</artifactId>
|
||||
<version>3.0.4.RELEASE</version>
|
||||
</parent>
|
||||
<packaging>jar</packaging>
|
||||
<artifactId>spring-security-aspects</artifactId>
|
||||
<name>Spring Security - Aspects</name>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.aspectj</groupId>
|
||||
<artifactId>aspectjweaver</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-core</artifactId>
|
||||
<version>3.0.4.RELEASE</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>aspectj-maven-plugin</artifactId>
|
||||
<version>1.2</version>
|
||||
<dependencies>
|
||||
<!--
|
||||
NB: You must use Maven 2.0.9 or above or these
|
||||
are ignored (see MNG-2972)
|
||||
-->
|
||||
<dependency>
|
||||
<groupId>org.aspectj</groupId>
|
||||
<artifactId>aspectjrt</artifactId>
|
||||
<version>1.6.8</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.aspectj</groupId>
|
||||
<artifactId>aspectjtools</artifactId>
|
||||
<version>1.6.8</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>compile</goal>
|
||||
<goal>test-compile</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<source>1.5</source>
|
||||
<target>1.5</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
+9
-89
@@ -1,10 +1,6 @@
|
||||
package org.springframework.security.access.intercept.aspectj.aspect;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
@@ -18,17 +14,12 @@ import org.springframework.security.access.annotation.Secured;
|
||||
import org.springframework.security.access.annotation.SecuredAnnotationSecurityMetadataSource;
|
||||
import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler;
|
||||
import org.springframework.security.access.expression.method.ExpressionBasedAnnotationAttributeFactory;
|
||||
import org.springframework.security.access.expression.method.ExpressionBasedPostInvocationAdvice;
|
||||
import org.springframework.security.access.expression.method.ExpressionBasedPreInvocationAdvice;
|
||||
import org.springframework.security.access.intercept.AfterInvocationProviderManager;
|
||||
import org.springframework.security.access.intercept.aspectj.AspectJMethodSecurityInterceptor;
|
||||
import org.springframework.security.access.prepost.PostFilter;
|
||||
import org.springframework.security.access.prepost.PostInvocationAdviceProvider;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.security.access.prepost.PreInvocationAuthorizationAdviceVoter;
|
||||
import org.springframework.security.access.prepost.PrePostAnnotationSecurityMetadataSource;
|
||||
import org.springframework.security.access.vote.AffirmativeBased;
|
||||
import org.springframework.security.access.vote.RoleVoter;
|
||||
import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.TestingAuthenticationToken;
|
||||
@@ -40,23 +31,18 @@ import org.springframework.security.core.context.SecurityContextHolder;
|
||||
* @since 3.0.3
|
||||
*/
|
||||
public class AnnotationSecurityAspectTests {
|
||||
private AffirmativeBased adm;
|
||||
private @Mock AccessDecisionManager adm;
|
||||
private @Mock AuthenticationManager authman;
|
||||
private TestingAuthenticationToken anne = new TestingAuthenticationToken("anne", "", "ROLE_A");
|
||||
// private TestingAuthenticationToken bob = new TestingAuthenticationToken("bob", "", "ROLE_B");
|
||||
private AspectJMethodSecurityInterceptor interceptor;
|
||||
private SecuredImpl secured = new SecuredImpl();
|
||||
private SecuredImplSubclass securedSub = new SecuredImplSubclass();
|
||||
private PrePostSecured prePostSecured = new PrePostSecured();
|
||||
|
||||
@Before
|
||||
public final void setUp() throws Exception {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
interceptor = new AspectJMethodSecurityInterceptor();
|
||||
adm = new AffirmativeBased();
|
||||
AccessDecisionVoter[] voters = new AccessDecisionVoter[]
|
||||
{new RoleVoter(), new PreInvocationAuthorizationAdviceVoter(new ExpressionBasedPreInvocationAdvice())};
|
||||
adm.setDecisionVoters(Arrays.asList(voters));
|
||||
interceptor.setAccessDecisionManager(adm);
|
||||
interceptor.setAuthenticationManager(authman);
|
||||
interceptor.setSecurityMetadataSource(new SecuredAnnotationSecurityMetadataSource());
|
||||
@@ -85,57 +71,18 @@ public class AnnotationSecurityAspectTests {
|
||||
secured.securedClassMethod();
|
||||
}
|
||||
|
||||
@Test(expected=AccessDeniedException.class)
|
||||
public void internalPrivateCallIsIntercepted() {
|
||||
SecurityContextHolder.getContext().setAuthentication(anne);
|
||||
|
||||
try {
|
||||
secured.publicCallsPrivate();
|
||||
fail("Expected AccessDeniedException");
|
||||
} catch (AccessDeniedException expected) {
|
||||
}
|
||||
securedSub.publicCallsPrivate();
|
||||
}
|
||||
|
||||
@Test(expected=AccessDeniedException.class)
|
||||
public void protectedMethodIsIntercepted() throws Exception {
|
||||
SecurityContextHolder.getContext().setAuthentication(anne);
|
||||
|
||||
secured.protectedMethod();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void overriddenProtectedMethodIsNotIntercepted() throws Exception {
|
||||
// AspectJ doesn't inherit annotations
|
||||
securedSub.protectedMethod();
|
||||
}
|
||||
|
||||
// SEC-1262
|
||||
@Test(expected=AccessDeniedException.class)
|
||||
public void denyAllPreAuthorizeDeniesAccess() throws Exception {
|
||||
configureForElAnnotations();
|
||||
SecurityContextHolder.getContext().setAuthentication(anne);
|
||||
prePostSecured.denyAllMethod();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void postFilterIsApplied() throws Exception {
|
||||
configureForElAnnotations();
|
||||
SecurityContextHolder.getContext().setAuthentication(anne);
|
||||
List<String> objects = prePostSecured.postFilterMethod();
|
||||
assertEquals(2, objects.size());
|
||||
assertTrue(objects.contains("apple"));
|
||||
assertTrue(objects.contains("aubergine"));
|
||||
}
|
||||
|
||||
private void configureForElAnnotations() {
|
||||
DefaultMethodSecurityExpressionHandler eh = new DefaultMethodSecurityExpressionHandler();
|
||||
interceptor.setSecurityMetadataSource(new PrePostAnnotationSecurityMetadataSource(
|
||||
new ExpressionBasedAnnotationAttributeFactory(eh)));
|
||||
new ExpressionBasedAnnotationAttributeFactory(new DefaultMethodSecurityExpressionHandler())));
|
||||
AffirmativeBased adm = new AffirmativeBased();
|
||||
AccessDecisionVoter[] voters = new AccessDecisionVoter[]
|
||||
{new PreInvocationAuthorizationAdviceVoter(new ExpressionBasedPreInvocationAdvice())};
|
||||
adm.setDecisionVoters(Arrays.asList(voters));
|
||||
interceptor.setAccessDecisionManager(adm);
|
||||
AfterInvocationProviderManager aim = new AfterInvocationProviderManager();
|
||||
aim.setProviders(Arrays.asList(new PostInvocationAdviceProvider(new ExpressionBasedPostInvocationAdvice(eh))));
|
||||
interceptor.setAfterInvocationManager(aim);
|
||||
prePostSecured.denyAllMethod();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,6 +92,7 @@ interface SecuredInterface {
|
||||
}
|
||||
|
||||
class SecuredImpl implements SecuredInterface {
|
||||
|
||||
// Not really secured because AspectJ doesn't inherit annotations from interfaces
|
||||
public void securedMethod() {
|
||||
}
|
||||
@@ -152,39 +100,11 @@ class SecuredImpl implements SecuredInterface {
|
||||
@Secured("ROLE_A")
|
||||
public void securedClassMethod() {
|
||||
}
|
||||
|
||||
@Secured("ROLE_X")
|
||||
private void privateMethod() {
|
||||
}
|
||||
|
||||
@Secured("ROLE_X")
|
||||
protected void protectedMethod() {
|
||||
}
|
||||
|
||||
@Secured("ROLE_X")
|
||||
public void publicCallsPrivate() {
|
||||
privateMethod();
|
||||
}
|
||||
}
|
||||
|
||||
class SecuredImplSubclass extends SecuredImpl {
|
||||
protected void protectedMethod() {
|
||||
}
|
||||
|
||||
public void publicCallsPrivate() {
|
||||
super.publicCallsPrivate();
|
||||
}
|
||||
}
|
||||
|
||||
class PrePostSecured {
|
||||
|
||||
@PreAuthorize("denyAll")
|
||||
public void denyAllMethod() {
|
||||
}
|
||||
|
||||
@PostFilter("filterObject.startsWith('a')")
|
||||
public List<String> postFilterMethod() {
|
||||
ArrayList<String> objects = new ArrayList<String>();
|
||||
objects.addAll(Arrays.asList(new String[] {"apple", "banana", "aubergine", "orange"}));
|
||||
return objects;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
Implementation-Title: org.springframework.security.aspects
|
||||
Implementation-Version: ${version}
|
||||
Bundle-SymbolicName: org.springframework.security.aspects
|
||||
Bundle-Name: Spring Security Aspects
|
||||
Bundle-Vendor: SpringSource
|
||||
Bundle-ManifestVersion: 2
|
||||
Bundle-Version: ${version}
|
||||
Ignored-Existing-Headers:
|
||||
Import-Package,
|
||||
Export-Package
|
||||
Import-Template:
|
||||
org.aspectj.*;version="${aspectjRange}";resolution:=optional,
|
||||
org.apache.commons.logging.*;version="${cloggingRange}",
|
||||
org.springframework.security.core.*;version="${secRange}",
|
||||
org.springframework.security.access.intercept.aspectj;version="${secRange}",
|
||||
org.springframework.beans.factory;version="${springRange}"
|
||||
+163
-36
@@ -1,63 +1,120 @@
|
||||
apply plugin: 'base'
|
||||
|
||||
description = 'Spring Security'
|
||||
|
||||
allprojects {
|
||||
version = '3.1.0.RELEASE'
|
||||
version = '3.0.4.CI-SNAPSHOT'
|
||||
releaseBuild = version.endsWith('RELEASE')
|
||||
snapshotBuild = version.endsWith('SNAPSHOT')
|
||||
|
||||
group = 'org.springframework.security'
|
||||
|
||||
repositories {
|
||||
mavenLocal()
|
||||
mavenRepo name:'Local', urls: "file://" + System.properties['user.home'] + "/.m2/repository"
|
||||
mavenCentral()
|
||||
mavenRepo name: 'SpringSource Milestone Repo', urls: 'http://repository.springsource.com/maven/bundles/milestone'
|
||||
mavenRepo name: 'SpringSource Maven Snapshot Repo', urls: 'http://maven.springframework.org/snapshot/'
|
||||
mavenRepo name: 'SpringSource Enterprise Release', urls: 'http://repository.springsource.com/maven/bundles/release'
|
||||
mavenRepo name: 'SpringSource Enterprise External', urls: 'http://repository.springsource.com/maven/bundles/external'
|
||||
}
|
||||
}
|
||||
|
||||
// Set up different subproject lists for individual configuration
|
||||
javaProjects = subprojects.findAll { project -> project.name != 'docs' && project.name != 'faq' && project.name != 'manual' }
|
||||
sampleProjects = subprojects.findAll { project -> project.name.startsWith('spring-security-samples') }
|
||||
itestProjects = subprojects.findAll { project -> project.name.startsWith('itest') }
|
||||
coreModuleProjects = javaProjects - sampleProjects - itestProjects
|
||||
aspectjProjects = [project(':spring-security-aspects'), project(':spring-security-samples-aspectj')]
|
||||
|
||||
configure(javaProjects) {
|
||||
apply from: "$rootDir/gradle/javaprojects.gradle"
|
||||
apply from: "$rootDir/gradle/maven.gradle"
|
||||
}
|
||||
|
||||
configure(coreModuleProjects) {
|
||||
apply from: "$rootDir/gradle/bundlor.gradle"
|
||||
// Gives better names in structure101 jar diagram
|
||||
sourceSets.main.classesDir = new File(buildDir, "classes/" + project.name.substring("spring-security".length() + 1))
|
||||
apply plugin: 'bundlor'
|
||||
bundlor.expansions = bundlorProperties
|
||||
apply from: "$rootDir/gradle/maven-deployment.gradle"
|
||||
apply plugin: 'emma'
|
||||
}
|
||||
|
||||
task coreBuild {
|
||||
dependsOn coreModuleProjects*.tasks*.matching { task -> task.name == 'build' }
|
||||
}
|
||||
|
||||
configure (aspectjProjects) {
|
||||
apply plugin: 'aspectj'
|
||||
apply from: "$rootDir/gradle/aspectj.gradle"
|
||||
}
|
||||
|
||||
// Task for creating the distro zip
|
||||
configurations {
|
||||
antlibs
|
||||
}
|
||||
|
||||
dependencies {
|
||||
antlibs "org.springframework.build:org.springframework.build.aws.ant:3.0.3.RELEASE",
|
||||
"net.java.dev.jets3t:jets3t:0.6.1"
|
||||
}
|
||||
|
||||
task apidocs(type: Javadoc) {
|
||||
destinationDir = new File(buildDir, 'apidocs')
|
||||
title = "Spring Security $version API"
|
||||
optionsFile = file("$buildDir/tmp/javadoc.options")
|
||||
|
||||
source coreModuleProjects.collect {project ->
|
||||
project.sourceSets.main.allJava
|
||||
}
|
||||
|
||||
classpath = files(coreModuleProjects.collect {project ->
|
||||
project.sourceSets.main.compileClasspath
|
||||
})
|
||||
}
|
||||
|
||||
task docSiteLogin(type: Login) {
|
||||
if (project.hasProperty('sshHost')) {
|
||||
host = project.property('sshHost')
|
||||
}
|
||||
}
|
||||
|
||||
// Define remoteSiteDir and sshHost in gradle.properties
|
||||
def remoteDocsDir = null
|
||||
|
||||
if (hasProperty('remoteSiteDir')) {
|
||||
remoteDocsDir="$remoteSiteDir/docs/3.0.x"
|
||||
}
|
||||
|
||||
task uploadApidocs(type: TarUpload) {
|
||||
dependsOn apidocs
|
||||
classifier = 'apidocs'
|
||||
remoteDir = remoteDocsDir
|
||||
login = docSiteLogin
|
||||
|
||||
into('apidocs') {
|
||||
from apidocs.destinationDir
|
||||
}
|
||||
}
|
||||
|
||||
def docsDir = new File(project(':manual').buildDir, 'docs')
|
||||
|
||||
task uploadDoc(type: TarUpload) {
|
||||
dependsOn ':manual:doc'
|
||||
classifier = 'doc'
|
||||
remoteDir = remoteDocsDir
|
||||
login = docSiteLogin
|
||||
|
||||
into('reference') {
|
||||
from docsDir
|
||||
}
|
||||
}
|
||||
|
||||
task uploadFaq(type: TarUpload) {
|
||||
dependsOn ':faq:docbookHtmlSingle'
|
||||
classifier = 'faq'
|
||||
if (project.hasProperty('remoteSiteDir')) {
|
||||
remoteDir = project.property('remoteSiteDir')
|
||||
}
|
||||
login = docSiteLogin
|
||||
|
||||
def faqDir = new File(project(':faq').buildDir, 'docs')
|
||||
|
||||
into('faq') {
|
||||
from faqDir
|
||||
}
|
||||
}
|
||||
|
||||
task dist(type: Zip) {
|
||||
dependsOn subprojects*.tasks*.matching { task -> task.name == 'assemble' }
|
||||
|
||||
evaluationDependsOn(':docs')
|
||||
|
||||
def zipRootDir = "${project.name}-$version"
|
||||
into(zipRootDir) {
|
||||
from(rootDir) {
|
||||
include '*.txt'
|
||||
into('docs/apidocs') {
|
||||
from apidocs.destinationDir
|
||||
}
|
||||
into('docs') {
|
||||
with(project(':docs').apiSpec)
|
||||
with(project(':docs:manual').spec)
|
||||
into('docs/reference') {
|
||||
from docsDir
|
||||
}
|
||||
into('dist') {
|
||||
from coreModuleProjects.collect {project -> project.libsDir }
|
||||
@@ -67,13 +124,83 @@ task dist(type: Zip) {
|
||||
}
|
||||
}
|
||||
|
||||
task uploadDist(type: S3DistroUpload) {
|
||||
dist {
|
||||
dependsOn apidocs, ':manual:doc', subprojects.collect { "$it.path:assemble" }
|
||||
doLast {
|
||||
ant.checksum(file: archivePath, algorithm: 'SHA1', fileext: '.sha1')
|
||||
}
|
||||
}
|
||||
|
||||
task uploadDist(type: UploadDist) {
|
||||
archiveFile = dist.archivePath
|
||||
projectKey = 'SEC'
|
||||
shaFile = "${dist.archivePath}.sha1" as File
|
||||
archiveName = dist.archiveName
|
||||
classpath = configurations.antlibs
|
||||
}
|
||||
|
||||
apply from: "$rootDir/gradle/ide-integration.gradle"
|
||||
|
||||
task wrapper(type: Wrapper) {
|
||||
gradleVersion = '1.0-milestone-3'
|
||||
def getJavaProjects() {
|
||||
subprojects.findAll {project -> project.name != 'faq' && project.name != 'manual' }
|
||||
}
|
||||
|
||||
def getSampleProjects() {
|
||||
subprojects.findAll {project -> project.name.startsWith('spring-security-samples') }
|
||||
}
|
||||
|
||||
def getItestProjects() {
|
||||
subprojects.findAll {project -> project.name.startsWith('itest') }
|
||||
}
|
||||
|
||||
def getCoreModuleProjects() {
|
||||
javaProjects - sampleProjects - itestProjects - aspectjProjects
|
||||
}
|
||||
|
||||
def getAspectjProjects() {
|
||||
subprojects.findAll {project -> project.name == 'spring-security-aspects' || project.name == 'spring-security-samples-aspectj'}
|
||||
}
|
||||
|
||||
class UploadDist extends DefaultTask {
|
||||
@InputFile
|
||||
File shaFile
|
||||
|
||||
@InputFile
|
||||
File archiveFile
|
||||
|
||||
@Input
|
||||
String archiveName
|
||||
|
||||
@InputFiles
|
||||
def classpath
|
||||
|
||||
@TaskAction
|
||||
def upload() {
|
||||
def accessKey = project.s3AccessKey
|
||||
def secretKey = project.s3SecretAccessKey
|
||||
def version = project.version
|
||||
|
||||
project.ant {
|
||||
taskdef(resource: 'org/springframework/build/aws/ant/antlib.xml', classpath: classpath.asPath)
|
||||
s3(accessKey: accessKey, secretKey: secretKey) {
|
||||
upload(bucketName: 'dist.springframework.org', file: archiveFile,
|
||||
toFile: releaseType() + "/SEC/${archiveName}", publicRead: 'true') {
|
||||
metadata(name: 'project.name', value: 'Spring Security')
|
||||
metadata(name: 'release.type', value: releaseType())
|
||||
metadata(name: 'bundle.version', value: version)
|
||||
metadata(name: 'package.file.name', value: archiveName)
|
||||
}
|
||||
upload(bucketName: 'dist.springframework.org', file: shaFile,
|
||||
toFile: releaseType() + "/SEC/${archiveName}.sha1", publicRead: 'true')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def releaseType() {
|
||||
if (project.releaseBuild) {
|
||||
'release'
|
||||
} else if (project.snapshotBuild) {
|
||||
'snapshot'
|
||||
} else {
|
||||
'milestone'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+4
-28
@@ -1,13 +1,11 @@
|
||||
apply plugin: 'groovy'
|
||||
|
||||
repositories {
|
||||
mavenLocal()
|
||||
mavenRepo name:'localRepo', urls: "file://" + System.properties['user.home'] + "/.m2/repository"
|
||||
mavenCentral()
|
||||
mavenRepo name: 'SpringSource Enterprise Release', urls: 'http://repository.springsource.com/maven/bundles/release'
|
||||
mavenRepo name: 'SpringSource Enterprise External', urls: 'http://repository.springsource.com/maven/bundles/external'
|
||||
mavenRepo name:'Shibboleth Repo', urls:'http://shibboleth.internet2.edu/downloads/maven2'
|
||||
}
|
||||
|
||||
// Docbook Plugin
|
||||
dependencies {
|
||||
def fopDeps = [ 'org.apache.xmlgraphics:fop:0.95-1@jar',
|
||||
'org.apache.xmlgraphics:xmlgraphics-commons:1.3',
|
||||
@@ -19,38 +17,16 @@ dependencies {
|
||||
'org.apache.avalon.framework:avalon-framework-api:4.3.1']
|
||||
groovy localGroovy()
|
||||
compile gradleApi(),
|
||||
'xml-resolver:xml-resolver:1.2',
|
||||
'xerces:xercesImpl:2.9.1',
|
||||
'org.apache.xerces:resolver:2.9.1',
|
||||
'saxon:saxon:6.5.3',
|
||||
'net.java.dev.jets3t:jets3t:0.6.1',
|
||||
'org.apache.xerces:xercesImpl:2.9.1',
|
||||
fopDeps
|
||||
|
||||
runtime 'net.sf.xslthl:xslthl:2.0.1',
|
||||
'net.sf.docbook:docbook-xsl:1.75.2:ns-resources@zip'
|
||||
}
|
||||
|
||||
// GAE
|
||||
dependencies {
|
||||
compile 'com.google.appengine:appengine-tools-sdk:1.4.2'
|
||||
}
|
||||
|
||||
dependencies{
|
||||
compile "emma:emma:2.0.5312"
|
||||
}
|
||||
|
||||
// Bundlor
|
||||
dependencies {
|
||||
compile 'com.springsource.bundlor:com.springsource.bundlor:1.0.0.RELEASE',
|
||||
'com.springsource.bundlor:com.springsource.bundlor.blint:1.0.0.RELEASE'
|
||||
}
|
||||
|
||||
task ide(type: Copy) {
|
||||
from configurations.runtime
|
||||
into 'ide'
|
||||
}
|
||||
|
||||
apply plugin: 'idea'
|
||||
|
||||
ideaModule {
|
||||
excludeDirs += file('.gradle')
|
||||
}
|
||||
|
||||
@@ -1,92 +0,0 @@
|
||||
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.tasks.InputFile
|
||||
import org.gradle.api.tasks.Input
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
import org.jets3t.service.security.AWSCredentials
|
||||
import org.jets3t.service.impl.rest.httpclient.RestS3Service
|
||||
import org.jets3t.service.S3Service
|
||||
import org.jets3t.service.model.S3Bucket
|
||||
import org.jets3t.service.model.S3Object
|
||||
import org.jets3t.service.acl.AccessControlList
|
||||
|
||||
/**
|
||||
* @author Luke Taylor
|
||||
*/
|
||||
class S3DistroUpload extends DefaultTask {
|
||||
@InputFile
|
||||
File archiveFile
|
||||
|
||||
@Input
|
||||
String bucketName = 'dist.springframework.org'
|
||||
|
||||
// 'Spring Security'
|
||||
@Input
|
||||
String projectName = project.description
|
||||
|
||||
// e.g 'SEC'
|
||||
@Input
|
||||
String projectKey
|
||||
|
||||
@TaskAction
|
||||
def upload() {
|
||||
def accessKey = project.s3AccessKey
|
||||
def secretKey = project.s3SecretAccessKey
|
||||
def version = project.version.toString()
|
||||
|
||||
assert version.length() > 0
|
||||
assert accessKey.length() > 0
|
||||
assert secretKey.length() > 0
|
||||
assert projectName.length() > 0
|
||||
|
||||
assert archiveFile.exists()
|
||||
|
||||
String archiveName = archiveFile.getName()
|
||||
|
||||
logger.info("Creating SHA checksum file...")
|
||||
project.ant.checksum(file: archiveFile, algorithm: 'SHA1', fileext: '.sha1', forceoverwrite: 'true')
|
||||
File shaFile = "${archiveFile}.sha1" as File
|
||||
|
||||
assert shaFile.exists()
|
||||
|
||||
AWSCredentials creds = new AWSCredentials(accessKey, secretKey);
|
||||
S3Service s3 = new RestS3Service(creds)
|
||||
S3Bucket bucket = new S3Bucket(bucketName)
|
||||
|
||||
String releaseType = releaseType(version)
|
||||
|
||||
String key = releaseType + '/' + projectKey + '/' + archiveName
|
||||
|
||||
S3Object archiveDest = new S3Object(bucket, key)
|
||||
archiveDest.setAcl(AccessControlList.REST_CANNED_PUBLIC_READ)
|
||||
archiveDest.setDataInputFile(archiveFile)
|
||||
archiveDest.setContentLength(archiveFile.length())
|
||||
archiveDest.addMetadata('project.name', projectName)
|
||||
archiveDest.addMetadata('bundle.version', version)
|
||||
archiveDest.addMetadata('release.type', releaseType)
|
||||
archiveDest.addMetadata('package.file.name', archiveName)
|
||||
|
||||
logger.info("Uploading archive " + archiveFile.getName() + " to " + archiveDest + "...")
|
||||
s3.putObject(bucket, archiveDest)
|
||||
logger.info("Done")
|
||||
|
||||
S3Object shaDest = new S3Object(bucket, key + '.sha1')
|
||||
shaDest.setAcl(AccessControlList.REST_CANNED_PUBLIC_READ)
|
||||
shaDest.setDataInputFile(shaFile)
|
||||
shaDest.setContentLength(shaFile.length())
|
||||
|
||||
logger.info("Uploading SHA checksum " + shaFile.getName() + " to " + key + '.sha1' + "...")
|
||||
s3.putObject(bucket, shaDest);
|
||||
logger.info("Done")
|
||||
}
|
||||
|
||||
def releaseType(String version) {
|
||||
if (version.endsWith('RELEASE')) {
|
||||
'release'
|
||||
} else if (version.endsWith('SNAPSHOT')) {
|
||||
'snapshot'
|
||||
} else {
|
||||
'milestone'
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,23 +10,12 @@ import org.gradle.api.tasks.bundling.Compression;
|
||||
class TarUpload extends Tar {
|
||||
@Input
|
||||
String remoteDir
|
||||
Login login
|
||||
|
||||
@Input
|
||||
String host
|
||||
Login login
|
||||
|
||||
TarUpload() {
|
||||
compression = Compression.BZIP2
|
||||
if (project.configurations.findByName('antjsch') == null) {
|
||||
project.configurations.add('antjsch')
|
||||
project.dependencies {
|
||||
antjsch 'org.apache.ant:ant-jsch:1.8.1'
|
||||
}
|
||||
def classpath = project.configurations.antjsch.asPath
|
||||
project.ant {
|
||||
taskdef(name: 'scp', classname: 'org.apache.tools.ant.taskdefs.optional.ssh.Scp', classpath: classpath)
|
||||
taskdef(name: 'sshexec', classname: 'org.apache.tools.ant.taskdefs.optional.ssh.SSHExec', classpath: classpath)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@TaskAction
|
||||
@@ -49,7 +38,6 @@ class TarUpload extends Tar {
|
||||
void setLogin(Login login) {
|
||||
dependsOn(login)
|
||||
this.login = login
|
||||
this.host = login.host
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,12 +52,11 @@ class Login extends DefaultTask {
|
||||
|
||||
@TaskAction
|
||||
login() {
|
||||
def console = System.console()
|
||||
if (console) {
|
||||
username = console.readLine("\nPlease enter the ssh username for host '$host': ")
|
||||
password = new String(console.readPassword("Please enter the ssh password for '$host': "))
|
||||
} else {
|
||||
logger.error "Unable to access System.console()."
|
||||
project.ant {
|
||||
input("Please enter the ssh username for host '$host'", addproperty: "user.$host")
|
||||
input("Please enter the ssh password '$host'", addproperty: "pass.$host")
|
||||
}
|
||||
username = ant.properties["user.$host"]
|
||||
password = ant.properties["pass.$host"]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,100 +0,0 @@
|
||||
package aspectj
|
||||
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.Plugin
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
import org.gradle.api.logging.LogLevel
|
||||
import org.gradle.api.file.FileCollection
|
||||
import org.gradle.api.tasks.SourceSet
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.GradleException
|
||||
|
||||
import org.gradle.plugins.ide.eclipse.GenerateEclipseProject
|
||||
import org.gradle.plugins.ide.eclipse.GenerateEclipseClasspath
|
||||
import org.gradle.plugins.ide.eclipse.model.BuildCommand
|
||||
import org.gradle.tooling.model.ProjectDependency
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Luke Taylor
|
||||
*/
|
||||
class AspectJPlugin implements Plugin<Project> {
|
||||
|
||||
void apply(Project project) {
|
||||
if (!project.hasProperty('aspectjVersion')) {
|
||||
throw new GradleException("You must set the property 'aspectjVersion' before applying the aspectj plugin")
|
||||
}
|
||||
|
||||
if (project.configurations.findByName('ajtools') == null) {
|
||||
project.configurations.add('ajtools')
|
||||
project.dependencies {
|
||||
ajtools "org.aspectj:aspectjtools:${project.aspectjVersion}"
|
||||
compile "org.aspectj:aspectjrt:${project.aspectjVersion}"
|
||||
}
|
||||
}
|
||||
|
||||
if (project.configurations.findByName('aspectpath') == null) {
|
||||
project.configurations.add('aspectpath')
|
||||
}
|
||||
|
||||
project.tasks.add(name: 'compileJava', overwrite: true, description: 'Compiles AspectJ Source', type: Ajc) {
|
||||
dependsOn project.processResources
|
||||
sourceSet = project.sourceSets.main
|
||||
inputs.files(sourceSet.java.srcDirs)
|
||||
outputs.dir(sourceSet.classesDir)
|
||||
aspectPath = project.configurations.aspectpath
|
||||
}
|
||||
|
||||
project.tasks.add(name: 'compileTestJava', overwrite: true, description: 'Compiles AspectJ Test Source', type: Ajc) {
|
||||
dependsOn project.processTestResources, project.compileJava, project.jar
|
||||
sourceSet = project.sourceSets.test
|
||||
inputs.files(sourceSet.java.srcDirs)
|
||||
outputs.dir(sourceSet.classesDir)
|
||||
aspectPath = project.files(project.configurations.aspectpath, project.jar.archivePath)
|
||||
}
|
||||
|
||||
project.tasks.withType(GenerateEclipseProject).all {
|
||||
whenConfigured { p ->
|
||||
p.natures.add(0, 'org.eclipse.ajdt.ui.ajnature')
|
||||
p.buildCommands = [new BuildCommand('org.eclipse.ajdt.core.ajbuilder',[:])]
|
||||
}
|
||||
}
|
||||
|
||||
project.tasks.withType(GenerateEclipseClasspath).all {
|
||||
whenConfigured { classpath ->
|
||||
def entries = classpath.entries.findAll { it instanceof ProjectDependency}.findAll { entry ->
|
||||
def projectPath = entry.path.replaceAll('/',':')
|
||||
project.rootProject.findProject(projectPath).plugins.findPlugin(AspectJPlugin)
|
||||
}
|
||||
entries.each { entry->
|
||||
entry.entryAttributes.put('org.eclipse.ajdt.aspectpath','org.eclipse.ajdt.aspectpath')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Ajc extends DefaultTask {
|
||||
SourceSet sourceSet
|
||||
FileCollection aspectPath
|
||||
|
||||
Ajc() {
|
||||
logging.captureStandardOutput(LogLevel.INFO)
|
||||
}
|
||||
|
||||
@TaskAction
|
||||
def compile() {
|
||||
logger.info("Running ajc ...")
|
||||
ant.taskdef(resource: "org/aspectj/tools/ant/taskdefs/aspectjTaskdefs.properties", classpath: project.configurations.ajtools.asPath)
|
||||
ant.iajc(classpath: sourceSet.compileClasspath.asPath, fork: 'true', destDir: sourceSet.classesDir.absolutePath,
|
||||
source: project.convention.plugins.java.sourceCompatibility,
|
||||
target: project.convention.plugins.java.targetCompatibility,
|
||||
aspectPath: aspectPath.asPath, sourceRootCopyFilter: '**/*.java', showWeaveInfo: 'true') {
|
||||
sourceroots {
|
||||
sourceSet.java.srcDirs.each {
|
||||
pathelement(location: it.absolutePath)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,150 +0,0 @@
|
||||
package bundlor
|
||||
|
||||
import com.springsource.bundlor.ClassPath
|
||||
import com.springsource.bundlor.ManifestGenerator
|
||||
import com.springsource.bundlor.ManifestWriter
|
||||
import com.springsource.bundlor.blint.ManifestValidator
|
||||
import com.springsource.bundlor.blint.support.DefaultManifestValidatorContributorsFactory
|
||||
import com.springsource.bundlor.blint.support.StandardManifestValidator
|
||||
import com.springsource.bundlor.support.DefaultManifestGeneratorContributorsFactory
|
||||
import com.springsource.bundlor.support.StandardManifestGenerator
|
||||
import com.springsource.bundlor.support.classpath.FileSystemClassPath
|
||||
import com.springsource.bundlor.support.manifestwriter.FileSystemManifestWriter
|
||||
import com.springsource.bundlor.support.properties.EmptyPropertiesSource
|
||||
import com.springsource.bundlor.support.properties.FileSystemPropertiesSource
|
||||
import com.springsource.bundlor.support.properties.PropertiesPropertiesSource
|
||||
import com.springsource.bundlor.support.properties.PropertiesSource
|
||||
import com.springsource.bundlor.util.BundleManifestUtils
|
||||
import com.springsource.util.parser.manifest.ManifestContents
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.GradleException
|
||||
import org.gradle.api.Plugin
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.Task
|
||||
import org.gradle.api.file.FileCollection
|
||||
import org.gradle.api.logging.LogLevel
|
||||
import org.gradle.api.tasks.Input
|
||||
import org.gradle.api.tasks.InputFile
|
||||
import org.gradle.api.tasks.InputFiles
|
||||
import org.gradle.api.tasks.Optional
|
||||
import org.gradle.api.tasks.OutputDirectory
|
||||
import org.gradle.api.tasks.OutputFile
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
|
||||
/**
|
||||
* @author Luke Taylor
|
||||
*/
|
||||
class BundlorPlugin implements Plugin<Project> {
|
||||
void apply(Project project) {
|
||||
Task bundlor = project.tasks.add('bundlor', Bundlor.class)
|
||||
bundlor.setDescription('Generates OSGi manifest using bundlor tool')
|
||||
bundlor.dependsOn(project.classes)
|
||||
project.jar.dependsOn bundlor
|
||||
}
|
||||
}
|
||||
|
||||
public class Bundlor extends DefaultTask {
|
||||
@InputFile
|
||||
@Optional
|
||||
File manifestTemplate
|
||||
|
||||
@OutputDirectory
|
||||
File bundlorDir = new File("${project.buildDir}/bundlor")
|
||||
|
||||
@OutputFile
|
||||
File manifest = project.file("${bundlorDir}/META-INF/MANIFEST.MF")
|
||||
|
||||
@Input
|
||||
Map<String,String> expansions = [:]
|
||||
|
||||
@InputFile
|
||||
@Optional
|
||||
File osgiProfile
|
||||
|
||||
@InputFiles
|
||||
@Optional
|
||||
FileCollection inputPaths
|
||||
|
||||
@Input
|
||||
boolean failOnWarnings = false
|
||||
|
||||
Bundlor() {
|
||||
manifestTemplate = new File(project.projectDir, 'template.mf')
|
||||
|
||||
if (!manifestTemplate.exists()) {
|
||||
logger.info("No bundlor template for project " + project.name)
|
||||
manifestTemplate = null
|
||||
}
|
||||
|
||||
inputPaths = project.files(project.sourceSets.main.classesDir)
|
||||
|
||||
if (manifestTemplate != null) {
|
||||
project.jar.manifest.from manifest
|
||||
project.jar.inputs.files manifest
|
||||
}
|
||||
}
|
||||
|
||||
@TaskAction
|
||||
void createManifest() {
|
||||
if (manifestTemplate == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
logging.captureStandardOutput(LogLevel.INFO)
|
||||
|
||||
project.mkdir(bundlorDir)
|
||||
|
||||
//String inputPath = project.sourceSets.main.classesDir
|
||||
|
||||
List<ClassPath> inputClassPath = [] as List;
|
||||
|
||||
ManifestWriter manifestWriter = new FileSystemManifestWriter(project.file(bundlorDir.absolutePath));
|
||||
ManifestContents mfTemplate = BundleManifestUtils.getManifest(manifestTemplate);
|
||||
|
||||
inputPaths.each {f ->
|
||||
inputClassPath.add(new FileSystemClassPath(f))
|
||||
}
|
||||
|
||||
// Must be a better way of doing this...
|
||||
Properties p = new Properties()
|
||||
expansions.each {entry ->
|
||||
p.setProperty(entry.key, entry.value as String)
|
||||
}
|
||||
|
||||
PropertiesSource expansionProps = new PropertiesPropertiesSource(p)
|
||||
PropertiesSource osgiProfileProps = osgiProfile == null ? new EmptyPropertiesSource() :
|
||||
new FileSystemPropertiesSource(osgiProfile);
|
||||
|
||||
ManifestGenerator manifestGenerator = new StandardManifestGenerator(
|
||||
DefaultManifestGeneratorContributorsFactory.create(expansionProps, osgiProfileProps));
|
||||
|
||||
ManifestContents mf = manifestGenerator.generate(mfTemplate, inputClassPath.toArray(new ClassPath[inputClassPath.size()]));
|
||||
|
||||
try {
|
||||
manifestWriter.write(mf);
|
||||
} finally {
|
||||
manifestWriter.close();
|
||||
}
|
||||
|
||||
ManifestValidator manifestValidator = new StandardManifestValidator(DefaultManifestValidatorContributorsFactory.create());
|
||||
|
||||
List<String> warnings = manifestValidator.validate(mf);
|
||||
|
||||
if (warnings.isEmpty()) {
|
||||
return
|
||||
}
|
||||
|
||||
logger.warn("Bundlor Warnings:");
|
||||
for (String warning : warnings) {
|
||||
logger.warn(" " + warning);
|
||||
}
|
||||
|
||||
if (failOnWarnings) {
|
||||
throw new GradleException("Bundlor returned warnings. Please fix manifest template at " + manifestTemplate.absolutePath + " and try again.")
|
||||
}
|
||||
}
|
||||
|
||||
def inputPath(FileCollection paths) {
|
||||
inputPaths = project.files(inputPaths, paths)
|
||||
}
|
||||
}
|
||||
@@ -48,9 +48,6 @@ class DocbookPlugin implements Plugin<Project> {
|
||||
Task docbookFoPdf = project.tasks.add("docbookFoPdf", DocbookFoPdf.class);
|
||||
docbookFoPdf.setDescription('Generates PDF output');
|
||||
docbookFoPdf.extension = 'fo'
|
||||
|
||||
Task docbook = project.tasks.add("docbook", DefaultTask.class);
|
||||
docbook.dependsOn (docbookHtml, docbookHtmlSingle, docbookFoPdf)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,8 +69,6 @@ public class Docbook extends DefaultTask {
|
||||
|
||||
String admonGraphicsPath;
|
||||
|
||||
String imgSrcPath;
|
||||
|
||||
@InputDirectory
|
||||
File sourceDirectory = new File(project.getProjectDir(), "src/docbook");
|
||||
|
||||
@@ -117,15 +112,11 @@ public class Docbook extends DefaultTask {
|
||||
}
|
||||
|
||||
transformer.setParameter("highlight.xslthl.config", new File(highlightingDir, "xslthl-config.xml").toURI().toURL());
|
||||
}
|
||||
|
||||
if (admonGraphicsPath != null) {
|
||||
transformer.setParameter("admon.graphics", "1");
|
||||
transformer.setParameter("admon.graphics.path", admonGraphicsPath);
|
||||
}
|
||||
|
||||
if (imgSrcPath != null) {
|
||||
transformer.setParameter("img.src.path", imgSrcPath);
|
||||
if (admonGraphicsPath != null) {
|
||||
transformer.setParameter("admon.graphics", "1");
|
||||
transformer.setParameter("admon.graphics.path", admonGraphicsPath);
|
||||
}
|
||||
}
|
||||
|
||||
preTransform(transformer, srcFile, outputFile);
|
||||
@@ -263,9 +254,9 @@ class DocbookFoPdf extends Docbook {
|
||||
}
|
||||
}
|
||||
|
||||
/* if (!foFile.delete()) {
|
||||
if (!foFile.delete()) {
|
||||
logger.warn("Failed to delete 'fo' file " + foFile);
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
private File getPdfOutputFile(File foFile) {
|
||||
|
||||
@@ -1,114 +0,0 @@
|
||||
package emma;
|
||||
|
||||
import org.gradle.api.*
|
||||
import org.gradle.api.tasks.testing.Test
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
import org.gradle.api.tasks.Input
|
||||
import com.vladium.emma.instr.InstrProcessor
|
||||
import com.vladium.emma.report.ReportProcessor
|
||||
import org.gradle.api.tasks.InputFiles
|
||||
import com.vladium.util.XProperties;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Luke Taylor
|
||||
*/
|
||||
class EmmaPlugin implements Plugin<Project> {
|
||||
|
||||
void apply(Project project) {
|
||||
Project rootProject = project.rootProject
|
||||
def emmaMetaDataFile = "${rootProject.buildDir}/emma/emma.em"
|
||||
def emmaCoverageFile = "${rootProject.buildDir}/emma/emma.ec"
|
||||
|
||||
if (project.configurations.findByName('emma_rt') == null) {
|
||||
project.configurations.add('emma_rt')
|
||||
project.dependencies {
|
||||
emma_rt 'emma:emma:2.0.5312'
|
||||
}
|
||||
}
|
||||
|
||||
project.task('emmaInstrument') {
|
||||
dependsOn project.classes
|
||||
|
||||
doFirst {
|
||||
InstrProcessor processor = InstrProcessor.create ();
|
||||
String[] classesDirPath = [project.sourceSets.main.classesDir.absolutePath]
|
||||
|
||||
processor.setInstrPath(classesDirPath, false);
|
||||
processor.setOutMode(InstrProcessor.OutMode.OUT_MODE_COPY);
|
||||
processor.setInstrOutDir("${project.buildDir}/emma/classes");
|
||||
processor.setMetaOutFile(emmaMetaDataFile);
|
||||
processor.setMetaOutMerge(true);
|
||||
//processor.setInclExclFilter (null);
|
||||
processor.run();
|
||||
}
|
||||
}
|
||||
|
||||
// Modify test tasks in the project to generate coverage data
|
||||
project.afterEvaluate {
|
||||
if (project.hasProperty('coverage') && ['on','true'].contains(project.properties.coverage)) {
|
||||
project.tasks.withType(Test.class).each { task ->
|
||||
task.dependsOn project.emmaInstrument
|
||||
task.configure() {
|
||||
jvmArgs '-Dsec.log.level=DEBUG', "-Demma.coverage.out.file=$emmaCoverageFile"
|
||||
jvmArgs '-Demma.verbosity.level=quiet'
|
||||
}
|
||||
task.doFirst {
|
||||
classpath = project.files("${project.buildDir}/emma/classes") + project.configurations.emma_rt + classpath
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<Task> reportTasks = rootProject.getTasksByName('coverageReport', false) as List;
|
||||
CoverageReport task;
|
||||
|
||||
if (reportTasks.isEmpty()) {
|
||||
task = rootProject.tasks.add('coverageReport', CoverageReport.class);
|
||||
task.dataPath = [emmaMetaDataFile, emmaCoverageFile];
|
||||
} else {
|
||||
task = reportTasks[0];
|
||||
}
|
||||
|
||||
task.modules.add(project);
|
||||
}
|
||||
}
|
||||
|
||||
class CoverageReport extends DefaultTask {
|
||||
@Input
|
||||
List<Project> modules = [];
|
||||
|
||||
@Input
|
||||
String[] dataPath;
|
||||
|
||||
@TaskAction
|
||||
void generateReport() {
|
||||
def buildDir = project.rootProject.buildDir
|
||||
|
||||
if (!buildDir.exists()) {
|
||||
throw new GradleException("No coverage data. Run gradle with -Pcoverage=on if using coverageReport");
|
||||
}
|
||||
|
||||
ReportProcessor processor = ReportProcessor.create ();
|
||||
processor.setDataPath(dataPath)
|
||||
|
||||
def srcPath = []
|
||||
modules.each {module->
|
||||
module.sourceSets.main.java.srcDirs.each {
|
||||
srcPath.add(it.absolutePath)
|
||||
}
|
||||
}
|
||||
|
||||
processor.setSourcePath(srcPath as String[]);
|
||||
|
||||
|
||||
def types = ['txt', 'html']
|
||||
processor.setReportTypes(types as String[]);
|
||||
XProperties properties = new XProperties();
|
||||
properties.setProperty('report.html.out.file', "$buildDir/emma/coverage.html");
|
||||
properties.setProperty('report.txt.out.file', "$buildDir/emma/coverage.txt");
|
||||
processor.setPropertyOverrides(properties)
|
||||
|
||||
processor.run()
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package gae;
|
||||
|
||||
import com.google.appengine.tools.admin.AppCfg
|
||||
import org.gradle.api.*;
|
||||
|
||||
class GaePlugin implements Plugin<Project> {
|
||||
public void apply(Project project) {
|
||||
if (!project.hasProperty('appEngineSdkRoot')) {
|
||||
println "'appEngineSdkRoot' must be set in gradle.properties"
|
||||
} else {
|
||||
System.setProperty('appengine.sdk.root', project.property('appEngineSdkRoot'))
|
||||
}
|
||||
|
||||
File explodedWar = new File(project.buildDir, "gae-exploded")
|
||||
|
||||
project.task('gaeDeploy') << {
|
||||
AppCfg.main("update", explodedWar.toString())
|
||||
}
|
||||
|
||||
project.gaeDeploy.dependsOn project.war
|
||||
|
||||
project.war.doLast {
|
||||
ant.unzip(src: project.war.archivePath, dest: explodedWar)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
implementation-class=aspectj.AspectJPlugin
|
||||
@@ -1 +0,0 @@
|
||||
implementation-class=bundlor.BundlorPlugin
|
||||
@@ -1 +0,0 @@
|
||||
implementation-class=emma.EmmaPlugin
|
||||
@@ -1 +0,0 @@
|
||||
implementation-class=gae.GaePlugin
|
||||
+2
-1
@@ -4,8 +4,9 @@ dependencies {
|
||||
project(':spring-security-web'),
|
||||
"org.springframework:spring-context:$springVersion",
|
||||
"org.springframework:spring-beans:$springVersion",
|
||||
"org.springframework:spring-tx:$springVersion",
|
||||
"org.springframework:spring-web:$springVersion",
|
||||
"org.jasig.cas.client:cas-client-core:3.1.12",
|
||||
"org.jasig.cas:cas-client-core:3.1.9",
|
||||
"net.sf.ehcache:ehcache:$ehcacheVersion"
|
||||
|
||||
provided 'javax.servlet:servlet-api:2.5'
|
||||
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-parent</artifactId>
|
||||
<version>3.0.4.RELEASE</version>
|
||||
</parent>
|
||||
<artifactId>spring-security-cas-client</artifactId>
|
||||
<name>Spring Security - CAS support</name>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-web</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>servlet-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-tx</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jasig.cas</groupId>
|
||||
<artifactId>cas-client-core</artifactId>
|
||||
<version>3.1.10</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.sf.ehcache</groupId>
|
||||
<artifactId>ehcache</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>com.springsource.bundlor</groupId>
|
||||
<artifactId>com.springsource.bundlor.maven</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@@ -38,8 +38,6 @@ public class ServiceProperties implements InitializingBean {
|
||||
|
||||
private String service;
|
||||
|
||||
private boolean authenticateAllArtifacts;
|
||||
|
||||
private boolean sendRenew = false;
|
||||
|
||||
private String artifactParameter = DEFAULT_CAS_ARTIFACT_PARAMETER;
|
||||
@@ -49,9 +47,7 @@ public class ServiceProperties implements InitializingBean {
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
if(!authenticateAllArtifacts) {
|
||||
Assert.hasLength(this.service, "service must be specified unless authenticateAllArtifacts is true.");
|
||||
}
|
||||
Assert.hasLength(this.service, "service must be specified.");
|
||||
Assert.hasLength(this.artifactParameter, "artifactParameter cannot be empty.");
|
||||
Assert.hasLength(this.serviceParameter, "serviceParameter cannot be empty.");
|
||||
}
|
||||
@@ -119,19 +115,4 @@ public class ServiceProperties implements InitializingBean {
|
||||
public final void setServiceParameter(final String serviceParameter) {
|
||||
this.serviceParameter = serviceParameter;
|
||||
}
|
||||
|
||||
public final boolean isAuthenticateAllArtifacts() {
|
||||
return authenticateAllArtifacts;
|
||||
}
|
||||
|
||||
/**
|
||||
* If true, then any non-null artifact (ticket) should be authenticated.
|
||||
* Additionally, the service will be determined dynamically in order to
|
||||
* ensure the service matches the expected value for this artifact.
|
||||
*
|
||||
* @param authenticateAllArtifacts
|
||||
*/
|
||||
public final void setAuthenticateAllArtifacts(final boolean authenticateAllArtifacts) {
|
||||
this.authenticateAllArtifacts = authenticateAllArtifacts;
|
||||
}
|
||||
}
|
||||
|
||||
-3
@@ -19,7 +19,6 @@ import java.util.ArrayList;
|
||||
import org.jasig.cas.client.validation.Assertion;
|
||||
import org.springframework.security.authentication.AbstractAuthenticationToken;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.SpringSecurityCoreVersion;
|
||||
|
||||
/**
|
||||
* Temporary authentication object needed to load the user details service.
|
||||
@@ -29,8 +28,6 @@ import org.springframework.security.core.SpringSecurityCoreVersion;
|
||||
*/
|
||||
public final class CasAssertionAuthenticationToken extends AbstractAuthenticationToken {
|
||||
|
||||
private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
|
||||
|
||||
private final Assertion assertion;
|
||||
|
||||
private final String ticket;
|
||||
|
||||
+7
-48
@@ -15,8 +15,6 @@
|
||||
|
||||
package org.springframework.security.cas.authentication;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.jasig.cas.client.validation.Assertion;
|
||||
import org.jasig.cas.client.validation.TicketValidationException;
|
||||
import org.jasig.cas.client.validation.TicketValidator;
|
||||
@@ -30,12 +28,9 @@ import org.springframework.security.authentication.BadCredentialsException;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.cas.ServiceProperties;
|
||||
import org.springframework.security.cas.web.CasAuthenticationFilter;
|
||||
import org.springframework.security.cas.web.authentication.ServiceAuthenticationDetails;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.core.SpringSecurityMessageSource;
|
||||
import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
|
||||
import org.springframework.security.core.authority.mapping.NullAuthoritiesMapper;
|
||||
import org.springframework.security.core.userdetails.*;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@@ -53,22 +48,17 @@ import org.springframework.util.Assert;
|
||||
* @author Scott Battaglia
|
||||
*/
|
||||
public class CasAuthenticationProvider implements AuthenticationProvider, InitializingBean, MessageSourceAware {
|
||||
//~ Static fields/initializers =====================================================================================
|
||||
|
||||
private static final Log logger = LogFactory.getLog(CasAuthenticationProvider.class);
|
||||
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private AuthenticationUserDetailsService<CasAssertionAuthenticationToken> authenticationUserDetailsService;
|
||||
private AuthenticationUserDetailsService authenticationUserDetailsService;
|
||||
|
||||
private final UserDetailsChecker userDetailsChecker = new AccountStatusUserDetailsChecker();
|
||||
private UserDetailsChecker userDetailsChecker = new AccountStatusUserDetailsChecker();
|
||||
protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();
|
||||
private StatelessTicketCache statelessTicketCache = new NullStatelessTicketCache();
|
||||
private String key;
|
||||
private TicketValidator ticketValidator;
|
||||
private ServiceProperties serviceProperties;
|
||||
private GrantedAuthoritiesMapper authoritiesMapper = new NullAuthoritiesMapper();
|
||||
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
@@ -78,6 +68,7 @@ public class CasAuthenticationProvider implements AuthenticationProvider, Initia
|
||||
Assert.notNull(this.statelessTicketCache, "A statelessTicketCache must be set");
|
||||
Assert.hasText(this.key, "A Key is required so CasAuthenticationProvider can identify tokens it previously authenticated");
|
||||
Assert.notNull(this.messages, "A message source must be set");
|
||||
Assert.notNull(this.serviceProperties, "serviceProperties is a required field.");
|
||||
}
|
||||
|
||||
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
|
||||
@@ -137,42 +128,15 @@ public class CasAuthenticationProvider implements AuthenticationProvider, Initia
|
||||
|
||||
private CasAuthenticationToken authenticateNow(final Authentication authentication) throws AuthenticationException {
|
||||
try {
|
||||
final Assertion assertion = this.ticketValidator.validate(authentication.getCredentials().toString(), getServiceUrl(authentication));
|
||||
final Assertion assertion = this.ticketValidator.validate(authentication.getCredentials().toString(), serviceProperties.getService());
|
||||
final UserDetails userDetails = loadUserByAssertion(assertion);
|
||||
userDetailsChecker.check(userDetails);
|
||||
return new CasAuthenticationToken(this.key, userDetails, authentication.getCredentials(),
|
||||
authoritiesMapper.mapAuthorities(userDetails.getAuthorities()), userDetails, assertion);
|
||||
return new CasAuthenticationToken(this.key, userDetails, authentication.getCredentials(), userDetails.getAuthorities(), userDetails, assertion);
|
||||
} catch (final TicketValidationException e) {
|
||||
throw new BadCredentialsException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the serviceUrl. If the {@link Authentication#getDetails()} is an
|
||||
* instance of {@link ServiceAuthenticationDetails}, then
|
||||
* {@link ServiceAuthenticationDetails#getServiceUrl()} is used. Otherwise,
|
||||
* the {@link ServiceProperties#getService()} is used.
|
||||
*
|
||||
* @param authentication
|
||||
* @return
|
||||
*/
|
||||
private String getServiceUrl(Authentication authentication) {
|
||||
String serviceUrl;
|
||||
if(authentication.getDetails() instanceof ServiceAuthenticationDetails) {
|
||||
serviceUrl = ((ServiceAuthenticationDetails)authentication.getDetails()).getServiceUrl();
|
||||
}else if(serviceProperties == null){
|
||||
throw new IllegalStateException("serviceProperties cannot be null unless Authentication.getDetails() implements ServiceAuthenticationDetails.");
|
||||
}else if(serviceProperties.getService() == null){
|
||||
throw new IllegalStateException("serviceProperties.getService() cannot be null unless Authentication.getDetails() implements ServiceAuthenticationDetails.");
|
||||
}else {
|
||||
serviceUrl = serviceProperties.getService();
|
||||
}
|
||||
if(logger.isDebugEnabled()) {
|
||||
logger.debug("serviceUrl = "+serviceUrl);
|
||||
}
|
||||
return serviceUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Template method for retrieving the UserDetails based on the assertion. Default is to call configured userDetailsService and pass the username. Deployers
|
||||
* can override this method and retrieve the user based on any criteria they desire.
|
||||
@@ -186,7 +150,6 @@ public class CasAuthenticationProvider implements AuthenticationProvider, Initia
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@SuppressWarnings("unchecked")
|
||||
/**
|
||||
* @deprecated as of 3.0. Use the {@link org.springframework.security.cas.authentication.CasAuthenticationProvider#setAuthenticationUserDetailsService(org.springframework.security.core.userdetails.AuthenticationUserDetailsService)} instead.
|
||||
*/
|
||||
@@ -194,7 +157,7 @@ public class CasAuthenticationProvider implements AuthenticationProvider, Initia
|
||||
this.authenticationUserDetailsService = new UserDetailsByNameServiceWrapper(userDetailsService);
|
||||
}
|
||||
|
||||
public void setAuthenticationUserDetailsService(final AuthenticationUserDetailsService<CasAssertionAuthenticationToken> authenticationUserDetailsService) {
|
||||
public void setAuthenticationUserDetailsService(final AuthenticationUserDetailsService authenticationUserDetailsService) {
|
||||
this.authenticationUserDetailsService = authenticationUserDetailsService;
|
||||
}
|
||||
|
||||
@@ -230,11 +193,7 @@ public class CasAuthenticationProvider implements AuthenticationProvider, Initia
|
||||
this.ticketValidator = ticketValidator;
|
||||
}
|
||||
|
||||
public void setAuthoritiesMapper(GrantedAuthoritiesMapper authoritiesMapper) {
|
||||
this.authoritiesMapper = authoritiesMapper;
|
||||
}
|
||||
|
||||
public boolean supports(final Class<?> authentication) {
|
||||
public boolean supports(final Class<? extends Object> authentication) {
|
||||
return (UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication)) ||
|
||||
(CasAuthenticationToken.class.isAssignableFrom(authentication)) ||
|
||||
(CasAssertionAuthenticationToken.class.isAssignableFrom(authentication));
|
||||
|
||||
+2
-4
@@ -21,7 +21,6 @@ import java.util.Collection;
|
||||
import org.jasig.cas.client.validation.Assertion;
|
||||
import org.springframework.security.authentication.AbstractAuthenticationToken;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.SpringSecurityCoreVersion;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
|
||||
/**
|
||||
@@ -31,10 +30,9 @@ import org.springframework.security.core.userdetails.UserDetails;
|
||||
* @author Scott Battaglia
|
||||
*/
|
||||
public class CasAuthenticationToken extends AbstractAuthenticationToken implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
|
||||
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private final Object credentials;
|
||||
private final Object principal;
|
||||
private final UserDetails userDetails;
|
||||
|
||||
+18
-7
@@ -15,17 +15,23 @@
|
||||
|
||||
package org.springframework.security.cas.authentication;
|
||||
|
||||
import net.sf.ehcache.Ehcache;
|
||||
import net.sf.ehcache.CacheException;
|
||||
import net.sf.ehcache.Element;
|
||||
import net.sf.ehcache.Ehcache;
|
||||
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
import org.springframework.dao.DataRetrievalFailureException;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
|
||||
/**
|
||||
* Caches tickets using a Spring IoC defined <a href="http://ehcache.sourceforge.net">EHCACHE</a>.
|
||||
* Caches tickets using a Spring IoC defined <A HREF="http://ehcache.sourceforge.net">EHCACHE</a>.
|
||||
*
|
||||
* @author Ben Alex
|
||||
*/
|
||||
@@ -45,13 +51,18 @@ public class EhCacheBasedTicketCache implements StatelessTicketCache, Initializi
|
||||
}
|
||||
|
||||
public CasAuthenticationToken getByTicketId(final String serviceTicket) {
|
||||
final Element element = cache.get(serviceTicket);
|
||||
try {
|
||||
final Element element = cache.get(serviceTicket);
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Cache hit: " + (element != null) + "; service ticket: " + serviceTicket);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Cache hit: " + (element != null) + "; service ticket: " + serviceTicket);
|
||||
}
|
||||
|
||||
return element == null ? null : (CasAuthenticationToken) element.getValue();
|
||||
|
||||
} catch (CacheException cacheException) {
|
||||
throw new DataRetrievalFailureException("Cache failure: " + cacheException.getMessage());
|
||||
}
|
||||
|
||||
return element == null ? null : (CasAuthenticationToken) element.getValue();
|
||||
}
|
||||
|
||||
public Ehcache getCache() {
|
||||
|
||||
+9
-6
@@ -14,10 +14,13 @@
|
||||
*/
|
||||
package org.springframework.security.cas.userdetails;
|
||||
|
||||
import org.jasig.cas.client.validation.Assertion;
|
||||
import org.springframework.security.cas.authentication.CasAssertionAuthenticationToken;
|
||||
import org.springframework.security.core.userdetails.AuthenticationUserDetailsService;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.cas.authentication.CasAssertionAuthenticationToken;
|
||||
import org.springframework.util.Assert;
|
||||
import org.jasig.cas.client.validation.Assertion;
|
||||
|
||||
/**
|
||||
* Abstract class for using the provided CAS assertion to construct a new User object. This generally is most
|
||||
@@ -26,11 +29,11 @@ import org.springframework.security.core.userdetails.UserDetails;
|
||||
* @author Scott Battaglia
|
||||
* @since 3.0
|
||||
*/
|
||||
public abstract class AbstractCasAssertionUserDetailsService
|
||||
implements AuthenticationUserDetailsService<CasAssertionAuthenticationToken> {
|
||||
public abstract class AbstractCasAssertionUserDetailsService implements AuthenticationUserDetailsService {
|
||||
|
||||
public final UserDetails loadUserDetails(final CasAssertionAuthenticationToken token) {
|
||||
return loadUserDetails(token.getAssertion());
|
||||
public final UserDetails loadUserDetails(final Authentication token) throws UsernameNotFoundException {
|
||||
Assert.isInstanceOf(CasAssertionAuthenticationToken.class, token, "The provided token MUST be an instance of CasAssertionAuthenticationToken.class");
|
||||
return loadUserDetails(((CasAssertionAuthenticationToken) token).getAssertion());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+4
-4
@@ -17,7 +17,7 @@ package org.springframework.security.cas.userdetails;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.User;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.authority.GrantedAuthorityImpl;
|
||||
import org.springframework.util.Assert;
|
||||
import org.jasig.cas.client.validation.Assertion;
|
||||
|
||||
@@ -36,7 +36,7 @@ public final class GrantedAuthorityFromAssertionAttributesUserDetailsService ext
|
||||
|
||||
private static final String NON_EXISTENT_PASSWORD_VALUE = "NO_PASSWORD";
|
||||
|
||||
private final String[] attributes;
|
||||
private String[] attributes;
|
||||
|
||||
private boolean convertToUpperCase = true;
|
||||
|
||||
@@ -62,11 +62,11 @@ public final class GrantedAuthorityFromAssertionAttributesUserDetailsService ext
|
||||
final List list = (List) value;
|
||||
|
||||
for (final Object o : list) {
|
||||
grantedAuthorities.add(new SimpleGrantedAuthority(this.convertToUpperCase ? o.toString().toUpperCase() : o.toString()));
|
||||
grantedAuthorities.add(new GrantedAuthorityImpl(this.convertToUpperCase ? o.toString().toUpperCase() : o.toString()));
|
||||
}
|
||||
|
||||
} else {
|
||||
grantedAuthorities.add(new SimpleGrantedAuthority(this.convertToUpperCase ? value.toString().toUpperCase() : value.toString()));
|
||||
grantedAuthorities.add(new GrantedAuthorityImpl(this.convertToUpperCase ? value.toString().toUpperCase() : value.toString()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
-1
@@ -65,7 +65,6 @@ public class CasAuthenticationEntryPoint implements AuthenticationEntryPoint, In
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.hasLength(this.loginUrl, "loginUrl must be specified");
|
||||
Assert.notNull(this.serviceProperties, "serviceProperties must be specified");
|
||||
Assert.notNull(this.serviceProperties.getService(),"serviceProperties.getService() cannot be null.");
|
||||
}
|
||||
|
||||
public final void commence(final HttpServletRequest servletRequest, final HttpServletResponse response,
|
||||
|
||||
+25
-280
@@ -17,142 +17,43 @@ package org.springframework.security.cas.web;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.jasig.cas.client.proxy.ProxyGrantingTicketStorage;
|
||||
import org.jasig.cas.client.util.CommonUtils;
|
||||
import org.jasig.cas.client.validation.TicketValidator;
|
||||
import org.springframework.security.authentication.AnonymousAuthenticationToken;
|
||||
import org.springframework.security.authentication.AuthenticationDetailsSource;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.authentication.event.InteractiveAuthenticationSuccessEvent;
|
||||
import org.springframework.security.cas.ServiceProperties;
|
||||
import org.springframework.security.cas.web.authentication.ServiceAuthenticationDetails;
|
||||
import org.springframework.security.cas.web.authentication.ServiceAuthenticationDetailsSource;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
|
||||
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
|
||||
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
|
||||
/**
|
||||
* Processes a CAS service ticket, obtains proxy granting tickets, and processes proxy tickets.
|
||||
* <h2>Service Tickets</h2>
|
||||
* Processes a CAS service ticket.
|
||||
* <p>
|
||||
* A service ticket consists of an opaque ticket string. It arrives at this filter by the user's browser successfully
|
||||
* authenticating using CAS, and then receiving a HTTP redirect to a <code>service</code>. The opaque ticket string is
|
||||
* presented in the <code>ticket</code> request parameter.
|
||||
* <p>
|
||||
* This filter monitors the <code>service</code> URL so it can
|
||||
* receive the service ticket and process it. By default this filter processes the URL <tt>/j_spring_cas_security_check</tt>.
|
||||
* When processing this URL, the value of {@link ServiceProperties#getService()} is used as the <tt>service</tt> when validating
|
||||
* the <code>ticket</code>. This means that it is important that {@link ServiceProperties#getService()} specifies the same value
|
||||
* as the <tt>filterProcessesUrl</tt>.
|
||||
* presented in the <code>ticket</code> request parameter. This filter monitors the <code>service</code> URL so it can
|
||||
* receive the service ticket and process it. The CAS server knows which <code>service</code> URL to use via the
|
||||
* {@link ServiceProperties#getService()} method.
|
||||
* <p>
|
||||
* Processing the service ticket involves creating a <code>UsernamePasswordAuthenticationToken</code> which
|
||||
* uses {@link #CAS_STATEFUL_IDENTIFIER} for the <code>principal</code> and the opaque ticket string as the
|
||||
* <code>credentials</code>.
|
||||
* <h2>Obtaining Proxy Granting Tickets</h2>
|
||||
* <p>
|
||||
* If specified, the filter can also monitor the <code>proxyReceptorUrl</code>. The filter will respond to requests matching
|
||||
* this url so that the CAS Server can provide a PGT to the filter. Note that in addition to the <code>proxyReceptorUrl</code> a non-null
|
||||
* <code>proxyGrantingTicketStorage</code> must be provided in order for the filter to respond to proxy receptor requests. By configuring
|
||||
* a shared {@link ProxyGrantingTicketStorage} between the {@link TicketValidator} and the CasAuthenticationFilter one can have the
|
||||
* CasAuthenticationFilter handle the proxying requirements for CAS.
|
||||
* <h2>Proxy Tickets</h2>
|
||||
* <p>
|
||||
* The filter can process tickets present on any url. This is useful when wanting to process proxy tickets. In order for proxy
|
||||
* tickets to get processed {@link ServiceProperties#isAuthenticateAllArtifacts()} must return <code>true</code>. Additionally,
|
||||
* if the request is already authenticated, authentication will <b>not</b> occur. Last, {@link AuthenticationDetailsSource#buildDetails(Object)}
|
||||
* must return a {@link ServiceAuthenticationDetails}. This can be accomplished using the {@link ServiceAuthenticationDetailsSource}.
|
||||
* In this case {@link ServiceAuthenticationDetails#getServiceUrl()} will be used for the service url.
|
||||
* <p>
|
||||
* Processing the proxy ticket involves creating a <code>UsernamePasswordAuthenticationToken</code> which
|
||||
* uses {@link #CAS_STATELESS_IDENTIFIER} for the <code>principal</code> and the opaque ticket string as the
|
||||
* <code>credentials</code>. When a proxy ticket is successfully authenticated, the FilterChain continues and the
|
||||
* <code>authenticationSuccessHandler</code> is not used.
|
||||
* <h2>Notes about the <code>AuthenticationManager</code></h2>
|
||||
* <p>
|
||||
* The configured <code>AuthenticationManager</code> is expected to provide a provider that can recognise
|
||||
* <code>UsernamePasswordAuthenticationToken</code>s containing this special <code>principal</code> name, and process
|
||||
* them accordingly by validation with the CAS server. Additionally, it should be capable of using the result of
|
||||
* {@link ServiceAuthenticationDetails#getServiceUrl()} as the service when validating the ticket.
|
||||
* <h2>Example Configuration</h2>
|
||||
* them accordingly by validation with the CAS server.
|
||||
* <p>
|
||||
* An example configuration that supports service tickets, obtaining proxy granting tickets, and proxy tickets is
|
||||
* illustrated below:
|
||||
*
|
||||
* <pre>
|
||||
* <b:bean id="serviceProperties"
|
||||
* class="org.springframework.security.cas.ServiceProperties"
|
||||
* p:service="https://service.example.com/cas-sample/j_spring_cas_security_check"
|
||||
* p:authenticateAllArtifacts="true"/>
|
||||
* <b:bean id="casEntryPoint"
|
||||
* class="org.springframework.security.cas.web.CasAuthenticationEntryPoint"
|
||||
* p:serviceProperties-ref="serviceProperties" p:loginUrl="https://login.example.org/cas/login" />
|
||||
* <b:bean id="casFilter"
|
||||
* class="org.springframework.security.cas.web.CasAuthenticationFilter"
|
||||
* p:authenticationManager-ref="authManager"
|
||||
* p:serviceProperties-ref="serviceProperties"
|
||||
* p:proxyGrantingTicketStorage-ref="pgtStorage"
|
||||
* p:proxyReceptorUrl="/j_spring_cas_security_proxyreceptor">
|
||||
* <b:property name="authenticationDetailsSource">
|
||||
* <b:bean class="org.springframework.security.cas.web.authentication.ServiceAuthenticationDetailsSource"/>
|
||||
* </b:property>
|
||||
* <b:property name="authenticationFailureHandler">
|
||||
* <b:bean class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler"
|
||||
* p:defaultFailureUrl="/casfailed.jsp"/>
|
||||
* </b:property>
|
||||
* </b:bean>
|
||||
* <!--
|
||||
* NOTE: In a real application you should not use an in memory implementation. You will also want
|
||||
* to ensure to clean up expired tickets by calling ProxyGrantingTicketStorage.cleanup()
|
||||
* -->
|
||||
* <b:bean id="pgtStorage" class="org.jasig.cas.client.proxy.ProxyGrantingTicketStorageImpl"/>
|
||||
* <b:bean id="casAuthProvider" class="org.springframework.security.cas.authentication.CasAuthenticationProvider"
|
||||
* p:serviceProperties-ref="serviceProperties"
|
||||
* p:key="casAuthProviderKey">
|
||||
* <b:property name="authenticationUserDetailsService">
|
||||
* <b:bean
|
||||
* class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">
|
||||
* <b:constructor-arg ref="userService" />
|
||||
* </b:bean>
|
||||
* </b:property>
|
||||
* <b:property name="ticketValidator">
|
||||
* <b:bean
|
||||
* class="org.jasig.cas.client.validation.Cas20ProxyTicketValidator"
|
||||
* p:acceptAnyProxy="true"
|
||||
* p:proxyCallbackUrl="https://service.example.com/cas-sample/j_spring_cas_security_proxyreceptor"
|
||||
* p:proxyGrantingTicketStorage-ref="pgtStorage">
|
||||
* <b:constructor-arg value="https://login.example.org/cas" />
|
||||
* </b:bean>
|
||||
* </b:property>
|
||||
* <b:property name="statelessTicketCache">
|
||||
* <b:bean class="org.springframework.security.cas.authentication.EhCacheBasedTicketCache">
|
||||
* <b:property name="cache">
|
||||
* <b:bean class="net.sf.ehcache.Cache"
|
||||
* init-method="initialise"
|
||||
* destroy-method="dispose">
|
||||
* <b:constructor-arg value="casTickets"/>
|
||||
* <b:constructor-arg value="50"/>
|
||||
* <b:constructor-arg value="true"/>
|
||||
* <b:constructor-arg value="false"/>
|
||||
* <b:constructor-arg value="3600"/>
|
||||
* <b:constructor-arg value="900"/>
|
||||
* </b:bean>
|
||||
* </b:property>
|
||||
* </b:bean>
|
||||
* </b:property>
|
||||
* </b:bean>
|
||||
* </pre>
|
||||
* By configuring a shared {@link ProxyGrantingTicketStorage} between the {@link TicketValidator} and the
|
||||
* CasAuthenticationFilter one can have the CasAuthenticationFilter handle the proxying requirements for CAS. In addition, the
|
||||
* URI endpoint for the proxying would also need to be configured (i.e. the part after protocol, hostname, and port).
|
||||
* <p>
|
||||
* By default this filter processes the URL <tt>/j_spring_cas_security_check</tt>.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @author Rob Winch
|
||||
*/
|
||||
public class CasAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
|
||||
//~ Static fields/initializers =====================================================================================
|
||||
@@ -179,59 +80,20 @@ public class CasAuthenticationFilter extends AbstractAuthenticationProcessingFil
|
||||
|
||||
private String artifactParameter = ServiceProperties.DEFAULT_CAS_ARTIFACT_PARAMETER;
|
||||
|
||||
private boolean authenticateAllArtifacts;
|
||||
|
||||
private AuthenticationFailureHandler proxyFailureHandler = new SimpleUrlAuthenticationFailureHandler();
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
public CasAuthenticationFilter() {
|
||||
super("/j_spring_cas_security_check");
|
||||
setAuthenticationFailureHandler(new SimpleUrlAuthenticationFailureHandler());
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
@Override
|
||||
protected final void successfulAuthentication(HttpServletRequest request,
|
||||
HttpServletResponse response, FilterChain chain, Authentication authResult)
|
||||
throws IOException, ServletException {
|
||||
boolean continueFilterChain = proxyTicketRequest(serviceTicketRequest(request, response),request);
|
||||
if(!continueFilterChain) {
|
||||
super.successfulAuthentication(request, response, chain, authResult);
|
||||
return;
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Authentication success. Updating SecurityContextHolder to contain: " + authResult);
|
||||
}
|
||||
|
||||
SecurityContextHolder.getContext().setAuthentication(authResult);
|
||||
|
||||
// Fire event
|
||||
if (this.eventPublisher != null) {
|
||||
eventPublisher.publishEvent(new InteractiveAuthenticationSuccessEvent(authResult, this.getClass()));
|
||||
}
|
||||
|
||||
chain.doFilter(request, response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Authentication attemptAuthentication(final HttpServletRequest request, final HttpServletResponse response)
|
||||
throws AuthenticationException, IOException {
|
||||
// if the request is a proxy request process it and return null to indicate the request has been processed
|
||||
if(proxyReceptorRequest(request)) {
|
||||
logger.debug("Responding to proxy receptor request");
|
||||
CommonUtils.readAndRespondToProxyReceptorRequest(request, response, this.proxyGrantingTicketStorage);
|
||||
return null;
|
||||
}
|
||||
|
||||
final boolean serviceTicketRequest = serviceTicketRequest(request, response);
|
||||
final String username = serviceTicketRequest ? CAS_STATEFUL_IDENTIFIER : CAS_STATELESS_IDENTIFIER;
|
||||
String password = obtainArtifact(request);
|
||||
throws AuthenticationException {
|
||||
final String username = CAS_STATEFUL_IDENTIFIER;
|
||||
String password = request.getParameter(this.artifactParameter);
|
||||
|
||||
if (password == null) {
|
||||
logger.debug("Failed to obtain an artifact (cas ticket)");
|
||||
password = "";
|
||||
}
|
||||
|
||||
@@ -242,47 +104,22 @@ public class CasAuthenticationFilter extends AbstractAuthenticationProcessingFil
|
||||
return this.getAuthenticationManager().authenticate(authRequest);
|
||||
}
|
||||
|
||||
/**
|
||||
* If present, gets the artifact (CAS ticket) from the {@link HttpServletRequest}.
|
||||
* @param request
|
||||
* @return if present the artifact from the {@link HttpServletRequest}, else null
|
||||
*/
|
||||
protected String obtainArtifact(HttpServletRequest request) {
|
||||
return request.getParameter(artifactParameter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Overridden to provide proxying capabilities.
|
||||
*/
|
||||
@Override
|
||||
protected boolean requiresAuthentication(final HttpServletRequest request, final HttpServletResponse response) {
|
||||
final boolean serviceTicketRequest = serviceTicketRequest(request, response);
|
||||
final boolean result = serviceTicketRequest || proxyReceptorRequest(request) || (proxyTicketRequest(serviceTicketRequest, request));
|
||||
if(logger.isDebugEnabled()) {
|
||||
logger.debug("requiresAuthentication = "+result);
|
||||
final String requestUri = request.getRequestURI();
|
||||
|
||||
if (CommonUtils.isEmpty(this.proxyReceptorUrl) || !requestUri.endsWith(this.proxyReceptorUrl) || this.proxyGrantingTicketStorage == null) {
|
||||
return super.requiresAuthentication(request, response);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link AuthenticationFailureHandler} for proxy requests.
|
||||
* @param proxyFailureHandler
|
||||
*/
|
||||
public final void setProxyAuthenticationFailureHandler(
|
||||
AuthenticationFailureHandler proxyFailureHandler) {
|
||||
Assert.notNull(proxyFailureHandler,"proxyFailureHandler cannot be null");
|
||||
this.proxyFailureHandler = proxyFailureHandler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps the {@link AuthenticationFailureHandler} to distinguish between
|
||||
* handling proxy ticket authentication failures and service ticket
|
||||
* failures.
|
||||
*/
|
||||
@Override
|
||||
public final void setAuthenticationFailureHandler(
|
||||
AuthenticationFailureHandler failureHandler) {
|
||||
super.setAuthenticationFailureHandler(new CasAuthenticationFailureHandler(failureHandler));
|
||||
try {
|
||||
CommonUtils.readAndRespondToProxyReceptorRequest(request, response, this.proxyGrantingTicketStorage);
|
||||
return false;
|
||||
} catch (final IOException e) {
|
||||
return super.requiresAuthentication(request, response);
|
||||
}
|
||||
}
|
||||
|
||||
public final void setProxyReceptorUrl(final String proxyReceptorUrl) {
|
||||
@@ -296,97 +133,5 @@ public class CasAuthenticationFilter extends AbstractAuthenticationProcessingFil
|
||||
|
||||
public final void setServiceProperties(final ServiceProperties serviceProperties) {
|
||||
this.artifactParameter = serviceProperties.getArtifactParameter();
|
||||
this.authenticateAllArtifacts = serviceProperties.isAuthenticateAllArtifacts();
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if the request is elgible to process a service ticket. This method exists for readability.
|
||||
* @param request
|
||||
* @param response
|
||||
* @return
|
||||
*/
|
||||
private boolean serviceTicketRequest(final HttpServletRequest request, final HttpServletResponse response) {
|
||||
boolean result = super.requiresAuthentication(request, response);
|
||||
if(logger.isDebugEnabled()) {
|
||||
logger.debug("serviceTicketRequest = "+result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if the request is elgible to process a proxy ticket.
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
private boolean proxyTicketRequest(final boolean serviceTicketRequest, final HttpServletRequest request) {
|
||||
if(serviceTicketRequest) {
|
||||
return false;
|
||||
}
|
||||
final boolean result = authenticateAllArtifacts && obtainArtifact(request) != null && !authenticated();
|
||||
if(logger.isDebugEnabled()) {
|
||||
logger.debug("proxyTicketRequest = "+result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if a user is already authenticated.
|
||||
* @return
|
||||
*/
|
||||
private boolean authenticated() {
|
||||
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||
return authentication != null && authentication.isAuthenticated() && !(authentication instanceof AnonymousAuthenticationToken);
|
||||
}
|
||||
/**
|
||||
* Indicates if the request is elgible to be processed as the proxy receptor.
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
private boolean proxyReceptorRequest(final HttpServletRequest request) {
|
||||
final String requestUri = request.getRequestURI();
|
||||
final boolean result = proxyReceptorConfigured() && requestUri.endsWith(this.proxyReceptorUrl);
|
||||
if(logger.isDebugEnabled()) {
|
||||
logger.debug("proxyReceptorRequest = "+result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the {@link CasAuthenticationFilter} is configured to handle the proxy receptor requests.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private boolean proxyReceptorConfigured() {
|
||||
final boolean result = this.proxyGrantingTicketStorage != null && !CommonUtils.isEmpty(this.proxyReceptorUrl);
|
||||
if(logger.isDebugEnabled()) {
|
||||
logger.debug("proxyReceptorConfigured = "+result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* A wrapper for the AuthenticationFailureHandler that will flex the {@link AuthenticationFailureHandler} that is used. The value
|
||||
* {@link CasAuthenticationFilter#setProxyAuthenticationFailureHandler(AuthenticationFailureHandler) will be used for proxy requests
|
||||
* that fail. The value {@link CasAuthenticationFilter#setAuthenticationFailureHandler(AuthenticationFailureHandler)} will be used for
|
||||
* service tickets that fail.
|
||||
*
|
||||
* @author Rob Winch
|
||||
*/
|
||||
private class CasAuthenticationFailureHandler implements AuthenticationFailureHandler {
|
||||
private final AuthenticationFailureHandler serviceTicketFailureHandler;
|
||||
public CasAuthenticationFailureHandler(AuthenticationFailureHandler failureHandler) {
|
||||
Assert.notNull(failureHandler,"failureHandler");
|
||||
this.serviceTicketFailureHandler = failureHandler;
|
||||
}
|
||||
public void onAuthenticationFailure(HttpServletRequest request,
|
||||
HttpServletResponse response,
|
||||
AuthenticationException exception) throws IOException,
|
||||
ServletException {
|
||||
if(serviceTicketRequest(request, response)) {
|
||||
serviceTicketFailureHandler.onAuthenticationFailure(request, response, exception);
|
||||
}else {
|
||||
proxyFailureHandler.onAuthenticationFailure(request, response, exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-131
@@ -1,131 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed 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
|
||||
*
|
||||
* 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.springframework.security.cas.web.authentication;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.security.web.authentication.WebAuthenticationDetails;
|
||||
import org.springframework.security.web.util.UrlUtils;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A default implementation of {@link ServiceAuthenticationDetails} that figures
|
||||
* out the value for {@link #getServiceUrl()} by inspecting the current
|
||||
* {@link HttpServletRequest} and using the current URL minus the artifact and
|
||||
* the corresponding value.
|
||||
*
|
||||
* @author Rob Winch
|
||||
*/
|
||||
final class DefaultServiceAuthenticationDetails extends WebAuthenticationDetails implements ServiceAuthenticationDetails {
|
||||
private static final long serialVersionUID = 6192409090610517700L;
|
||||
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private final String serviceUrl;
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
/**
|
||||
* Creates a new instance
|
||||
* @param request
|
||||
* the current {@link HttpServletRequest} to obtain the
|
||||
* {@link #getServiceUrl()} from.
|
||||
* @param artifactPattern
|
||||
* the {@link Pattern} that will be used to clean up the query
|
||||
* string from containing the artifact name and value. This can
|
||||
* be created using {@link #createArtifactPattern(String)}.
|
||||
*/
|
||||
DefaultServiceAuthenticationDetails(HttpServletRequest request, Pattern artifactPattern) {
|
||||
super(request);
|
||||
final String query = getQueryString(request,artifactPattern);
|
||||
this.serviceUrl = UrlUtils.buildFullRequestUrl(request.getScheme(),
|
||||
request.getServerName(), request.getServerPort(),
|
||||
request.getRequestURI(), query);
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
/**
|
||||
* Returns the current URL minus the artifact parameter and its value, if present.
|
||||
* @see org.springframework.security.cas.web.authentication.ServiceAuthenticationDetails#getServiceUrl()
|
||||
*/
|
||||
public String getServiceUrl() {
|
||||
return serviceUrl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = super.hashCode();
|
||||
result = prime * result
|
||||
+ serviceUrl.hashCode();
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (!super.equals(obj) || !(obj instanceof DefaultServiceAuthenticationDetails)) {
|
||||
return false;
|
||||
}
|
||||
ServiceAuthenticationDetails that = (ServiceAuthenticationDetails) obj;
|
||||
return serviceUrl.equals(that.getServiceUrl());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder result = new StringBuilder();
|
||||
result.append(super.toString());
|
||||
result.append("ServiceUrl: ");
|
||||
result.append(serviceUrl);
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* If present, removes the artifactParameterName and the corresponding value from the query String.
|
||||
* @param request
|
||||
* @return the query String minus the artifactParameterName and the corresponding value.
|
||||
*/
|
||||
private String getQueryString(final HttpServletRequest request, final Pattern artifactPattern) {
|
||||
final String query = request.getQueryString();
|
||||
if(query == null) {
|
||||
return null;
|
||||
}
|
||||
final String result = artifactPattern.matcher(query).replaceFirst("");
|
||||
if(result.length() == 0) {
|
||||
return null;
|
||||
}
|
||||
// strip off the trailing & only if the artifact was the first query param
|
||||
return result.startsWith("&") ? result.substring(1) : result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link Pattern} that can be passed into the constructor. This
|
||||
* allows the {@link Pattern} to be reused for every instance of
|
||||
* {@link DefaultServiceAuthenticationDetails}.
|
||||
*
|
||||
* @param artifactParameterName
|
||||
* @return
|
||||
*/
|
||||
static Pattern createArtifactPattern(String artifactParameterName) {
|
||||
Assert.hasLength(artifactParameterName);
|
||||
return Pattern.compile("&?"+Pattern.quote(artifactParameterName)+"=[^&]*");
|
||||
}
|
||||
}
|
||||
-43
@@ -1,43 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed 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
|
||||
*
|
||||
* 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.springframework.security.cas.web.authentication;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.springframework.security.cas.ServiceProperties;
|
||||
import org.springframework.security.cas.authentication.CasAuthenticationProvider;
|
||||
import org.springframework.security.core.Authentication;
|
||||
|
||||
/**
|
||||
* In order for the {@link CasAuthenticationProvider} to provide the correct
|
||||
* service url to authenticate the ticket, the returned value of
|
||||
* {@link Authentication#getDetails()} should implement this interface when
|
||||
* tickets can be sent to any URL rather than only
|
||||
* {@link ServiceProperties#getService()}.
|
||||
*
|
||||
* @author Rob Winch
|
||||
*
|
||||
* @see ServiceAuthenticationDetailsSource
|
||||
*/
|
||||
public interface ServiceAuthenticationDetails extends Serializable {
|
||||
|
||||
/**
|
||||
* Gets the absolute service url (i.e. https://example.com/service/).
|
||||
*
|
||||
* @return the service url. Cannot be <code>null</code>.
|
||||
*/
|
||||
String getServiceUrl();
|
||||
}
|
||||
-71
@@ -1,71 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed 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
|
||||
*
|
||||
* 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.springframework.security.cas.web.authentication;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.security.authentication.AuthenticationDetailsSource;
|
||||
import org.springframework.security.cas.ServiceProperties;
|
||||
|
||||
/**
|
||||
* The {@code AuthenticationDetailsSource} that is set on the
|
||||
* {@code CasAuthenticationFilter} should return a value that implements
|
||||
* {@code ServiceAuthenticationDetails} if the application needs to authenticate
|
||||
* dynamic service urls. The
|
||||
* {@code ServiceAuthenticationDetailsSource#buildDetails(HttpServletRequest)}
|
||||
* creates a default {@code ServiceAuthenticationDetails}.
|
||||
*
|
||||
* @author Rob Winch
|
||||
*/
|
||||
public class ServiceAuthenticationDetailsSource implements AuthenticationDetailsSource<HttpServletRequest,
|
||||
ServiceAuthenticationDetails> {
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private final Pattern artifactPattern;
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
/**
|
||||
* Creates an implementation that uses the default CAS artifactParameterName.
|
||||
*/
|
||||
public ServiceAuthenticationDetailsSource() {
|
||||
this(ServiceProperties.DEFAULT_CAS_ARTIFACT_PARAMETER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an implementation that uses the specified artifactParameterName
|
||||
*
|
||||
* @param artifactParameterName
|
||||
* the artifactParameterName that is removed from the current
|
||||
* URL. The result becomes the service url. Cannot be null and
|
||||
* cannot be an empty String.
|
||||
*/
|
||||
public ServiceAuthenticationDetailsSource(final String artifactParameterName) {
|
||||
this.artifactPattern = DefaultServiceAuthenticationDetails.createArtifactPattern(artifactParameterName);
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
/**
|
||||
* @param context the {@code HttpServletRequest} object.
|
||||
* @return the {@code ServiceAuthenticationDetails} containing information about the current request
|
||||
*/
|
||||
public ServiceAuthenticationDetails buildDetails(HttpServletRequest context) {
|
||||
return new DefaultServiceAuthenticationDetails(context,artifactPattern);
|
||||
}
|
||||
}
|
||||
-5
@@ -1,5 +0,0 @@
|
||||
/**
|
||||
* Authentication processing mechanisms which respond to the submission of authentication
|
||||
* credentials using CAS.
|
||||
*/
|
||||
package org.springframework.security.cas.web.authentication;
|
||||
+11
-93
@@ -15,31 +15,30 @@
|
||||
|
||||
package org.springframework.security.cas.authentication;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jasig.cas.client.validation.Assertion;
|
||||
import org.jasig.cas.client.validation.AssertionImpl;
|
||||
import org.jasig.cas.client.validation.TicketValidationException;
|
||||
import org.jasig.cas.client.validation.TicketValidator;
|
||||
import org.junit.*;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.junit.Test;
|
||||
import org.springframework.security.authentication.BadCredentialsException;
|
||||
import org.springframework.security.authentication.TestingAuthenticationToken;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.cas.ServiceProperties;
|
||||
import org.springframework.security.cas.web.CasAuthenticationFilter;
|
||||
import org.springframework.security.cas.web.authentication.ServiceAuthenticationDetails;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.authority.GrantedAuthorityImpl;
|
||||
import org.springframework.security.core.userdetails.AuthenticationUserDetailsService;
|
||||
import org.springframework.security.core.userdetails.User;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.security.web.authentication.WebAuthenticationDetails;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
|
||||
/**
|
||||
@@ -48,7 +47,6 @@ import java.util.*;
|
||||
* @author Ben Alex
|
||||
* @author Scott Battaglia
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public class CasAuthenticationProviderTests {
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
@@ -99,8 +97,8 @@ public class CasAuthenticationProviderTests {
|
||||
CasAuthenticationToken casResult = (CasAuthenticationToken) result;
|
||||
assertEquals(makeUserDetailsFromAuthoritiesPopulator(), casResult.getPrincipal());
|
||||
assertEquals("ST-123", casResult.getCredentials());
|
||||
assertTrue(casResult.getAuthorities().contains(new SimpleGrantedAuthority("ROLE_A")));
|
||||
assertTrue(casResult.getAuthorities().contains(new SimpleGrantedAuthority("ROLE_B")));
|
||||
assertTrue(casResult.getAuthorities().contains(new GrantedAuthorityImpl("ROLE_A")));
|
||||
assertTrue(casResult.getAuthorities().contains(new GrantedAuthorityImpl("ROLE_B")));
|
||||
assertEquals(cap.getKey().hashCode(), casResult.getKeyHash());
|
||||
assertEquals("details", casResult.getDetails());
|
||||
|
||||
@@ -151,87 +149,6 @@ public class CasAuthenticationProviderTests {
|
||||
assertEquals("ST-456", newResult.getCredentials());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authenticateAllNullService() throws Exception {
|
||||
String serviceUrl = "https://service/context";
|
||||
ServiceAuthenticationDetails details = mock(ServiceAuthenticationDetails.class);
|
||||
when(details.getServiceUrl()).thenReturn(serviceUrl);
|
||||
TicketValidator validator = mock(TicketValidator.class);
|
||||
when(validator.validate(any(String.class),any(String.class))).thenReturn(new AssertionImpl("rod"));
|
||||
|
||||
ServiceProperties serviceProperties = makeServiceProperties();
|
||||
serviceProperties.setAuthenticateAllArtifacts(true);
|
||||
|
||||
CasAuthenticationProvider cap = new CasAuthenticationProvider();
|
||||
cap.setAuthenticationUserDetailsService(new MockAuthoritiesPopulator());
|
||||
cap.setKey("qwerty");
|
||||
|
||||
cap.setTicketValidator(validator);
|
||||
cap.setServiceProperties(serviceProperties);
|
||||
cap.afterPropertiesSet();
|
||||
|
||||
String ticket = "ST-456";
|
||||
UsernamePasswordAuthenticationToken token =
|
||||
new UsernamePasswordAuthenticationToken(CasAuthenticationFilter.CAS_STATELESS_IDENTIFIER, ticket);
|
||||
|
||||
Authentication result = cap.authenticate(token);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authenticateAllAuthenticationIsSuccessful() throws Exception {
|
||||
String serviceUrl = "https://service/context";
|
||||
ServiceAuthenticationDetails details = mock(ServiceAuthenticationDetails.class);
|
||||
when(details.getServiceUrl()).thenReturn(serviceUrl);
|
||||
TicketValidator validator = mock(TicketValidator.class);
|
||||
when(validator.validate(any(String.class),any(String.class))).thenReturn(new AssertionImpl("rod"));
|
||||
|
||||
ServiceProperties serviceProperties = makeServiceProperties();
|
||||
serviceProperties.setAuthenticateAllArtifacts(true);
|
||||
|
||||
CasAuthenticationProvider cap = new CasAuthenticationProvider();
|
||||
cap.setAuthenticationUserDetailsService(new MockAuthoritiesPopulator());
|
||||
cap.setKey("qwerty");
|
||||
|
||||
cap.setTicketValidator(validator);
|
||||
cap.setServiceProperties(serviceProperties);
|
||||
cap.afterPropertiesSet();
|
||||
|
||||
String ticket = "ST-456";
|
||||
UsernamePasswordAuthenticationToken token =
|
||||
new UsernamePasswordAuthenticationToken(CasAuthenticationFilter.CAS_STATELESS_IDENTIFIER, ticket);
|
||||
|
||||
Authentication result = cap.authenticate(token);
|
||||
verify(validator).validate(ticket, serviceProperties.getService());
|
||||
|
||||
serviceProperties.setAuthenticateAllArtifacts(true);
|
||||
result = cap.authenticate(token);
|
||||
verify(validator,times(2)).validate(ticket, serviceProperties.getService());
|
||||
|
||||
token.setDetails(details);
|
||||
result = cap.authenticate(token);
|
||||
verify(validator).validate(ticket, serviceUrl);
|
||||
|
||||
serviceProperties.setAuthenticateAllArtifacts(false);
|
||||
serviceProperties.setService(null);
|
||||
cap.setServiceProperties(serviceProperties);
|
||||
cap.afterPropertiesSet();
|
||||
result = cap.authenticate(token);
|
||||
verify(validator,times(2)).validate(ticket, serviceUrl);
|
||||
|
||||
token.setDetails(new WebAuthenticationDetails(new MockHttpServletRequest()));
|
||||
try {
|
||||
cap.authenticate(token);
|
||||
fail("Expected Exception");
|
||||
}catch(IllegalStateException success) {}
|
||||
|
||||
cap.setServiceProperties(null);
|
||||
cap.afterPropertiesSet();
|
||||
try {
|
||||
cap.authenticate(token);
|
||||
fail("Expected Exception");
|
||||
}catch(IllegalStateException success) {}
|
||||
}
|
||||
|
||||
@Test(expected = BadCredentialsException.class)
|
||||
public void missingTicketIdIsDetected() throws Exception {
|
||||
CasAuthenticationProvider cap = new CasAuthenticationProvider();
|
||||
@@ -338,7 +255,8 @@ public class CasAuthenticationProviderTests {
|
||||
cap.setServiceProperties(makeServiceProperties());
|
||||
cap.afterPropertiesSet();
|
||||
|
||||
TestingAuthenticationToken token = new TestingAuthenticationToken("user", "password", "ROLE_A");
|
||||
TestingAuthenticationToken token = new TestingAuthenticationToken("user", "password",
|
||||
new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_A")});
|
||||
assertFalse(cap.supports(TestingAuthenticationToken.class));
|
||||
|
||||
// Try it anyway
|
||||
|
||||
+6
-5
@@ -15,18 +15,19 @@
|
||||
|
||||
package org.springframework.security.cas.authentication;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.jasig.cas.client.validation.Assertion;
|
||||
import org.jasig.cas.client.validation.AssertionImpl;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.authority.GrantedAuthorityImpl;
|
||||
import org.springframework.security.core.userdetails.User;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Tests {@link CasAuthenticationToken}.
|
||||
*
|
||||
@@ -107,8 +108,8 @@ public class CasAuthenticationTokenTests extends TestCase {
|
||||
assertEquals("key".hashCode(), token.getKeyHash());
|
||||
assertEquals(makeUserDetails(), token.getPrincipal());
|
||||
assertEquals("Password", token.getCredentials());
|
||||
assertTrue(token.getAuthorities().contains(new SimpleGrantedAuthority("ROLE_ONE")));
|
||||
assertTrue(token.getAuthorities().contains(new SimpleGrantedAuthority("ROLE_TWO")));
|
||||
assertTrue(token.getAuthorities().contains(new GrantedAuthorityImpl("ROLE_ONE")));
|
||||
assertTrue(token.getAuthorities().contains(new GrantedAuthorityImpl("ROLE_TWO")));
|
||||
assertEquals(assertion, token.getAssertion());
|
||||
assertEquals(makeUserDetails().getUsername(), token.getUserDetails().getUsername());
|
||||
}
|
||||
|
||||
-49
@@ -1,49 +0,0 @@
|
||||
package org.springframework.security.cas.userdetails;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.jasig.cas.client.authentication.AttributePrincipal;
|
||||
import org.jasig.cas.client.validation.Assertion;
|
||||
import org.junit.Test;
|
||||
import org.springframework.security.cas.authentication.CasAssertionAuthenticationToken;
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author Luke Taylor
|
||||
*/
|
||||
public class GrantedAuthorityFromAssertionAttributesUserDetailsServiceTests {
|
||||
|
||||
@Test
|
||||
public void correctlyExtractsNamedAttributesFromAssertionAndConvertsThemToAuthorities() {
|
||||
GrantedAuthorityFromAssertionAttributesUserDetailsService uds =
|
||||
new GrantedAuthorityFromAssertionAttributesUserDetailsService(new String[] {"a", "b", "c", "d"});
|
||||
uds.setConvertToUpperCase(false);
|
||||
Assertion assertion = mock(Assertion.class);
|
||||
AttributePrincipal principal = mock(AttributePrincipal.class);
|
||||
Map<String, Object> attributes = new HashMap<String, Object>();
|
||||
attributes.put("a", Arrays.asList("role_a1", "role_a2"));
|
||||
attributes.put("b", "role_b");
|
||||
attributes.put("c", "role_c");
|
||||
attributes.put("d", null);
|
||||
attributes.put("someother", "unused");
|
||||
when(assertion.getPrincipal()).thenReturn(principal);
|
||||
when(principal.getAttributes()).thenReturn(attributes);
|
||||
when(principal.getName()).thenReturn("somebody");
|
||||
CasAssertionAuthenticationToken token = new CasAssertionAuthenticationToken(assertion, "ticket");
|
||||
UserDetails user = uds.loadUserDetails(token);
|
||||
Set<String> roles = AuthorityUtils.authorityListToSet(user.getAuthorities());
|
||||
assertTrue(roles.size() == 4);
|
||||
assertTrue(roles.contains("role_a1"));
|
||||
assertTrue(roles.contains("role_a2"));
|
||||
assertTrue(roles.contains("role_b"));
|
||||
assertTrue(roles.contains("role_c"));
|
||||
}
|
||||
}
|
||||
+3
-146
@@ -16,62 +16,33 @@
|
||||
package org.springframework.security.cas.web;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.jasig.cas.client.proxy.ProxyGrantingTicketStorage;
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.security.authentication.AnonymousAuthenticationToken;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.BadCredentialsException;
|
||||
import org.springframework.security.authentication.TestingAuthenticationToken;
|
||||
import org.springframework.security.cas.ServiceProperties;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
|
||||
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
|
||||
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
|
||||
import org.springframework.security.web.authentication.NullRememberMeServices;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
|
||||
/**
|
||||
* Tests {@link CasAuthenticationFilter}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @author Rob Winch
|
||||
*/
|
||||
public class CasAuthenticationFilterTests {
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
SecurityContextHolder.clearContext();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGettersSetters() {
|
||||
public void testGetters() {
|
||||
CasAuthenticationFilter filter = new CasAuthenticationFilter();
|
||||
assertEquals("/j_spring_cas_security_check", filter.getFilterProcessesUrl());
|
||||
filter.setProxyGrantingTicketStorage(mock(ProxyGrantingTicketStorage.class));
|
||||
filter.setProxyReceptorUrl("/someurl");
|
||||
filter.setServiceProperties(new ServiceProperties());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNormalOperation() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/j_spring_cas_security_check");
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addParameter("ticket", "ST-0-ER94xMJmn6pha35CQRoZ");
|
||||
|
||||
CasAuthenticationFilter filter = new CasAuthenticationFilter();
|
||||
@@ -81,8 +52,6 @@ public class CasAuthenticationFilterTests {
|
||||
}
|
||||
});
|
||||
|
||||
assertTrue(filter.requiresAuthentication(request, new MockHttpServletResponse()));
|
||||
|
||||
Authentication result = filter.attemptAuthentication(request, new MockHttpServletResponse());
|
||||
assertTrue(result != null);
|
||||
}
|
||||
@@ -98,116 +67,4 @@ public class CasAuthenticationFilterTests {
|
||||
|
||||
filter.attemptAuthentication(new MockHttpServletRequest(), new MockHttpServletResponse());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRequiresAuthenticationFilterProcessUrl() {
|
||||
CasAuthenticationFilter filter = new CasAuthenticationFilter();
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
request.setRequestURI(filter.getFilterProcessesUrl());
|
||||
assertTrue(filter.requiresAuthentication(request, response));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRequiresAuthenticationProxyRequest() {
|
||||
CasAuthenticationFilter filter = new CasAuthenticationFilter();
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
request.setRequestURI("/pgtCallback");
|
||||
assertFalse(filter.requiresAuthentication(request, response));
|
||||
filter.setProxyReceptorUrl(request.getRequestURI());
|
||||
assertFalse(filter.requiresAuthentication(request, response));
|
||||
filter.setProxyGrantingTicketStorage(mock(ProxyGrantingTicketStorage.class));
|
||||
assertTrue(filter.requiresAuthentication(request, response));
|
||||
request.setRequestURI("/other");
|
||||
assertFalse(filter.requiresAuthentication(request, response));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRequiresAuthenticationAuthAll() {
|
||||
ServiceProperties properties = new ServiceProperties();
|
||||
properties.setAuthenticateAllArtifacts(true);
|
||||
|
||||
CasAuthenticationFilter filter = new CasAuthenticationFilter();
|
||||
filter.setServiceProperties(properties);
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
request.setRequestURI(filter.getFilterProcessesUrl());
|
||||
assertTrue(filter.requiresAuthentication(request, response));
|
||||
|
||||
request.setRequestURI("/other");
|
||||
assertFalse(filter.requiresAuthentication(request, response));
|
||||
request.setParameter(properties.getArtifactParameter(), "value");
|
||||
assertTrue(filter.requiresAuthentication(request, response));
|
||||
SecurityContextHolder.getContext().setAuthentication(new AnonymousAuthenticationToken("key", "principal", AuthorityUtils.createAuthorityList("ROLE_ANONYMOUS")));
|
||||
assertTrue(filter.requiresAuthentication(request, response));
|
||||
SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken("un", "principal", AuthorityUtils.createAuthorityList("ROLE_ANONYMOUS")));
|
||||
assertTrue(filter.requiresAuthentication(request, response));
|
||||
SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken("un", "principal", "ROLE_ANONYMOUS"));
|
||||
assertFalse(filter.requiresAuthentication(request, response));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAuthenticateProxyUrl() throws Exception {
|
||||
CasAuthenticationFilter filter = new CasAuthenticationFilter();
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
request.setRequestURI("/pgtCallback");
|
||||
filter.setProxyGrantingTicketStorage(mock(ProxyGrantingTicketStorage.class));
|
||||
filter.setProxyReceptorUrl(request.getRequestURI());
|
||||
assertNull(filter.attemptAuthentication(request, response));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDoFilterAuthenticateAll() throws Exception {
|
||||
AuthenticationSuccessHandler successHandler = mock(AuthenticationSuccessHandler.class);
|
||||
AuthenticationManager manager = mock(AuthenticationManager.class);
|
||||
Authentication authentication = new TestingAuthenticationToken("un", "pwd","ROLE_USER");
|
||||
when(manager.authenticate(any(Authentication.class))).thenReturn(authentication);
|
||||
ServiceProperties serviceProperties = new ServiceProperties();
|
||||
serviceProperties.setAuthenticateAllArtifacts(true);
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setParameter("ticket", "ST-1-123");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
FilterChain chain = mock(FilterChain.class);
|
||||
|
||||
CasAuthenticationFilter filter = new CasAuthenticationFilter();
|
||||
filter.setServiceProperties(serviceProperties);
|
||||
filter.setAuthenticationSuccessHandler(successHandler);
|
||||
filter.setProxyGrantingTicketStorage(mock(ProxyGrantingTicketStorage.class));
|
||||
filter.setAuthenticationManager(manager);
|
||||
filter.afterPropertiesSet();
|
||||
|
||||
filter.doFilter(request,response,chain);
|
||||
assertFalse("Authentication should not be null",SecurityContextHolder.getContext().getAuthentication() == null);
|
||||
verify(chain).doFilter(request, response);
|
||||
verifyZeroInteractions(successHandler);
|
||||
|
||||
// validate for when the filterProcessUrl matches
|
||||
filter.setFilterProcessesUrl(request.getRequestURI());
|
||||
SecurityContextHolder.clearContext();
|
||||
filter.doFilter(request,response,chain);
|
||||
verifyNoMoreInteractions(chain);
|
||||
verify(successHandler).onAuthenticationSuccess(request, response, authentication);
|
||||
}
|
||||
|
||||
// SEC-1592
|
||||
@Test
|
||||
public void testChainNotInvokedForProxyReceptor() throws Exception {
|
||||
CasAuthenticationFilter filter = new CasAuthenticationFilter();
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
FilterChain chain = mock(FilterChain.class);
|
||||
|
||||
request.setRequestURI("/pgtCallback");
|
||||
filter.setProxyGrantingTicketStorage(mock(ProxyGrantingTicketStorage.class));
|
||||
filter.setProxyReceptorUrl(request.getRequestURI());
|
||||
|
||||
filter.doFilter(request,response,chain);
|
||||
verifyZeroInteractions(chain);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+21
-36
@@ -15,55 +15,40 @@
|
||||
|
||||
package org.springframework.security.cas.web;
|
||||
|
||||
import static junit.framework.Assert.*;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.security.cas.SamlServiceProperties;
|
||||
import org.springframework.security.cas.ServiceProperties;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
|
||||
/**
|
||||
* Tests {@link ServiceProperties}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
*/
|
||||
public class ServicePropertiesTests {
|
||||
public class ServicePropertiesTests extends TestCase {
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void detectsMissingService() throws Exception {
|
||||
public void testDetectsMissingLoginFormUrl() throws Exception {
|
||||
ServiceProperties sp = new ServiceProperties();
|
||||
sp.afterPropertiesSet();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void allowNullServiceWhenAuthenticateAllTokens() throws Exception {
|
||||
ServiceProperties sp = new ServiceProperties();
|
||||
sp.setAuthenticateAllArtifacts(true);
|
||||
sp.afterPropertiesSet();
|
||||
sp.setAuthenticateAllArtifacts(false);
|
||||
try {
|
||||
sp.afterPropertiesSet();
|
||||
fail("Expected Exception");
|
||||
}catch(IllegalArgumentException success) {}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGettersSetters() throws Exception {
|
||||
ServiceProperties[] sps = {new ServiceProperties(), new SamlServiceProperties()};
|
||||
for(ServiceProperties sp : sps) {
|
||||
sp.setSendRenew(false);
|
||||
assertFalse(sp.isSendRenew());
|
||||
sp.setSendRenew(true);
|
||||
assertTrue(sp.isSendRenew());
|
||||
sp.setArtifactParameter("notticket");
|
||||
assertEquals("notticket", sp.getArtifactParameter());
|
||||
sp.setServiceParameter("notservice");
|
||||
assertEquals("notservice", sp.getServiceParameter());
|
||||
|
||||
sp.setService("https://mycompany.com/service");
|
||||
assertEquals("https://mycompany.com/service", sp.getService());
|
||||
|
||||
sp.afterPropertiesSet();
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertEquals("service must be specified.", expected.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void testGettersSetters() throws Exception {
|
||||
ServiceProperties sp = new ServiceProperties();
|
||||
sp.setSendRenew(false);
|
||||
assertFalse(sp.isSendRenew());
|
||||
sp.setSendRenew(true);
|
||||
assertTrue(sp.isSendRenew());
|
||||
|
||||
sp.setService("https://mycompany.com/service");
|
||||
assertEquals("https://mycompany.com/service", sp.getService());
|
||||
|
||||
sp.afterPropertiesSet();
|
||||
}
|
||||
}
|
||||
|
||||
-88
@@ -1,88 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed 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
|
||||
*
|
||||
* 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.springframework.security.cas.web.authentication;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.security.cas.ServiceProperties;
|
||||
import org.springframework.security.web.util.UrlUtils;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Rob Winch
|
||||
*/
|
||||
public class DefaultServiceAuthenticationDetailsTests {
|
||||
private DefaultServiceAuthenticationDetails details;
|
||||
private MockHttpServletRequest request;
|
||||
private Pattern artifactPattern;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
request = new MockHttpServletRequest();
|
||||
request.setScheme("https");
|
||||
request.setServerName("localhost");
|
||||
request.setServerPort(8443);
|
||||
request.setRequestURI("/cas-sample/secure/");
|
||||
artifactPattern = DefaultServiceAuthenticationDetails.createArtifactPattern(ServiceProperties.DEFAULT_CAS_ARTIFACT_PARAMETER);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getServiceUrlNullQuery() throws Exception {
|
||||
details = new DefaultServiceAuthenticationDetails(request,artifactPattern);
|
||||
assertEquals(UrlUtils.buildFullRequestUrl(request),details.getServiceUrl());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getServiceUrlTicketOnlyParam() {
|
||||
request.setQueryString("ticket=123");
|
||||
details = new DefaultServiceAuthenticationDetails(request,artifactPattern);
|
||||
String serviceUrl = details.getServiceUrl();
|
||||
request.setQueryString(null);
|
||||
assertEquals(UrlUtils.buildFullRequestUrl(request),serviceUrl);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getServiceUrlTicketFirstMultiParam() {
|
||||
request.setQueryString("ticket=123&other=value");
|
||||
details = new DefaultServiceAuthenticationDetails(request,artifactPattern);
|
||||
String serviceUrl = details.getServiceUrl();
|
||||
request.setQueryString("other=value");
|
||||
assertEquals(UrlUtils.buildFullRequestUrl(request),serviceUrl);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getServiceUrlTicketLastMultiParam() {
|
||||
request.setQueryString("other=value&ticket=123");
|
||||
details = new DefaultServiceAuthenticationDetails(request,artifactPattern);
|
||||
String serviceUrl = details.getServiceUrl();
|
||||
request.setQueryString("other=value");
|
||||
assertEquals(UrlUtils.buildFullRequestUrl(request),serviceUrl);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getServiceUrlTicketMiddleMultiParam() {
|
||||
request.setQueryString("other=value&ticket=123&last=this");
|
||||
details = new DefaultServiceAuthenticationDetails(request,artifactPattern);
|
||||
String serviceUrl = details.getServiceUrl();
|
||||
request.setQueryString("other=value&last=this");
|
||||
assertEquals(UrlUtils.buildFullRequestUrl(request),serviceUrl);
|
||||
}
|
||||
}
|
||||
+12
-12
@@ -5,18 +5,18 @@ Bundle-Name: Spring Security CAS
|
||||
Bundle-Vendor: SpringSource
|
||||
Bundle-Version: ${version}
|
||||
Bundle-ManifestVersion: 2
|
||||
Ignored-Existing-Headers:
|
||||
Ignored-Existing-Headers:
|
||||
Import-Package,
|
||||
Export-Package
|
||||
Import-Template:
|
||||
org.apache.commons.logging.*;version="${cloggingRange}",
|
||||
org.jasig.cas.client.*;version="${casRange}",
|
||||
org.springframework.security.core.*;version="${secRange}",
|
||||
org.springframework.security.authentication.*;version="${secRange}",
|
||||
org.springframework.security.web.*;version="${secRange}",
|
||||
org.springframework.beans.factory;version="${springRange}",
|
||||
org.springframework.context.*;version="${springRange}",
|
||||
org.springframework.dao;version="${springRange}",
|
||||
org.springframework.util;version="${springRange}",
|
||||
net.sf.ehcache.*;version="${ehcacheRange}";resolution:=optional,
|
||||
Import-Template:
|
||||
org.apache.commons.logging.*;version="[1.0.4, 2.0.0)",
|
||||
org.jasig.cas.client.*;version="[3.1.1,3.2)",
|
||||
org.springframework.security.core.*;version="[${version}, 3.1.0)",
|
||||
org.springframework.security.authentication.*;version="[${version}, 3.1.0)",
|
||||
org.springframework.security.web.*;version="[${version}, 3.1.0)",
|
||||
org.springframework.beans.factory;version="[${spring.version}, 3.1.0)",
|
||||
org.springframework.context.*;version="[${spring.version}, 3.1.0)",
|
||||
org.springframework.dao;version="[${spring.version}, 3.1.0)",
|
||||
org.springframework.util;version="[${spring.version}, 3.1.0)",
|
||||
net.sf.ehcache.*;version="[1.4.1, 2.0.0)";resolution:=optional,
|
||||
javax.servlet.*;version="0"
|
||||
|
||||
+5
-34
@@ -1,53 +1,24 @@
|
||||
// Config Module build file
|
||||
|
||||
apply plugin: 'groovy'
|
||||
|
||||
compileTestJava.dependsOn(':spring-security-core:compileTestJava')
|
||||
|
||||
configurations {
|
||||
// GRADLE-1124
|
||||
compile.extendsFrom = []
|
||||
testCompile.extendsFrom groovy
|
||||
}
|
||||
|
||||
dependencies {
|
||||
// NB: Don't add other compile time dependencies to the config module as this breaks tooling
|
||||
compile project(':spring-security-core'),
|
||||
project(':spring-security-web'),
|
||||
"org.aspectj:aspectjweaver:$aspectjVersion",
|
||||
'aopalliance:aopalliance:1.0',
|
||||
"org.aspectj:aspectjweaver:$aspectjVersion",
|
||||
"org.springframework:spring-aop:$springVersion",
|
||||
"org.springframework:spring-context:$springVersion",
|
||||
"org.springframework:spring-web:$springVersion",
|
||||
"org.springframework:spring-beans:$springVersion"
|
||||
"org.springframework:spring-beans:$springVersion",
|
||||
"org.springframework:spring-tx:$springVersion"
|
||||
|
||||
provided "javax.servlet:servlet-api:2.5"
|
||||
|
||||
groovy group: 'org.codehaus.groovy', name: 'groovy', version: '1.7.10'
|
||||
|
||||
testCompile project(':spring-security-ldap'),
|
||||
project(':spring-security-openid'),
|
||||
project(':spring-security-core').sourceSets.test.classes,
|
||||
files(this.project(':spring-security-core').sourceSets.test.classesDir),
|
||||
'javax.annotation:jsr250-api:1.0',
|
||||
"org.springframework.ldap:spring-ldap-core:$springLdapVersion",
|
||||
"org.springframework:spring-expression:$springVersion",
|
||||
"org.springframework:spring-jdbc:$springVersion",
|
||||
"org.springframework:spring-tx:$springVersion",
|
||||
'org.spockframework:spock-core:0.5-groovy-1.7',
|
||||
"org.slf4j:jcl-over-slf4j:$slf4jVersion"
|
||||
testCompile('org.openid4java:openid4java-nodeps:0.9.6') {
|
||||
exclude group: 'com.google.code.guice', module: 'guice'
|
||||
}
|
||||
|
||||
|
||||
testRuntime "hsqldb:hsqldb:$hsqlVersion",
|
||||
"cglib:cglib-nodep:2.2"
|
||||
}
|
||||
|
||||
test {
|
||||
inputs.file file("$rootDir/docs/manual/src/docbook/appendix-namespace.xml")
|
||||
}
|
||||
|
||||
integrationTest {
|
||||
systemProperties['apacheDSWorkDir'] = "${buildDir}/apacheDSWork"
|
||||
"org.springframework:spring-jdbc:$springVersion"
|
||||
}
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
pushd src/main/resources/org/springframework/security/config/
|
||||
|
||||
echo "Converting rnc file to xsd ..."
|
||||
java -jar ~/bin/trang.jar spring-security-3.1.rnc spring-security-3.1.xsd
|
||||
java -jar ~/bin/trang.jar spring-security-3.0.4.rnc spring-security-3.0.4.xsd
|
||||
|
||||
echo "Applying XSL transformation to xsd ..."
|
||||
xsltproc --output spring-security-3.1.xsd spring-security.xsl spring-security-3.1.xsd
|
||||
xsltproc --output spring-security-3.0.4.xsd spring-security.xsl spring-security-3.0.4.xsd
|
||||
|
||||
popd
|
||||
+113
@@ -0,0 +1,113 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-parent</artifactId>
|
||||
<version>3.0.4.RELEASE</version>
|
||||
</parent>
|
||||
<packaging>jar</packaging>
|
||||
<artifactId>spring-security-config</artifactId>
|
||||
<name>Spring Security - Namespace Configuration Module</name>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-web</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<classifier>tests</classifier>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-web</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<classifier>tests</classifier>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-openid</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-ldap</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-jdbc</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-web</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.directory.server</groupId>
|
||||
<artifactId>apacheds-core</artifactId>
|
||||
<version>1.5.5</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.directory.server</groupId>
|
||||
<artifactId>apacheds-server-jndi</artifactId>
|
||||
<version>1.5.5</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-log4j12</artifactId>
|
||||
<version>1.6.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>hsqldb</groupId>
|
||||
<artifactId>hsqldb</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cglib</groupId>
|
||||
<artifactId>cglib-nodep</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.annotation</groupId>
|
||||
<artifactId>jsr250-api</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>servlet-api</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>com.springsource.bundlor</groupId>
|
||||
<artifactId>com.springsource.bundlor.maven</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
-153
@@ -1,153 +0,0 @@
|
||||
package org.springframework.security.config.ldap
|
||||
|
||||
import java.text.MessageFormat
|
||||
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer
|
||||
import org.springframework.security.config.AbstractXmlConfigTests
|
||||
import org.springframework.security.config.BeanIds
|
||||
import org.springframework.security.util.FieldUtils
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken
|
||||
import org.springframework.context.ApplicationContextException
|
||||
import org.springframework.security.core.AuthenticationException
|
||||
import org.springframework.security.ldap.userdetails.InetOrgPersonContextMapper
|
||||
|
||||
/**
|
||||
* @author Luke Taylor
|
||||
*/
|
||||
class LdapProviderBeanDefinitionParserTests extends AbstractXmlConfigTests {
|
||||
|
||||
// SEC-1182
|
||||
def multipleProvidersAreSupported() {
|
||||
xml.'ldap-server'(url: 'ldap://blah:389/dc=blah')
|
||||
xml.'authentication-manager'() {
|
||||
'ldap-authentication-provider'('group-search-filter': 'member={0}')
|
||||
'ldap-authentication-provider'('group-search-filter': 'uniqueMember={0}')
|
||||
}
|
||||
|
||||
createAppContext('')
|
||||
|
||||
def providers = appContext.getBean(BeanIds.AUTHENTICATION_MANAGER).providers
|
||||
|
||||
expect:
|
||||
|
||||
providers.size() == 2
|
||||
providers[0].authoritiesPopulator.groupSearchFilter == "member={0}"
|
||||
providers[1].authoritiesPopulator.groupSearchFilter == "uniqueMember={0}"
|
||||
}
|
||||
|
||||
|
||||
def simpleProviderAuthenticatesCorrectly() {
|
||||
xml.'ldap-server'()
|
||||
xml.'authentication-manager'{
|
||||
'ldap-authentication-provider'('group-search-filter':'member={0}')
|
||||
}
|
||||
|
||||
createAppContext('')
|
||||
|
||||
def am = appContext.getBean(BeanIds.AUTHENTICATION_MANAGER)
|
||||
|
||||
when:
|
||||
def auth = am.authenticate(new UsernamePasswordAuthenticationToken("ben", "benspassword"))
|
||||
def ben = auth.principal;
|
||||
|
||||
then:
|
||||
ben.authorities.size() == 3
|
||||
}
|
||||
|
||||
def missingServerEltCausesConfigException() {
|
||||
xml.'authentication-manager'{
|
||||
'ldap-authentication-provider'()
|
||||
}
|
||||
|
||||
when:
|
||||
createAppContext('')
|
||||
|
||||
then:
|
||||
thrown(ApplicationContextException)
|
||||
}
|
||||
|
||||
def supportsPasswordComparisonAuthentication() {
|
||||
xml.'ldap-server'()
|
||||
xml.'authentication-manager'{
|
||||
'ldap-authentication-provider'('user-dn-pattern': 'uid={0},ou=people')
|
||||
'password-compare'
|
||||
}
|
||||
createAppContext('')
|
||||
def am = appContext.getBean(BeanIds.AUTHENTICATION_MANAGER)
|
||||
|
||||
when:
|
||||
def auth = am.authenticate(new UsernamePasswordAuthenticationToken("ben", "benspassword"))
|
||||
|
||||
then:
|
||||
auth != null
|
||||
notThrown(AuthenticationException)
|
||||
}
|
||||
|
||||
def supportsPasswordComparisonAuthenticationWithHashAttribute() {
|
||||
xml.'ldap-server'()
|
||||
xml.'authentication-manager'{
|
||||
'ldap-authentication-provider'('user-dn-pattern': 'uid={0},ou=people') {
|
||||
'password-compare'('password-attribute': 'uid', hash: 'plaintext')
|
||||
}
|
||||
}
|
||||
createAppContext('')
|
||||
def am = appContext.getBean(BeanIds.AUTHENTICATION_MANAGER)
|
||||
|
||||
when:
|
||||
def auth = am.authenticate(new UsernamePasswordAuthenticationToken("ben", "ben"))
|
||||
|
||||
then:
|
||||
auth != null
|
||||
notThrown(AuthenticationException)
|
||||
|
||||
}
|
||||
|
||||
def supportsPasswordComparisonAuthenticationWithPasswordEncoder() {
|
||||
xml.'ldap-server'()
|
||||
xml.'authentication-manager'{
|
||||
'ldap-authentication-provider'('user-dn-pattern': 'uid={0},ou=people') {
|
||||
'password-compare'('password-attribute': 'uid') {
|
||||
'password-encoder'(hash: 'plaintext')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
createAppContext('')
|
||||
def am = appContext.getBean(BeanIds.AUTHENTICATION_MANAGER)
|
||||
|
||||
when:
|
||||
def auth = am.authenticate(new UsernamePasswordAuthenticationToken("ben", "ben"))
|
||||
|
||||
then:
|
||||
auth != null
|
||||
notThrown(AuthenticationException)
|
||||
}
|
||||
|
||||
def inetOrgContextMapperIsSupported() {
|
||||
xml.'ldap-server'(url: 'ldap://127.0.0.1:343/dc=springframework,dc=org')
|
||||
xml.'authentication-manager'{
|
||||
'ldap-authentication-provider'('user-details-class' :'inetOrgPerson')
|
||||
}
|
||||
createAppContext('')
|
||||
|
||||
expect:
|
||||
appContext.getBean(BeanIds.AUTHENTICATION_MANAGER).providers[0].userDetailsContextMapper instanceof InetOrgPersonContextMapper
|
||||
}
|
||||
|
||||
def ldapAuthenticationProviderWorksWithPlaceholders() {
|
||||
System.setProperty('udp','people')
|
||||
System.setProperty('gsf','member')
|
||||
|
||||
xml.'ldap-server'()
|
||||
xml.'authentication-manager'{
|
||||
'ldap-authentication-provider'('user-dn-pattern':'uid={0},ou=${udp}','group-search-filter':'${gsf}={0}')
|
||||
}
|
||||
bean(PropertyPlaceholderConfigurer.class.name, PropertyPlaceholderConfigurer.class)
|
||||
|
||||
createAppContext('')
|
||||
def provider = this.appContext.getBean(BeanIds.AUTHENTICATION_MANAGER).providers[0]
|
||||
|
||||
expect:
|
||||
[new MessageFormat("uid={0},ou=people")] == FieldUtils.getFieldValue(provider,"authenticator.userDnFormat")
|
||||
"member={0}" == FieldUtils.getFieldValue(provider, "authoritiesPopulator.groupSearchFilter")
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
<configuration>
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<logger name="org.springframework.security" level="${sec.log.level}:-WARN"/>
|
||||
|
||||
<logger name="org.apache.directory" level="ERROR"/>
|
||||
<logger name="JdbmTable" level="INFO"/>
|
||||
<logger name="JdbmIndex" level="INFO"/>
|
||||
<logger name="org.apache.mina" level="WARN"/>
|
||||
|
||||
<root level="${root.level}:-WARN">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</root>
|
||||
|
||||
</configuration>
|
||||
@@ -6,7 +6,6 @@ package org.springframework.security.config;
|
||||
* These are intended for internal use.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @author Luke Taylor
|
||||
*/
|
||||
public abstract class BeanIds {
|
||||
private static final String PREFIX = "org.springframework.security.";
|
||||
@@ -20,16 +19,12 @@ public abstract class BeanIds {
|
||||
public static final String CONTEXT_SOURCE_SETTING_POST_PROCESSOR = PREFIX + "contextSettingPostProcessor";
|
||||
|
||||
public static final String USER_DETAILS_SERVICE = PREFIX + "userDetailsService";
|
||||
public static final String USER_DETAILS_SERVICE_FACTORY = PREFIX + "userDetailsServiceFactory";
|
||||
|
||||
public static final String METHOD_ACCESS_MANAGER = PREFIX + "defaultMethodAccessManager";
|
||||
|
||||
public static final String FILTER_CHAIN_PROXY = PREFIX + "filterChainProxy";
|
||||
public static final String FILTER_CHAINS = PREFIX + "filterChains";
|
||||
|
||||
public static final String METHOD_SECURITY_METADATA_SOURCE_ADVISOR = PREFIX + "methodSecurityMetadataSourceAdvisor";
|
||||
public static final String EMBEDDED_APACHE_DS = PREFIX + "apacheDirectoryServerContainer";
|
||||
public static final String CONTEXT_SOURCE = PREFIX + "securityContextSource";
|
||||
|
||||
public static final String DEBUG_FILTER = PREFIX + "debugFilter";
|
||||
}
|
||||
|
||||
-20
@@ -1,20 +0,0 @@
|
||||
package org.springframework.security.config;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.security.config.debug.SecurityDebugBeanFactoryPostProcessor;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* @author Luke Taylor
|
||||
*/
|
||||
public class DebugBeanDefinitionParser implements BeanDefinitionParser {
|
||||
public BeanDefinition parse(Element element, ParserContext parserContext) {
|
||||
RootBeanDefinition debugPP = new RootBeanDefinition(SecurityDebugBeanFactoryPostProcessor.class);
|
||||
parserContext.getReaderContext().registerWithGeneratedName(debugPP);
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
package org.springframework.security.config;
|
||||
|
||||
/**
|
||||
* Contains all the element names used by Spring Security 3 namespace support.
|
||||
* Contains all the element names used by Spring Security 2 namespace support.
|
||||
*
|
||||
* @author Ben Alex
|
||||
*/
|
||||
@@ -46,12 +46,9 @@ public abstract class Elements {
|
||||
public static final String CUSTOM_FILTER = "custom-filter";
|
||||
public static final String REQUEST_CACHE = "request-cache";
|
||||
public static final String X509 = "x509";
|
||||
public static final String JEE = "jee";
|
||||
public static final String FILTER_SECURITY_METADATA_SOURCE = "filter-security-metadata-source";
|
||||
public static final String METHOD_SECURITY_METADATA_SOURCE = "method-security-metadata-source";
|
||||
@Deprecated
|
||||
public static final String FILTER_INVOCATION_DEFINITION_SOURCE = "filter-invocation-definition-source";
|
||||
public static final String LDAP_PASSWORD_COMPARE = "password-compare";
|
||||
public static final String DEBUG = "debug";
|
||||
public static final String HTTP_FIREWALL = "http-firewall";
|
||||
}
|
||||
|
||||
+19
-27
@@ -1,5 +1,8 @@
|
||||
package org.springframework.security.config;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
@@ -12,7 +15,6 @@ import org.springframework.security.config.authentication.AuthenticationManagerB
|
||||
import org.springframework.security.config.authentication.AuthenticationProviderBeanDefinitionParser;
|
||||
import org.springframework.security.config.authentication.JdbcUserServiceBeanDefinitionParser;
|
||||
import org.springframework.security.config.authentication.UserServiceBeanDefinitionParser;
|
||||
import org.springframework.security.config.http.FilterChainBeanDefinitionParser;
|
||||
import org.springframework.security.config.http.FilterChainMapBeanDefinitionDecorator;
|
||||
import org.springframework.security.config.http.FilterInvocationSecurityMetadataSourceParser;
|
||||
import org.springframework.security.config.http.HttpFirewallBeanDefinitionParser;
|
||||
@@ -22,14 +24,11 @@ import org.springframework.security.config.ldap.LdapServerBeanDefinitionParser;
|
||||
import org.springframework.security.config.ldap.LdapUserServiceBeanDefinitionParser;
|
||||
import org.springframework.security.config.method.GlobalMethodSecurityBeanDefinitionParser;
|
||||
import org.springframework.security.config.method.InterceptMethodsBeanDefinitionDecorator;
|
||||
import org.springframework.security.config.method.MethodSecurityMetadataSourceBeanDefinitionParser;
|
||||
import org.springframework.security.core.SpringSecurityCoreVersion;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Parses elements from the "security" namespace (http://www.springframework.org/schema/security).
|
||||
*
|
||||
@@ -39,6 +38,7 @@ import java.util.*;
|
||||
*/
|
||||
public final class SecurityNamespaceHandler implements NamespaceHandler {
|
||||
private final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private final Map<String, BeanDefinitionParser> parsers = new HashMap<String, BeanDefinitionParser>();
|
||||
private final BeanDefinitionDecorator interceptMethodsBDD = new InterceptMethodsBeanDefinitionDecorator();
|
||||
private BeanDefinitionDecorator filterChainMapBDD;
|
||||
@@ -63,8 +63,9 @@ public final class SecurityNamespaceHandler implements NamespaceHandler {
|
||||
|
||||
public BeanDefinition parse(Element element, ParserContext pc) {
|
||||
if (!namespaceMatchesVersion(element)) {
|
||||
pc.getReaderContext().fatal("You cannot use a spring-security-2.0.xsd or spring-security-3.0.xsd schema " +
|
||||
"with Spring Security 3.1. Please update your schema declarations to the 3.1 schema.", element);
|
||||
pc.getReaderContext().fatal("You must use a 3.0 schema with Spring Security 3.0." +
|
||||
"(2.0 or 3.1 versions are not valid)" +
|
||||
" Please update your schema declarations to the 3.0.3 schema (spring-security-3.0.3.xsd).", element);
|
||||
}
|
||||
String name = pc.getDelegate().getLocalName(element);
|
||||
BeanDefinitionParser parser = parsers.get(name);
|
||||
@@ -75,20 +76,18 @@ public final class SecurityNamespaceHandler implements NamespaceHandler {
|
||||
}
|
||||
|
||||
if (parser == null) {
|
||||
if (Elements.HTTP.equals(name) || Elements.FILTER_SECURITY_METADATA_SOURCE.equals(name) ||
|
||||
Elements.FILTER_CHAIN_MAP.equals(name) || Elements.FILTER_CHAIN.equals(name)) {
|
||||
if (Elements.HTTP.equals(name) || Elements.FILTER_SECURITY_METADATA_SOURCE.equals(name)) {
|
||||
reportMissingWebClasses(name, pc, element);
|
||||
} else {
|
||||
reportUnsupportedNodeType(name, pc, element);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
return parser.parse(element, pc);
|
||||
}
|
||||
|
||||
public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder definition, ParserContext pc) {
|
||||
BeanDefinitionDecorator decorator = null;
|
||||
String name = pc.getDelegate().getLocalName(node);
|
||||
|
||||
// We only handle elements
|
||||
@@ -108,7 +107,9 @@ public final class SecurityNamespaceHandler implements NamespaceHandler {
|
||||
}
|
||||
}
|
||||
|
||||
reportUnsupportedNodeType(name, pc, node);
|
||||
if (decorator == null) {
|
||||
reportUnsupportedNodeType(name, pc, node);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -119,8 +120,8 @@ public final class SecurityNamespaceHandler implements NamespaceHandler {
|
||||
}
|
||||
|
||||
private void reportMissingWebClasses(String nodeName, ParserContext pc, Node node) {
|
||||
pc.getReaderContext().fatal("The classes from the spring-security-web jar " +
|
||||
"(or one of its dependencies) are not available. You need these to use <" + nodeName + ">", node);
|
||||
pc.getReaderContext().fatal("spring-security-web classes are not available. " +
|
||||
"You need these to use <" + Elements.FILTER_CHAIN_MAP + ">", node);
|
||||
}
|
||||
|
||||
public void init() {
|
||||
@@ -138,30 +139,21 @@ public final class SecurityNamespaceHandler implements NamespaceHandler {
|
||||
parsers.put(Elements.AUTHENTICATION_PROVIDER, new AuthenticationProviderBeanDefinitionParser());
|
||||
parsers.put(Elements.GLOBAL_METHOD_SECURITY, new GlobalMethodSecurityBeanDefinitionParser());
|
||||
parsers.put(Elements.AUTHENTICATION_MANAGER, new AuthenticationManagerBeanDefinitionParser());
|
||||
parsers.put(Elements.METHOD_SECURITY_METADATA_SOURCE, new MethodSecurityMetadataSourceBeanDefinitionParser());
|
||||
|
||||
// Only load the web-namespace parsers if the web classes are available
|
||||
try {
|
||||
ClassUtils.forName("org.springframework.security.web.FilterChainProxy", getClass().getClassLoader());
|
||||
parsers.put(Elements.DEBUG, new DebugBeanDefinitionParser());
|
||||
if (ClassUtils.isPresent("org.springframework.security.web.FilterChainProxy", getClass().getClassLoader())) {
|
||||
parsers.put(Elements.HTTP, new HttpSecurityBeanDefinitionParser());
|
||||
parsers.put(Elements.HTTP_FIREWALL, new HttpFirewallBeanDefinitionParser());
|
||||
parsers.put(Elements.FILTER_INVOCATION_DEFINITION_SOURCE, new FilterInvocationSecurityMetadataSourceParser());
|
||||
parsers.put(Elements.FILTER_SECURITY_METADATA_SOURCE, new FilterInvocationSecurityMetadataSourceParser());
|
||||
parsers.put(Elements.FILTER_CHAIN, new FilterChainBeanDefinitionParser());
|
||||
filterChainMapBDD = new FilterChainMapBeanDefinitionDecorator();
|
||||
} catch(Throwable t) {
|
||||
logger.error("Failed to load required web classes", t);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the schema location declared in the source file being parsed matches the Spring Security version.
|
||||
* The old 2.0 schema is not compatible with the 3.1 parser, so it is an error to explicitly use
|
||||
* 2.0.
|
||||
* <p>
|
||||
* There are also differences between 3.0 and 3.1 which are sufficient that we report using 3.0 as an error too.
|
||||
* It might be an error to declare spring-security.xsd as an alias, but you are only going to find that out
|
||||
* The old 2.0 schema is not compatible with the new 3.0 parser, so it is an error to explicitly use
|
||||
* 3.0. It might be an error to declare spring-security.xsd as an alias, but you are only going to find that out
|
||||
* when one of the sub parsers breaks.
|
||||
*
|
||||
* @param element the element that is to be parsed next
|
||||
@@ -173,8 +165,8 @@ public final class SecurityNamespaceHandler implements NamespaceHandler {
|
||||
|
||||
private boolean matchesVersionInternal(Element element) {
|
||||
String schemaLocation = element.getAttributeNS("http://www.w3.org/2001/XMLSchema-instance", "schemaLocation");
|
||||
return schemaLocation.matches("(?m).*spring-security-3\\.1.*.xsd.*")
|
||||
|| schemaLocation.matches("(?m).*spring-security.xsd.*")
|
||||
return schemaLocation.matches("(?m).*spring-security-3\\.0.*xsd.*")
|
||||
|| schemaLocation.matches("(?m).*spring-security\\.xsd.*")
|
||||
|| !schemaLocation.matches("(?m).*spring-security.*");
|
||||
}
|
||||
|
||||
|
||||
+16
-32
@@ -38,14 +38,8 @@ public class AuthenticationManagerBeanDefinitionParser implements BeanDefinition
|
||||
private static final String ATT_ERASE_CREDENTIALS = "erase-credentials";
|
||||
|
||||
public BeanDefinition parse(Element element, ParserContext pc) {
|
||||
String id = element.getAttribute("id");
|
||||
|
||||
if (!StringUtils.hasText(id)) {
|
||||
if (pc.getRegistry().containsBeanDefinition(BeanIds.AUTHENTICATION_MANAGER)) {
|
||||
pc.getReaderContext().warning("Overriding globally registered AuthenticationManager", pc.extractSource(element));
|
||||
}
|
||||
id = BeanIds.AUTHENTICATION_MANAGER;
|
||||
}
|
||||
Assert.state(!pc.getRegistry().containsBeanDefinition(BeanIds.AUTHENTICATION_MANAGER),
|
||||
"AuthenticationManager has already been registered!");
|
||||
pc.pushContainingComponent(new CompositeComponentDefinition(element.getTagName(), pc.extractSource(element)));
|
||||
|
||||
BeanDefinitionBuilder providerManagerBldr = BeanDefinitionBuilder.rootBeanDefinition(ProviderManager.class);
|
||||
@@ -63,24 +57,13 @@ public class AuthenticationManagerBeanDefinitionParser implements BeanDefinition
|
||||
if (node instanceof Element) {
|
||||
Element providerElt = (Element)node;
|
||||
if (StringUtils.hasText(providerElt.getAttribute(ATT_REF))) {
|
||||
if (providerElt.getAttributes().getLength() > 1) {
|
||||
pc.getReaderContext().error("authentication-provider element cannot be used with other attributes " +
|
||||
"when using 'ref' attribute", pc.extractSource(element));
|
||||
}
|
||||
NodeList providerChildren = providerElt.getChildNodes();
|
||||
for (int j = 0; j < providerChildren.getLength(); j++) {
|
||||
if (providerChildren.item(j) instanceof Element) {
|
||||
pc.getReaderContext().error("authentication-provider element cannot have child elements when used " +
|
||||
"with 'ref' attribute", pc.extractSource(element));
|
||||
}
|
||||
}
|
||||
providers.add(new RuntimeBeanReference(providerElt.getAttribute(ATT_REF)));
|
||||
} else {
|
||||
BeanDefinition provider = resolver.resolve(providerElt.getNamespaceURI()).parse(providerElt, pc);
|
||||
Assert.notNull(provider, "Parser for " + providerElt.getNodeName() + " returned a null bean definition");
|
||||
String providerId = pc.getReaderContext().generateBeanName(provider);
|
||||
pc.registerBeanComponent(new BeanComponentDefinition(provider, providerId));
|
||||
providers.add(new RuntimeBeanReference(providerId));
|
||||
String id = pc.getReaderContext().generateBeanName(provider);
|
||||
pc.registerBeanComponent(new BeanComponentDefinition(provider, id));
|
||||
providers.add(new RuntimeBeanReference(id));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -89,23 +72,24 @@ public class AuthenticationManagerBeanDefinitionParser implements BeanDefinition
|
||||
providers.add(new RootBeanDefinition(NullAuthenticationProvider.class));
|
||||
}
|
||||
|
||||
providerManagerBldr.addConstructorArgValue(providers);
|
||||
providerManagerBldr.addPropertyValue("providers", providers);
|
||||
|
||||
if ("false".equals(element.getAttribute(ATT_ERASE_CREDENTIALS))) {
|
||||
providerManagerBldr.addPropertyValue("eraseCredentialsAfterAuthentication", false);
|
||||
if ("true".equals(element.getAttribute(ATT_ERASE_CREDENTIALS))) {
|
||||
providerManagerBldr.addPropertyValue("eraseCredentialsAfterAuthentication", true);
|
||||
}
|
||||
|
||||
// Add the default event publisher
|
||||
BeanDefinition publisher = new RootBeanDefinition(DefaultAuthenticationEventPublisher.class);
|
||||
String pubId = pc.getReaderContext().generateBeanName(publisher);
|
||||
pc.registerBeanComponent(new BeanComponentDefinition(publisher, pubId));
|
||||
providerManagerBldr.addPropertyReference("authenticationEventPublisher", pubId);
|
||||
String id = pc.getReaderContext().generateBeanName(publisher);
|
||||
pc.registerBeanComponent(new BeanComponentDefinition(publisher, id));
|
||||
providerManagerBldr.addPropertyReference("authenticationEventPublisher", id);
|
||||
|
||||
pc.registerBeanComponent(new BeanComponentDefinition(providerManagerBldr.getBeanDefinition(), id));
|
||||
pc.registerBeanComponent(
|
||||
new BeanComponentDefinition(providerManagerBldr.getBeanDefinition(), BeanIds.AUTHENTICATION_MANAGER));
|
||||
|
||||
if (StringUtils.hasText(alias)) {
|
||||
pc.getRegistry().registerAlias(id, alias);
|
||||
pc.getReaderContext().fireAliasRegistered(id, alias, pc.extractSource(element));
|
||||
pc.getRegistry().registerAlias(BeanIds.AUTHENTICATION_MANAGER, alias);
|
||||
pc.getReaderContext().fireAliasRegistered(BeanIds.AUTHENTICATION_MANAGER, alias, pc.extractSource(element));
|
||||
}
|
||||
|
||||
pc.popAndRegisterContainingComponent();
|
||||
@@ -133,7 +117,7 @@ public class AuthenticationManagerBeanDefinitionParser implements BeanDefinition
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean supports(Class<?> authentication) {
|
||||
public boolean supports(Class<? extends Object> authentication) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
+2
-3
@@ -19,9 +19,8 @@ import org.springframework.security.config.BeanIds;
|
||||
*/
|
||||
public class AuthenticationManagerFactoryBean implements FactoryBean<AuthenticationManager>, BeanFactoryAware {
|
||||
private BeanFactory bf;
|
||||
public static final String MISSING_BEAN_ERROR_MESSAGE = "Did you forget to add a gobal <authentication-manager> element " +
|
||||
"to your configuration (with child <authentication-provider> elements)? Alternatively you can use the " +
|
||||
"authentication-manager-ref attribute on your <http> and <global-method-security> elements.";
|
||||
public static final String MISSING_BEAN_ERROR_MESSAGE = "Did you forget to add an <authentication-manager> element " +
|
||||
"to your configuration (with child <authentication-provider> elements) ?";
|
||||
|
||||
public AuthenticationManager getObject() throws Exception {
|
||||
try {
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@ import org.w3c.dom.Element;
|
||||
* @author Luke Taylor
|
||||
*/
|
||||
public class AuthenticationProviderBeanDefinitionParser implements BeanDefinitionParser {
|
||||
private static final String ATT_USER_DETAILS_REF = "user-service-ref";
|
||||
private static String ATT_USER_DETAILS_REF = "user-service-ref";
|
||||
|
||||
public BeanDefinition parse(Element element, ParserContext pc) {
|
||||
RootBeanDefinition authProvider = new RootBeanDefinition(DaoAuthenticationProvider.class);
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@ import org.springframework.util.Assert;
|
||||
*/
|
||||
public class CachingUserDetailsService implements UserDetailsService {
|
||||
private UserCache userCache = new NullUserCache();
|
||||
private final UserDetailsService delegate;
|
||||
private UserDetailsService delegate;
|
||||
|
||||
CachingUserDetailsService(UserDetailsService delegate) {
|
||||
this.delegate = delegate;
|
||||
|
||||
+3
-3
@@ -55,7 +55,7 @@ public class PasswordEncoderParser {
|
||||
ENCODER_CLASSES.put(OPT_HASH_LDAP_SSHA, LdapShaPasswordEncoder.class);
|
||||
}
|
||||
|
||||
private static final Log logger = LogFactory.getLog(PasswordEncoderParser.class);
|
||||
private static Log logger = LogFactory.getLog(PasswordEncoderParser.class);
|
||||
|
||||
private BeanMetadataElement passwordEncoder;
|
||||
private BeanMetadataElement saltSource;
|
||||
@@ -69,7 +69,7 @@ public class PasswordEncoderParser {
|
||||
boolean useBase64 = false;
|
||||
|
||||
if (StringUtils.hasText(element.getAttribute(ATT_BASE_64))) {
|
||||
useBase64 = Boolean.valueOf(element.getAttribute(ATT_BASE_64)).booleanValue();
|
||||
useBase64 = new Boolean(element.getAttribute(ATT_BASE_64)).booleanValue();
|
||||
}
|
||||
|
||||
String ref = element.getAttribute(ATT_REF);
|
||||
@@ -93,7 +93,7 @@ public class PasswordEncoderParser {
|
||||
BeanDefinitionBuilder beanBldr = BeanDefinitionBuilder.rootBeanDefinition(beanClass);
|
||||
|
||||
if (OPT_HASH_SHA256.equals(hash)) {
|
||||
beanBldr.addConstructorArgValue(Integer.valueOf(256));
|
||||
beanBldr.addConstructorArgValue(new Integer(256));
|
||||
}
|
||||
|
||||
if (useBase64) {
|
||||
|
||||
+14
-10
@@ -9,12 +9,12 @@ import org.springframework.beans.factory.BeanDefinitionStoreException;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.PropertiesFactoryBean;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.ManagedList;
|
||||
import org.springframework.beans.factory.support.ManagedMap;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
import org.springframework.security.core.userdetails.User;
|
||||
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
|
||||
import org.springframework.security.core.userdetails.memory.UserMap;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.util.xml.DomUtils;
|
||||
@@ -24,6 +24,7 @@ import org.w3c.dom.Element;
|
||||
* @author Luke Taylor
|
||||
* @author Ben Alex
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public class UserServiceBeanDefinitionParser extends AbstractUserDetailsServiceBeanDefinitionParser {
|
||||
|
||||
static final String ATT_PASSWORD = "password";
|
||||
@@ -37,7 +38,7 @@ public class UserServiceBeanDefinitionParser extends AbstractUserDetailsServiceB
|
||||
private SecureRandom random;
|
||||
|
||||
protected String getBeanClassName(Element element) {
|
||||
return InMemoryUserDetailsManager.class.getName();
|
||||
return "org.springframework.security.core.userdetails.memory.InMemoryDaoImpl";
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -53,20 +54,21 @@ public class UserServiceBeanDefinitionParser extends AbstractUserDetailsServiceB
|
||||
|
||||
BeanDefinition bd = new RootBeanDefinition(PropertiesFactoryBean.class);
|
||||
bd.getPropertyValues().addPropertyValue("location", userProperties);
|
||||
builder.addConstructorArgValue(bd);
|
||||
builder.addPropertyValue("userProperties", bd);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (CollectionUtils.isEmpty(userElts)) {
|
||||
if(CollectionUtils.isEmpty(userElts)) {
|
||||
throw new BeanDefinitionStoreException("You must supply user definitions, either with <" + ELT_USER + "> child elements or a " +
|
||||
"properties file (using the '" + ATT_PROPERTIES + "' attribute)" );
|
||||
}
|
||||
|
||||
ManagedList<BeanDefinition> users = new ManagedList<BeanDefinition>();
|
||||
BeanDefinition userMap = new RootBeanDefinition(UserMap.class);
|
||||
ManagedMap<String, BeanDefinition> users = new ManagedMap<String, BeanDefinition>();
|
||||
|
||||
for (Object elt : userElts) {
|
||||
Element userElt = (Element) elt;
|
||||
for (Iterator i = userElts.iterator(); i.hasNext();) {
|
||||
Element userElt = (Element) i.next();
|
||||
String userName = userElt.getAttribute(ATT_NAME);
|
||||
String password = userElt.getAttribute(ATT_PASSWORD);
|
||||
|
||||
@@ -89,10 +91,12 @@ public class UserServiceBeanDefinitionParser extends AbstractUserDetailsServiceB
|
||||
user.addConstructorArgValue(!locked);
|
||||
user.addConstructorArgValue(authorities.getBeanDefinition());
|
||||
|
||||
users.add(user.getBeanDefinition());
|
||||
users.put(userName.toLowerCase(), user.getBeanDefinition());
|
||||
}
|
||||
|
||||
builder.addConstructorArgValue(users);
|
||||
userMap.getPropertyValues().addPropertyValue("users", users);
|
||||
|
||||
builder.addPropertyValue("userMap", userMap);
|
||||
}
|
||||
|
||||
private String generateRandomPassword() {
|
||||
|
||||
@@ -1,105 +0,0 @@
|
||||
package org.springframework.security.config.debug;
|
||||
|
||||
import org.springframework.security.web.FilterChainProxy;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
import org.springframework.security.web.util.UrlUtils;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletRequestWrapper;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSession;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Spring Security debugging filter.
|
||||
* <p>
|
||||
* Logs information (such as session creation) to help the user understand how requests are being handled
|
||||
* by Spring Security and provide them with other relevant information (such as when sessions are being created).
|
||||
*
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @since 3.1
|
||||
*/
|
||||
class DebugFilter extends OncePerRequestFilter {
|
||||
private final FilterChainProxy fcp;
|
||||
private final Logger logger = new Logger();
|
||||
|
||||
public DebugFilter(FilterChainProxy fcp) {
|
||||
this.fcp = fcp;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
|
||||
List<Filter> filters = getFilters(request);
|
||||
logger.log("Request received for '" + UrlUtils.buildRequestUrl(request) + "':\n\n" +
|
||||
request + "\n\n" +
|
||||
"servletPath:" + request.getServletPath() + "\n" +
|
||||
"pathInfo:" + request.getPathInfo() + "\n\n" +
|
||||
formatFilters(filters));
|
||||
|
||||
fcp.doFilter(new DebugRequestWrapper(request), response, filterChain);
|
||||
}
|
||||
|
||||
String formatFilters(List<Filter> filters) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("Security filter chain: ");
|
||||
if (filters == null) {
|
||||
sb.append("no match");
|
||||
} else if (filters.isEmpty()) {
|
||||
sb.append("[] empty (bypassed by security='none') ");
|
||||
} else {
|
||||
sb.append("[\n");
|
||||
for (Filter f : filters) {
|
||||
sb.append(" ").append(f.getClass().getSimpleName()).append("\n");
|
||||
}
|
||||
sb.append("]");
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private List<Filter> getFilters(HttpServletRequest request) {
|
||||
for (SecurityFilterChain chain : fcp.getFilterChains()) {
|
||||
if (chain.matches(request)) {
|
||||
return chain.getFilters();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
class DebugRequestWrapper extends HttpServletRequestWrapper {
|
||||
private static final Logger logger = new Logger();
|
||||
|
||||
public DebugRequestWrapper(HttpServletRequest request) {
|
||||
super(request);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpSession getSession() {
|
||||
boolean sessionExists = super.getSession(false) != null;
|
||||
HttpSession session = super.getSession();
|
||||
|
||||
if (!sessionExists) {
|
||||
logger.log("New HTTP session created: " + session.getId(), true);
|
||||
}
|
||||
|
||||
return session;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpSession getSession(boolean create) {
|
||||
if (!create) {
|
||||
return super.getSession(create);
|
||||
}
|
||||
return getSession();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
package org.springframework.security.config.debug;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* Controls output for the Spring Security debug feature.
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @since 3.1
|
||||
*/
|
||||
final class Logger {
|
||||
final static Log logger = LogFactory.getLog("Spring Security Debugger");
|
||||
|
||||
void log(String message) {
|
||||
log(message, false);
|
||||
}
|
||||
|
||||
void log(String message, boolean dumpStack) {
|
||||
StringBuilder output = new StringBuilder(256);
|
||||
output.append("\n\n************************************************************\n\n");
|
||||
output.append(message).append("\n");
|
||||
|
||||
if (dumpStack) {
|
||||
StringWriter os = new StringWriter();
|
||||
new Exception().printStackTrace(new PrintWriter(os));
|
||||
StringBuffer buffer = os.getBuffer();
|
||||
// Remove the exception in case it scares people.
|
||||
int start = buffer.indexOf("java.lang.Exception");
|
||||
buffer.replace(start, start + 19, "");
|
||||
output.append("\nCall stack: \n").append(os.toString());
|
||||
}
|
||||
|
||||
output.append("\n\n************************************************************\n\n");
|
||||
|
||||
logger.info(output.toString());
|
||||
}
|
||||
}
|
||||
-28
@@ -1,28 +0,0 @@
|
||||
package org.springframework.security.config.debug;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.security.config.BeanIds;
|
||||
import org.springframework.security.web.FilterChainProxy;
|
||||
|
||||
/**
|
||||
* @author Luke Taylor
|
||||
*/
|
||||
public class SecurityDebugBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
|
||||
|
||||
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
|
||||
Logger.logger.warn("\n\n" +
|
||||
"********************************************************************\n" +
|
||||
"********** Security debugging is enabled. *************\n" +
|
||||
"********** This may include sensitive information. *************\n" +
|
||||
"********** Do not use in a production system! *************\n" +
|
||||
"********************************************************************\n\n");
|
||||
if (beanFactory.getBean(BeanIds.SPRING_SECURITY_FILTER_CHAIN) != null) {
|
||||
FilterChainProxy fcp = beanFactory.getBean(BeanIds.FILTER_CHAIN_PROXY, FilterChainProxy.class);
|
||||
beanFactory.registerSingleton(BeanIds.DEBUG_FILTER, new DebugFilter(fcp));
|
||||
// Overwrite the filter chain alias
|
||||
beanFactory.registerAlias(BeanIds.DEBUG_FILTER, BeanIds.SPRING_SECURITY_FILTER_CHAIN);
|
||||
}
|
||||
}
|
||||
}
|
||||
+139
-229
@@ -2,6 +2,11 @@ package org.springframework.security.config.http;
|
||||
|
||||
import static org.springframework.security.config.http.SecurityFilters.*;
|
||||
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.BeanMetadataElement;
|
||||
@@ -13,36 +18,28 @@ import org.springframework.beans.factory.config.RuntimeBeanReference;
|
||||
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.ManagedList;
|
||||
import org.springframework.beans.factory.support.ManagedMap;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.security.authentication.AnonymousAuthenticationProvider;
|
||||
import org.springframework.security.authentication.RememberMeAuthenticationProvider;
|
||||
import org.springframework.security.config.BeanIds;
|
||||
import org.springframework.security.config.Elements;
|
||||
import org.springframework.security.core.authority.mapping.SimpleAttributes2GrantedAuthoritiesMapper;
|
||||
import org.springframework.security.core.authority.mapping.SimpleMappableAttributesRetriever;
|
||||
import org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper;
|
||||
import org.springframework.security.web.PortResolverImpl;
|
||||
import org.springframework.security.web.access.AccessDeniedHandlerImpl;
|
||||
import org.springframework.security.web.access.ExceptionTranslationFilter;
|
||||
import org.springframework.security.web.authentication.AnonymousAuthenticationFilter;
|
||||
import org.springframework.security.web.authentication.Http403ForbiddenEntryPoint;
|
||||
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider;
|
||||
import org.springframework.security.web.authentication.preauth.PreAuthenticatedGrantedAuthoritiesUserDetailsService;
|
||||
import org.springframework.security.web.authentication.preauth.j2ee.J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource;
|
||||
import org.springframework.security.web.authentication.preauth.j2ee.J2eePreAuthenticatedProcessingFilter;
|
||||
import org.springframework.security.web.authentication.preauth.x509.SubjectDnX509PrincipalExtractor;
|
||||
import org.springframework.security.web.authentication.preauth.x509.X509AuthenticationFilter;
|
||||
import org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter;
|
||||
import org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint;
|
||||
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint;
|
||||
import org.springframework.security.web.savedrequest.HttpSessionRequestCache;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.util.xml.DomUtils;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Handles creation of authentication mechanism filters and related beans for <http> parsing.
|
||||
*
|
||||
@@ -57,13 +54,10 @@ final class AuthenticationConfigBuilder {
|
||||
|
||||
static final String OPEN_ID_AUTHENTICATION_PROCESSING_FILTER_CLASS = "org.springframework.security.openid.OpenIDAuthenticationFilter";
|
||||
static final String OPEN_ID_AUTHENTICATION_PROVIDER_CLASS = "org.springframework.security.openid.OpenIDAuthenticationProvider";
|
||||
private static final String OPEN_ID_CONSUMER_CLASS = "org.springframework.security.openid.OpenID4JavaConsumer";
|
||||
static final String OPEN_ID_CONSUMER_CLASS = "org.springframework.security.openid.OpenID4JavaConsumer";
|
||||
static final String OPEN_ID_ATTRIBUTE_CLASS = "org.springframework.security.openid.OpenIDAttribute";
|
||||
private static final String OPEN_ID_ATTRIBUTE_FACTORY_CLASS = "org.springframework.security.openid.RegexBasedAxFetchListFactory";
|
||||
static final String AUTHENTICATION_PROCESSING_FILTER_CLASS = "org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter";
|
||||
|
||||
static final String ATT_AUTH_DETAILS_SOURCE_REF = "authentication-details-source-ref";
|
||||
|
||||
private static final String ATT_AUTO_CONFIG = "auto-config";
|
||||
|
||||
private static final String ATT_ACCESS_DENIED_PAGE = "access-denied-page";
|
||||
@@ -72,13 +66,14 @@ final class AuthenticationConfigBuilder {
|
||||
|
||||
private static final String ATT_USER_SERVICE_REF = "user-service-ref";
|
||||
|
||||
private static final String ATT_KEY = "key";
|
||||
private static final String ATT_REF = "ref";
|
||||
|
||||
private final Element httpElt;
|
||||
private final ParserContext pc;
|
||||
private Element httpElt;
|
||||
private ParserContext pc;
|
||||
|
||||
private final boolean autoConfig;
|
||||
private final boolean allowSessionCreation;
|
||||
private final String portMapperName;
|
||||
|
||||
private RootBeanDefinition anonymousFilter;
|
||||
private BeanReference anonymousProviderRef;
|
||||
@@ -86,47 +81,44 @@ final class AuthenticationConfigBuilder {
|
||||
private String rememberMeServicesId;
|
||||
private BeanReference rememberMeProviderRef;
|
||||
private BeanDefinition basicFilter;
|
||||
private RuntimeBeanReference basicEntryPoint;
|
||||
private BeanReference basicEntryPoint;
|
||||
private RootBeanDefinition formFilter;
|
||||
private BeanDefinition formEntryPoint;
|
||||
private RootBeanDefinition openIDFilter;
|
||||
private BeanDefinition openIDEntryPoint;
|
||||
private BeanReference openIDProviderRef;
|
||||
private String openIDProviderId;
|
||||
private String formFilterId = null;
|
||||
private String openIDFilterId = null;
|
||||
private BeanDefinition x509Filter;
|
||||
private BeanDefinition x509EntryPoint;
|
||||
private BeanReference x509ProviderRef;
|
||||
private BeanDefinition jeeFilter;
|
||||
private BeanReference jeeProviderRef;
|
||||
private RootBeanDefinition preAuthEntryPoint;
|
||||
|
||||
private String x509ProviderId;
|
||||
private BeanDefinition logoutFilter;
|
||||
private BeanDefinition loginPageGenerationFilter;
|
||||
private BeanDefinition etf;
|
||||
private final BeanReference requestCache;
|
||||
private BeanReference requestCache;
|
||||
|
||||
public AuthenticationConfigBuilder(Element element, ParserContext pc, SessionCreationPolicy sessionPolicy,
|
||||
BeanReference requestCache, BeanReference authenticationManager, BeanReference sessionStrategy) {
|
||||
final SecureRandom random;
|
||||
|
||||
public AuthenticationConfigBuilder(Element element, ParserContext pc, boolean allowSessionCreation,
|
||||
String portMapperName) {
|
||||
this.httpElt = element;
|
||||
this.pc = pc;
|
||||
this.requestCache = requestCache;
|
||||
this.portMapperName = portMapperName;
|
||||
autoConfig = "true".equals(element.getAttribute(ATT_AUTO_CONFIG));
|
||||
this.allowSessionCreation = sessionPolicy != SessionCreationPolicy.never
|
||||
&& sessionPolicy != SessionCreationPolicy.stateless;
|
||||
|
||||
createAnonymousFilter();
|
||||
createRememberMeFilter(authenticationManager);
|
||||
createBasicFilter(authenticationManager);
|
||||
createFormLoginFilter(sessionStrategy, authenticationManager);
|
||||
createOpenIDLoginFilter(sessionStrategy, authenticationManager);
|
||||
createX509Filter(authenticationManager);
|
||||
createJeeFilter(authenticationManager);
|
||||
createLogoutFilter();
|
||||
createLoginPageFilterIfNeeded();
|
||||
createUserDetailsServiceFactory();
|
||||
createExceptionTranslationFilter();
|
||||
|
||||
this.allowSessionCreation = allowSessionCreation;
|
||||
try {
|
||||
random = SecureRandom.getInstance("SHA1PRNG");
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
// Shouldn't happen...
|
||||
throw new RuntimeException("Failed find SHA1PRNG algorithm!");
|
||||
}
|
||||
}
|
||||
|
||||
void createRememberMeFilter(BeanReference authenticationManager) {
|
||||
final String ATT_KEY = "key";
|
||||
final String DEF_KEY = "SpringSecured";
|
||||
|
||||
// Parse remember me before logout as RememberMeServices is also a LogoutHandler implementation.
|
||||
Element rememberMeElt = DomUtils.getChildElementByTagName(httpElt, Elements.REMEMBER_ME);
|
||||
@@ -135,10 +127,10 @@ final class AuthenticationConfigBuilder {
|
||||
String key = rememberMeElt.getAttribute(ATT_KEY);
|
||||
|
||||
if (!StringUtils.hasText(key)) {
|
||||
key = createKey();
|
||||
key = DEF_KEY;
|
||||
}
|
||||
|
||||
rememberMeFilter = new RememberMeBeanDefinitionParser(key).parse(rememberMeElt, pc);
|
||||
rememberMeFilter = (RootBeanDefinition) new RememberMeBeanDefinitionParser(key).parse(rememberMeElt, pc);
|
||||
rememberMeFilter.getPropertyValues().addPropertyValue("authenticationManager", authenticationManager);
|
||||
rememberMeServicesId = ((RuntimeBeanReference) rememberMeFilter.getPropertyValues().getPropertyValue("rememberMeServices").getValue()).getBeanName();
|
||||
createRememberMeProvider(key);
|
||||
@@ -160,7 +152,6 @@ final class AuthenticationConfigBuilder {
|
||||
void createFormLoginFilter(BeanReference sessionStrategy, BeanReference authManager) {
|
||||
|
||||
Element formLoginElt = DomUtils.getChildElementByTagName(httpElt, Elements.FORM_LOGIN);
|
||||
RootBeanDefinition formFilter = null;
|
||||
|
||||
if (formLoginElt != null || autoConfig) {
|
||||
FormLoginBeanDefinitionParser parser = new FormLoginBeanDefinitionParser("/j_spring_security_check",
|
||||
@@ -175,6 +166,7 @@ final class AuthenticationConfigBuilder {
|
||||
formFilter.getPropertyValues().addPropertyValue("allowSessionCreation", allowSessionCreation);
|
||||
formFilter.getPropertyValues().addPropertyValue("authenticationManager", authManager);
|
||||
|
||||
|
||||
// Id is required by login page filter
|
||||
formFilterId = pc.getReaderContext().generateBeanName(formFilter);
|
||||
pc.registerBeanComponent(new BeanComponentDefinition(formFilter, formFilterId));
|
||||
@@ -184,7 +176,6 @@ final class AuthenticationConfigBuilder {
|
||||
|
||||
void createOpenIDLoginFilter(BeanReference sessionStrategy, BeanReference authManager) {
|
||||
Element openIDLoginElt = DomUtils.getChildElementByTagName(httpElt, Elements.OPENID_LOGIN);
|
||||
RootBeanDefinition openIDFilter = null;
|
||||
|
||||
if (openIDLoginElt != null) {
|
||||
FormLoginBeanDefinitionParser parser = new FormLoginBeanDefinitionParser("/j_spring_openid_security_check",
|
||||
@@ -194,31 +185,30 @@ final class AuthenticationConfigBuilder {
|
||||
openIDFilter = parser.getFilterBean();
|
||||
openIDEntryPoint = parser.getEntryPointBean();
|
||||
|
||||
List<Element> attrExElts = DomUtils.getChildElementsByTagName(openIDLoginElt, Elements.OPENID_ATTRIBUTE_EXCHANGE);
|
||||
Element attrExElt = DomUtils.getChildElementByTagName(openIDLoginElt, Elements.OPENID_ATTRIBUTE_EXCHANGE);
|
||||
|
||||
if (!attrExElts.isEmpty()) {
|
||||
if (attrExElt != null) {
|
||||
// Set up the consumer with the required attribute list
|
||||
BeanDefinitionBuilder consumerBldr = BeanDefinitionBuilder.rootBeanDefinition(OPEN_ID_CONSUMER_CLASS);
|
||||
BeanDefinitionBuilder axFactory = BeanDefinitionBuilder.rootBeanDefinition(OPEN_ID_ATTRIBUTE_FACTORY_CLASS);
|
||||
ManagedMap<String, ManagedList<BeanDefinition>> axMap = new ManagedMap<String, ManagedList<BeanDefinition>>();
|
||||
|
||||
for (Element attrExElt : attrExElts) {
|
||||
String identifierMatch = attrExElt.getAttribute("identifier-match");
|
||||
|
||||
if (!StringUtils.hasText(identifierMatch)) {
|
||||
if (attrExElts.size() > 1) {
|
||||
pc.getReaderContext().error("You must supply an identifier-match attribute if using more" +
|
||||
" than one " + Elements.OPENID_ATTRIBUTE_EXCHANGE + " element", attrExElt);
|
||||
}
|
||||
// Match anything
|
||||
identifierMatch = ".*";
|
||||
ManagedList<BeanDefinition> attributes = new ManagedList<BeanDefinition> ();
|
||||
for (Element attElt : DomUtils.getChildElementsByTagName(attrExElt, Elements.OPENID_ATTRIBUTE)) {
|
||||
String name = attElt.getAttribute("name");
|
||||
String type = attElt.getAttribute("type");
|
||||
String required = attElt.getAttribute("required");
|
||||
String count = attElt.getAttribute("count");
|
||||
BeanDefinitionBuilder attrBldr = BeanDefinitionBuilder.rootBeanDefinition(OPEN_ID_ATTRIBUTE_CLASS);
|
||||
attrBldr.addConstructorArgValue(name);
|
||||
attrBldr.addConstructorArgValue(type);
|
||||
if (StringUtils.hasLength(required)) {
|
||||
attrBldr.addPropertyValue("required", Boolean.valueOf(required));
|
||||
}
|
||||
|
||||
axMap.put(identifierMatch, parseOpenIDAttributes(attrExElt));
|
||||
if (StringUtils.hasLength(count)) {
|
||||
attrBldr.addPropertyValue("count", Integer.parseInt(count));
|
||||
}
|
||||
attributes.add(attrBldr.getBeanDefinition());
|
||||
}
|
||||
axFactory.addConstructorArgValue(axMap);
|
||||
|
||||
consumerBldr.addConstructorArgValue(axFactory.getBeanDefinition());
|
||||
consumerBldr.addConstructorArgValue(attributes);
|
||||
openIDFilter.getPropertyValues().addPropertyValue("consumer", consumerBldr.getBeanDefinition());
|
||||
}
|
||||
}
|
||||
@@ -235,43 +225,20 @@ final class AuthenticationConfigBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
private ManagedList<BeanDefinition> parseOpenIDAttributes(Element attrExElt) {
|
||||
ManagedList<BeanDefinition> attributes = new ManagedList<BeanDefinition> ();
|
||||
for (Element attElt : DomUtils.getChildElementsByTagName(attrExElt, Elements.OPENID_ATTRIBUTE)) {
|
||||
String name = attElt.getAttribute("name");
|
||||
String type = attElt.getAttribute("type");
|
||||
String required = attElt.getAttribute("required");
|
||||
String count = attElt.getAttribute("count");
|
||||
BeanDefinitionBuilder attrBldr = BeanDefinitionBuilder.rootBeanDefinition(OPEN_ID_ATTRIBUTE_CLASS);
|
||||
attrBldr.addConstructorArgValue(name);
|
||||
attrBldr.addConstructorArgValue(type);
|
||||
if (StringUtils.hasLength(required)) {
|
||||
attrBldr.addPropertyValue("required", Boolean.valueOf(required));
|
||||
}
|
||||
|
||||
if (StringUtils.hasLength(count)) {
|
||||
attrBldr.addPropertyValue("count", Integer.parseInt(count));
|
||||
}
|
||||
attributes.add(attrBldr.getBeanDefinition());
|
||||
}
|
||||
|
||||
return attributes;
|
||||
}
|
||||
|
||||
private void createOpenIDProvider() {
|
||||
Element openIDLoginElt = DomUtils.getChildElementByTagName(httpElt, Elements.OPENID_LOGIN);
|
||||
BeanDefinitionBuilder openIDProviderBuilder =
|
||||
BeanDefinitionBuilder.rootBeanDefinition(OPEN_ID_AUTHENTICATION_PROVIDER_CLASS);
|
||||
|
||||
RootBeanDefinition uds = new RootBeanDefinition();
|
||||
uds.setFactoryBeanName(BeanIds.USER_DETAILS_SERVICE_FACTORY);
|
||||
uds.setFactoryMethodName("authenticationUserDetailsService");
|
||||
uds.getConstructorArgumentValues().addGenericArgumentValue(openIDLoginElt.getAttribute(ATT_USER_SERVICE_REF));
|
||||
String userService = openIDLoginElt.getAttribute(ATT_USER_SERVICE_REF);
|
||||
|
||||
openIDProviderBuilder.addPropertyValue("authenticationUserDetailsService", uds);
|
||||
if (StringUtils.hasText(userService)) {
|
||||
openIDProviderBuilder.addPropertyReference("userDetailsService", userService);
|
||||
}
|
||||
|
||||
BeanDefinition openIDProvider = openIDProviderBuilder.getBeanDefinition();
|
||||
openIDProviderRef = new RuntimeBeanReference(pc.getReaderContext().registerWithGeneratedName(openIDProvider));
|
||||
openIDProviderId = pc.getReaderContext().registerWithGeneratedName(openIDProvider);
|
||||
openIDProviderRef = new RuntimeBeanReference(openIDProviderId);
|
||||
}
|
||||
|
||||
private void injectRememberMeServicesRef(RootBeanDefinition bean, String rememberMeServicesId) {
|
||||
@@ -283,46 +250,41 @@ final class AuthenticationConfigBuilder {
|
||||
void createBasicFilter(BeanReference authManager) {
|
||||
Element basicAuthElt = DomUtils.getChildElementByTagName(httpElt, Elements.BASIC_AUTH);
|
||||
|
||||
if (basicAuthElt == null && !autoConfig) {
|
||||
// No basic auth, do nothing
|
||||
return;
|
||||
}
|
||||
|
||||
String realm = httpElt.getAttribute(ATT_REALM);
|
||||
if (!StringUtils.hasText(realm)) {
|
||||
realm = DEF_REALM;
|
||||
}
|
||||
|
||||
BeanDefinitionBuilder filterBuilder = BeanDefinitionBuilder.rootBeanDefinition(BasicAuthenticationFilter.class);
|
||||
RootBeanDefinition filter = null;
|
||||
|
||||
String entryPointId;
|
||||
if (basicAuthElt != null || autoConfig) {
|
||||
BeanDefinitionBuilder filterBuilder = BeanDefinitionBuilder.rootBeanDefinition(BasicAuthenticationFilter.class);
|
||||
|
||||
if (basicAuthElt != null) {
|
||||
if (StringUtils.hasText(basicAuthElt.getAttribute(ATT_ENTRY_POINT_REF))) {
|
||||
String entryPointId;
|
||||
|
||||
if (basicAuthElt != null && StringUtils.hasText(basicAuthElt.getAttribute(ATT_ENTRY_POINT_REF))) {
|
||||
basicEntryPoint = new RuntimeBeanReference(basicAuthElt.getAttribute(ATT_ENTRY_POINT_REF));
|
||||
} else {
|
||||
RootBeanDefinition entryPoint = new RootBeanDefinition(BasicAuthenticationEntryPoint.class);
|
||||
entryPoint.setSource(pc.extractSource(httpElt));
|
||||
entryPoint.getPropertyValues().addPropertyValue("realmName", realm);
|
||||
entryPointId = pc.getReaderContext().generateBeanName(entryPoint);
|
||||
pc.registerBeanComponent(new BeanComponentDefinition(entryPoint, entryPointId));
|
||||
basicEntryPoint = new RuntimeBeanReference(entryPointId);
|
||||
}
|
||||
|
||||
injectAuthenticationDetailsSource(basicAuthElt, filterBuilder);
|
||||
|
||||
filterBuilder.addPropertyValue("authenticationManager", authManager);
|
||||
filterBuilder.addPropertyValue("authenticationEntryPoint", basicEntryPoint);
|
||||
filter = (RootBeanDefinition) filterBuilder.getBeanDefinition();
|
||||
}
|
||||
|
||||
if (basicEntryPoint == null) {
|
||||
RootBeanDefinition entryPoint = new RootBeanDefinition(BasicAuthenticationEntryPoint.class);
|
||||
entryPoint.setSource(pc.extractSource(httpElt));
|
||||
entryPoint.getPropertyValues().addPropertyValue("realmName", realm);
|
||||
entryPointId = pc.getReaderContext().generateBeanName(entryPoint);
|
||||
pc.registerBeanComponent(new BeanComponentDefinition(entryPoint, entryPointId));
|
||||
basicEntryPoint = new RuntimeBeanReference(entryPointId);
|
||||
}
|
||||
|
||||
filterBuilder.addPropertyValue("authenticationManager", authManager);
|
||||
filterBuilder.addPropertyValue("authenticationEntryPoint", basicEntryPoint);
|
||||
basicFilter = filterBuilder.getBeanDefinition();
|
||||
basicFilter = filter;
|
||||
}
|
||||
|
||||
void createX509Filter(BeanReference authManager) {
|
||||
Element x509Elt = DomUtils.getChildElementByTagName(httpElt, Elements.X509);
|
||||
RootBeanDefinition filter = null;
|
||||
RootBeanDefinition entryPoint = null;
|
||||
|
||||
if (x509Elt != null) {
|
||||
BeanDefinitionBuilder filterBuilder = BeanDefinitionBuilder.rootBeanDefinition(X509AuthenticationFilter.class);
|
||||
@@ -337,102 +299,37 @@ final class AuthenticationConfigBuilder {
|
||||
|
||||
filterBuilder.addPropertyValue("principalExtractor", extractor.getBeanDefinition());
|
||||
}
|
||||
|
||||
injectAuthenticationDetailsSource(x509Elt, filterBuilder);
|
||||
|
||||
filter = (RootBeanDefinition) filterBuilder.getBeanDefinition();
|
||||
createPrauthEntryPoint(x509Elt);
|
||||
entryPoint = new RootBeanDefinition(Http403ForbiddenEntryPoint.class);
|
||||
entryPoint.setSource(pc.extractSource(x509Elt));
|
||||
|
||||
createX509Provider();
|
||||
}
|
||||
|
||||
x509Filter = filter;
|
||||
}
|
||||
|
||||
private void injectAuthenticationDetailsSource(Element elt, BeanDefinitionBuilder filterBuilder) {
|
||||
String authDetailsSourceRef = elt.getAttribute(AuthenticationConfigBuilder.ATT_AUTH_DETAILS_SOURCE_REF);
|
||||
|
||||
if (StringUtils.hasText(authDetailsSourceRef)) {
|
||||
filterBuilder.addPropertyReference("authenticationDetailsSource", authDetailsSourceRef);
|
||||
}
|
||||
x509EntryPoint = entryPoint;
|
||||
}
|
||||
|
||||
private void createX509Provider() {
|
||||
Element x509Elt = DomUtils.getChildElementByTagName(httpElt, Elements.X509);
|
||||
BeanDefinition provider = new RootBeanDefinition(PreAuthenticatedAuthenticationProvider.class);
|
||||
|
||||
RootBeanDefinition uds = new RootBeanDefinition();
|
||||
uds.setFactoryBeanName(BeanIds.USER_DETAILS_SERVICE_FACTORY);
|
||||
uds.setFactoryMethodName("authenticationUserDetailsService");
|
||||
uds.getConstructorArgumentValues().addGenericArgumentValue(x509Elt.getAttribute(ATT_USER_SERVICE_REF));
|
||||
String userServiceRef = x509Elt.getAttribute(ATT_USER_SERVICE_REF);
|
||||
|
||||
provider.getPropertyValues().addPropertyValue("preAuthenticatedUserDetailsService", uds);
|
||||
|
||||
x509ProviderRef = new RuntimeBeanReference(pc.getReaderContext().registerWithGeneratedName(provider));
|
||||
}
|
||||
|
||||
private void createPrauthEntryPoint(Element source) {
|
||||
if (preAuthEntryPoint == null) {
|
||||
preAuthEntryPoint = new RootBeanDefinition(Http403ForbiddenEntryPoint.class);
|
||||
preAuthEntryPoint.setSource(pc.extractSource(source));
|
||||
}
|
||||
}
|
||||
|
||||
void createJeeFilter(BeanReference authManager) {
|
||||
final String ATT_MAPPABLE_ROLES = "mappable-roles";
|
||||
|
||||
Element jeeElt = DomUtils.getChildElementByTagName(httpElt, Elements.JEE);
|
||||
RootBeanDefinition filter = null;
|
||||
|
||||
if (jeeElt != null) {
|
||||
BeanDefinitionBuilder filterBuilder = BeanDefinitionBuilder.rootBeanDefinition(J2eePreAuthenticatedProcessingFilter.class);
|
||||
filterBuilder.getRawBeanDefinition().setSource(pc.extractSource(jeeElt));
|
||||
filterBuilder.addPropertyValue("authenticationManager", authManager);
|
||||
|
||||
BeanDefinitionBuilder adsBldr = BeanDefinitionBuilder.rootBeanDefinition(J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource.class);
|
||||
adsBldr.addPropertyValue("userRoles2GrantedAuthoritiesMapper", new RootBeanDefinition(SimpleAttributes2GrantedAuthoritiesMapper.class));
|
||||
|
||||
String roles = jeeElt.getAttribute(ATT_MAPPABLE_ROLES);
|
||||
Assert.state(StringUtils.hasText(roles));
|
||||
BeanDefinitionBuilder rolesBuilder = BeanDefinitionBuilder.rootBeanDefinition(StringUtils.class);
|
||||
rolesBuilder.addConstructorArgValue(roles);
|
||||
rolesBuilder.setFactoryMethod("commaDelimitedListToSet");
|
||||
|
||||
RootBeanDefinition mappableRolesRetriever = new RootBeanDefinition(SimpleMappableAttributesRetriever.class);
|
||||
mappableRolesRetriever.getPropertyValues().addPropertyValue("mappableAttributes", rolesBuilder.getBeanDefinition());
|
||||
adsBldr.addPropertyValue("mappableRolesRetriever", mappableRolesRetriever);
|
||||
filterBuilder.addPropertyValue("authenticationDetailsSource", adsBldr.getBeanDefinition());
|
||||
|
||||
filter = (RootBeanDefinition) filterBuilder.getBeanDefinition();
|
||||
|
||||
createPrauthEntryPoint(jeeElt);
|
||||
createJeeProvider();
|
||||
if (StringUtils.hasText(userServiceRef)) {
|
||||
RootBeanDefinition preAuthUserService = new RootBeanDefinition(UserDetailsByNameServiceWrapper.class);
|
||||
preAuthUserService.setSource(pc.extractSource(x509Elt));
|
||||
preAuthUserService.getPropertyValues().addPropertyValue("userDetailsService", new RuntimeBeanReference(userServiceRef));
|
||||
provider.getPropertyValues().addPropertyValue("preAuthenticatedUserDetailsService", preAuthUserService);
|
||||
}
|
||||
|
||||
jeeFilter = filter;
|
||||
x509ProviderId = pc.getReaderContext().registerWithGeneratedName(provider);
|
||||
x509ProviderRef = new RuntimeBeanReference(x509ProviderId);
|
||||
}
|
||||
|
||||
private void createJeeProvider() {
|
||||
Element jeeElt = DomUtils.getChildElementByTagName(httpElt, Elements.JEE);
|
||||
BeanDefinition provider = new RootBeanDefinition(PreAuthenticatedAuthenticationProvider.class);
|
||||
|
||||
RootBeanDefinition uds;
|
||||
if (StringUtils.hasText(jeeElt.getAttribute(ATT_USER_SERVICE_REF))) {
|
||||
uds = new RootBeanDefinition();
|
||||
uds.setFactoryBeanName(BeanIds.USER_DETAILS_SERVICE_FACTORY);
|
||||
uds.setFactoryMethodName("authenticationUserDetailsService");
|
||||
uds.getConstructorArgumentValues().addGenericArgumentValue(jeeElt.getAttribute(ATT_USER_SERVICE_REF));
|
||||
} else {
|
||||
uds = new RootBeanDefinition(PreAuthenticatedGrantedAuthoritiesUserDetailsService.class);
|
||||
}
|
||||
|
||||
provider.getPropertyValues().addPropertyValue("preAuthenticatedUserDetailsService", uds);
|
||||
|
||||
jeeProviderRef = new RuntimeBeanReference(pc.getReaderContext().registerWithGeneratedName(provider));
|
||||
}
|
||||
|
||||
void createLoginPageFilterIfNeeded() {
|
||||
boolean needLoginPage = formFilterId != null || openIDFilterId != null;
|
||||
boolean needLoginPage = formFilter != null || openIDFilter != null;
|
||||
String formLoginPage = getLoginFormUrl(formEntryPoint);
|
||||
String openIDLoginPage = getLoginFormUrl(openIDEntryPoint);
|
||||
|
||||
@@ -443,11 +340,11 @@ final class AuthenticationConfigBuilder {
|
||||
BeanDefinitionBuilder loginPageFilter =
|
||||
BeanDefinitionBuilder.rootBeanDefinition(DefaultLoginPageGeneratingFilter.class);
|
||||
|
||||
if (formFilterId != null) {
|
||||
if (formFilter != null) {
|
||||
loginPageFilter.addConstructorArgReference(formFilterId);
|
||||
}
|
||||
|
||||
if (openIDFilterId != null) {
|
||||
if (openIDFilter != null) {
|
||||
loginPageFilter.addConstructorArgReference(openIDFilterId);
|
||||
}
|
||||
|
||||
@@ -477,7 +374,7 @@ final class AuthenticationConfigBuilder {
|
||||
if (anonymousElt != null) {
|
||||
grantedAuthority = anonymousElt.getAttribute("granted-authority");
|
||||
username = anonymousElt.getAttribute("username");
|
||||
key = anonymousElt.getAttribute(ATT_KEY);
|
||||
key = anonymousElt.getAttribute("key");
|
||||
source = pc.extractSource(anonymousElt);
|
||||
}
|
||||
|
||||
@@ -491,7 +388,7 @@ final class AuthenticationConfigBuilder {
|
||||
|
||||
if (!StringUtils.hasText(key)) {
|
||||
// Generate a random key for the Anonymous provider
|
||||
key = createKey();
|
||||
key = Long.toString(random.nextLong());
|
||||
}
|
||||
|
||||
anonymousFilter = new RootBeanDefinition(AnonymousAuthenticationFilter.class);
|
||||
@@ -511,11 +408,6 @@ final class AuthenticationConfigBuilder {
|
||||
|
||||
}
|
||||
|
||||
private String createKey() {
|
||||
SecureRandom random = new SecureRandom();
|
||||
return Long.toString(random.nextLong());
|
||||
}
|
||||
|
||||
void createExceptionTranslationFilter() {
|
||||
BeanDefinitionBuilder etfBuilder = BeanDefinitionBuilder.rootBeanDefinition(ExceptionTranslationFilter.class);
|
||||
etfBuilder.addPropertyValue("accessDeniedHandler", createAccessDeniedHandler(httpElt, pc));
|
||||
@@ -526,6 +418,28 @@ final class AuthenticationConfigBuilder {
|
||||
etf = etfBuilder.getBeanDefinition();
|
||||
}
|
||||
|
||||
void createRequestCache() {
|
||||
Element requestCacheElt = DomUtils.getChildElementByTagName(httpElt, Elements.REQUEST_CACHE);
|
||||
|
||||
if (requestCacheElt != null) {
|
||||
requestCache = new RuntimeBeanReference(requestCacheElt.getAttribute(ATT_REF));
|
||||
return;
|
||||
}
|
||||
|
||||
BeanDefinitionBuilder requestCacheBldr = BeanDefinitionBuilder.rootBeanDefinition(HttpSessionRequestCache.class);
|
||||
BeanDefinitionBuilder portResolver = BeanDefinitionBuilder.rootBeanDefinition(PortResolverImpl.class);
|
||||
portResolver.addPropertyReference("portMapper", portMapperName);
|
||||
requestCacheBldr.addPropertyValue("createSessionAllowed", allowSessionCreation);
|
||||
requestCacheBldr.addPropertyValue("portResolver", portResolver.getBeanDefinition());
|
||||
|
||||
BeanDefinition bean = requestCacheBldr.getBeanDefinition();
|
||||
String id = pc.getReaderContext().generateBeanName(bean);
|
||||
pc.registerBeanComponent(new BeanComponentDefinition(bean, id));
|
||||
|
||||
this.requestCache = new RuntimeBeanReference(id);
|
||||
}
|
||||
|
||||
|
||||
private BeanMetadataElement createAccessDeniedHandler(Element element, ParserContext pc) {
|
||||
String accessDeniedPage = element.getAttribute(ATT_ACCESS_DENIED_PAGE);
|
||||
WebConfigUtils.validateHttpRedirect(accessDeniedPage, pc, pc.extractSource(element));
|
||||
@@ -589,18 +503,18 @@ final class AuthenticationConfigBuilder {
|
||||
"but not both.", pc.extractSource(openIDLoginElt));
|
||||
}
|
||||
|
||||
if (formFilterId != null && openIDLoginPage == null) {
|
||||
if (formFilter != null && openIDLoginPage == null) {
|
||||
return formEntryPoint;
|
||||
}
|
||||
|
||||
// Otherwise use OpenID if enabled
|
||||
if (openIDFilterId != null) {
|
||||
if (openIDFilter != null) {
|
||||
return openIDEntryPoint;
|
||||
}
|
||||
|
||||
// If X.509 or JEE have been enabled, use the preauth entry point.
|
||||
if (preAuthEntryPoint != null) {
|
||||
return preAuthEntryPoint;
|
||||
// If X.509 has been enabled, use the preauth entry point.
|
||||
if (DomUtils.getChildElementByTagName(httpElt, Elements.X509) != null) {
|
||||
return x509EntryPoint;
|
||||
}
|
||||
|
||||
pc.getReaderContext().error("No AuthenticationEntryPoint could be established. Please " +
|
||||
@@ -629,14 +543,14 @@ final class AuthenticationConfigBuilder {
|
||||
return (String) pv.getValue();
|
||||
}
|
||||
|
||||
private void createUserDetailsServiceFactory() {
|
||||
if (pc.getRegistry().containsBeanDefinition(BeanIds.USER_DETAILS_SERVICE_FACTORY)) {
|
||||
// Multiple <http> case
|
||||
return;
|
||||
}
|
||||
RootBeanDefinition bean = new RootBeanDefinition(UserDetailsServiceFactoryBean.class);
|
||||
bean.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
pc.registerBeanComponent(new BeanComponentDefinition(bean, BeanIds.USER_DETAILS_SERVICE_FACTORY));
|
||||
void createUserServiceInjector() {
|
||||
BeanDefinitionBuilder userServiceInjector =
|
||||
BeanDefinitionBuilder.rootBeanDefinition(UserDetailsServiceInjectionBeanPostProcessor.class);
|
||||
userServiceInjector.addConstructorArgValue(x509ProviderId);
|
||||
userServiceInjector.addConstructorArgValue(rememberMeServicesId);
|
||||
userServiceInjector.addConstructorArgValue(openIDProviderId);
|
||||
userServiceInjector.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
pc.getReaderContext().registerWithGeneratedName(userServiceInjector.getBeanDefinition());
|
||||
}
|
||||
|
||||
List<OrderDecorator> getFilters() {
|
||||
@@ -658,16 +572,12 @@ final class AuthenticationConfigBuilder {
|
||||
filters.add(new OrderDecorator(x509Filter, X509_FILTER));
|
||||
}
|
||||
|
||||
if (jeeFilter != null) {
|
||||
filters.add(new OrderDecorator(jeeFilter, PRE_AUTH_FILTER));
|
||||
if (formFilter != null) {
|
||||
filters.add(new OrderDecorator(formFilter, FORM_LOGIN_FILTER));
|
||||
}
|
||||
|
||||
if (formFilterId != null) {
|
||||
filters.add(new OrderDecorator(new RuntimeBeanReference(formFilterId), FORM_LOGIN_FILTER));
|
||||
}
|
||||
|
||||
if (openIDFilterId != null) {
|
||||
filters.add(new OrderDecorator(new RuntimeBeanReference(openIDFilterId), OPENID_FILTER));
|
||||
if (openIDFilter != null) {
|
||||
filters.add(new OrderDecorator(openIDFilter, OPENID_FILTER));
|
||||
}
|
||||
|
||||
if (loginPageGenerationFilter != null) {
|
||||
@@ -702,11 +612,11 @@ final class AuthenticationConfigBuilder {
|
||||
providers.add(x509ProviderRef);
|
||||
}
|
||||
|
||||
if (jeeProviderRef != null) {
|
||||
providers.add(jeeProviderRef);
|
||||
}
|
||||
|
||||
return providers;
|
||||
}
|
||||
|
||||
public BeanReference getRequestCache() {
|
||||
return requestCache;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user