Compare commits
55 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 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 |
@@ -4,5 +4,8 @@ target/
|
|||||||
.settings/
|
.settings/
|
||||||
build/
|
build/
|
||||||
*.log
|
*.log
|
||||||
|
*.log.1
|
||||||
|
.DS_Store
|
||||||
|
*.iml
|
||||||
.gradle/
|
.gradle/
|
||||||
gradle.properties
|
gradle.properties
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ dependencies {
|
|||||||
"net.sf.ehcache:ehcache:$ehcacheVersion",
|
"net.sf.ehcache:ehcache:$ehcacheVersion",
|
||||||
"org.springframework:spring-aop:$springVersion",
|
"org.springframework:spring-aop:$springVersion",
|
||||||
"org.springframework:spring-context:$springVersion",
|
"org.springframework:spring-context:$springVersion",
|
||||||
"org.springframework:spring-core:$springVersion",
|
|
||||||
"org.springframework:spring-tx:$springVersion",
|
"org.springframework:spring-tx:$springVersion",
|
||||||
"org.springframework:spring-jdbc:$springVersion"
|
"org.springframework:spring-jdbc:$springVersion"
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>spring-security-parent</artifactId>
|
<artifactId>spring-security-parent</artifactId>
|
||||||
<groupId>org.springframework.security</groupId>
|
<groupId>org.springframework.security</groupId>
|
||||||
<version>3.0.2.RELEASE</version>
|
<version>3.0.3.RELEASE</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>org.springframework.security</groupId>
|
<groupId>org.springframework.security</groupId>
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
|
||||||
|
dependencies {
|
||||||
|
compile project(':spring-security-core'),
|
||||||
|
"org.springframework:spring-beans:$springVersion",
|
||||||
|
"org.springframework:spring-context:$springVersion"
|
||||||
|
}
|
||||||
+4
-8
@@ -5,16 +5,12 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.springframework.security</groupId>
|
<groupId>org.springframework.security</groupId>
|
||||||
<artifactId>spring-security-parent</artifactId>
|
<artifactId>spring-security-parent</artifactId>
|
||||||
<version>3.0.2.RELEASE</version>
|
<version>3.0.3.RELEASE</version>
|
||||||
</parent>
|
</parent>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
<artifactId>spring-security-aspects</artifactId>
|
<artifactId>spring-security-aspects</artifactId>
|
||||||
<name>Spring Security - Aspects</name>
|
<name>Spring Security - Aspects</name>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
|
||||||
<groupId>commons-logging</groupId>
|
|
||||||
<artifactId>commons-logging</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.aspectj</groupId>
|
<groupId>org.aspectj</groupId>
|
||||||
<artifactId>aspectjweaver</artifactId>
|
<artifactId>aspectjweaver</artifactId>
|
||||||
@@ -22,7 +18,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.security</groupId>
|
<groupId>org.springframework.security</groupId>
|
||||||
<artifactId>spring-security-core</artifactId>
|
<artifactId>spring-security-core</artifactId>
|
||||||
<version>3.0.2.RELEASE</version>
|
<version>3.0.3.RELEASE</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<build>
|
<build>
|
||||||
@@ -39,12 +35,12 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.aspectj</groupId>
|
<groupId>org.aspectj</groupId>
|
||||||
<artifactId>aspectjrt</artifactId>
|
<artifactId>aspectjrt</artifactId>
|
||||||
<version>1.6.5</version>
|
<version>1.6.8</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.aspectj</groupId>
|
<groupId>org.aspectj</groupId>
|
||||||
<artifactId>aspectjtools</artifactId>
|
<artifactId>aspectjtools</artifactId>
|
||||||
<version>1.6.5</version>
|
<version>1.6.8</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<executions>
|
<executions>
|
||||||
|
|||||||
+18
-8
@@ -2,11 +2,12 @@ package org.springframework.security.access.intercept.aspectj.aspect;
|
|||||||
|
|
||||||
import org.springframework.beans.factory.InitializingBean;
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
import org.springframework.security.access.annotation.Secured;
|
import org.springframework.security.access.annotation.Secured;
|
||||||
|
import org.springframework.security.access.prepost.*;
|
||||||
import org.springframework.security.access.intercept.aspectj.AspectJCallback;
|
import org.springframework.security.access.intercept.aspectj.AspectJCallback;
|
||||||
import org.springframework.security.access.intercept.aspectj.AspectJSecurityInterceptor;
|
import org.springframework.security.access.intercept.aspectj.AspectJMethodSecurityInterceptor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Concrete AspectJ transaction aspect using Spring Security @Secured annotation
|
* Concrete AspectJ aspect using Spring Security @Secured annotation
|
||||||
* for JDK 1.5+.
|
* for JDK 1.5+.
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
@@ -16,8 +17,8 @@ import org.springframework.security.access.intercept.aspectj.AspectJSecurityInte
|
|||||||
* interfaces are <i>not</i> inherited. This will vary from Spring AOP.
|
* interfaces are <i>not</i> inherited. This will vary from Spring AOP.
|
||||||
*
|
*
|
||||||
* @author Mike Wiesner
|
* @author Mike Wiesner
|
||||||
* @since 1.0
|
* @author Luke Taylor
|
||||||
* @version $Id$
|
* @since 3.1
|
||||||
*/
|
*/
|
||||||
public aspect AnnotationSecurityAspect implements InitializingBean {
|
public aspect AnnotationSecurityAspect implements InitializingBean {
|
||||||
|
|
||||||
@@ -34,11 +35,19 @@ public aspect AnnotationSecurityAspect implements InitializingBean {
|
|||||||
private pointcut executionOfSecuredMethod() :
|
private pointcut executionOfSecuredMethod() :
|
||||||
execution(* *(..)) && @annotation(Secured);
|
execution(* *(..)) && @annotation(Secured);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Matches the execution of any method with Pre/Post annotations.
|
||||||
|
*/
|
||||||
|
private pointcut executionOfPrePostAnnotatedMethod() :
|
||||||
|
execution(* *(..)) && (@annotation(PreAuthorize) || @annotation(PreFilter)
|
||||||
|
|| @annotation(PostAuthorize) || @annotation(PostFilter));
|
||||||
|
|
||||||
private pointcut securedMethodExecution() :
|
private pointcut securedMethodExecution() :
|
||||||
executionOfAnyPublicMethodInAtSecuredType() ||
|
executionOfAnyPublicMethodInAtSecuredType() ||
|
||||||
executionOfSecuredMethod();
|
executionOfSecuredMethod() ||
|
||||||
|
executionOfPrePostAnnotatedMethod();
|
||||||
|
|
||||||
private AspectJSecurityInterceptor securityInterceptor;
|
private AspectJMethodSecurityInterceptor securityInterceptor;
|
||||||
|
|
||||||
Object around(): securedMethodExecution() {
|
Object around(): securedMethodExecution() {
|
||||||
if (this.securityInterceptor == null) {
|
if (this.securityInterceptor == null) {
|
||||||
@@ -54,13 +63,14 @@ public aspect AnnotationSecurityAspect implements InitializingBean {
|
|||||||
return this.securityInterceptor.invoke(thisJoinPoint, callback);
|
return this.securityInterceptor.invoke(thisJoinPoint, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSecurityInterceptor(AspectJSecurityInterceptor securityInterceptor) {
|
public void setSecurityInterceptor(AspectJMethodSecurityInterceptor securityInterceptor) {
|
||||||
this.securityInterceptor = securityInterceptor;
|
this.securityInterceptor = securityInterceptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void afterPropertiesSet() throws Exception {
|
public void afterPropertiesSet() throws Exception {
|
||||||
if (this.securityInterceptor == null)
|
if (this.securityInterceptor == null) {
|
||||||
throw new IllegalArgumentException("securityInterceptor required");
|
throw new IllegalArgumentException("securityInterceptor required");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+110
@@ -0,0 +1,110 @@
|
|||||||
|
package org.springframework.security.access.intercept.aspectj.aspect;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.MockitoAnnotations;
|
||||||
|
import org.springframework.security.access.AccessDecisionManager;
|
||||||
|
import org.springframework.security.access.AccessDecisionVoter;
|
||||||
|
import org.springframework.security.access.AccessDeniedException;
|
||||||
|
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.ExpressionBasedPreInvocationAdvice;
|
||||||
|
import org.springframework.security.access.intercept.aspectj.AspectJMethodSecurityInterceptor;
|
||||||
|
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.authentication.AuthenticationCredentialsNotFoundException;
|
||||||
|
import org.springframework.security.authentication.AuthenticationManager;
|
||||||
|
import org.springframework.security.authentication.TestingAuthenticationToken;
|
||||||
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Luke Taylor
|
||||||
|
* @since 3.0.3
|
||||||
|
*/
|
||||||
|
public class AnnotationSecurityAspectTests {
|
||||||
|
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 PrePostSecured prePostSecured = new PrePostSecured();
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public final void setUp() throws Exception {
|
||||||
|
MockitoAnnotations.initMocks(this);
|
||||||
|
interceptor = new AspectJMethodSecurityInterceptor();
|
||||||
|
interceptor.setAccessDecisionManager(adm);
|
||||||
|
interceptor.setAuthenticationManager(authman);
|
||||||
|
interceptor.setSecurityMetadataSource(new SecuredAnnotationSecurityMetadataSource());
|
||||||
|
AnnotationSecurityAspect secAspect = AnnotationSecurityAspect.aspectOf();
|
||||||
|
secAspect.setSecurityInterceptor(interceptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void clearContext() {
|
||||||
|
SecurityContextHolder.clearContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void securedInterfaceMethodAllowsAllAccess() throws Exception {
|
||||||
|
secured.securedMethod();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected=AuthenticationCredentialsNotFoundException.class)
|
||||||
|
public void securedClassMethodDeniesUnauthenticatedAccess() throws Exception {
|
||||||
|
secured.securedClassMethod();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void securedClassMethodAllowsAccessToRoleA() throws Exception {
|
||||||
|
SecurityContextHolder.getContext().setAuthentication(anne);
|
||||||
|
secured.securedClassMethod();
|
||||||
|
}
|
||||||
|
|
||||||
|
// SEC-1262
|
||||||
|
@Test(expected=AccessDeniedException.class)
|
||||||
|
public void denyAllPreAuthorizeDeniesAccess() throws Exception {
|
||||||
|
SecurityContextHolder.getContext().setAuthentication(anne);
|
||||||
|
interceptor.setSecurityMetadataSource(new PrePostAnnotationSecurityMetadataSource(
|
||||||
|
new ExpressionBasedAnnotationAttributeFactory(new DefaultMethodSecurityExpressionHandler())));
|
||||||
|
AffirmativeBased adm = new AffirmativeBased();
|
||||||
|
AccessDecisionVoter[] voters = new AccessDecisionVoter[]
|
||||||
|
{new PreInvocationAuthorizationAdviceVoter(new ExpressionBasedPreInvocationAdvice())};
|
||||||
|
adm.setDecisionVoters(Arrays.asList(voters));
|
||||||
|
interceptor.setAccessDecisionManager(adm);
|
||||||
|
prePostSecured.denyAllMethod();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface SecuredInterface {
|
||||||
|
@Secured("ROLE_X")
|
||||||
|
void securedMethod();
|
||||||
|
}
|
||||||
|
|
||||||
|
class SecuredImpl implements SecuredInterface {
|
||||||
|
|
||||||
|
// Not really secured because AspectJ doesn't inherit annotations from interfaces
|
||||||
|
public void securedMethod() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Secured("ROLE_A")
|
||||||
|
public void securedClassMethod() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class PrePostSecured {
|
||||||
|
|
||||||
|
@PreAuthorize("denyAll")
|
||||||
|
public void denyAllMethod() {
|
||||||
|
}
|
||||||
|
}
|
||||||
+132
-192
@@ -1,137 +1,35 @@
|
|||||||
import java.util.jar.Manifest
|
apply plugin: 'base'
|
||||||
import org.gradle.api.tasks.bundling.GradleManifest
|
|
||||||
|
|
||||||
apply id: 'base'
|
|
||||||
|
|
||||||
allprojects {
|
allprojects {
|
||||||
version = '3.0.2.RELEASE'
|
version = '3.0.3.RELEASE'
|
||||||
releaseBuild = version.endsWith('RELEASE')
|
releaseBuild = version.endsWith('RELEASE')
|
||||||
snapshotBuild = version.endsWith('SNAPSHOT')
|
snapshotBuild = version.endsWith('SNAPSHOT')
|
||||||
|
|
||||||
group = 'org.springframework.security'
|
group = 'org.springframework.security'
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenRepo name:'Local', urls:'file:///Users/luke/.m2/repository'
|
mavenRepo name:'Local', urls: "file://" + System.properties['user.home'] + "/.m2/repository"
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
// mavenRepo name:'SpringSource Milestone Repo', urls:'http://repository.springsource.com/maven/bundles/milestone'
|
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'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
configure(javaProjects()) {
|
configure(javaProjects) {
|
||||||
apply id: 'java'
|
apply from: "$rootDir/gradle/javaprojects.gradle"
|
||||||
|
apply from: "$rootDir/gradle/maven.gradle"
|
||||||
springVersion = '3.0.1.RELEASE'
|
|
||||||
springLdapVersion = '1.3.0.RELEASE'
|
|
||||||
ehcacheVersion = '1.6.2'
|
|
||||||
aspectjVersion = '1.6.8'
|
|
||||||
apacheDsVersion = '1.5.5'
|
|
||||||
jstlVersion = '1.1.2'
|
|
||||||
jettyVersion = '6.1.22'
|
|
||||||
|
|
||||||
configurations {
|
|
||||||
bundlor
|
|
||||||
provided
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
compile 'commons-logging:commons-logging:1.1.1'
|
|
||||||
|
|
||||||
testCompile 'junit:junit:4.7',
|
|
||||||
'org.mockito:mockito-core:1.7',
|
|
||||||
'org.jmock:jmock:2.5.1',
|
|
||||||
'org.jmock:jmock-junit4:2.5.1',
|
|
||||||
'org.hamcrest:hamcrest-core:1.1',
|
|
||||||
'org.hamcrest:hamcrest-library:1.1',
|
|
||||||
"org.springframework:spring-test:$springVersion"
|
|
||||||
bundlor 'com.springsource.bundlor:com.springsource.bundlor.ant:1.0.0.RC1',
|
|
||||||
'com.springsource.bundlor:com.springsource.bundlor:1.0.0.RC1',
|
|
||||||
'com.springsource.bundlor:com.springsource.bundlor.blint:1.0.0.RC1'
|
|
||||||
}
|
|
||||||
|
|
||||||
sourceSets {
|
|
||||||
main {
|
|
||||||
compileClasspath = compileClasspath + configurations.provided
|
|
||||||
}
|
|
||||||
test {
|
|
||||||
compileClasspath = compileClasspath + configurations.provided
|
|
||||||
runtimeClasspath = runtimeClasspath + configurations.provided
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
test {
|
|
||||||
options.fork(forkMode: ForkMode.ONCE, jvmArgs: ["-ea", '-Xms128m', '-Xmx500m', '-XX:MaxPermSize=128m', '-XX:+HeapDumpOnOutOfMemoryError'])
|
|
||||||
}
|
|
||||||
|
|
||||||
task bundlor (dependsOn: compileJava) << {
|
|
||||||
if (!dependsOnTaskDidWork()) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ant.taskdef(resource: 'com/springsource/bundlor/ant/antlib.xml', classpath: configurations.bundlor.asPath)
|
|
||||||
File template = new File(projectDir, 'template.mf')
|
|
||||||
mkdir(buildDir, 'bundlor')
|
|
||||||
if (template.exists()) {
|
|
||||||
ant.bundlor(inputPath: sourceSets.main.classesDir, outputPath: "$buildDir/bundlor", manifestTemplatePath: template) {
|
|
||||||
property(name: 'version', value: "$version")
|
|
||||||
property(name: 'spring.version', value: "$springVersion")
|
|
||||||
}
|
|
||||||
// See GRADLE-395 for support for using an existing manifest
|
|
||||||
jar.manifest = new GradleManifest(new Manifest(new File("$buildDir/bundlor/META-INF/MANIFEST.MF").newInputStream()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
jar.dependsOn bundlor
|
|
||||||
}
|
}
|
||||||
|
|
||||||
configure(javaProjects()) {
|
configure(coreModuleProjects) {
|
||||||
apply id: 'maven'
|
apply from: "$rootDir/gradle/bundlor.gradle"
|
||||||
|
|
||||||
// Create a source jar for uploading
|
|
||||||
task sourceJar(type: Jar) {
|
|
||||||
classifier = 'sources'
|
|
||||||
from sourceSets.main.java
|
|
||||||
}
|
|
||||||
|
|
||||||
configurations {
|
|
||||||
deployerJars
|
|
||||||
}
|
|
||||||
|
|
||||||
artifacts {
|
|
||||||
archives sourceJar
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
deployerJars "org.springframework.build.aws:org.springframework.build.aws.maven:2.0.1.BUILD-SNAPSHOT"
|
|
||||||
}
|
|
||||||
|
|
||||||
uploadArchives {
|
|
||||||
repositories.mavenDeployer {
|
|
||||||
configuration = configurations.deployerJars
|
|
||||||
if (releaseBuild) {
|
|
||||||
// "mavenSyncRepoDir" should be set in properties
|
|
||||||
repository(url: mavenSyncRepoDir)
|
|
||||||
} else {
|
|
||||||
s3credentials = [userName: s3AccessKey, passphrase: s3SecretAccessKey]
|
|
||||||
repository(url: "s3://maven.springframework.org/milestone") {
|
|
||||||
authentication(s3credentials)
|
|
||||||
}
|
|
||||||
snapshotRepository(url: "s3://maven.springframework.org/snapshot") {
|
|
||||||
authentication(s3credentials)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
conf2ScopeMappings.addMapping(1, configurations.provided, "provided")
|
|
||||||
}
|
|
||||||
|
|
||||||
configure(coreModuleProjects()) {
|
|
||||||
// Gives better names in structure101 jar diagram
|
// Gives better names in structure101 jar diagram
|
||||||
sourceSets.main.classesDir = new File(buildDir, "classes/" + project.name.substring("spring-security".length() + 1))
|
sourceSets.main.classesDir = new File(buildDir, "classes/" + project.name.substring("spring-security".length() + 1))
|
||||||
}
|
}
|
||||||
|
|
||||||
repositories {
|
configure (aspectjProjects) {
|
||||||
// Required for ant s3 task
|
apply from: "$rootDir/gradle/aspectj.gradle"
|
||||||
mavenRepo name: "s2.com release", urls: "http://repository.springsource.com/maven/bundles/release"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
configurations {
|
configurations {
|
||||||
@@ -143,62 +41,75 @@ dependencies {
|
|||||||
"net.java.dev.jets3t:jets3t:0.6.1"
|
"net.java.dev.jets3t:jets3t:0.6.1"
|
||||||
}
|
}
|
||||||
|
|
||||||
def docsDir = new File(project(':manual').buildDir, 'docs')
|
|
||||||
|
|
||||||
task apidocs(type: Javadoc) {
|
task apidocs(type: Javadoc) {
|
||||||
destinationDir = new File(buildDir, 'apidocs')
|
destinationDir = new File(buildDir, 'apidocs')
|
||||||
title = "Spring Security $version API"
|
title = "Spring Security $version API"
|
||||||
optionsFile = file("$buildDir/tmp/javadoc.options")
|
optionsFile = file("$buildDir/tmp/javadoc.options")
|
||||||
|
|
||||||
source coreModuleProjects().collect { project ->
|
source coreModuleProjects.collect {project ->
|
||||||
project.sourceSets.main.allJava
|
project.sourceSets.main.allJava
|
||||||
}
|
}
|
||||||
|
|
||||||
classpath = files(coreModuleProjects().collect { project ->
|
classpath = files(coreModuleProjects.collect {project ->
|
||||||
project.sourceSets.main.compileClasspath })
|
project.sourceSets.main.compileClasspath
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
task apitar(type: Tar, dependsOn: apidocs) {
|
task docSiteLogin(type: Login) {
|
||||||
compression = Compression.BZIP2
|
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'
|
classifier = 'apidocs'
|
||||||
|
remoteDir = remoteDocsDir
|
||||||
|
login = docSiteLogin
|
||||||
|
|
||||||
into('apidocs') {
|
into('apidocs') {
|
||||||
from apidocs.destinationDir
|
from apidocs.destinationDir
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
task doctar(type: Tar, dependsOn: ':manual:doc') {
|
def docsDir = new File(project(':manual').buildDir, 'docs')
|
||||||
compression = Compression.BZIP2
|
|
||||||
|
task uploadDoc(type: TarUpload) {
|
||||||
|
dependsOn ':manual:doc'
|
||||||
classifier = 'doc'
|
classifier = 'doc'
|
||||||
|
remoteDir = remoteDocsDir
|
||||||
|
login = docSiteLogin
|
||||||
|
|
||||||
into('reference') {
|
into('reference') {
|
||||||
from docsDir
|
from docsDir
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def username;
|
task uploadFaq(type: TarUpload) {
|
||||||
def password;
|
dependsOn ':faq:docbookHtmlSingle'
|
||||||
|
classifier = 'faq'
|
||||||
|
if (project.hasProperty('remoteSiteDir')) {
|
||||||
|
remoteDir = project.property('remoteSiteDir')
|
||||||
|
}
|
||||||
|
login = docSiteLogin
|
||||||
|
|
||||||
task login << {
|
def faqDir = new File(project(':faq').buildDir, 'docs')
|
||||||
ant.input("Please enter the ssh username for host '$sshHost'", addproperty: "ssh.username")
|
|
||||||
ant.input("Please enter the ssh password '$sshHost'", addproperty: "ssh.password")
|
into('faq') {
|
||||||
username = ant.properties['ssh.username']
|
from faqDir
|
||||||
password = ant.properties['ssh.password']
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
task uploadApidocs (dependsOn: login) << {
|
task dist(type: Zip) {
|
||||||
ant.scp(file: apitar.archivePath, todir: "$username@$sshHost:$remoteDocsDir", password: password)
|
|
||||||
ant.sshexec(host: sshHost, username: username, password: password, command: "cd $remoteDocsDir && tar -xjf ${apitar.archiveName}")
|
|
||||||
ant.sshexec(host: sshHost, username: username, password: password, command: "rm $remoteDocsDir/${apitar.archiveName}")
|
|
||||||
}
|
|
||||||
|
|
||||||
task uploadManual (dependsOn: login) << {
|
|
||||||
ant.scp(file: doctar.archivePath, todir: "$username@$sshHost:$remoteDocsDir", password: password)
|
|
||||||
ant.sshexec(host: sshHost, username: username, password: password, command: "cd $remoteDocsDir && tar -xjf ${doctar.archiveName}")
|
|
||||||
ant.sshexec(host: sshHost, username: username, password: password, command: "rm $remoteDocsDir/${doctar.archiveName}")
|
|
||||||
}
|
|
||||||
|
|
||||||
task dist (type: Zip) {
|
|
||||||
def zipRootDir = "${project.name}-$version"
|
def zipRootDir = "${project.name}-$version"
|
||||||
into (zipRootDir) {
|
into(zipRootDir) {
|
||||||
into('docs/apidocs') {
|
into('docs/apidocs') {
|
||||||
from apidocs.destinationDir
|
from apidocs.destinationDir
|
||||||
}
|
}
|
||||||
@@ -206,61 +117,90 @@ task dist (type: Zip) {
|
|||||||
from docsDir
|
from docsDir
|
||||||
}
|
}
|
||||||
into('dist') {
|
into('dist') {
|
||||||
from coreModuleProjects().collect { project -> project.libsDir }
|
from coreModuleProjects.collect {project -> project.libsDir }
|
||||||
from project(':spring-security-samples-tutorial').libsDir
|
from project(':spring-security-samples-tutorial').libsDir
|
||||||
from project(':spring-security-samples-contacts').libsDir
|
from project(':spring-security-samples-contacts').libsDir
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dist.dependsOn apidocs, ':manual:doc'
|
dist {
|
||||||
dist.dependsOn subprojects.collect { "$it.path:assemble" }
|
dependsOn apidocs, ':manual:doc', subprojects.collect { "$it.path:assemble" }
|
||||||
|
doLast {
|
||||||
dist.doLast {
|
ant.checksum(file: archivePath, algorithm: 'SHA1', fileext: '.sha1')
|
||||||
ant.checksum(file: archivePath, algorithm: 'SHA1', fileext: '.sha1')
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
task uploadDist << {
|
task uploadDist(type: UploadDist) {
|
||||||
def shaFile = file("${dist.archivePath}.sha1")
|
archiveFile = dist.archivePath
|
||||||
assert dist.archivePath.isFile()
|
shaFile = "${dist.archivePath}.sha1" as File
|
||||||
assert shaFile.isFile()
|
archiveName = dist.archiveName
|
||||||
ant.taskdef(resource: 'org/springframework/build/aws/ant/antlib.xml', classpath: configurations.antlibs.asPath)
|
classpath = configurations.antlibs
|
||||||
ant.s3(accessKey: s3AccessKey, secretKey: s3SecretAccessKey) {
|
}
|
||||||
upload(bucketName: 'dist.springframework.org', file: dist.archivePath,
|
|
||||||
toFile: releaseType() + "/SEC/${dist.archiveName}", publicRead: 'true') {
|
def getJavaProjects() {
|
||||||
metadata(name: 'project.name', value: 'Spring Security')
|
subprojects.findAll {project -> project.name != 'faq' && project.name != 'manual' }
|
||||||
metadata(name: 'release.type', value: releaseType())
|
}
|
||||||
metadata(name: 'bundle.version', value: version)
|
|
||||||
metadata(name: 'package.file.name', value: dist.archiveName)
|
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'
|
||||||
}
|
}
|
||||||
upload(bucketName: 'dist.springframework.org', file: shaFile,
|
|
||||||
toFile: releaseType() + "/SEC/${dist.archiveName}.sha1", publicRead: 'true')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def javaProjects() {
|
|
||||||
subprojects.findAll { project -> project.name != 'faq' && project.name != 'manual' }
|
|
||||||
}
|
|
||||||
|
|
||||||
def sampleProjects() {
|
|
||||||
subprojects.findAll { project -> project.name.startsWith('spring-security-samples') }
|
|
||||||
}
|
|
||||||
|
|
||||||
def itestProjects() {
|
|
||||||
subprojects.findAll { project -> project.name.startsWith('itest') }
|
|
||||||
}
|
|
||||||
|
|
||||||
def coreModuleProjects() {
|
|
||||||
javaProjects() - sampleProjects() - itestProjects()
|
|
||||||
}
|
|
||||||
|
|
||||||
def releaseType() {
|
|
||||||
if (releaseBuild) {
|
|
||||||
'release'
|
|
||||||
} else if (snapshotBuild) {
|
|
||||||
'snapshot'
|
|
||||||
} else {
|
|
||||||
'milestone'
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
apply plugin: 'groovy'
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenRepo name:'localRepo', urls: "file://" + System.properties['user.home'] + "/.m2/repository"
|
||||||
|
mavenCentral()
|
||||||
|
mavenRepo name:'Shibboleth Repo', urls:'http://shibboleth.internet2.edu/downloads/maven2'
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
def fopDeps = [ 'org.apache.xmlgraphics:fop:0.95-1@jar',
|
||||||
|
'org.apache.xmlgraphics:xmlgraphics-commons:1.3',
|
||||||
|
'org.apache.xmlgraphics:batik-bridge:1.7@jar',
|
||||||
|
'org.apache.xmlgraphics:batik-util:1.7@jar',
|
||||||
|
'org.apache.xmlgraphics:batik-css:1.7@jar',
|
||||||
|
'org.apache.xmlgraphics:batik-dom:1.7',
|
||||||
|
'org.apache.xmlgraphics:batik-svg-dom:1.7@jar',
|
||||||
|
'org.apache.avalon.framework:avalon-framework-api:4.3.1']
|
||||||
|
groovy localGroovy()
|
||||||
|
compile gradleApi(),
|
||||||
|
'org.apache.xerces:resolver:2.9.1',
|
||||||
|
'saxon:saxon:6.5.3',
|
||||||
|
'org.apache.xerces:xercesImpl:2.9.1',
|
||||||
|
fopDeps
|
||||||
|
|
||||||
|
runtime 'net.sf.xslthl:xslthl:2.0.1',
|
||||||
|
'net.sf.docbook:docbook-xsl:1.75.2:resources@zip'
|
||||||
|
}
|
||||||
|
|
||||||
|
task ide(type: Copy) {
|
||||||
|
from configurations.runtime
|
||||||
|
into 'ide'
|
||||||
|
}
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
import org.gradle.api.DefaultTask;
|
||||||
|
import org.gradle.api.tasks.*;
|
||||||
|
import org.gradle.api.tasks.bundling.Tar;
|
||||||
|
import org.gradle.api.tasks.bundling.Compression;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extends the Tar task, uploading the created archive to a remote directory, unpacking and deleting it.
|
||||||
|
* Requires Ant ssh (jsch) support.
|
||||||
|
*/
|
||||||
|
class TarUpload extends Tar {
|
||||||
|
@Input
|
||||||
|
String remoteDir
|
||||||
|
|
||||||
|
@Input
|
||||||
|
Login login
|
||||||
|
|
||||||
|
TarUpload() {
|
||||||
|
compression = Compression.BZIP2
|
||||||
|
}
|
||||||
|
|
||||||
|
@TaskAction
|
||||||
|
void copy() {
|
||||||
|
super.copy();
|
||||||
|
upload();
|
||||||
|
}
|
||||||
|
|
||||||
|
def upload() {
|
||||||
|
String username = login.username
|
||||||
|
String password = login.password
|
||||||
|
String host = login.host
|
||||||
|
project.ant {
|
||||||
|
scp(file: archivePath, todir: "$username@$host:$remoteDir", password: password)
|
||||||
|
sshexec(host: host, username: username, password: password, command: "cd $remoteDir && tar -xjf $archiveName")
|
||||||
|
sshexec(host: host, username: username, password: password, command: "rm $remoteDir/$archiveName")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setLogin(Login login) {
|
||||||
|
dependsOn(login)
|
||||||
|
this.login = login
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores login information for a remote host.
|
||||||
|
*/
|
||||||
|
class Login extends DefaultTask {
|
||||||
|
@Input
|
||||||
|
String host
|
||||||
|
String username
|
||||||
|
String password
|
||||||
|
|
||||||
|
@TaskAction
|
||||||
|
login() {
|
||||||
|
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"]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,266 @@
|
|||||||
|
package docbook;
|
||||||
|
|
||||||
|
import org.gradle.api.Plugin;
|
||||||
|
import org.gradle.api.GradleException;
|
||||||
|
import org.gradle.api.DefaultTask;
|
||||||
|
import org.gradle.api.Task;
|
||||||
|
import org.gradle.api.Project;
|
||||||
|
import org.gradle.api.Action;
|
||||||
|
import org.gradle.api.tasks.*;
|
||||||
|
import org.gradle.api.file.FileCollection;
|
||||||
|
|
||||||
|
import org.xml.sax.XMLReader;
|
||||||
|
import org.xml.sax.InputSource;
|
||||||
|
import org.apache.xml.resolver.CatalogManager;
|
||||||
|
import org.apache.xml.resolver.tools.CatalogResolver;
|
||||||
|
|
||||||
|
import javax.xml.parsers.SAXParserFactory;
|
||||||
|
import javax.xml.transform.*;
|
||||||
|
import javax.xml.transform.sax.SAXSource;
|
||||||
|
import javax.xml.transform.sax.SAXResult;
|
||||||
|
import javax.xml.transform.stream.StreamResult;
|
||||||
|
import javax.xml.transform.stream.StreamSource;
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.zip.*;
|
||||||
|
import java.net.*;
|
||||||
|
|
||||||
|
import org.apache.fop.apps.*;
|
||||||
|
|
||||||
|
import com.icl.saxon.TransformerFactoryImpl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gradle Docbook plugin implementation.
|
||||||
|
* <p>
|
||||||
|
* Creates three tasks: docbookHtml, docbookHtmlSingle and docbookPdf. Each task takes a single File on
|
||||||
|
* which it operates.
|
||||||
|
*/
|
||||||
|
class DocbookPlugin implements Plugin<Project> {
|
||||||
|
public void apply(Project project) {
|
||||||
|
// Add the plugin tasks to the project
|
||||||
|
Task docbookHtml = project.tasks.add('docbookHtml', DocbookHtml.class);
|
||||||
|
docbookHtml.setDescription('Generates chunked docbook html output');
|
||||||
|
|
||||||
|
Task docbookHtmlSingle = project.tasks.add('docbookHtmlSingle', Docbook.class);
|
||||||
|
docbookHtmlSingle.setDescription('Generates single page docbook html output')
|
||||||
|
docbookHtmlSingle.suffix = '-single'
|
||||||
|
|
||||||
|
Task docbookFoPdf = project.tasks.add("docbookFoPdf", DocbookFoPdf.class);
|
||||||
|
docbookFoPdf.setDescription('Generates PDF output');
|
||||||
|
docbookFoPdf.extension = 'fo'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
public class Docbook extends DefaultTask {
|
||||||
|
|
||||||
|
@Input
|
||||||
|
String extension = 'html';
|
||||||
|
|
||||||
|
@Input
|
||||||
|
String suffix = '';
|
||||||
|
|
||||||
|
@Input
|
||||||
|
boolean XIncludeAware = true;
|
||||||
|
|
||||||
|
@Input
|
||||||
|
boolean highlightingEnabled = true;
|
||||||
|
|
||||||
|
String admonGraphicsPath;
|
||||||
|
|
||||||
|
@InputDirectory
|
||||||
|
File sourceDirectory = new File(project.getProjectDir(), "src/docbook");
|
||||||
|
|
||||||
|
@Input
|
||||||
|
String sourceFileName;
|
||||||
|
|
||||||
|
@InputFile
|
||||||
|
File stylesheet;
|
||||||
|
|
||||||
|
@OutputDirectory
|
||||||
|
File docsDir = new File(project.getBuildDir(), "docs");
|
||||||
|
|
||||||
|
@TaskAction
|
||||||
|
public final void transform() {
|
||||||
|
SAXParserFactory factory = new org.apache.xerces.jaxp.SAXParserFactoryImpl();
|
||||||
|
factory.setXIncludeAware(XIncludeAware);
|
||||||
|
docsDir.mkdirs();
|
||||||
|
|
||||||
|
File srcFile = new File(sourceDirectory, sourceFileName);
|
||||||
|
String outputFilename = srcFile.getName().substring(0, srcFile.getName().length() - 4) + suffix + '.' + extension;
|
||||||
|
|
||||||
|
File outputFile = new File(getDocsDir(), outputFilename);
|
||||||
|
|
||||||
|
Result result = new StreamResult(outputFile.getAbsolutePath());
|
||||||
|
CatalogResolver resolver = new CatalogResolver(createCatalogManager());
|
||||||
|
InputSource inputSource = new InputSource(srcFile.getAbsolutePath());
|
||||||
|
|
||||||
|
XMLReader reader = factory.newSAXParser().getXMLReader();
|
||||||
|
reader.setEntityResolver(resolver);
|
||||||
|
TransformerFactory transformerFactory = new TransformerFactoryImpl();
|
||||||
|
transformerFactory.setURIResolver(resolver);
|
||||||
|
URL url = stylesheet.toURL();
|
||||||
|
Source source = new StreamSource(url.openStream(), url.toExternalForm());
|
||||||
|
Transformer transformer = transformerFactory.newTransformer(source);
|
||||||
|
|
||||||
|
if (highlightingEnabled) {
|
||||||
|
File highlightingDir = new File(getProject().getBuildDir(), "highlighting");
|
||||||
|
if (!highlightingDir.exists()) {
|
||||||
|
highlightingDir.mkdirs();
|
||||||
|
extractHighlightFiles(highlightingDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
preTransform(transformer, srcFile, outputFile);
|
||||||
|
|
||||||
|
transformer.transform(new SAXSource(reader, inputSource), result);
|
||||||
|
|
||||||
|
postTransform(outputFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void extractHighlightFiles(File toDir) {
|
||||||
|
URLClassLoader cl = (URLClassLoader) getClass().getClassLoader();
|
||||||
|
URL[] urls = cl.getURLs();
|
||||||
|
URL docbookZip = null;
|
||||||
|
|
||||||
|
for (URL url : urls) {
|
||||||
|
if (url.toString().contains("docbook-xsl-")) {
|
||||||
|
docbookZip = url;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (docbookZip == null) {
|
||||||
|
throw new GradleException("Docbook zip file not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
ZipFile zipFile = new ZipFile(new File(docbookZip.toURI()));
|
||||||
|
|
||||||
|
Enumeration e = zipFile.entries();
|
||||||
|
while (e.hasMoreElements()) {
|
||||||
|
ZipEntry ze = (ZipEntry) e.nextElement();
|
||||||
|
if (ze.getName().matches(".*/highlighting/.*\\.xml")) {
|
||||||
|
String filename = ze.getName().substring(ze.getName().lastIndexOf("/highlighting/") + 14);
|
||||||
|
copyFile(zipFile.getInputStream(ze), new File(toDir, filename));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void copyFile(InputStream source, File destFile) {
|
||||||
|
destFile.createNewFile();
|
||||||
|
FileOutputStream to = null;
|
||||||
|
try {
|
||||||
|
to = new FileOutputStream(destFile);
|
||||||
|
byte[] buffer = new byte[4096];
|
||||||
|
int bytesRead;
|
||||||
|
|
||||||
|
while ((bytesRead = source.read(buffer)) > 0) {
|
||||||
|
to.write(buffer, 0, bytesRead);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if (source != null) {
|
||||||
|
source.close();
|
||||||
|
}
|
||||||
|
if (to != null) {
|
||||||
|
to.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void preTransform(Transformer transformer, File sourceFile, File outputFile) {
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void postTransform(File outputFile) {
|
||||||
|
}
|
||||||
|
|
||||||
|
private CatalogManager createCatalogManager() {
|
||||||
|
CatalogManager manager = new CatalogManager();
|
||||||
|
manager.setIgnoreMissingProperties(true);
|
||||||
|
ClassLoader classLoader = this.getClass().getClassLoader();
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
String docbookCatalogName = "docbook/catalog.xml";
|
||||||
|
URL docbookCatalog = classLoader.getResource(docbookCatalogName);
|
||||||
|
|
||||||
|
if (docbookCatalog == null) {
|
||||||
|
throw new IllegalStateException("Docbook catalog " + docbookCatalogName + " could not be found in " + classLoader);
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.append(docbookCatalog.toExternalForm());
|
||||||
|
|
||||||
|
Enumeration enumeration = classLoader.getResources("/catalog.xml");
|
||||||
|
while (enumeration.hasMoreElements()) {
|
||||||
|
builder.append(';');
|
||||||
|
URL resource = (URL) enumeration.nextElement();
|
||||||
|
builder.append(resource.toExternalForm());
|
||||||
|
}
|
||||||
|
String catalogFiles = builder.toString();
|
||||||
|
manager.setCatalogFiles(catalogFiles);
|
||||||
|
return manager;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
class DocbookHtml extends Docbook {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void preTransform(Transformer transformer, File sourceFile, File outputFile) {
|
||||||
|
String rootFilename = outputFile.getName();
|
||||||
|
rootFilename = rootFilename.substring(0, rootFilename.lastIndexOf('.'));
|
||||||
|
transformer.setParameter("root.filename", rootFilename);
|
||||||
|
transformer.setParameter("base.dir", outputFile.getParent() + File.separator);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
class DocbookFoPdf extends Docbook {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <a href="http://xmlgraphics.apache.org/fop/0.95/embedding.html#render">From the FOP usage guide</a>
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected void postTransform(File foFile) {
|
||||||
|
FopFactory fopFactory = FopFactory.newInstance();
|
||||||
|
|
||||||
|
OutputStream out = null;
|
||||||
|
final File pdfFile = getPdfOutputFile(foFile);
|
||||||
|
logger.debug("Transforming 'fo' file "+ foFile + " to PDF: " + pdfFile);
|
||||||
|
|
||||||
|
try {
|
||||||
|
out = new BufferedOutputStream(new FileOutputStream(pdfFile));
|
||||||
|
|
||||||
|
Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, out);
|
||||||
|
|
||||||
|
TransformerFactory factory = TransformerFactory.newInstance();
|
||||||
|
Transformer transformer = factory.newTransformer();
|
||||||
|
|
||||||
|
Source src = new StreamSource(foFile);
|
||||||
|
|
||||||
|
Result res = new SAXResult(fop.getDefaultHandler());
|
||||||
|
|
||||||
|
transformer.transform(src, res);
|
||||||
|
} finally {
|
||||||
|
if (out != null) {
|
||||||
|
out.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!foFile.delete()) {
|
||||||
|
logger.warn("Failed to delete 'fo' file " + foFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private File getPdfOutputFile(File foFile) {
|
||||||
|
String name = foFile.getAbsolutePath();
|
||||||
|
return new File(name.substring(0, name.length() - 2) + "pdf");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
implementation-class=docbook.DocbookPlugin
|
||||||
+4
-4
@@ -2,12 +2,12 @@
|
|||||||
dependencies {
|
dependencies {
|
||||||
compile project(':spring-security-core'),
|
compile project(':spring-security-core'),
|
||||||
project(':spring-security-web'),
|
project(':spring-security-web'),
|
||||||
"javax.servlet:servlet-api:2.5",
|
"org.springframework:spring-context:$springVersion",
|
||||||
"org.springframework:spring-core:$springVersion",
|
|
||||||
"org.springframework:spring-context:$springVersion",
|
|
||||||
"org.springframework:spring-beans:$springVersion",
|
"org.springframework:spring-beans:$springVersion",
|
||||||
"org.springframework:spring-tx:$springVersion",
|
"org.springframework:spring-tx:$springVersion",
|
||||||
"org.springframework:spring-web:$springVersion",
|
"org.springframework:spring-web:$springVersion",
|
||||||
"org.jasig.cas:cas-client-core:3.1.9",
|
"org.jasig.cas:cas-client-core:3.1.9",
|
||||||
"net.sf.ehcache:ehcache:$ehcacheVersion"
|
"net.sf.ehcache:ehcache:$ehcacheVersion"
|
||||||
|
|
||||||
|
provided 'javax.servlet:servlet-api:2.5'
|
||||||
}
|
}
|
||||||
+1
-1
@@ -3,7 +3,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.springframework.security</groupId>
|
<groupId>org.springframework.security</groupId>
|
||||||
<artifactId>spring-security-parent</artifactId>
|
<artifactId>spring-security-parent</artifactId>
|
||||||
<version>3.0.2.RELEASE</version>
|
<version>3.0.3.RELEASE</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>spring-security-cas-client</artifactId>
|
<artifactId>spring-security-cas-client</artifactId>
|
||||||
<name>Spring Security - CAS support</name>
|
<name>Spring Security - CAS support</name>
|
||||||
|
|||||||
+1
-1
@@ -59,7 +59,7 @@ public class CasAuthenticationToken extends AbstractAuthenticationToken implemen
|
|||||||
* @throws IllegalArgumentException if a <code>null</code> was passed
|
* @throws IllegalArgumentException if a <code>null</code> was passed
|
||||||
*/
|
*/
|
||||||
public CasAuthenticationToken(final String key, final Object principal, final Object credentials,
|
public CasAuthenticationToken(final String key, final Object principal, final Object credentials,
|
||||||
final Collection<GrantedAuthority> authorities, final UserDetails userDetails, final Assertion assertion) {
|
final Collection<? extends GrantedAuthority> authorities, final UserDetails userDetails, final Assertion assertion) {
|
||||||
super(authorities);
|
super(authorities);
|
||||||
|
|
||||||
if ((key == null) || ("".equals(key)) || (principal == null) || "".equals(principal) || (credentials == null)
|
if ((key == null) || ("".equals(key)) || (principal == null) || "".equals(principal) || (credentials == null)
|
||||||
|
|||||||
@@ -5,24 +5,20 @@ compileTestJava.dependsOn(':spring-security-core:compileTestJava')
|
|||||||
dependencies {
|
dependencies {
|
||||||
compile project(':spring-security-core'),
|
compile project(':spring-security-core'),
|
||||||
project(':spring-security-web'),
|
project(':spring-security-web'),
|
||||||
"javax.servlet:servlet-api:2.5",
|
'aopalliance:aopalliance:1.0',
|
||||||
"org.aspectj:aspectjweaver:$aspectjVersion",
|
"org.aspectj:aspectjweaver:$aspectjVersion",
|
||||||
"org.springframework:spring-aop:$springVersion",
|
"org.springframework:spring-aop:$springVersion",
|
||||||
"org.springframework:spring-core:$springVersion",
|
|
||||||
"org.springframework:spring-context:$springVersion",
|
"org.springframework:spring-context:$springVersion",
|
||||||
"org.springframework:spring-web:$springVersion",
|
"org.springframework:spring-web:$springVersion",
|
||||||
"org.springframework:spring-beans:$springVersion",
|
"org.springframework:spring-beans:$springVersion",
|
||||||
"org.springframework:spring-tx:$springVersion"
|
"org.springframework:spring-tx:$springVersion"
|
||||||
|
|
||||||
|
provided "javax.servlet:servlet-api:2.5"
|
||||||
|
|
||||||
testCompile project(':spring-security-ldap'),
|
testCompile project(':spring-security-ldap'),
|
||||||
project(':spring-security-openid'),
|
project(':spring-security-openid'),
|
||||||
files(this.project(':spring-security-core').sourceSets.test.classesDir),
|
files(this.project(':spring-security-core').sourceSets.test.classesDir),
|
||||||
'javax.annotation:jsr250-api:1.0',
|
'javax.annotation:jsr250-api:1.0',
|
||||||
'aopalliance:aopalliance:1.0',
|
|
||||||
"org.springframework.ldap:spring-ldap-core:$springLdapVersion",
|
"org.springframework.ldap:spring-ldap-core:$springLdapVersion",
|
||||||
"org.springframework:spring-jdbc:$springVersion"
|
"org.springframework:spring-jdbc:$springVersion"
|
||||||
}
|
}
|
||||||
|
|
||||||
task show << {
|
|
||||||
println dependencies
|
|
||||||
}
|
|
||||||
@@ -3,9 +3,9 @@
|
|||||||
pushd src/main/resources/org/springframework/security/config/
|
pushd src/main/resources/org/springframework/security/config/
|
||||||
|
|
||||||
echo "Converting rnc file to xsd ..."
|
echo "Converting rnc file to xsd ..."
|
||||||
java -jar ~/bin/trang.jar spring-security-3.0.rnc spring-security-3.0.xsd
|
java -jar ~/bin/trang.jar spring-security-3.0.3.rnc spring-security-3.0.3.xsd
|
||||||
|
|
||||||
echo "Applying XSL transformation to xsd ..."
|
echo "Applying XSL transformation to xsd ..."
|
||||||
xsltproc --output spring-security-3.0.xsd spring-security.xsl spring-security-3.0.xsd
|
xsltproc --output spring-security-3.0.3.xsd spring-security.xsl spring-security-3.0.3.xsd
|
||||||
|
|
||||||
popd
|
popd
|
||||||
+2
-6
@@ -3,7 +3,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.springframework.security</groupId>
|
<groupId>org.springframework.security</groupId>
|
||||||
<artifactId>spring-security-parent</artifactId>
|
<artifactId>spring-security-parent</artifactId>
|
||||||
<version>3.0.2.RELEASE</version>
|
<version>3.0.3.RELEASE</version>
|
||||||
</parent>
|
</parent>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
<artifactId>spring-security-config</artifactId>
|
<artifactId>spring-security-config</artifactId>
|
||||||
@@ -41,10 +41,6 @@
|
|||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>commons-logging</groupId>
|
|
||||||
<artifactId>commons-logging</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.security</groupId>
|
<groupId>org.springframework.security</groupId>
|
||||||
<artifactId>spring-security-ldap</artifactId>
|
<artifactId>spring-security-ldap</artifactId>
|
||||||
@@ -76,7 +72,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.slf4j</groupId>
|
<groupId>org.slf4j</groupId>
|
||||||
<artifactId>slf4j-log4j12</artifactId>
|
<artifactId>slf4j-log4j12</artifactId>
|
||||||
<version>1.5.10</version>
|
<version>1.6.0</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
|
|||||||
+15
-5
@@ -45,6 +45,11 @@ public final class SecurityNamespaceHandler implements NamespaceHandler {
|
|||||||
String name = pc.getDelegate().getLocalName(element);
|
String name = pc.getDelegate().getLocalName(element);
|
||||||
BeanDefinitionParser parser = parsers.get(name);
|
BeanDefinitionParser parser = parsers.get(name);
|
||||||
|
|
||||||
|
if (parser == null) {
|
||||||
|
// SEC-1455. Load parsers when required, not just on init().
|
||||||
|
loadParsers();
|
||||||
|
}
|
||||||
|
|
||||||
if (parser == null) {
|
if (parser == null) {
|
||||||
if (Elements.HTTP.equals(name) || Elements.FILTER_SECURITY_METADATA_SOURCE.equals(name)) {
|
if (Elements.HTTP.equals(name) || Elements.FILTER_SECURITY_METADATA_SOURCE.equals(name)) {
|
||||||
reportMissingWebClasses(name, pc, element);
|
reportMissingWebClasses(name, pc, element);
|
||||||
@@ -67,6 +72,9 @@ public final class SecurityNamespaceHandler implements NamespaceHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (Elements.FILTER_CHAIN_MAP.equals(name)) {
|
if (Elements.FILTER_CHAIN_MAP.equals(name)) {
|
||||||
|
if (filterChainMapBDD == null) {
|
||||||
|
loadParsers();
|
||||||
|
}
|
||||||
if (filterChainMapBDD == null) {
|
if (filterChainMapBDD == null) {
|
||||||
reportMissingWebClasses(name, pc, node);
|
reportMissingWebClasses(name, pc, node);
|
||||||
}
|
}
|
||||||
@@ -91,8 +99,12 @@ public final class SecurityNamespaceHandler implements NamespaceHandler {
|
|||||||
"You need these to use <" + Elements.FILTER_CHAIN_MAP + ">", node);
|
"You need these to use <" + Elements.FILTER_CHAIN_MAP + ">", node);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
public void init() {
|
public void init() {
|
||||||
|
loadParsers();
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
private void loadParsers() {
|
||||||
// Parsers
|
// Parsers
|
||||||
parsers.put(Elements.LDAP_PROVIDER, new LdapProviderBeanDefinitionParser());
|
parsers.put(Elements.LDAP_PROVIDER, new LdapProviderBeanDefinitionParser());
|
||||||
parsers.put(Elements.LDAP_SERVER, new LdapServerBeanDefinitionParser());
|
parsers.put(Elements.LDAP_SERVER, new LdapServerBeanDefinitionParser());
|
||||||
@@ -102,7 +114,6 @@ public final class SecurityNamespaceHandler implements NamespaceHandler {
|
|||||||
parsers.put(Elements.AUTHENTICATION_PROVIDER, new AuthenticationProviderBeanDefinitionParser());
|
parsers.put(Elements.AUTHENTICATION_PROVIDER, new AuthenticationProviderBeanDefinitionParser());
|
||||||
parsers.put(Elements.GLOBAL_METHOD_SECURITY, new GlobalMethodSecurityBeanDefinitionParser());
|
parsers.put(Elements.GLOBAL_METHOD_SECURITY, new GlobalMethodSecurityBeanDefinitionParser());
|
||||||
parsers.put(Elements.AUTHENTICATION_MANAGER, new AuthenticationManagerBeanDefinitionParser());
|
parsers.put(Elements.AUTHENTICATION_MANAGER, new AuthenticationManagerBeanDefinitionParser());
|
||||||
// registerBeanDefinitionDecorator(Elements.INTERCEPT_METHODS, new InterceptMethodsBeanDefinitionDecorator());
|
|
||||||
|
|
||||||
// Only load the web-namespace parsers if the web classes are available
|
// Only load the web-namespace parsers if the web classes are available
|
||||||
if (ClassUtils.isPresent("org.springframework.security.web.FilterChainProxy", getClass().getClassLoader())) {
|
if (ClassUtils.isPresent("org.springframework.security.web.FilterChainProxy", getClass().getClassLoader())) {
|
||||||
@@ -110,7 +121,6 @@ public final class SecurityNamespaceHandler implements NamespaceHandler {
|
|||||||
parsers.put(Elements.FILTER_INVOCATION_DEFINITION_SOURCE, new FilterInvocationSecurityMetadataSourceParser());
|
parsers.put(Elements.FILTER_INVOCATION_DEFINITION_SOURCE, new FilterInvocationSecurityMetadataSourceParser());
|
||||||
parsers.put(Elements.FILTER_SECURITY_METADATA_SOURCE, new FilterInvocationSecurityMetadataSourceParser());
|
parsers.put(Elements.FILTER_SECURITY_METADATA_SOURCE, new FilterInvocationSecurityMetadataSourceParser());
|
||||||
filterChainMapBDD = new FilterChainMapBeanDefinitionDecorator();
|
filterChainMapBDD = new FilterChainMapBeanDefinitionDecorator();
|
||||||
//registerBeanDefinitionDecorator(Elements.FILTER_CHAIN_MAP, new FilterChainMapBeanDefinitionDecorator());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,8 +139,8 @@ public final class SecurityNamespaceHandler implements NamespaceHandler {
|
|||||||
|
|
||||||
private boolean matchesVersionInternal(Element element) {
|
private boolean matchesVersionInternal(Element element) {
|
||||||
String schemaLocation = element.getAttributeNS("http://www.w3.org/2001/XMLSchema-instance", "schemaLocation");
|
String schemaLocation = element.getAttributeNS("http://www.w3.org/2001/XMLSchema-instance", "schemaLocation");
|
||||||
return schemaLocation.matches("(?m).*spring-security-3.0.xsd.*")
|
return schemaLocation.matches("(?m).*spring-security-3\\.0.*xsd.*")
|
||||||
|| schemaLocation.matches("(?m).*spring-security.xsd.*")
|
|| schemaLocation.matches("(?m).*spring-security\\.xsd.*")
|
||||||
|| !schemaLocation.matches("(?m).*spring-security.*");
|
|| !schemaLocation.matches("(?m).*spring-security.*");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+14
-20
@@ -1,18 +1,16 @@
|
|||||||
package org.springframework.security.config.authentication;
|
package org.springframework.security.config.authentication;
|
||||||
|
|
||||||
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
import org.springframework.beans.factory.BeanDefinitionStoreException;
|
||||||
import org.springframework.beans.factory.xml.ParserContext;
|
|
||||||
import org.springframework.beans.factory.config.BeanDefinition;
|
import org.springframework.beans.factory.config.BeanDefinition;
|
||||||
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
||||||
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
|
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
|
||||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||||
import org.springframework.beans.factory.BeanDefinitionStoreException;
|
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
||||||
|
import org.springframework.beans.factory.xml.ParserContext;
|
||||||
import org.springframework.security.config.BeanIds;
|
import org.springframework.security.config.BeanIds;
|
||||||
import org.springframework.security.config.Elements;
|
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
import org.w3c.dom.Element;
|
import org.w3c.dom.Element;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -22,9 +20,6 @@ public abstract class AbstractUserDetailsServiceBeanDefinitionParser implements
|
|||||||
static final String CACHE_REF = "cache-ref";
|
static final String CACHE_REF = "cache-ref";
|
||||||
public static final String CACHING_SUFFIX = ".caching";
|
public static final String CACHING_SUFFIX = ".caching";
|
||||||
|
|
||||||
/** UserDetailsService bean Id. For use in a stateful context (i.e. in AuthenticationProviderBDP) */
|
|
||||||
private String id;
|
|
||||||
|
|
||||||
protected abstract String getBeanClassName(Element element);
|
protected abstract String getBeanClassName(Element element);
|
||||||
|
|
||||||
protected abstract void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder);
|
protected abstract void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder);
|
||||||
@@ -51,34 +46,33 @@ public abstract class AbstractUserDetailsServiceBeanDefinitionParser implements
|
|||||||
parserContext.registerBeanComponent(new BeanComponentDefinition(cachingUserService, beanId + CACHING_SUFFIX));
|
parserContext.registerBeanComponent(new BeanComponentDefinition(cachingUserService, beanId + CACHING_SUFFIX));
|
||||||
}
|
}
|
||||||
|
|
||||||
id = beanId;
|
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String resolveId(Element element, AbstractBeanDefinition definition, ParserContext parserContext)
|
private String resolveId(Element element, AbstractBeanDefinition definition, ParserContext pc)
|
||||||
throws BeanDefinitionStoreException {
|
throws BeanDefinitionStoreException {
|
||||||
|
|
||||||
String id = element.getAttribute("id");
|
String id = element.getAttribute("id");
|
||||||
|
|
||||||
|
if (pc.isNested()) {
|
||||||
|
// We're inside an <authentication-provider> element
|
||||||
|
if (!StringUtils.hasText(id)) {
|
||||||
|
id = pc.getReaderContext().generateBeanName(definition);
|
||||||
|
}
|
||||||
|
BeanDefinition container = pc.getContainingBeanDefinition();
|
||||||
|
container.getPropertyValues().add("userDetailsService", new RuntimeBeanReference(id));
|
||||||
|
}
|
||||||
|
|
||||||
if (StringUtils.hasText(id)) {
|
if (StringUtils.hasText(id)) {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(Elements.AUTHENTICATION_PROVIDER.equals(element.getParentNode().getNodeName())) {
|
|
||||||
return parserContext.getReaderContext().generateBeanName(definition);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If top level, use the default name or throw an exception if already used
|
// If top level, use the default name or throw an exception if already used
|
||||||
if (parserContext.getRegistry().containsBeanDefinition(BeanIds.USER_DETAILS_SERVICE)) {
|
if (pc.getRegistry().containsBeanDefinition(BeanIds.USER_DETAILS_SERVICE)) {
|
||||||
throw new BeanDefinitionStoreException("No id supplied and another " +
|
throw new BeanDefinitionStoreException("No id supplied and another " +
|
||||||
"bean is already registered as " + BeanIds.USER_DETAILS_SERVICE);
|
"bean is already registered as " + BeanIds.USER_DETAILS_SERVICE);
|
||||||
}
|
}
|
||||||
|
|
||||||
return BeanIds.USER_DETAILS_SERVICE;
|
return BeanIds.USER_DETAILS_SERVICE;
|
||||||
}
|
}
|
||||||
|
|
||||||
String getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+6
@@ -35,6 +35,7 @@ import org.w3c.dom.NodeList;
|
|||||||
public class AuthenticationManagerBeanDefinitionParser implements BeanDefinitionParser {
|
public class AuthenticationManagerBeanDefinitionParser implements BeanDefinitionParser {
|
||||||
private static final String ATT_ALIAS = "alias";
|
private static final String ATT_ALIAS = "alias";
|
||||||
private static final String ATT_REF = "ref";
|
private static final String ATT_REF = "ref";
|
||||||
|
private static final String ATT_ERASE_CREDENTIALS = "erase-credentials";
|
||||||
|
|
||||||
public BeanDefinition parse(Element element, ParserContext pc) {
|
public BeanDefinition parse(Element element, ParserContext pc) {
|
||||||
Assert.state(!pc.getRegistry().containsBeanDefinition(BeanIds.AUTHENTICATION_MANAGER),
|
Assert.state(!pc.getRegistry().containsBeanDefinition(BeanIds.AUTHENTICATION_MANAGER),
|
||||||
@@ -72,6 +73,11 @@ public class AuthenticationManagerBeanDefinitionParser implements BeanDefinition
|
|||||||
}
|
}
|
||||||
|
|
||||||
providerManagerBldr.addPropertyValue("providers", providers);
|
providerManagerBldr.addPropertyValue("providers", providers);
|
||||||
|
|
||||||
|
if ("true".equals(element.getAttribute(ATT_ERASE_CREDENTIALS))) {
|
||||||
|
providerManagerBldr.addPropertyValue("eraseCredentialsAfterAuthentication", true);
|
||||||
|
}
|
||||||
|
|
||||||
// Add the default event publisher
|
// Add the default event publisher
|
||||||
BeanDefinition publisher = new RootBeanDefinition(DefaultAuthenticationEventPublisher.class);
|
BeanDefinition publisher = new RootBeanDefinition(DefaultAuthenticationEventPublisher.class);
|
||||||
String id = pc.getReaderContext().generateBeanName(publisher);
|
String id = pc.getReaderContext().generateBeanName(publisher);
|
||||||
|
|||||||
+16
-76
@@ -7,7 +7,6 @@ import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
|||||||
import org.springframework.beans.factory.xml.ParserContext;
|
import org.springframework.beans.factory.xml.ParserContext;
|
||||||
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
|
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
|
||||||
import org.springframework.security.config.Elements;
|
import org.springframework.security.config.Elements;
|
||||||
import org.springframework.security.config.ldap.LdapUserServiceBeanDefinitionParser;
|
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
import org.springframework.util.xml.DomUtils;
|
import org.springframework.util.xml.DomUtils;
|
||||||
import org.w3c.dom.Element;
|
import org.w3c.dom.Element;
|
||||||
@@ -21,14 +20,14 @@ import org.w3c.dom.Element;
|
|||||||
public class AuthenticationProviderBeanDefinitionParser implements BeanDefinitionParser {
|
public class AuthenticationProviderBeanDefinitionParser implements BeanDefinitionParser {
|
||||||
private static String ATT_USER_DETAILS_REF = "user-service-ref";
|
private static String ATT_USER_DETAILS_REF = "user-service-ref";
|
||||||
|
|
||||||
public BeanDefinition parse(Element element, ParserContext parserContext) {
|
public BeanDefinition parse(Element element, ParserContext pc) {
|
||||||
RootBeanDefinition authProvider = new RootBeanDefinition(DaoAuthenticationProvider.class);
|
RootBeanDefinition authProvider = new RootBeanDefinition(DaoAuthenticationProvider.class);
|
||||||
authProvider.setSource(parserContext.extractSource(element));
|
authProvider.setSource(pc.extractSource(element));
|
||||||
|
|
||||||
Element passwordEncoderElt = DomUtils.getChildElementByTagName(element, Elements.PASSWORD_ENCODER);
|
Element passwordEncoderElt = DomUtils.getChildElementByTagName(element, Elements.PASSWORD_ENCODER);
|
||||||
|
|
||||||
if (passwordEncoderElt != null) {
|
if (passwordEncoderElt != null) {
|
||||||
PasswordEncoderParser pep = new PasswordEncoderParser(passwordEncoderElt, parserContext);
|
PasswordEncoderParser pep = new PasswordEncoderParser(passwordEncoderElt, pc);
|
||||||
authProvider.getPropertyValues().addPropertyValue("passwordEncoder", pep.getPasswordEncoder());
|
authProvider.getPropertyValues().addPropertyValue("passwordEncoder", pep.getPasswordEncoder());
|
||||||
|
|
||||||
if (pep.getSaltSource() != null) {
|
if (pep.getSaltSource() != null) {
|
||||||
@@ -37,98 +36,39 @@ public class AuthenticationProviderBeanDefinitionParser implements BeanDefinitio
|
|||||||
}
|
}
|
||||||
|
|
||||||
Element userServiceElt = DomUtils.getChildElementByTagName(element, Elements.USER_SERVICE);
|
Element userServiceElt = DomUtils.getChildElementByTagName(element, Elements.USER_SERVICE);
|
||||||
Element jdbcUserServiceElt = DomUtils.getChildElementByTagName(element, Elements.JDBC_USER_SERVICE);
|
if (userServiceElt == null) {
|
||||||
Element ldapUserServiceElt = DomUtils.getChildElementByTagName(element, Elements.LDAP_USER_SERVICE);
|
userServiceElt = DomUtils.getChildElementByTagName(element, Elements.JDBC_USER_SERVICE);
|
||||||
|
}
|
||||||
|
if (userServiceElt == null) {
|
||||||
|
userServiceElt = DomUtils.getChildElementByTagName(element, Elements.LDAP_USER_SERVICE);
|
||||||
|
}
|
||||||
|
|
||||||
String ref = element.getAttribute(ATT_USER_DETAILS_REF);
|
String ref = element.getAttribute(ATT_USER_DETAILS_REF);
|
||||||
|
|
||||||
if (StringUtils.hasText(ref)) {
|
if (StringUtils.hasText(ref)) {
|
||||||
if (userServiceElt != null || jdbcUserServiceElt != null || ldapUserServiceElt != null) {
|
if (userServiceElt != null) {
|
||||||
parserContext.getReaderContext().error("The " + ATT_USER_DETAILS_REF + " attribute cannot be used in combination with child" +
|
pc.getReaderContext().error("The " + ATT_USER_DETAILS_REF + " attribute cannot be used in combination with child" +
|
||||||
"elements '" + Elements.USER_SERVICE + "', '" + Elements.JDBC_USER_SERVICE + "' or '" +
|
"elements '" + Elements.USER_SERVICE + "', '" + Elements.JDBC_USER_SERVICE + "' or '" +
|
||||||
Elements.LDAP_USER_SERVICE + "'", element);
|
Elements.LDAP_USER_SERVICE + "'", element);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
authProvider.getPropertyValues().add("userDetailsService", new RuntimeBeanReference(ref));
|
||||||
} else {
|
} else {
|
||||||
// Use the child elements to create the UserDetailsService
|
// Use the child elements to create the UserDetailsService
|
||||||
AbstractUserDetailsServiceBeanDefinitionParser parser = null;
|
|
||||||
Element elt = null;
|
|
||||||
|
|
||||||
if (userServiceElt != null) {
|
if (userServiceElt != null) {
|
||||||
elt = userServiceElt;
|
pc.getDelegate().parseCustomElement(userServiceElt, authProvider);
|
||||||
parser = new UserServiceBeanDefinitionParser();
|
|
||||||
} else if (jdbcUserServiceElt != null) {
|
|
||||||
elt = jdbcUserServiceElt;
|
|
||||||
parser = new JdbcUserServiceBeanDefinitionParser();
|
|
||||||
} else if (ldapUserServiceElt != null) {
|
|
||||||
elt = ldapUserServiceElt;
|
|
||||||
parser = new LdapUserServiceBeanDefinitionParser();
|
|
||||||
} else {
|
} else {
|
||||||
parserContext.getReaderContext().error("A user-service is required", element);
|
pc.getReaderContext().error("A user-service is required", element);
|
||||||
}
|
}
|
||||||
|
|
||||||
parser.parse(elt, parserContext);
|
|
||||||
ref = parser.getId();
|
|
||||||
|
|
||||||
// Pinch the cache-ref from the UserDetailService element, if set.
|
// Pinch the cache-ref from the UserDetailService element, if set.
|
||||||
String cacheRef = elt.getAttribute(AbstractUserDetailsServiceBeanDefinitionParser.CACHE_REF);
|
String cacheRef = userServiceElt.getAttribute(AbstractUserDetailsServiceBeanDefinitionParser.CACHE_REF);
|
||||||
|
|
||||||
if (StringUtils.hasText(cacheRef)) {
|
if (StringUtils.hasText(cacheRef)) {
|
||||||
authProvider.getPropertyValues().addPropertyValue("userCache", new RuntimeBeanReference(cacheRef));
|
authProvider.getPropertyValues().addPropertyValue("userCache", new RuntimeBeanReference(cacheRef));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
authProvider.getPropertyValues().addPropertyValue("userDetailsService", new RuntimeBeanReference(ref));
|
|
||||||
|
|
||||||
// We need to register the provider to access it in the post processor to check if it has a cache
|
|
||||||
// final String id = parserContext.getReaderContext().generateBeanName(authProvider);
|
|
||||||
// parserContext.getRegistry().registerBeanDefinition(id, authProvider);
|
|
||||||
// parserContext.registerComponent(new BeanComponentDefinition(authProvider, id));
|
|
||||||
|
|
||||||
|
|
||||||
// BeanDefinitionBuilder cacheResolverBldr = BeanDefinitionBuilder.rootBeanDefinition(AuthenticationProviderCacheResolver.class);
|
|
||||||
// cacheResolverBldr.addConstructorArgValue(id);
|
|
||||||
// cacheResolverBldr.addConstructorArgValue(ref);
|
|
||||||
// cacheResolverBldr.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
|
||||||
// BeanDefinition cacheResolver = cacheResolverBldr.getBeanDefinition();
|
|
||||||
//
|
|
||||||
// String name = parserContext.getReaderContext().generateBeanName(cacheResolver);
|
|
||||||
// parserContext.getRegistry().registerBeanDefinition(name , cacheResolver);
|
|
||||||
// parserContext.registerComponent(new BeanComponentDefinition(cacheResolver, name));
|
|
||||||
|
|
||||||
// ConfigUtils.addAuthenticationProvider(parserContext, id, element);
|
|
||||||
|
|
||||||
return authProvider;
|
return authProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks whether the registered user service bean has an associated cache and, if so, sets it on the
|
|
||||||
* authentication provider.
|
|
||||||
*/
|
|
||||||
// static class AuthenticationProviderCacheResolver implements BeanFactoryPostProcessor, Ordered {
|
|
||||||
// private String providerId;
|
|
||||||
// private String userServiceId;
|
|
||||||
//
|
|
||||||
// public AuthenticationProviderCacheResolver(String providerId, String userServiceId) {
|
|
||||||
// this.providerId = providerId;
|
|
||||||
// this.userServiceId = userServiceId;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
|
|
||||||
// RootBeanDefinition provider = (RootBeanDefinition) beanFactory.getBeanDefinition(providerId);
|
|
||||||
//
|
|
||||||
// String cachingId = userServiceId + AbstractUserDetailsServiceBeanDefinitionParser.CACHING_SUFFIX;
|
|
||||||
//
|
|
||||||
// if (beanFactory.containsBeanDefinition(cachingId)) {
|
|
||||||
// RootBeanDefinition cachingUserService = (RootBeanDefinition) beanFactory.getBeanDefinition(cachingId);
|
|
||||||
//
|
|
||||||
// PropertyValue userCacheProperty = cachingUserService.getPropertyValues().getPropertyValue("userCache");
|
|
||||||
//
|
|
||||||
// provider.getPropertyValues().addPropertyValue(userCacheProperty);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// public int getOrder() {
|
|
||||||
// return HIGHEST_PRECEDENCE;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -24,6 +24,7 @@ import org.w3c.dom.Element;
|
|||||||
* @author Luke Taylor
|
* @author Luke Taylor
|
||||||
* @author Ben Alex
|
* @author Ben Alex
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
public class UserServiceBeanDefinitionParser extends AbstractUserDetailsServiceBeanDefinitionParser {
|
public class UserServiceBeanDefinitionParser extends AbstractUserDetailsServiceBeanDefinitionParser {
|
||||||
|
|
||||||
static final String ATT_PASSWORD = "password";
|
static final String ATT_PASSWORD = "password";
|
||||||
@@ -90,7 +91,7 @@ public class UserServiceBeanDefinitionParser extends AbstractUserDetailsServiceB
|
|||||||
user.addConstructorArgValue(!locked);
|
user.addConstructorArgValue(!locked);
|
||||||
user.addConstructorArgValue(authorities.getBeanDefinition());
|
user.addConstructorArgValue(authorities.getBeanDefinition());
|
||||||
|
|
||||||
users.put(userName, user.getBeanDefinition());
|
users.put(userName.toLowerCase(), user.getBeanDefinition());
|
||||||
}
|
}
|
||||||
|
|
||||||
userMap.getPropertyValues().addPropertyValue("users", users);
|
userMap.getPropertyValues().addPropertyValue("users", users);
|
||||||
|
|||||||
+19
-14
@@ -81,7 +81,7 @@ final class AuthenticationConfigBuilder {
|
|||||||
private String rememberMeServicesId;
|
private String rememberMeServicesId;
|
||||||
private BeanReference rememberMeProviderRef;
|
private BeanReference rememberMeProviderRef;
|
||||||
private BeanDefinition basicFilter;
|
private BeanDefinition basicFilter;
|
||||||
private BeanDefinition basicEntryPoint;
|
private BeanReference basicEntryPoint;
|
||||||
private RootBeanDefinition formFilter;
|
private RootBeanDefinition formFilter;
|
||||||
private BeanDefinition formEntryPoint;
|
private BeanDefinition formEntryPoint;
|
||||||
private RootBeanDefinition openIDFilter;
|
private RootBeanDefinition openIDFilter;
|
||||||
@@ -155,7 +155,7 @@ final class AuthenticationConfigBuilder {
|
|||||||
|
|
||||||
if (formLoginElt != null || autoConfig) {
|
if (formLoginElt != null || autoConfig) {
|
||||||
FormLoginBeanDefinitionParser parser = new FormLoginBeanDefinitionParser("/j_spring_security_check",
|
FormLoginBeanDefinitionParser parser = new FormLoginBeanDefinitionParser("/j_spring_security_check",
|
||||||
AUTHENTICATION_PROCESSING_FILTER_CLASS, requestCache, sessionStrategy);
|
AUTHENTICATION_PROCESSING_FILTER_CLASS, requestCache, sessionStrategy, allowSessionCreation);
|
||||||
|
|
||||||
parser.parse(formLoginElt, pc);
|
parser.parse(formLoginElt, pc);
|
||||||
formFilter = parser.getFilterBean();
|
formFilter = parser.getFilterBean();
|
||||||
@@ -163,7 +163,7 @@ final class AuthenticationConfigBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (formFilter != null) {
|
if (formFilter != null) {
|
||||||
formFilter.getPropertyValues().addPropertyValue("allowSessionCreation", new Boolean(allowSessionCreation));
|
formFilter.getPropertyValues().addPropertyValue("allowSessionCreation", allowSessionCreation);
|
||||||
formFilter.getPropertyValues().addPropertyValue("authenticationManager", authManager);
|
formFilter.getPropertyValues().addPropertyValue("authenticationManager", authManager);
|
||||||
|
|
||||||
|
|
||||||
@@ -179,7 +179,7 @@ final class AuthenticationConfigBuilder {
|
|||||||
|
|
||||||
if (openIDLoginElt != null) {
|
if (openIDLoginElt != null) {
|
||||||
FormLoginBeanDefinitionParser parser = new FormLoginBeanDefinitionParser("/j_spring_openid_security_check",
|
FormLoginBeanDefinitionParser parser = new FormLoginBeanDefinitionParser("/j_spring_openid_security_check",
|
||||||
OPEN_ID_AUTHENTICATION_PROCESSING_FILTER_CLASS, requestCache, sessionStrategy);
|
OPEN_ID_AUTHENTICATION_PROCESSING_FILTER_CLASS, requestCache, sessionStrategy, allowSessionCreation);
|
||||||
|
|
||||||
parser.parse(openIDLoginElt, pc);
|
parser.parse(openIDLoginElt, pc);
|
||||||
openIDFilter = parser.getFilterBean();
|
openIDFilter = parser.getFilterBean();
|
||||||
@@ -214,7 +214,7 @@ final class AuthenticationConfigBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (openIDFilter != null) {
|
if (openIDFilter != null) {
|
||||||
openIDFilter.getPropertyValues().addPropertyValue("allowSessionCreation", new Boolean(allowSessionCreation));
|
openIDFilter.getPropertyValues().addPropertyValue("allowSessionCreation", allowSessionCreation);
|
||||||
openIDFilter.getPropertyValues().addPropertyValue("authenticationManager", authManager);
|
openIDFilter.getPropertyValues().addPropertyValue("authenticationManager", authManager);
|
||||||
// Required by login page filter
|
// Required by login page filter
|
||||||
openIDFilterId = pc.getReaderContext().generateBeanName(openIDFilter);
|
openIDFilterId = pc.getReaderContext().generateBeanName(openIDFilter);
|
||||||
@@ -256,25 +256,29 @@ final class AuthenticationConfigBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
RootBeanDefinition filter = null;
|
RootBeanDefinition filter = null;
|
||||||
RootBeanDefinition entryPoint = null;
|
|
||||||
|
|
||||||
if (basicAuthElt != null || autoConfig) {
|
if (basicAuthElt != null || autoConfig) {
|
||||||
BeanDefinitionBuilder filterBuilder = BeanDefinitionBuilder.rootBeanDefinition(BasicAuthenticationFilter.class);
|
BeanDefinitionBuilder filterBuilder = BeanDefinitionBuilder.rootBeanDefinition(BasicAuthenticationFilter.class);
|
||||||
entryPoint = new RootBeanDefinition(BasicAuthenticationEntryPoint.class);
|
|
||||||
entryPoint.setSource(pc.extractSource(httpElt));
|
|
||||||
|
|
||||||
entryPoint.getPropertyValues().addPropertyValue("realmName", realm);
|
String entryPointId;
|
||||||
|
|
||||||
String entryPointId = pc.getReaderContext().generateBeanName(entryPoint);
|
if (basicAuthElt != null && StringUtils.hasText(basicAuthElt.getAttribute(ATT_ENTRY_POINT_REF))) {
|
||||||
pc.registerBeanComponent(new BeanComponentDefinition(entryPoint, entryPointId));
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
filterBuilder.addPropertyValue("authenticationManager", authManager);
|
filterBuilder.addPropertyValue("authenticationManager", authManager);
|
||||||
filterBuilder.addPropertyValue("authenticationEntryPoint", new RuntimeBeanReference(entryPointId));
|
filterBuilder.addPropertyValue("authenticationEntryPoint", basicEntryPoint);
|
||||||
filter = (RootBeanDefinition) filterBuilder.getBeanDefinition();
|
filter = (RootBeanDefinition) filterBuilder.getBeanDefinition();
|
||||||
}
|
}
|
||||||
|
|
||||||
basicFilter = filter;
|
basicFilter = filter;
|
||||||
basicEntryPoint = entryPoint;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void createX509Filter(BeanReference authManager) {
|
void createX509Filter(BeanReference authManager) {
|
||||||
@@ -540,7 +544,8 @@ final class AuthenticationConfigBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void createUserServiceInjector() {
|
void createUserServiceInjector() {
|
||||||
BeanDefinitionBuilder userServiceInjector = BeanDefinitionBuilder.rootBeanDefinition(UserDetailsServiceInjectionBeanPostProcessor.class);
|
BeanDefinitionBuilder userServiceInjector =
|
||||||
|
BeanDefinitionBuilder.rootBeanDefinition(UserDetailsServiceInjectionBeanPostProcessor.class);
|
||||||
userServiceInjector.addConstructorArgValue(x509ProviderId);
|
userServiceInjector.addConstructorArgValue(x509ProviderId);
|
||||||
userServiceInjector.addConstructorArgValue(rememberMeServicesId);
|
userServiceInjector.addConstructorArgValue(rememberMeServicesId);
|
||||||
userServiceInjector.addConstructorArgValue(openIDProviderId);
|
userServiceInjector.addConstructorArgValue(openIDProviderId);
|
||||||
|
|||||||
+6
-2
@@ -31,7 +31,8 @@ public class FormLoginBeanDefinitionParser {
|
|||||||
private static final String DEF_FORM_LOGIN_TARGET_URL = "/";
|
private static final String DEF_FORM_LOGIN_TARGET_URL = "/";
|
||||||
|
|
||||||
private static final String ATT_FORM_LOGIN_AUTHENTICATION_FAILURE_URL = "authentication-failure-url";
|
private static final String ATT_FORM_LOGIN_AUTHENTICATION_FAILURE_URL = "authentication-failure-url";
|
||||||
private static final String DEF_FORM_LOGIN_AUTHENTICATION_FAILURE_URL = DefaultLoginPageGeneratingFilter.DEFAULT_LOGIN_PAGE_URL + "?" + DefaultLoginPageGeneratingFilter.ERROR_PARAMETER_NAME;
|
private static final String DEF_FORM_LOGIN_AUTHENTICATION_FAILURE_URL =
|
||||||
|
DefaultLoginPageGeneratingFilter.DEFAULT_LOGIN_PAGE_URL + "?" + DefaultLoginPageGeneratingFilter.ERROR_PARAMETER_NAME;
|
||||||
|
|
||||||
private static final String ATT_SUCCESS_HANDLER_REF = "authentication-success-handler-ref";
|
private static final String ATT_SUCCESS_HANDLER_REF = "authentication-success-handler-ref";
|
||||||
private static final String ATT_FAILURE_HANDLER_REF = "authentication-failure-handler-ref";
|
private static final String ATT_FAILURE_HANDLER_REF = "authentication-failure-handler-ref";
|
||||||
@@ -40,17 +41,19 @@ public class FormLoginBeanDefinitionParser {
|
|||||||
private final String filterClassName;
|
private final String filterClassName;
|
||||||
private final BeanReference requestCache;
|
private final BeanReference requestCache;
|
||||||
private final BeanReference sessionStrategy;
|
private final BeanReference sessionStrategy;
|
||||||
|
private final boolean allowSessionCreation;
|
||||||
|
|
||||||
private RootBeanDefinition filterBean;
|
private RootBeanDefinition filterBean;
|
||||||
private RootBeanDefinition entryPointBean;
|
private RootBeanDefinition entryPointBean;
|
||||||
private String loginPage;
|
private String loginPage;
|
||||||
|
|
||||||
FormLoginBeanDefinitionParser(String defaultLoginProcessingUrl, String filterClassName,
|
FormLoginBeanDefinitionParser(String defaultLoginProcessingUrl, String filterClassName,
|
||||||
BeanReference requestCache, BeanReference sessionStrategy) {
|
BeanReference requestCache, BeanReference sessionStrategy, boolean allowSessionCreation) {
|
||||||
this.defaultLoginProcessingUrl = defaultLoginProcessingUrl;
|
this.defaultLoginProcessingUrl = defaultLoginProcessingUrl;
|
||||||
this.filterClassName = filterClassName;
|
this.filterClassName = filterClassName;
|
||||||
this.requestCache = requestCache;
|
this.requestCache = requestCache;
|
||||||
this.sessionStrategy = sessionStrategy;
|
this.sessionStrategy = sessionStrategy;
|
||||||
|
this.allowSessionCreation = allowSessionCreation;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BeanDefinition parse(Element elt, ParserContext pc) {
|
public BeanDefinition parse(Element elt, ParserContext pc) {
|
||||||
@@ -135,6 +138,7 @@ public class FormLoginBeanDefinitionParser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
failureHandler.addPropertyValue("defaultFailureUrl", authenticationFailureUrl);
|
failureHandler.addPropertyValue("defaultFailureUrl", authenticationFailureUrl);
|
||||||
|
failureHandler.addPropertyValue("allowSessionCreation", allowSessionCreation);
|
||||||
filterBuilder.addPropertyValue("authenticationFailureHandler", failureHandler.getBeanDefinition());
|
filterBuilder.addPropertyValue("authenticationFailureHandler", failureHandler.getBeanDefinition());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -83,7 +83,7 @@ class HttpConfigurationBuilder {
|
|||||||
private final List<Element> interceptUrls;
|
private final List<Element> interceptUrls;
|
||||||
|
|
||||||
// Use ManagedMap to allow placeholder resolution
|
// Use ManagedMap to allow placeholder resolution
|
||||||
private ManagedMap<BeanDefinition, List<BeanMetadataElement>> filterChainMap;
|
private ManagedMap<Object, List<BeanMetadataElement>> filterChainMap;
|
||||||
|
|
||||||
private BeanDefinition cpf;
|
private BeanDefinition cpf;
|
||||||
private BeanDefinition securityContextPersistenceFilter;
|
private BeanDefinition securityContextPersistenceFilter;
|
||||||
@@ -109,7 +109,7 @@ class HttpConfigurationBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void parseInterceptUrlsForEmptyFilterChains() {
|
void parseInterceptUrlsForEmptyFilterChains() {
|
||||||
filterChainMap = new ManagedMap<BeanDefinition, List<BeanMetadataElement>>();
|
filterChainMap = new ManagedMap<Object, List<BeanMetadataElement>>();
|
||||||
|
|
||||||
for (Element urlElt : interceptUrls) {
|
for (Element urlElt : interceptUrls) {
|
||||||
String path = urlElt.getAttribute(ATT_PATH_PATTERN);
|
String path = urlElt.getAttribute(ATT_PATH_PATTERN);
|
||||||
@@ -464,7 +464,7 @@ class HttpConfigurationBuilder {
|
|||||||
return allowSessionCreation;
|
return allowSessionCreation;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ManagedMap<BeanDefinition, List<BeanMetadataElement>> getFilterChainMap() {
|
public ManagedMap<Object, List<BeanMetadataElement>> getFilterChainMap() {
|
||||||
return filterChainMap;
|
return filterChainMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+8
-5
@@ -12,6 +12,7 @@ import org.apache.commons.logging.LogFactory;
|
|||||||
import org.springframework.beans.BeanMetadataElement;
|
import org.springframework.beans.BeanMetadataElement;
|
||||||
import org.springframework.beans.factory.config.BeanDefinition;
|
import org.springframework.beans.factory.config.BeanDefinition;
|
||||||
import org.springframework.beans.factory.config.BeanReference;
|
import org.springframework.beans.factory.config.BeanReference;
|
||||||
|
import org.springframework.beans.factory.config.MethodInvokingFactoryBean;
|
||||||
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
||||||
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
|
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
|
||||||
import org.springframework.beans.factory.parsing.CompositeComponentDefinition;
|
import org.springframework.beans.factory.parsing.CompositeComponentDefinition;
|
||||||
@@ -135,10 +136,8 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
|||||||
filterChain.add(od.bean);
|
filterChain.add(od.bean);
|
||||||
}
|
}
|
||||||
|
|
||||||
ManagedMap<BeanDefinition, List<BeanMetadataElement>> filterChainMap = httpBldr.getFilterChainMap();
|
ManagedMap<Object, List<BeanMetadataElement>> filterChainMap = httpBldr.getFilterChainMap();
|
||||||
BeanDefinition universalMatch = new RootBeanDefinition(String.class);
|
filterChainMap.put(matcher.getUniversalMatchPattern(), filterChain);
|
||||||
universalMatch.getConstructorArgumentValues().addGenericArgumentValue(matcher.getUniversalMatchPattern());
|
|
||||||
filterChainMap.put(universalMatch, filterChain);
|
|
||||||
|
|
||||||
registerFilterChainProxy(pc, filterChainMap, matcher, source);
|
registerFilterChainProxy(pc, filterChainMap, matcher, source);
|
||||||
|
|
||||||
@@ -168,6 +167,10 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
|||||||
BeanDefinitionBuilder authManager = BeanDefinitionBuilder.rootBeanDefinition(ProviderManager.class);
|
BeanDefinitionBuilder authManager = BeanDefinitionBuilder.rootBeanDefinition(ProviderManager.class);
|
||||||
authManager.addPropertyValue("parent", new RootBeanDefinition(AuthenticationManagerFactoryBean.class));
|
authManager.addPropertyValue("parent", new RootBeanDefinition(AuthenticationManagerFactoryBean.class));
|
||||||
authManager.addPropertyValue("providers", authenticationProviders);
|
authManager.addPropertyValue("providers", authenticationProviders);
|
||||||
|
RootBeanDefinition clearCredentials = new RootBeanDefinition(MethodInvokingFactoryBean.class);
|
||||||
|
clearCredentials.getPropertyValues().addPropertyValue("targetObject", new RootBeanDefinition(AuthenticationManagerFactoryBean.class));
|
||||||
|
clearCredentials.getPropertyValues().addPropertyValue("targetMethod", "isEraseCredentialsAfterAuthentication");
|
||||||
|
authManager.addPropertyValue("eraseCredentialsAfterAuthentication", clearCredentials);
|
||||||
|
|
||||||
if (concurrencyController != null) {
|
if (concurrencyController != null) {
|
||||||
authManager.addPropertyValue("sessionController", concurrencyController);
|
authManager.addPropertyValue("sessionController", concurrencyController);
|
||||||
@@ -247,7 +250,7 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
|||||||
return customFilters;
|
return customFilters;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void registerFilterChainProxy(ParserContext pc, Map<BeanDefinition, List<BeanMetadataElement>> filterChainMap, UrlMatcher matcher, Object source) {
|
private void registerFilterChainProxy(ParserContext pc, Map<Object, List<BeanMetadataElement>> filterChainMap, UrlMatcher matcher, Object source) {
|
||||||
if (pc.getRegistry().containsBeanDefinition(BeanIds.FILTER_CHAIN_PROXY)) {
|
if (pc.getRegistry().containsBeanDefinition(BeanIds.FILTER_CHAIN_PROXY)) {
|
||||||
pc.getReaderContext().error("Duplicate <http> element detected", source);
|
pc.getReaderContext().error("Duplicate <http> element detected", source);
|
||||||
}
|
}
|
||||||
|
|||||||
+26
-6
@@ -37,6 +37,7 @@ import org.springframework.security.access.expression.method.ExpressionBasedPreI
|
|||||||
import org.springframework.security.access.intercept.AfterInvocationProviderManager;
|
import org.springframework.security.access.intercept.AfterInvocationProviderManager;
|
||||||
import org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor;
|
import org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor;
|
||||||
import org.springframework.security.access.intercept.aopalliance.MethodSecurityMetadataSourceAdvisor;
|
import org.springframework.security.access.intercept.aopalliance.MethodSecurityMetadataSourceAdvisor;
|
||||||
|
import org.springframework.security.access.intercept.aspectj.AspectJMethodSecurityInterceptor;
|
||||||
import org.springframework.security.access.method.DelegatingMethodSecurityMetadataSource;
|
import org.springframework.security.access.method.DelegatingMethodSecurityMetadataSource;
|
||||||
import org.springframework.security.access.method.MapBasedMethodSecurityMetadataSource;
|
import org.springframework.security.access.method.MapBasedMethodSecurityMetadataSource;
|
||||||
import org.springframework.security.access.prepost.PostInvocationAdviceProvider;
|
import org.springframework.security.access.prepost.PostInvocationAdviceProvider;
|
||||||
@@ -76,6 +77,7 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP
|
|||||||
private static final String ATT_USE_SECURED = "secured-annotations";
|
private static final String ATT_USE_SECURED = "secured-annotations";
|
||||||
private static final String ATT_USE_PREPOST = "pre-post-annotations";
|
private static final String ATT_USE_PREPOST = "pre-post-annotations";
|
||||||
private static final String ATT_REF = "ref";
|
private static final String ATT_REF = "ref";
|
||||||
|
private static final String ATT_MODE = "mode";
|
||||||
private static final String ATT_ADVICE_ORDER = "order";
|
private static final String ATT_ADVICE_ORDER = "order";
|
||||||
|
|
||||||
public BeanDefinition parse(Element element, ParserContext pc) {
|
public BeanDefinition parse(Element element, ParserContext pc) {
|
||||||
@@ -90,6 +92,8 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP
|
|||||||
boolean jsr250Enabled = "enabled".equals(element.getAttribute(ATT_USE_JSR250));
|
boolean jsr250Enabled = "enabled".equals(element.getAttribute(ATT_USE_JSR250));
|
||||||
boolean useSecured = "enabled".equals(element.getAttribute(ATT_USE_SECURED));
|
boolean useSecured = "enabled".equals(element.getAttribute(ATT_USE_SECURED));
|
||||||
boolean prePostAnnotationsEnabled = "enabled".equals(element.getAttribute(ATT_USE_PREPOST));
|
boolean prePostAnnotationsEnabled = "enabled".equals(element.getAttribute(ATT_USE_PREPOST));
|
||||||
|
boolean useAspectJ = "aspectj".equals(element.getAttribute(ATT_MODE));
|
||||||
|
|
||||||
BeanDefinition preInvocationVoter = null;
|
BeanDefinition preInvocationVoter = null;
|
||||||
ManagedList<BeanMetadataElement> afterInvocationProviders = new ManagedList<BeanMetadataElement>();
|
ManagedList<BeanMetadataElement> afterInvocationProviders = new ManagedList<BeanMetadataElement>();
|
||||||
|
|
||||||
@@ -165,6 +169,9 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP
|
|||||||
DomUtils.getChildElementsByTagName(element, PROTECT_POINTCUT));
|
DomUtils.getChildElementsByTagName(element, PROTECT_POINTCUT));
|
||||||
|
|
||||||
if (pointcutMap.size() > 0) {
|
if (pointcutMap.size() > 0) {
|
||||||
|
if (useAspectJ) {
|
||||||
|
pc.getReaderContext().error("You can't use AspectJ mode with protect-pointcut definitions", source);
|
||||||
|
}
|
||||||
// Only add it if there are actually any pointcuts defined.
|
// Only add it if there are actually any pointcuts defined.
|
||||||
BeanDefinition mapBasedMetadataSource = new RootBeanDefinition(MapBasedMethodSecurityMetadataSource.class);
|
BeanDefinition mapBasedMetadataSource = new RootBeanDefinition(MapBasedMethodSecurityMetadataSource.class);
|
||||||
BeanReference ref = new RuntimeBeanReference(pc.getReaderContext().generateBeanName(mapBasedMetadataSource));
|
BeanReference ref = new RuntimeBeanReference(pc.getReaderContext().generateBeanName(mapBasedMetadataSource));
|
||||||
@@ -190,13 +197,22 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP
|
|||||||
}
|
}
|
||||||
|
|
||||||
String runAsManagerId = element.getAttribute(ATT_RUN_AS_MGR);
|
String runAsManagerId = element.getAttribute(ATT_RUN_AS_MGR);
|
||||||
|
|
||||||
BeanReference interceptor = registerMethodSecurityInterceptor(pc, accessManagerId, runAsManagerId,
|
BeanReference interceptor = registerMethodSecurityInterceptor(pc, accessManagerId, runAsManagerId,
|
||||||
metadataSource, afterInvocationProviders, source);
|
metadataSource, afterInvocationProviders, source, useAspectJ);
|
||||||
|
|
||||||
registerAdvisor(pc, interceptor, metadataSource, source, element.getAttribute(ATT_ADVICE_ORDER));
|
if (useAspectJ) {
|
||||||
|
BeanDefinitionBuilder aspect =
|
||||||
|
BeanDefinitionBuilder.rootBeanDefinition("org.springframework.security.access.intercept.aspectj.aspect.AnnotationSecurityAspect");
|
||||||
|
aspect.setFactoryMethod("aspectOf");
|
||||||
|
aspect.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||||
|
aspect.addPropertyValue("securityInterceptor", interceptor);
|
||||||
|
String id = pc.getReaderContext().registerWithGeneratedName(aspect.getBeanDefinition());
|
||||||
|
pc.registerBeanComponent(new BeanComponentDefinition(aspect.getBeanDefinition(), id));
|
||||||
|
} else {
|
||||||
|
registerAdvisor(pc, interceptor, metadataSource, source, element.getAttribute(ATT_ADVICE_ORDER));
|
||||||
|
AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(pc, element);
|
||||||
|
}
|
||||||
|
|
||||||
AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(pc, element);
|
|
||||||
pc.popAndRegisterContainingComponent();
|
pc.popAndRegisterContainingComponent();
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
@@ -284,12 +300,16 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP
|
|||||||
}
|
}
|
||||||
|
|
||||||
private BeanReference registerMethodSecurityInterceptor(ParserContext pc, String accessManagerId,
|
private BeanReference registerMethodSecurityInterceptor(ParserContext pc, String accessManagerId,
|
||||||
String runAsManagerId, BeanReference metadataSource, List<BeanMetadataElement> afterInvocationProviders, Object source) {
|
String runAsManagerId, BeanReference metadataSource,
|
||||||
BeanDefinitionBuilder bldr = BeanDefinitionBuilder.rootBeanDefinition(MethodSecurityInterceptor.class);
|
List<BeanMetadataElement> afterInvocationProviders, Object source, boolean useAspectJ) {
|
||||||
|
BeanDefinitionBuilder bldr =
|
||||||
|
BeanDefinitionBuilder.rootBeanDefinition(useAspectJ ?
|
||||||
|
AspectJMethodSecurityInterceptor.class : MethodSecurityInterceptor.class);
|
||||||
bldr.getRawBeanDefinition().setSource(source);
|
bldr.getRawBeanDefinition().setSource(source);
|
||||||
bldr.addPropertyReference("accessDecisionManager", accessManagerId);
|
bldr.addPropertyReference("accessDecisionManager", accessManagerId);
|
||||||
bldr.addPropertyValue("authenticationManager", new RootBeanDefinition(AuthenticationManagerDelegator.class));
|
bldr.addPropertyValue("authenticationManager", new RootBeanDefinition(AuthenticationManagerDelegator.class));
|
||||||
bldr.addPropertyValue("securityMetadataSource", metadataSource);
|
bldr.addPropertyValue("securityMetadataSource", metadataSource);
|
||||||
|
|
||||||
if (StringUtils.hasText(runAsManagerId)) {
|
if (StringUtils.hasText(runAsManagerId)) {
|
||||||
bldr.addPropertyReference("runAsManager", runAsManagerId);
|
bldr.addPropertyReference("runAsManager", runAsManagerId);
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-5
@@ -3,6 +3,7 @@ package org.springframework.security.config.method;
|
|||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@@ -44,7 +45,6 @@ import org.springframework.util.StringUtils;
|
|||||||
*
|
*
|
||||||
* @author Ben Alex
|
* @author Ben Alex
|
||||||
* @since 2.0
|
* @since 2.0
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
final class ProtectPointcutPostProcessor implements BeanPostProcessor {
|
final class ProtectPointcutPostProcessor implements BeanPostProcessor {
|
||||||
|
|
||||||
@@ -52,6 +52,7 @@ final class ProtectPointcutPostProcessor implements BeanPostProcessor {
|
|||||||
|
|
||||||
private Map<String,List<ConfigAttribute>> pointcutMap = new LinkedHashMap<String,List<ConfigAttribute>>();
|
private Map<String,List<ConfigAttribute>> pointcutMap = new LinkedHashMap<String,List<ConfigAttribute>>();
|
||||||
private MapBasedMethodSecurityMetadataSource mapBasedMethodSecurityMetadataSource;
|
private MapBasedMethodSecurityMetadataSource mapBasedMethodSecurityMetadataSource;
|
||||||
|
private Set<PointcutExpression> pointCutExpressions = new LinkedHashSet<PointcutExpression>();
|
||||||
private PointcutParser parser;
|
private PointcutParser parser;
|
||||||
|
|
||||||
public ProtectPointcutPostProcessor(MapBasedMethodSecurityMetadataSource mapBasedMethodSecurityMetadataSource) {
|
public ProtectPointcutPostProcessor(MapBasedMethodSecurityMetadataSource mapBasedMethodSecurityMetadataSource) {
|
||||||
@@ -88,10 +89,7 @@ final class ProtectPointcutPostProcessor implements BeanPostProcessor {
|
|||||||
|
|
||||||
// Check to see if any of those methods are compatible with our pointcut expressions
|
// Check to see if any of those methods are compatible with our pointcut expressions
|
||||||
for (int i = 0; i < methods.length; i++) {
|
for (int i = 0; i < methods.length; i++) {
|
||||||
for (String ex : pointcutMap.keySet()) {
|
for (PointcutExpression expression : pointCutExpressions) {
|
||||||
// Parse the presented AspectJ pointcut expression
|
|
||||||
PointcutExpression expression = parser.parsePointcutExpression(ex);
|
|
||||||
|
|
||||||
// Try for the bean class directly
|
// Try for the bean class directly
|
||||||
if (attemptMatch(bean.getClass(), methods[i], expression, beanName)) {
|
if (attemptMatch(bean.getClass(), methods[i], expression, beanName)) {
|
||||||
// We've found the first expression that matches this method, so move onto the next method now
|
// We've found the first expression that matches this method, so move onto the next method now
|
||||||
@@ -134,6 +132,8 @@ final class ProtectPointcutPostProcessor implements BeanPostProcessor {
|
|||||||
Assert.notNull(definition, "A List of ConfigAttributes is required");
|
Assert.notNull(definition, "A List of ConfigAttributes is required");
|
||||||
pointcutExpression = replaceBooleanOperators(pointcutExpression);
|
pointcutExpression = replaceBooleanOperators(pointcutExpression);
|
||||||
pointcutMap.put(pointcutExpression, definition);
|
pointcutMap.put(pointcutExpression, definition);
|
||||||
|
// Parse the presented AspectJ pointcut expression and add it to the cache
|
||||||
|
pointCutExpressions.add(parser.parsePointcutExpression(pointcutExpression));
|
||||||
|
|
||||||
if (logger.isDebugEnabled()) {
|
if (logger.isDebugEnabled()) {
|
||||||
logger.debug("AspectJ pointcut expression '" + pointcutExpression + "' registered for security configuration attribute '" + definition + "'");
|
logger.debug("AspectJ pointcut expression '" + pointcutExpression + "' registered for security configuration attribute '" + definition + "'");
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
http\://www.springframework.org/schema/security/spring-security.xsd=org/springframework/security/config/spring-security-3.0.xsd
|
http\://www.springframework.org/schema/security/spring-security.xsd=org/springframework/security/config/spring-security-3.0.3.xsd
|
||||||
http\://www.springframework.org/schema/security/spring-security-3.0.xsd=org/springframework/security/config/spring-security-3.0.xsd
|
http\://www.springframework.org/schema/security/spring-security-3.0.xsd=org/springframework/security/config/spring-security-3.0.xsd
|
||||||
|
http\://www.springframework.org/schema/security/spring-security-3.0.3.xsd=org/springframework/security/config/spring-security-3.0.3.xsd
|
||||||
http\://www.springframework.org/schema/security/spring-security-2.0.xsd=org/springframework/security/config/spring-security-2.0.xsd
|
http\://www.springframework.org/schema/security/spring-security-2.0.xsd=org/springframework/security/config/spring-security-2.0.xsd
|
||||||
http\://www.springframework.org/schema/security/spring-security-2.0.1.xsd=org/springframework/security/config/spring-security-2.0.1.xsd
|
http\://www.springframework.org/schema/security/spring-security-2.0.1.xsd=org/springframework/security/config/spring-security-2.0.1.xsd
|
||||||
http\://www.springframework.org/schema/security/spring-security-2.0.2.xsd=org/springframework/security/config/spring-security-2.0.2.xsd
|
http\://www.springframework.org/schema/security/spring-security-2.0.2.xsd=org/springframework/security/config/spring-security-2.0.2.xsd
|
||||||
|
|||||||
+93
-84
@@ -8,7 +8,7 @@ start = http | ldap-server | authentication-provider | ldap-authentication-provi
|
|||||||
hash =
|
hash =
|
||||||
## Defines the hashing algorithm used on user passwords. We recommend strongly against using MD4, as it is a very weak hashing algorithm.
|
## Defines the hashing algorithm used on user passwords. We recommend strongly against using MD4, as it is a very weak hashing algorithm.
|
||||||
attribute hash {"plaintext" | "sha" | "sha-256" | "md5" | "md4" | "{sha}" | "{ssha}"}
|
attribute hash {"plaintext" | "sha" | "sha-256" | "md5" | "md4" | "{sha}" | "{ssha}"}
|
||||||
base64 =
|
base64 =
|
||||||
## Whether a string should be base64 encoded
|
## Whether a string should be base64 encoded
|
||||||
attribute base64 {"true" | "false"}
|
attribute base64 {"true" | "false"}
|
||||||
path-type =
|
path-type =
|
||||||
@@ -20,9 +20,9 @@ port =
|
|||||||
url =
|
url =
|
||||||
## Specifies a URL.
|
## Specifies a URL.
|
||||||
attribute url { xsd:token }
|
attribute url { xsd:token }
|
||||||
id =
|
id =
|
||||||
## A bean identifier, used for referring to the bean elsewhere in the context.
|
## A bean identifier, used for referring to the bean elsewhere in the context.
|
||||||
attribute id {xsd:ID}
|
attribute id {xsd:ID}
|
||||||
ref =
|
ref =
|
||||||
## Defines a reference to a Spring bean Id.
|
## Defines a reference to a Spring bean Id.
|
||||||
attribute ref {xsd:token}
|
attribute ref {xsd:token}
|
||||||
@@ -35,47 +35,47 @@ user-service-ref =
|
|||||||
## A reference to a user-service (or UserDetailsService bean) Id
|
## A reference to a user-service (or UserDetailsService bean) Id
|
||||||
attribute user-service-ref {xsd:token}
|
attribute user-service-ref {xsd:token}
|
||||||
|
|
||||||
data-source-ref =
|
data-source-ref =
|
||||||
## A reference to a DataSource bean
|
## A reference to a DataSource bean
|
||||||
attribute data-source-ref {xsd:token}
|
attribute data-source-ref {xsd:token}
|
||||||
|
|
||||||
password-encoder =
|
password-encoder =
|
||||||
## element which defines a password encoding strategy. Used by an authentication provider to convert submitted passwords to hashed versions, for example.
|
## element which defines a password encoding strategy. Used by an authentication provider to convert submitted passwords to hashed versions, for example.
|
||||||
element password-encoder {password-encoder.attlist, salt-source?}
|
element password-encoder {password-encoder.attlist, salt-source?}
|
||||||
password-encoder.attlist &=
|
password-encoder.attlist &=
|
||||||
ref | (hash? & base64?)
|
ref | (hash? & base64?)
|
||||||
|
|
||||||
salt-source =
|
salt-source =
|
||||||
## Password salting strategy. A system-wide constant or a property from the UserDetails object can be used.
|
## Password salting strategy. A system-wide constant or a property from the UserDetails object can be used.
|
||||||
element salt-source {user-property | system-wide | ref}
|
element salt-source {user-property | system-wide | ref}
|
||||||
user-property =
|
user-property =
|
||||||
## A property of the UserDetails object which will be used as salt by a password encoder. Typically something like "username" might be used.
|
## A property of the UserDetails object which will be used as salt by a password encoder. Typically something like "username" might be used.
|
||||||
attribute user-property {xsd:token}
|
attribute user-property {xsd:token}
|
||||||
system-wide =
|
system-wide =
|
||||||
## A single value that will be used as the salt for a password encoder.
|
## A single value that will be used as the salt for a password encoder.
|
||||||
attribute system-wide {xsd:token}
|
attribute system-wide {xsd:token}
|
||||||
|
|
||||||
boolean = "true" | "false"
|
boolean = "true" | "false"
|
||||||
|
|
||||||
role-prefix =
|
role-prefix =
|
||||||
## A non-empty string prefix that will be added to role strings loaded from persistent storage (e.g. "ROLE_"). Use the value "none" for no prefix in cases where the default is non-empty.
|
## A non-empty string prefix that will be added to role strings loaded from persistent storage (e.g. "ROLE_"). Use the value "none" for no prefix in cases where the default is non-empty.
|
||||||
attribute role-prefix {xsd:token}
|
attribute role-prefix {xsd:token}
|
||||||
|
|
||||||
use-expressions =
|
use-expressions =
|
||||||
## Enables the use of expressions in the 'access' attributes in <intercept-url> elements rather than the traditional list of configuration attributes. Defaults to 'false'. If enabled, each attribute should contain a single boolean expression. If the expression evaluates to 'true', access will be granted.
|
## Enables the use of expressions in the 'access' attributes in <intercept-url> elements rather than the traditional list of configuration attributes. Defaults to 'false'. If enabled, each attribute should contain a single boolean expression. If the expression evaluates to 'true', access will be granted.
|
||||||
attribute use-expressions {boolean}
|
attribute use-expressions {boolean}
|
||||||
|
|
||||||
ldap-server =
|
ldap-server =
|
||||||
## Defines an LDAP server location or starts an embedded server. The url indicates the location of a remote server. If no url is given, an embedded server will be started, listening on the supplied port number. The port is optional and defaults to 33389. A Spring LDAP ContextSource bean will be registered for the server with the id supplied.
|
## Defines an LDAP server location or starts an embedded server. The url indicates the location of a remote server. If no url is given, an embedded server will be started, listening on the supplied port number. The port is optional and defaults to 33389. A Spring LDAP ContextSource bean will be registered for the server with the id supplied.
|
||||||
element ldap-server {ldap-server.attlist}
|
element ldap-server {ldap-server.attlist}
|
||||||
ldap-server.attlist &= id?
|
ldap-server.attlist &= id?
|
||||||
ldap-server.attlist &= (url | port)?
|
ldap-server.attlist &= (url | port)?
|
||||||
ldap-server.attlist &=
|
ldap-server.attlist &=
|
||||||
## Username (DN) of the "manager" user identity which will be used to authenticate to a (non-embedded) LDAP server. If omitted, anonymous access will be used.
|
## Username (DN) of the "manager" user identity which will be used to authenticate to a (non-embedded) LDAP server. If omitted, anonymous access will be used.
|
||||||
attribute manager-dn {xsd:string}?
|
attribute manager-dn {xsd:string}?
|
||||||
ldap-server.attlist &=
|
ldap-server.attlist &=
|
||||||
## The password for the manager DN.
|
## The password for the manager DN.
|
||||||
attribute manager-password {xsd:string}?
|
attribute manager-password {xsd:string}?
|
||||||
ldap-server.attlist &=
|
ldap-server.attlist &=
|
||||||
## Explicitly specifies an ldif file resource to load into an embedded LDAP server
|
## Explicitly specifies an ldif file resource to load into an embedded LDAP server
|
||||||
attribute ldif { xsd:string }?
|
attribute ldif { xsd:string }?
|
||||||
@@ -84,14 +84,14 @@ ldap-server.attlist &=
|
|||||||
attribute root { xsd:string }?
|
attribute root { xsd:string }?
|
||||||
|
|
||||||
ldap-server-ref-attribute =
|
ldap-server-ref-attribute =
|
||||||
## The optional server to use. If omitted, and a default LDAP server is registered (using <ldap-server> with no Id), that server will be used.
|
## The optional server to use. If omitted, and a default LDAP server is registered (using <ldap-server> with no Id), that server will be used.
|
||||||
attribute server-ref {xsd:token}
|
attribute server-ref {xsd:token}
|
||||||
|
|
||||||
|
|
||||||
group-search-filter-attribute =
|
group-search-filter-attribute =
|
||||||
## Group search filter. Defaults to (uniqueMember={0}). The substituted parameter is the DN of the user.
|
## Group search filter. Defaults to (uniqueMember={0}). The substituted parameter is the DN of the user.
|
||||||
attribute group-search-filter {xsd:token}
|
attribute group-search-filter {xsd:token}
|
||||||
group-search-base-attribute =
|
group-search-base-attribute =
|
||||||
## Search base for group membership searches. Defaults to "" (searching from the root).
|
## Search base for group membership searches. Defaults to "" (searching from the root).
|
||||||
attribute group-search-base {xsd:token}
|
attribute group-search-base {xsd:token}
|
||||||
user-search-filter-attribute =
|
user-search-filter-attribute =
|
||||||
@@ -103,7 +103,7 @@ user-search-base-attribute =
|
|||||||
group-role-attribute-attribute =
|
group-role-attribute-attribute =
|
||||||
## The LDAP attribute name which contains the role name which will be used within Spring Security. Defaults to "cn".
|
## The LDAP attribute name which contains the role name which will be used within Spring Security. Defaults to "cn".
|
||||||
attribute group-role-attribute {xsd:token}
|
attribute group-role-attribute {xsd:token}
|
||||||
user-details-class-attribute =
|
user-details-class-attribute =
|
||||||
## Allows the objectClass of the user entry to be specified. If set, the framework will attempt to load standard attributes for the defined class into the returned UserDetails object
|
## Allows the objectClass of the user entry to be specified. If set, the framework will attempt to load standard attributes for the defined class into the returned UserDetails object
|
||||||
attribute user-details-class {"person" | "inetOrgPerson"}
|
attribute user-details-class {"person" | "inetOrgPerson"}
|
||||||
user-context-mapper-attribute =
|
user-context-mapper-attribute =
|
||||||
@@ -113,7 +113,7 @@ user-context-mapper-attribute =
|
|||||||
|
|
||||||
ldap-user-service =
|
ldap-user-service =
|
||||||
element ldap-user-service {ldap-us.attlist}
|
element ldap-user-service {ldap-us.attlist}
|
||||||
ldap-us.attlist &= id?
|
ldap-us.attlist &= id?
|
||||||
ldap-us.attlist &=
|
ldap-us.attlist &=
|
||||||
ldap-server-ref-attribute?
|
ldap-server-ref-attribute?
|
||||||
ldap-us.attlist &=
|
ldap-us.attlist &=
|
||||||
@@ -144,7 +144,7 @@ ldap-ap.attlist &=
|
|||||||
user-search-filter-attribute?
|
user-search-filter-attribute?
|
||||||
ldap-ap.attlist &=
|
ldap-ap.attlist &=
|
||||||
group-search-base-attribute?
|
group-search-base-attribute?
|
||||||
ldap-ap.attlist &=
|
ldap-ap.attlist &=
|
||||||
group-search-filter-attribute?
|
group-search-filter-attribute?
|
||||||
ldap-ap.attlist &=
|
ldap-ap.attlist &=
|
||||||
group-role-attribute-attribute?
|
group-role-attribute-attribute?
|
||||||
@@ -159,7 +159,7 @@ ldap-ap.attlist &=
|
|||||||
password-compare-element =
|
password-compare-element =
|
||||||
## Specifies that an LDAP provider should use an LDAP compare operation of the user's password to authenticate the user
|
## Specifies that an LDAP provider should use an LDAP compare operation of the user's password to authenticate the user
|
||||||
element password-compare {password-compare.attlist, password-encoder?}
|
element password-compare {password-compare.attlist, password-encoder?}
|
||||||
|
|
||||||
password-compare.attlist &=
|
password-compare.attlist &=
|
||||||
## The attribute in the directory which contains the user password. Defaults to "userPassword".
|
## The attribute in the directory which contains the user password. Defaults to "userPassword".
|
||||||
attribute password-attribute {xsd:token}?
|
attribute password-attribute {xsd:token}?
|
||||||
@@ -208,26 +208,29 @@ global-method-security.attlist &=
|
|||||||
attribute order {xsd:token}?
|
attribute order {xsd:token}?
|
||||||
global-method-security.attlist &=
|
global-method-security.attlist &=
|
||||||
attribute proxy-target-class {boolean}?
|
attribute proxy-target-class {boolean}?
|
||||||
|
global-method-security.attlist &=
|
||||||
|
## Can be used to specify that AspectJ should be used instead of the default Spring AOP. If set, secured classes must be woven with the AnnotationSecurityAspect from the spring-security-aspects module.
|
||||||
|
attribute mode {"aspectj"}?
|
||||||
|
|
||||||
after-invocation-provider =
|
after-invocation-provider =
|
||||||
## Allows addition of extra AfterInvocationProvider beans which should be called by the MethodSecurityInterceptor created by global-method-security.
|
## Allows addition of extra AfterInvocationProvider beans which should be called by the MethodSecurityInterceptor created by global-method-security.
|
||||||
element after-invocation-provider {ref}
|
element after-invocation-provider {ref}
|
||||||
|
|
||||||
pre-post-annotation-handling =
|
pre-post-annotation-handling =
|
||||||
## Allows the default expression-based mechanism for handling Spring Security's pre and post invocation annotations (@PreFilter, @PreAuthorize, @PostFilter, @PostAuthorize) to be replace entirely. Only applies if these annotations are enabled.
|
## Allows the default expression-based mechanism for handling Spring Security's pre and post invocation annotations (@PreFilter, @PreAuthorize, @PostFilter, @PostAuthorize) to be replace entirely. Only applies if these annotations are enabled.
|
||||||
element pre-post-annotation-handling {invocation-attribute-factory, pre-invocation-advice, post-invocation-advice}
|
element pre-post-annotation-handling {invocation-attribute-factory, pre-invocation-advice, post-invocation-advice}
|
||||||
|
|
||||||
invocation-attribute-factory =
|
invocation-attribute-factory =
|
||||||
## Defines the PrePostInvocationAttributeFactory instance which is used to generate pre and post invocation metadata from the annotated methods.
|
## Defines the PrePostInvocationAttributeFactory instance which is used to generate pre and post invocation metadata from the annotated methods.
|
||||||
element invocation-attribute-factory {ref}
|
element invocation-attribute-factory {ref}
|
||||||
|
|
||||||
pre-invocation-advice =
|
pre-invocation-advice =
|
||||||
element pre-invocation-advice {ref}
|
element pre-invocation-advice {ref}
|
||||||
|
|
||||||
post-invocation-advice =
|
post-invocation-advice =
|
||||||
element post-invocation-advice {ref}
|
element post-invocation-advice {ref}
|
||||||
|
|
||||||
|
|
||||||
expression-handler =
|
expression-handler =
|
||||||
## Defines the SecurityExpressionHandler instance which will be used if expression-based access-control is enabled. A default implementation (with no ACL support) will be used if not supplied.
|
## Defines the SecurityExpressionHandler instance which will be used if expression-based access-control is enabled. A default implementation (with no ACL support) will be used if not supplied.
|
||||||
element expression-handler {ref}
|
element expression-handler {ref}
|
||||||
@@ -254,9 +257,9 @@ http.attlist &=
|
|||||||
http.attlist &=
|
http.attlist &=
|
||||||
## Controls the eagerness with which an HTTP session is created. If not set, defaults to "ifRequired". Note that if a custom SecurityContextRepository is set using security-context-repository-ref, then the only value which can be set is "always". Otherwise the session creation behaviour will be determined by the repository bean implementation.
|
## Controls the eagerness with which an HTTP session is created. If not set, defaults to "ifRequired". Note that if a custom SecurityContextRepository is set using security-context-repository-ref, then the only value which can be set is "always". Otherwise the session creation behaviour will be determined by the repository bean implementation.
|
||||||
attribute create-session {"ifRequired" | "always" | "never" }?
|
attribute create-session {"ifRequired" | "always" | "never" }?
|
||||||
http.attlist &=
|
http.attlist &=
|
||||||
## A reference to a SecurityContextRepository bean. This can be used to customize how the SecurityContext is stored between requests.
|
## A reference to a SecurityContextRepository bean. This can be used to customize how the SecurityContext is stored between requests.
|
||||||
attribute security-context-repository-ref {xsd:token}?
|
attribute security-context-repository-ref {xsd:token}?
|
||||||
http.attlist &=
|
http.attlist &=
|
||||||
## The path format used to define the paths in child elements.
|
## The path format used to define the paths in child elements.
|
||||||
path-type?
|
path-type?
|
||||||
@@ -273,7 +276,7 @@ http.attlist &=
|
|||||||
## Optional attribute specifying the realm name that will be used for all authentication features that require a realm name (eg BASIC and Digest authentication). If unspecified, defaults to "Spring Security Application".
|
## Optional attribute specifying the realm name that will be used for all authentication features that require a realm name (eg BASIC and Digest authentication). If unspecified, defaults to "Spring Security Application".
|
||||||
attribute realm {xsd:token}?
|
attribute realm {xsd:token}?
|
||||||
http.attlist &=
|
http.attlist &=
|
||||||
## Allows a customized AuthenticationEntryPoint to be used.
|
## Allows a customized AuthenticationEntryPoint to be set on the ExceptionTranslationFilter.
|
||||||
attribute entry-point-ref {xsd:token}?
|
attribute entry-point-ref {xsd:token}?
|
||||||
http.attlist &=
|
http.attlist &=
|
||||||
## Corresponds to the observeOncePerRequest property of FilterSecurityInterceptor. Defaults to "true"
|
## Corresponds to the observeOncePerRequest property of FilterSecurityInterceptor. Defaults to "true"
|
||||||
@@ -282,17 +285,17 @@ http.attlist &=
|
|||||||
## Deprecated in favour of the access-denied-handler element.
|
## Deprecated in favour of the access-denied-handler element.
|
||||||
attribute access-denied-page {xsd:token}?
|
attribute access-denied-page {xsd:token}?
|
||||||
http.attlist &=
|
http.attlist &=
|
||||||
##
|
##
|
||||||
attribute disable-url-rewriting {boolean}?
|
attribute disable-url-rewriting {boolean}?
|
||||||
|
|
||||||
|
|
||||||
access-denied-handler =
|
access-denied-handler =
|
||||||
## Defines the access-denied strategy that should be used. An access denied page can be defined or a reference to an AccessDeniedHandler instance.
|
## Defines the access-denied strategy that should be used. An access denied page can be defined or a reference to an AccessDeniedHandler instance.
|
||||||
element access-denied-handler {access-denied-handler.attlist, empty}
|
element access-denied-handler {access-denied-handler.attlist, empty}
|
||||||
access-denied-handler.attlist &= (ref | access-denied-handler-page)
|
access-denied-handler.attlist &= (ref | access-denied-handler-page)
|
||||||
|
|
||||||
access-denied-handler-page =
|
access-denied-handler-page =
|
||||||
## The access denied page that an authenticated user will be redirected to if they request a page which they don't have the authority to access.
|
## The access denied page that an authenticated user will be redirected to if they request a page which they don't have the authority to access.
|
||||||
attribute error-page {xsd:token}
|
attribute error-page {xsd:token}
|
||||||
|
|
||||||
intercept-url =
|
intercept-url =
|
||||||
@@ -346,8 +349,8 @@ form-login.attlist &=
|
|||||||
## The URL that will be redirected to after successful authentication, if the user's previous action could not be resumed. This generally happens if the user visits a login page without having first requested a secured operation that triggers authentication. If unspecified, defaults to the root of the application.
|
## The URL that will be redirected to after successful authentication, if the user's previous action could not be resumed. This generally happens if the user visits a login page without having first requested a secured operation that triggers authentication. If unspecified, defaults to the root of the application.
|
||||||
attribute default-target-url {xsd:token}?
|
attribute default-target-url {xsd:token}?
|
||||||
form-login.attlist &=
|
form-login.attlist &=
|
||||||
## Whether the user should always be redirected to the default-target-url after login.
|
## Whether the user should always be redirected to the default-target-url after login.
|
||||||
attribute always-use-default-target {boolean}?
|
attribute always-use-default-target {boolean}?
|
||||||
form-login.attlist &=
|
form-login.attlist &=
|
||||||
## The URL for the login page. If no login URL is specified, Spring Security will automatically create a login URL at /spring_security_login and a corresponding filter to render that login URL when requested.
|
## The URL for the login page. If no login URL is specified, Spring Security will automatically create a login URL at /spring_security_login and a corresponding filter to render that login URL when requested.
|
||||||
attribute login-page {xsd:token}?
|
attribute login-page {xsd:token}?
|
||||||
@@ -362,7 +365,7 @@ form-login.attlist &=
|
|||||||
attribute authentication-failure-handler-ref {xsd:token}?
|
attribute authentication-failure-handler-ref {xsd:token}?
|
||||||
|
|
||||||
|
|
||||||
openid-login =
|
openid-login =
|
||||||
## Sets up form login for authentication with an Open ID identity
|
## Sets up form login for authentication with an Open ID identity
|
||||||
element openid-login {form-login.attlist, user-service-ref?, attribute-exchange?}
|
element openid-login {form-login.attlist, user-service-ref?, attribute-exchange?}
|
||||||
|
|
||||||
@@ -380,7 +383,7 @@ openid-attribute.attlist &=
|
|||||||
attribute required {boolean}?
|
attribute required {boolean}?
|
||||||
openid-attribute.attlist &=
|
openid-attribute.attlist &=
|
||||||
attribute count {xsd:int}?
|
attribute count {xsd:int}?
|
||||||
|
|
||||||
|
|
||||||
filter-chain-map =
|
filter-chain-map =
|
||||||
## Used to explicitly configure a FilterChainProxy instance with a FilterChainMap
|
## Used to explicitly configure a FilterChainProxy instance with a FilterChainMap
|
||||||
@@ -397,7 +400,7 @@ filter-chain.attlist &=
|
|||||||
attribute filters {xsd:token}
|
attribute filters {xsd:token}
|
||||||
|
|
||||||
filter-security-metadata-source =
|
filter-security-metadata-source =
|
||||||
## Used to explicitly configure a FilterSecurityMetadataSource bean for use with a FilterSecurityInterceptor. Usually only needed if you are configuring a FilterChainProxy explicitly, rather than using the <http> element. The intercept-url elements used should only contain pattern, method and access attributes. Any others will result in a configuration error.
|
## Used to explicitly configure a FilterSecurityMetadataSource bean for use with a FilterSecurityInterceptor. Usually only needed if you are configuring a FilterChainProxy explicitly, rather than using the <http> element. The intercept-url elements used should only contain pattern, method and access attributes. Any others will result in a configuration error.
|
||||||
element filter-security-metadata-source {fsmds.attlist, intercept-url+}
|
element filter-security-metadata-source {fsmds.attlist, intercept-url+}
|
||||||
fsmds.attlist &=
|
fsmds.attlist &=
|
||||||
use-expressions?
|
use-expressions?
|
||||||
@@ -410,15 +413,18 @@ fsmds.attlist &=
|
|||||||
## as for http element
|
## as for http element
|
||||||
path-type?
|
path-type?
|
||||||
|
|
||||||
filter-invocation-definition-source =
|
filter-invocation-definition-source =
|
||||||
## Deprecated synonym for filter-security-metadata-source
|
## Deprecated synonym for filter-security-metadata-source
|
||||||
element filter-invocation-definition-source {fsmds.attlist, intercept-url+}
|
element filter-invocation-definition-source {fsmds.attlist, intercept-url+}
|
||||||
|
|
||||||
http-basic =
|
http-basic =
|
||||||
## Adds support for basic authentication (this is an element to permit future expansion, such as supporting an "ignoreFailure" attribute)
|
## Adds support for basic authentication (this is an element to permit future expansion, such as supporting an "ignoreFailure" attribute)
|
||||||
element http-basic {empty}
|
element http-basic {http-basic.attlist, empty}
|
||||||
|
http-basic.attlist &=
|
||||||
|
## Sets the AuthenticationEntryPoint which is used by the BasicAuthenticationFilter.
|
||||||
|
attribute entry-point-ref {xsd:token}?
|
||||||
|
|
||||||
session-management =
|
session-management =
|
||||||
element session-management {session-management.attlist, concurrency-control?}
|
element session-management {session-management.attlist, concurrency-control?}
|
||||||
|
|
||||||
session-management.attlist &=
|
session-management.attlist &=
|
||||||
@@ -431,18 +437,18 @@ session-management.attlist &=
|
|||||||
## Allows injection of the SessionAuthenticationStrategy instance used by the SessionManagementFilter
|
## Allows injection of the SessionAuthenticationStrategy instance used by the SessionManagementFilter
|
||||||
attribute session-authentication-strategy-ref {xsd:token}?
|
attribute session-authentication-strategy-ref {xsd:token}?
|
||||||
session-management.attlist &=
|
session-management.attlist &=
|
||||||
## Defines the URL of the error page which should be shown when the SessionAuthenticationStrategy raises an exception. If not set, an unauthorized (402) error code will be returned to the client. Note that this attribute doesn't apply if the error occurs during a form-based login, where the URL for authentication failure will take precedence.
|
## Defines the URL of the error page which should be shown when the SessionAuthenticationStrategy raises an exception. If not set, an unauthorized (402) error code will be returned to the client. Note that this attribute doesn't apply if the error occurs during a form-based login, where the URL for authentication failure will take precedence.
|
||||||
attribute session-authentication-error-url {xsd:token}?
|
attribute session-authentication-error-url {xsd:token}?
|
||||||
|
|
||||||
|
|
||||||
concurrency-control =
|
concurrency-control =
|
||||||
## Enables concurrent session control, limiting the number of authenticated sessions a user may have at the same time.
|
## Enables concurrent session control, limiting the number of authenticated sessions a user may have at the same time.
|
||||||
element concurrency-control {concurrency-control.attlist, empty}
|
element concurrency-control {concurrency-control.attlist, empty}
|
||||||
|
|
||||||
concurrency-control.attlist &=
|
concurrency-control.attlist &=
|
||||||
## The maximum number of sessions a single authenticated user can have open at the same time. Defaults to "1".
|
## The maximum number of sessions a single authenticated user can have open at the same time. Defaults to "1".
|
||||||
attribute max-sessions {xsd:positiveInteger}?
|
attribute max-sessions {xsd:positiveInteger}?
|
||||||
concurrency-control.attlist &=
|
concurrency-control.attlist &=
|
||||||
## The URL a user will be redirected to if they attempt to use a session which has been "expired" because they have logged in again.
|
## The URL a user will be redirected to if they attempt to use a session which has been "expired" because they have logged in again.
|
||||||
attribute expired-url {xsd:token}?
|
attribute expired-url {xsd:token}?
|
||||||
concurrency-control.attlist &=
|
concurrency-control.attlist &=
|
||||||
@@ -457,21 +463,21 @@ concurrency-control.attlist &=
|
|||||||
|
|
||||||
|
|
||||||
remember-me =
|
remember-me =
|
||||||
## Sets up remember-me authentication. If used with the "key" attribute (or no attributes) the cookie-only implementation will be used. Specifying "token-repository-ref" or "remember-me-data-source-ref" will use the more secure, persisten token approach.
|
## Sets up remember-me authentication. If used with the "key" attribute (or no attributes) the cookie-only implementation will be used. Specifying "token-repository-ref" or "remember-me-data-source-ref" will use the more secure, persisten token approach.
|
||||||
element remember-me {remember-me.attlist}
|
element remember-me {remember-me.attlist}
|
||||||
remember-me.attlist &=
|
remember-me.attlist &=
|
||||||
## The "key" used to identify cookies from a specific token-based remember-me application. You should set this to a unique value for your application.
|
## The "key" used to identify cookies from a specific token-based remember-me application. You should set this to a unique value for your application.
|
||||||
attribute key {xsd:token}?
|
attribute key {xsd:token}?
|
||||||
|
|
||||||
remember-me.attlist &=
|
remember-me.attlist &=
|
||||||
(token-repository-ref | remember-me-data-source-ref | remember-me-services-ref)
|
(token-repository-ref | remember-me-data-source-ref | remember-me-services-ref)
|
||||||
|
|
||||||
remember-me.attlist &=
|
remember-me.attlist &=
|
||||||
user-service-ref?
|
user-service-ref?
|
||||||
|
|
||||||
remember-me.attlist &=
|
remember-me.attlist &=
|
||||||
## Exports the internally defined RememberMeServices as a bean alias, allowing it to be used by other beans in the application context.
|
## Exports the internally defined RememberMeServices as a bean alias, allowing it to be used by other beans in the application context.
|
||||||
attribute services-alias {xsd:token}?
|
attribute services-alias {xsd:token}?
|
||||||
|
|
||||||
remember-me.attlist &=
|
remember-me.attlist &=
|
||||||
## Determines whether the "secure" flag will be set on the remember-me cookie. If set to true, the cookie will only be submitted over HTTPS. Defaults to false.
|
## Determines whether the "secure" flag will be set on the remember-me cookie. If set to true, the cookie will only be submitted over HTTPS. Defaults to false.
|
||||||
@@ -480,15 +486,15 @@ remember-me.attlist &=
|
|||||||
remember-me.attlist &=
|
remember-me.attlist &=
|
||||||
## The period (in seconds) for which the remember-me cookie should be valid.
|
## The period (in seconds) for which the remember-me cookie should be valid.
|
||||||
attribute token-validity-seconds {xsd:integer}?
|
attribute token-validity-seconds {xsd:integer}?
|
||||||
|
|
||||||
token-repository-ref =
|
token-repository-ref =
|
||||||
## Reference to a PersistentTokenRepository bean for use with the persistent token remember-me implementation.
|
## Reference to a PersistentTokenRepository bean for use with the persistent token remember-me implementation.
|
||||||
attribute token-repository-ref {xsd:token}
|
attribute token-repository-ref {xsd:token}
|
||||||
remember-me-services-ref =
|
remember-me-services-ref =
|
||||||
## Allows a custom implementation of RememberMeServices to be used. Note that this implementation should return RememberMeAuthenticationToken instances with the same "key" value as specified in the remember-me element. Alternatively it should register its own AuthenticationProvider.
|
## Allows a custom implementation of RememberMeServices to be used. Note that this implementation should return RememberMeAuthenticationToken instances with the same "key" value as specified in the remember-me element. Alternatively it should register its own AuthenticationProvider.
|
||||||
attribute services-ref {xsd:token}?
|
attribute services-ref {xsd:token}?
|
||||||
remember-me-data-source-ref =
|
remember-me-data-source-ref =
|
||||||
## DataSource bean for the database that contains the token repository schema.
|
## DataSource bean for the database that contains the token repository schema.
|
||||||
data-source-ref
|
data-source-ref
|
||||||
|
|
||||||
anonymous =
|
anonymous =
|
||||||
@@ -497,56 +503,59 @@ anonymous =
|
|||||||
anonymous.attlist &=
|
anonymous.attlist &=
|
||||||
## The key shared between the provider and filter. This generally does not need to be set. If unset, it will default to "doesNotMatter".
|
## The key shared between the provider and filter. This generally does not need to be set. If unset, it will default to "doesNotMatter".
|
||||||
attribute key {xsd:token}?
|
attribute key {xsd:token}?
|
||||||
anonymous.attlist &=
|
anonymous.attlist &=
|
||||||
## The username that should be assigned to the anonymous request. This allows the principal to be identified, which may be important for logging and auditing. if unset, defaults to "anonymousUser".
|
## The username that should be assigned to the anonymous request. This allows the principal to be identified, which may be important for logging and auditing. if unset, defaults to "anonymousUser".
|
||||||
attribute username {xsd:token}?
|
attribute username {xsd:token}?
|
||||||
anonymous.attlist &=
|
anonymous.attlist &=
|
||||||
## The granted authority that should be assigned to the anonymous request. Commonly this is used to assign the anonymous request particular roles, which can subsequently be used in authorization decisions. If unset, defaults to "ROLE_ANONYMOUS".
|
## The granted authority that should be assigned to the anonymous request. Commonly this is used to assign the anonymous request particular roles, which can subsequently be used in authorization decisions. If unset, defaults to "ROLE_ANONYMOUS".
|
||||||
attribute granted-authority {xsd:token}?
|
attribute granted-authority {xsd:token}?
|
||||||
anonymous.attlist &=
|
anonymous.attlist &=
|
||||||
## With the default namespace setup, the anonymous "authentication" facility is automatically enabled. You can disable it using this property.
|
## With the default namespace setup, the anonymous "authentication" facility is automatically enabled. You can disable it using this property.
|
||||||
attribute enabled {boolean}?
|
attribute enabled {boolean}?
|
||||||
|
|
||||||
|
|
||||||
port-mappings =
|
port-mappings =
|
||||||
## Defines the list of mappings between http and https ports for use in redirects
|
## Defines the list of mappings between http and https ports for use in redirects
|
||||||
element port-mappings {port-mappings.attlist, port-mapping+}
|
element port-mappings {port-mappings.attlist, port-mapping+}
|
||||||
|
|
||||||
port-mappings.attlist &= empty
|
port-mappings.attlist &= empty
|
||||||
|
|
||||||
port-mapping =
|
port-mapping =
|
||||||
element port-mapping {http-port, https-port}
|
element port-mapping {http-port, https-port}
|
||||||
|
|
||||||
http-port = attribute http {xsd:token}
|
http-port = attribute http {xsd:token}
|
||||||
|
|
||||||
https-port = attribute https {xsd:token}
|
https-port = attribute https {xsd:token}
|
||||||
|
|
||||||
|
|
||||||
x509 =
|
x509 =
|
||||||
## Adds support for X.509 client authentication.
|
## Adds support for X.509 client authentication.
|
||||||
element x509 {x509.attlist}
|
element x509 {x509.attlist}
|
||||||
x509.attlist &=
|
x509.attlist &=
|
||||||
## The regular expression used to obtain the username from the certificate's subject. Defaults to matching on the common name using the pattern "CN=(.*?),".
|
## The regular expression used to obtain the username from the certificate's subject. Defaults to matching on the common name using the pattern "CN=(.*?),".
|
||||||
attribute subject-principal-regex {xsd:token}?
|
attribute subject-principal-regex {xsd:token}?
|
||||||
x509.attlist &=
|
x509.attlist &=
|
||||||
## Explicitly specifies which user-service should be used to load user data for X.509 authenticated clients. If ommitted, the default user-service will be used.
|
## Explicitly specifies which user-service should be used to load user data for X.509 authenticated clients. If ommitted, the default user-service will be used.
|
||||||
user-service-ref?
|
user-service-ref?
|
||||||
|
|
||||||
authentication-manager =
|
authentication-manager =
|
||||||
## Registers the AuthenticationManager instance and allows its list of AuthenticationProviders to be defined. Also allows you to define an alias to allow you to reference the AuthenticationManager in your own beans.
|
## Registers the AuthenticationManager instance and allows its list of AuthenticationProviders to be defined. Also allows you to define an alias to allow you to reference the AuthenticationManager in your own beans.
|
||||||
element authentication-manager {authman.attlist & authentication-provider* & ldap-authentication-provider*}
|
element authentication-manager {authman.attlist & authentication-provider* & ldap-authentication-provider*}
|
||||||
authman.attlist &=
|
authman.attlist &=
|
||||||
## The alias you wish to use for the AuthenticationManager bean
|
## The alias you wish to use for the AuthenticationManager bean
|
||||||
attribute alias {xsd:ID}?
|
attribute alias {xsd:ID}?
|
||||||
|
authman.attlist &=
|
||||||
|
## If set to true, the AuthenticationManger will attempt to clear any credentials data in the returned Authentication object, once the user has been authenticated. Defaults to false.
|
||||||
|
attribute erase-credentials {boolean}?
|
||||||
|
|
||||||
authentication-provider =
|
authentication-provider =
|
||||||
## Indicates that the contained user-service should be used as an authentication source.
|
## Indicates that the contained user-service should be used as an authentication source.
|
||||||
element authentication-provider {ap.attlist & any-user-service & password-encoder?}
|
element authentication-provider {ap.attlist & any-user-service & password-encoder?}
|
||||||
ap.attlist &=
|
ap.attlist &=
|
||||||
## Specifies a reference to a separately configured AuthenticationProvider instance which should be registered within the AuthenticationManager.
|
## Specifies a reference to a separately configured AuthenticationProvider instance which should be registered within the AuthenticationManager.
|
||||||
ref?
|
ref?
|
||||||
ap.attlist &=
|
ap.attlist &=
|
||||||
## Specifies a reference to a separately configured UserDetailsService from which to obtain authentication data.
|
## Specifies a reference to a separately configured UserDetailsService from which to obtain authentication data.
|
||||||
user-service-ref?
|
user-service-ref?
|
||||||
|
|
||||||
user-service =
|
user-service =
|
||||||
@@ -554,7 +563,7 @@ user-service =
|
|||||||
element user-service {id? & (properties-file | (user*))}
|
element user-service {id? & (properties-file | (user*))}
|
||||||
properties-file =
|
properties-file =
|
||||||
attribute properties {xsd:token}?
|
attribute properties {xsd:token}?
|
||||||
|
|
||||||
user =
|
user =
|
||||||
## Represents a user in the application.
|
## Represents a user in the application.
|
||||||
element user {user.attlist, empty}
|
element user {user.attlist, empty}
|
||||||
@@ -576,7 +585,7 @@ user.attlist &=
|
|||||||
|
|
||||||
jdbc-user-service =
|
jdbc-user-service =
|
||||||
## Causes creation of a JDBC-based UserDetailsService.
|
## Causes creation of a JDBC-based UserDetailsService.
|
||||||
element jdbc-user-service {id? & jdbc-user-service.attlist}
|
element jdbc-user-service {id? & jdbc-user-service.attlist}
|
||||||
jdbc-user-service.attlist &=
|
jdbc-user-service.attlist &=
|
||||||
## The bean ID of the DataSource which provides the required tables.
|
## The bean ID of the DataSource which provides the required tables.
|
||||||
attribute data-source-ref {xsd:token}
|
attribute data-source-ref {xsd:token}
|
||||||
@@ -593,12 +602,12 @@ jdbc-user-service.attlist &=
|
|||||||
attribute group-authorities-by-username-query {xsd:token}?
|
attribute group-authorities-by-username-query {xsd:token}?
|
||||||
jdbc-user-service.attlist &=
|
jdbc-user-service.attlist &=
|
||||||
role-prefix?
|
role-prefix?
|
||||||
|
|
||||||
|
|
||||||
any-user-service = user-service | jdbc-user-service | ldap-user-service
|
any-user-service = user-service | jdbc-user-service | ldap-user-service
|
||||||
|
|
||||||
custom-filter =
|
custom-filter =
|
||||||
## Used to indicate that a filter bean declaration should be incorporated into the security filter chain.
|
## Used to indicate that a filter bean declaration should be incorporated into the security filter chain.
|
||||||
element custom-filter {custom-filter.attlist}
|
element custom-filter {custom-filter.attlist}
|
||||||
|
|
||||||
custom-filter.attlist &=
|
custom-filter.attlist &=
|
||||||
@@ -608,7 +617,7 @@ custom-filter.attlist &=
|
|||||||
(after | before | position)
|
(after | before | position)
|
||||||
|
|
||||||
after =
|
after =
|
||||||
## The filter immediately after which the custom-filter should be placed in the chain. This feature will only be needed by advanced users who wish to mix their own filters into the security filter chain and have some knowledge of the standard Spring Security filters. The filter names map to specific Spring Security implementation filters.
|
## The filter immediately after which the custom-filter should be placed in the chain. This feature will only be needed by advanced users who wish to mix their own filters into the security filter chain and have some knowledge of the standard Spring Security filters. The filter names map to specific Spring Security implementation filters.
|
||||||
attribute after {named-security-filter}
|
attribute after {named-security-filter}
|
||||||
before =
|
before =
|
||||||
## The filter immediately before which the custom-filter should be placed in the chain
|
## The filter immediately before which the custom-filter should be placed in the chain
|
||||||
@@ -619,5 +628,5 @@ position =
|
|||||||
|
|
||||||
|
|
||||||
named-security-filter = "FIRST" | "CHANNEL_FILTER" | "CONCURRENT_SESSION_FILTER" | "SECURITY_CONTEXT_FILTER" | "LOGOUT_FILTER" | "X509_FILTER" | "PRE_AUTH_FILTER" | "CAS_FILTER" | "FORM_LOGIN_FILTER" | "OPENID_FILTER" |"BASIC_AUTH_FILTER" | "SERVLET_API_SUPPORT_FILTER" | "REMEMBER_ME_FILTER" | "ANONYMOUS_FILTER" | "EXCEPTION_TRANSLATION_FILTER" | "SESSION_MANAGEMENT_FILTER" | "FILTER_SECURITY_INTERCEPTOR" | "SWITCH_USER_FILTER" | "LAST"
|
named-security-filter = "FIRST" | "CHANNEL_FILTER" | "CONCURRENT_SESSION_FILTER" | "SECURITY_CONTEXT_FILTER" | "LOGOUT_FILTER" | "X509_FILTER" | "PRE_AUTH_FILTER" | "CAS_FILTER" | "FORM_LOGIN_FILTER" | "OPENID_FILTER" |"BASIC_AUTH_FILTER" | "SERVLET_API_SUPPORT_FILTER" | "REMEMBER_ME_FILTER" | "ANONYMOUS_FILTER" | "EXCEPTION_TRANSLATION_FILTER" | "SESSION_MANAGEMENT_FILTER" | "FILTER_SECURITY_INTERCEPTOR" | "SWITCH_USER_FILTER" | "LAST"
|
||||||
|
|
||||||
|
|
||||||
+1381
File diff suppressed because it is too large
Load Diff
+14
@@ -53,6 +53,20 @@ public class AuthenticationManagerBeanDefinitionParserTests {
|
|||||||
assertEquals(1, listener.events.size());
|
assertEquals(1, listener.events.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void credentialsAreNotClearedByDefault() throws Exception {
|
||||||
|
setContext(CONTEXT, "3.0");
|
||||||
|
ProviderManager pm = (ProviderManager) appContext.getBeansOfType(ProviderManager.class).values().toArray()[0];
|
||||||
|
assertFalse(pm.isEraseCredentialsAfterAuthentication());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void clearCredentialsPropertyIsRespected() throws Exception {
|
||||||
|
setContext("<authentication-manager erase-credentials='true'/>", "3.0.3");
|
||||||
|
ProviderManager pm = (ProviderManager) appContext.getBeansOfType(ProviderManager.class).values().toArray()[0];
|
||||||
|
assertTrue(pm.isEraseCredentialsAfterAuthentication());
|
||||||
|
}
|
||||||
|
|
||||||
private void setContext(String context, String version) {
|
private void setContext(String context, String version) {
|
||||||
appContext = new InMemoryXmlApplicationContext(context, version, null);
|
appContext = new InMemoryXmlApplicationContext(context, version, null);
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -77,12 +77,12 @@ public class UserServiceBeanDefinitionParserTests {
|
|||||||
setContext(
|
setContext(
|
||||||
"<user-service id='service'>" +
|
"<user-service id='service'>" +
|
||||||
" <user name='joe' password='joespassword' authorities='ROLE_A' locked='true'/>" +
|
" <user name='joe' password='joespassword' authorities='ROLE_A' locked='true'/>" +
|
||||||
" <user name='bob' password='bobspassword' authorities='ROLE_A' disabled='true'/>" +
|
" <user name='Bob' password='bobspassword' authorities='ROLE_A' disabled='true'/>" +
|
||||||
"</user-service>");
|
"</user-service>");
|
||||||
UserDetailsService userService = (UserDetailsService) appContext.getBean("service");
|
UserDetailsService userService = (UserDetailsService) appContext.getBean("service");
|
||||||
UserDetails joe = userService.loadUserByUsername("joe");
|
UserDetails joe = userService.loadUserByUsername("joe");
|
||||||
assertFalse(joe.isAccountNonLocked());
|
assertFalse(joe.isAccountNonLocked());
|
||||||
UserDetails bob = userService.loadUserByUsername("bob");
|
UserDetails bob = userService.loadUserByUsername("bOb");
|
||||||
assertFalse(bob.isEnabled());
|
assertFalse(bob.isEnabled());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+15
@@ -416,6 +416,21 @@ public class HttpSecurityBeanDefinitionParserTests {
|
|||||||
assertFalse(fsi.isObserveOncePerRequest());
|
assertFalse(fsi.isObserveOncePerRequest());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void httpBasicSupportsSeparateEntryPoint() throws Exception {
|
||||||
|
setContext("<http><http-basic entry-point-ref='ep' /></http>" +
|
||||||
|
"<b:bean id='ep' class='org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint'>" +
|
||||||
|
" <b:property name='realmName' value='whocares'/>" +
|
||||||
|
"</b:bean>" + AUTH_PROVIDER_XML);
|
||||||
|
|
||||||
|
BasicAuthenticationFilter baf = getFilter(BasicAuthenticationFilter.class);
|
||||||
|
assertSame(appContext.getBean("ep"), FieldUtils.getFieldValue(baf, "authenticationEntryPoint"));
|
||||||
|
// Since no other authentication system is in use, this should also end up on the ETF
|
||||||
|
ExceptionTranslationFilter etf = getFilter(ExceptionTranslationFilter.class);
|
||||||
|
assertSame(appContext.getBean("ep"), FieldUtils.getFieldValue(etf, "authenticationEntryPoint"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void accessDeniedPageAttributeIsSupported() throws Exception {
|
public void accessDeniedPageAttributeIsSupported() throws Exception {
|
||||||
setContext("<http access-denied-page='/access-denied'><http-basic /></http>" + AUTH_PROVIDER_XML);
|
setContext("<http access-denied-page='/access-denied'><http-basic /></http>" + AUTH_PROVIDER_XML);
|
||||||
|
|||||||
+48
-6
@@ -16,12 +16,15 @@ import org.springframework.context.ApplicationContext;
|
|||||||
import org.springframework.context.support.AbstractXmlApplicationContext;
|
import org.springframework.context.support.AbstractXmlApplicationContext;
|
||||||
import org.springframework.context.support.StaticApplicationContext;
|
import org.springframework.context.support.StaticApplicationContext;
|
||||||
import org.springframework.security.access.AccessDeniedException;
|
import org.springframework.security.access.AccessDeniedException;
|
||||||
|
import org.springframework.security.access.ConfigAttribute;
|
||||||
|
import org.springframework.security.access.SecurityConfig;
|
||||||
import org.springframework.security.access.annotation.BusinessService;
|
import org.springframework.security.access.annotation.BusinessService;
|
||||||
import org.springframework.security.access.intercept.AfterInvocationProviderManager;
|
import org.springframework.security.access.intercept.AfterInvocationProviderManager;
|
||||||
import org.springframework.security.access.intercept.RunAsManagerImpl;
|
import org.springframework.security.access.intercept.RunAsManagerImpl;
|
||||||
import org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor;
|
import org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor;
|
||||||
import org.springframework.security.access.intercept.aopalliance.MethodSecurityMetadataSourceAdvisor;
|
import org.springframework.security.access.intercept.aopalliance.MethodSecurityMetadataSourceAdvisor;
|
||||||
import org.springframework.security.access.prepost.PostInvocationAdviceProvider;
|
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.PreInvocationAuthorizationAdviceVoter;
|
||||||
import org.springframework.security.access.vote.AffirmativeBased;
|
import org.springframework.security.access.vote.AffirmativeBased;
|
||||||
import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException;
|
import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException;
|
||||||
@@ -30,6 +33,7 @@ import org.springframework.security.authentication.UsernamePasswordAuthenticatio
|
|||||||
import org.springframework.security.config.ConfigTestUtils;
|
import org.springframework.security.config.ConfigTestUtils;
|
||||||
import org.springframework.security.config.PostProcessedMockUserDetailsService;
|
import org.springframework.security.config.PostProcessedMockUserDetailsService;
|
||||||
import org.springframework.security.config.util.InMemoryXmlApplicationContext;
|
import org.springframework.security.config.util.InMemoryXmlApplicationContext;
|
||||||
|
import org.springframework.security.core.AuthenticationException;
|
||||||
import org.springframework.security.core.authority.AuthorityUtils;
|
import org.springframework.security.core.authority.AuthorityUtils;
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||||
@@ -40,6 +44,8 @@ import org.springframework.security.util.FieldUtils;
|
|||||||
* @author Luke Taylor
|
* @author Luke Taylor
|
||||||
*/
|
*/
|
||||||
public class GlobalMethodSecurityBeanDefinitionParserTests {
|
public class GlobalMethodSecurityBeanDefinitionParserTests {
|
||||||
|
private final UsernamePasswordAuthenticationToken bob = new UsernamePasswordAuthenticationToken("bob","bobspassword");
|
||||||
|
|
||||||
private AbstractXmlApplicationContext appContext;
|
private AbstractXmlApplicationContext appContext;
|
||||||
|
|
||||||
private BusinessService target;
|
private BusinessService target;
|
||||||
@@ -166,7 +172,7 @@ public class GlobalMethodSecurityBeanDefinitionParserTests {
|
|||||||
" 'execution(* org.springframework.security.access.annotation.BusinessService.*(..)) " +
|
" 'execution(* org.springframework.security.access.annotation.BusinessService.*(..)) " +
|
||||||
" and not execution(* org.springframework.security.access.annotation.BusinessService.someOther(String)))' " +
|
" and not execution(* org.springframework.security.access.annotation.BusinessService.someOther(String)))' " +
|
||||||
" access='ROLE_USER'/>" +
|
" access='ROLE_USER'/>" +
|
||||||
"</global-method-security>" + ConfigTestUtils.AUTH_PROVIDER_XML
|
"</global-method-security>" + AUTH_PROVIDER_XML
|
||||||
);
|
);
|
||||||
target = (BusinessService) appContext.getBean("target");
|
target = (BusinessService) appContext.getBean("target");
|
||||||
// String method should not be protected
|
// String method should not be protected
|
||||||
@@ -231,7 +237,7 @@ public class GlobalMethodSecurityBeanDefinitionParserTests {
|
|||||||
"<global-method-security pre-post-annotations='enabled'/>" +
|
"<global-method-security pre-post-annotations='enabled'/>" +
|
||||||
"<b:bean id='target' class='org.springframework.security.access.annotation.ExpressionProtectedBusinessServiceImpl'/>" +
|
"<b:bean id='target' class='org.springframework.security.access.annotation.ExpressionProtectedBusinessServiceImpl'/>" +
|
||||||
AUTH_PROVIDER_XML);
|
AUTH_PROVIDER_XML);
|
||||||
SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken("bob","bobspassword"));
|
SecurityContextHolder.getContext().setAuthentication(bob);
|
||||||
target = (BusinessService) appContext.getBean("target");
|
target = (BusinessService) appContext.getBean("target");
|
||||||
target.someAdminMethod();
|
target.someAdminMethod();
|
||||||
}
|
}
|
||||||
@@ -242,7 +248,7 @@ public class GlobalMethodSecurityBeanDefinitionParserTests {
|
|||||||
"<global-method-security pre-post-annotations='enabled'/>" +
|
"<global-method-security pre-post-annotations='enabled'/>" +
|
||||||
"<b:bean id='target' class='org.springframework.security.access.annotation.ExpressionProtectedBusinessServiceImpl'/>" +
|
"<b:bean id='target' class='org.springframework.security.access.annotation.ExpressionProtectedBusinessServiceImpl'/>" +
|
||||||
AUTH_PROVIDER_XML);
|
AUTH_PROVIDER_XML);
|
||||||
SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken("bob","bobspassword"));
|
SecurityContextHolder.getContext().setAuthentication(bob);
|
||||||
target = (BusinessService) appContext.getBean("target");
|
target = (BusinessService) appContext.getBean("target");
|
||||||
List<String> arg = new ArrayList<String>();
|
List<String> arg = new ArrayList<String>();
|
||||||
arg.add("joe");
|
arg.add("joe");
|
||||||
@@ -261,7 +267,7 @@ public class GlobalMethodSecurityBeanDefinitionParserTests {
|
|||||||
"<global-method-security pre-post-annotations='enabled'/>" +
|
"<global-method-security pre-post-annotations='enabled'/>" +
|
||||||
"<b:bean id='target' class='org.springframework.security.access.annotation.ExpressionProtectedBusinessServiceImpl'/>" +
|
"<b:bean id='target' class='org.springframework.security.access.annotation.ExpressionProtectedBusinessServiceImpl'/>" +
|
||||||
AUTH_PROVIDER_XML);
|
AUTH_PROVIDER_XML);
|
||||||
SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken("bob","bobspassword"));
|
SecurityContextHolder.getContext().setAuthentication(bob);
|
||||||
target = (BusinessService) appContext.getBean("target");
|
target = (BusinessService) appContext.getBean("target");
|
||||||
Object[] arg = new String[] {"joe", "bob", "sam"};
|
Object[] arg = new String[] {"joe", "bob", "sam"};
|
||||||
Object[] result = target.methodReturningAnArray(arg);
|
Object[] result = target.methodReturningAnArray(arg);
|
||||||
@@ -283,6 +289,33 @@ public class GlobalMethodSecurityBeanDefinitionParserTests {
|
|||||||
AUTH_PROVIDER_XML);
|
AUTH_PROVIDER_XML);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SEC-1450
|
||||||
|
@Test(expected=AuthenticationException.class)
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public void genericsAreMatchedByProtectPointcut() throws Exception {
|
||||||
|
setContext(
|
||||||
|
"<b:bean id='target' class='org.springframework.security.config.method.GlobalMethodSecurityBeanDefinitionParserTests$ConcreteFoo'/>" +
|
||||||
|
"<global-method-security>" +
|
||||||
|
" <protect-pointcut expression='execution(* org..*Foo.foo(..))' access='ROLE_USER'/>" +
|
||||||
|
"</global-method-security>" + AUTH_PROVIDER_XML
|
||||||
|
);
|
||||||
|
Foo foo = (Foo) appContext.getBean("target");
|
||||||
|
foo.foo(new SecurityConfig("A"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// SEC-1448
|
||||||
|
@Test
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public void genericsMethodArgumentNamesAreResolved() throws Exception {
|
||||||
|
setContext(
|
||||||
|
"<b:bean id='target' class='" + ConcreteFoo.class.getName() + "'/>" +
|
||||||
|
"<global-method-security pre-post-annotations='enabled'/>" + AUTH_PROVIDER_XML
|
||||||
|
);
|
||||||
|
SecurityContextHolder.getContext().setAuthentication(bob);
|
||||||
|
Foo foo = (Foo) appContext.getBean("target");
|
||||||
|
foo.foo(new SecurityConfig("A"));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void runAsManagerIsSetCorrectly() throws Exception {
|
public void runAsManagerIsSetCorrectly() throws Exception {
|
||||||
StaticApplicationContext parent = new StaticApplicationContext();
|
StaticApplicationContext parent = new StaticApplicationContext();
|
||||||
@@ -305,6 +338,15 @@ public class GlobalMethodSecurityBeanDefinitionParserTests {
|
|||||||
private void setContext(String context, ApplicationContext parent) {
|
private void setContext(String context, ApplicationContext parent) {
|
||||||
appContext = new InMemoryXmlApplicationContext(context, parent);
|
appContext = new InMemoryXmlApplicationContext(context, parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface Foo<T extends ConfigAttribute> {
|
||||||
|
void foo(T action);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ConcreteFoo implements Foo<SecurityConfig> {
|
||||||
|
@PreAuthorize("#action.attribute == 'A'")
|
||||||
|
public void foo(SecurityConfig action) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -22,11 +22,11 @@ public class InMemoryXmlApplicationContext extends AbstractXmlApplicationContext
|
|||||||
Resource inMemoryXml;
|
Resource inMemoryXml;
|
||||||
|
|
||||||
public InMemoryXmlApplicationContext(String xml) {
|
public InMemoryXmlApplicationContext(String xml) {
|
||||||
this(xml, "3.0", null);
|
this(xml, "3.0.3", null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public InMemoryXmlApplicationContext(String xml, ApplicationContext parent) {
|
public InMemoryXmlApplicationContext(String xml, ApplicationContext parent) {
|
||||||
this(xml, "3.0", parent);
|
this(xml, "3.0.3", parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
public InMemoryXmlApplicationContext(String xml, String secVersion, ApplicationContext parent) {
|
public InMemoryXmlApplicationContext(String xml, String secVersion, ApplicationContext parent) {
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ dependencies {
|
|||||||
"net.sf.ehcache:ehcache:$ehcacheVersion",
|
"net.sf.ehcache:ehcache:$ehcacheVersion",
|
||||||
"org.springframework:spring-aop:$springVersion",
|
"org.springframework:spring-aop:$springVersion",
|
||||||
"org.springframework:spring-beans:$springVersion",
|
"org.springframework:spring-beans:$springVersion",
|
||||||
"org.springframework:spring-core:$springVersion",
|
|
||||||
"org.springframework:spring-context:$springVersion",
|
"org.springframework:spring-context:$springVersion",
|
||||||
"org.springframework:spring-expression:$springVersion",
|
"org.springframework:spring-expression:$springVersion",
|
||||||
"org.springframework:spring-jdbc:$springVersion",
|
"org.springframework:spring-jdbc:$springVersion",
|
||||||
|
|||||||
+1
-5
@@ -3,7 +3,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.springframework.security</groupId>
|
<groupId>org.springframework.security</groupId>
|
||||||
<artifactId>spring-security-parent</artifactId>
|
<artifactId>spring-security-parent</artifactId>
|
||||||
<version>3.0.2.RELEASE</version>
|
<version>3.0.3.RELEASE</version>
|
||||||
</parent>
|
</parent>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
<artifactId>spring-security-core</artifactId>
|
<artifactId>spring-security-core</artifactId>
|
||||||
@@ -65,10 +65,6 @@
|
|||||||
<artifactId>ehcache</artifactId>
|
<artifactId>ehcache</artifactId>
|
||||||
<optional>true</optional>
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>commons-logging</groupId>
|
|
||||||
<artifactId>commons-logging</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>commons-collections</groupId>
|
<groupId>commons-collections</groupId>
|
||||||
<artifactId>commons-collections</artifactId>
|
<artifactId>commons-collections</artifactId>
|
||||||
|
|||||||
@@ -37,6 +37,9 @@ public class Jsr250Voter implements AccessDecisionVoter {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Votes according to JSR 250.
|
* Votes according to JSR 250.
|
||||||
|
* <p>
|
||||||
|
* If no JSR-250 attributes are found, it will abstain, otherwise it will grant or deny access
|
||||||
|
* based on the attributes that are found.
|
||||||
*
|
*
|
||||||
* @param authentication The authentication object.
|
* @param authentication The authentication object.
|
||||||
* @param object The access object.
|
* @param object The access object.
|
||||||
@@ -44,6 +47,8 @@ public class Jsr250Voter implements AccessDecisionVoter {
|
|||||||
* @return The vote.
|
* @return The vote.
|
||||||
*/
|
*/
|
||||||
public int vote(Authentication authentication, Object object, Collection<ConfigAttribute> definition) {
|
public int vote(Authentication authentication, Object object, Collection<ConfigAttribute> definition) {
|
||||||
|
boolean jsr250AttributeFound = false;
|
||||||
|
|
||||||
for (ConfigAttribute attribute : definition) {
|
for (ConfigAttribute attribute : definition) {
|
||||||
if (Jsr250SecurityConfig.PERMIT_ALL_ATTRIBUTE.equals(attribute)) {
|
if (Jsr250SecurityConfig.PERMIT_ALL_ATTRIBUTE.equals(attribute)) {
|
||||||
return ACCESS_GRANTED;
|
return ACCESS_GRANTED;
|
||||||
@@ -54,18 +59,17 @@ public class Jsr250Voter implements AccessDecisionVoter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (supports(attribute)) {
|
if (supports(attribute)) {
|
||||||
|
jsr250AttributeFound = true;
|
||||||
// Attempt to find a matching granted authority
|
// Attempt to find a matching granted authority
|
||||||
for (GrantedAuthority authority : authentication.getAuthorities()) {
|
for (GrantedAuthority authority : authentication.getAuthorities()) {
|
||||||
if (attribute.getAttribute().equals(authority.getAuthority())) {
|
if (attribute.getAttribute().equals(authority.getAuthority())) {
|
||||||
return ACCESS_GRANTED;
|
return ACCESS_GRANTED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// No match - deny access
|
|
||||||
return ACCESS_DENIED;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ACCESS_ABSTAIN;
|
return jsr250AttributeFound ? ACCESS_DENIED : ACCESS_ABSTAIN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+17
-2
@@ -3,11 +3,13 @@ package org.springframework.security.access.expression.method;
|
|||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
import org.aopalliance.intercept.MethodInvocation;
|
import org.aopalliance.intercept.MethodInvocation;
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.springframework.aop.support.AopUtils;
|
||||||
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
|
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
|
||||||
import org.springframework.core.ParameterNameDiscoverer;
|
import org.springframework.core.ParameterNameDiscoverer;
|
||||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
import org.springframework.util.ClassUtils;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal security-specific EvaluationContext implementation which lazily adds the
|
* Internal security-specific EvaluationContext implementation which lazily adds the
|
||||||
@@ -18,6 +20,8 @@ import org.springframework.util.ClassUtils;
|
|||||||
* @since 3.0
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
class MethodSecurityEvaluationContext extends StandardEvaluationContext {
|
class MethodSecurityEvaluationContext extends StandardEvaluationContext {
|
||||||
|
private static Log logger = LogFactory.getLog(MethodSecurityEvaluationContext.class);
|
||||||
|
|
||||||
private ParameterNameDiscoverer parameterNameDiscoverer;
|
private ParameterNameDiscoverer parameterNameDiscoverer;
|
||||||
private boolean argumentsAdded;
|
private boolean argumentsAdded;
|
||||||
private MethodInvocation mi;
|
private MethodInvocation mi;
|
||||||
@@ -58,10 +62,21 @@ class MethodSecurityEvaluationContext extends StandardEvaluationContext {
|
|||||||
|
|
||||||
private void addArgumentsAsVariables() {
|
private void addArgumentsAsVariables() {
|
||||||
Object[] args = mi.getArguments();
|
Object[] args = mi.getArguments();
|
||||||
|
|
||||||
|
if (args.length == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Object targetObject = mi.getThis();
|
Object targetObject = mi.getThis();
|
||||||
Method method = ClassUtils.getMostSpecificMethod(mi.getMethod(), targetObject.getClass());
|
Method method = AopUtils.getMostSpecificMethod(mi.getMethod(), targetObject.getClass());
|
||||||
String[] paramNames = parameterNameDiscoverer.getParameterNames(method);
|
String[] paramNames = parameterNameDiscoverer.getParameterNames(method);
|
||||||
|
|
||||||
|
if (paramNames == null) {
|
||||||
|
logger.warn("Unable to resolve method parameter names for method: " + method
|
||||||
|
+ ". Debug symbol information is required if you are using parameter names in expressions.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for(int i=0; i < args.length; i++) {
|
for(int i=0; i < args.length; i++) {
|
||||||
super.setVariable(paramNames[i], args[i]);
|
super.setVariable(paramNames[i], args[i]);
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -6,8 +6,9 @@ package org.springframework.security.access.intercept.aspectj;
|
|||||||
* AspectJ processing to continue.
|
* AspectJ processing to continue.
|
||||||
*
|
*
|
||||||
* @author Mike Wiesner
|
* @author Mike Wiesner
|
||||||
|
* @deprecated
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public interface AspectJAnnotationCallback {
|
public interface AspectJAnnotationCallback {
|
||||||
//~ Methods ========================================================================================================
|
//~ Methods ========================================================================================================
|
||||||
|
|
||||||
|
|||||||
+2
@@ -11,7 +11,9 @@ import org.aspectj.lang.JoinPoint;
|
|||||||
* AspectJ interceptor that supports @Aspect notation.
|
* AspectJ interceptor that supports @Aspect notation.
|
||||||
*
|
*
|
||||||
* @author Mike Wiesner
|
* @author Mike Wiesner
|
||||||
|
* @deprecated Use AspectJMethodSecurityInterceptor instead
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public class AspectJAnnotationSecurityInterceptor extends AbstractSecurityInterceptor {
|
public class AspectJAnnotationSecurityInterceptor extends AbstractSecurityInterceptor {
|
||||||
//~ Instance fields ================================================================================================
|
//~ Instance fields ================================================================================================
|
||||||
|
|
||||||
|
|||||||
+51
@@ -0,0 +1,51 @@
|
|||||||
|
package org.springframework.security.access.intercept.aspectj;
|
||||||
|
|
||||||
|
import org.aspectj.lang.JoinPoint;
|
||||||
|
import org.springframework.security.access.intercept.InterceptorStatusToken;
|
||||||
|
import org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AspectJ {@code JoinPoint} security interceptor which wraps the {@code JoinPoint} in a {@code MethodInvocation}
|
||||||
|
* adapter to make it compatible with security infrastructure classes which only support {@code MethodInvocation}s.
|
||||||
|
* <p>
|
||||||
|
* One of the {@code invoke} methods should be called from the {@code around()} advice in your aspect.
|
||||||
|
* Alternatively you can use one of the pre-defined aspects from the aspects module.
|
||||||
|
*
|
||||||
|
* @author Luke Taylor
|
||||||
|
* @since 3.0.3
|
||||||
|
*/
|
||||||
|
public final class AspectJMethodSecurityInterceptor extends MethodSecurityInterceptor {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method that is suitable for user with @Aspect notation.
|
||||||
|
*
|
||||||
|
* @param jp The AspectJ joint point being invoked which requires a security decision
|
||||||
|
* @return The returned value from the method invocation
|
||||||
|
* @throws Throwable if the invocation throws one
|
||||||
|
*/
|
||||||
|
public Object invoke(JoinPoint jp) throws Throwable {
|
||||||
|
return super.invoke(new MethodInvocationAdapter(jp));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method that is suitable for user with traditional AspectJ-code aspects.
|
||||||
|
*
|
||||||
|
* @param jp The AspectJ joint point being invoked which requires a security decision
|
||||||
|
* @param advisorProceed the advice-defined anonymous class that implements {@code AspectJCallback} containing
|
||||||
|
* a simple {@code return proceed();} statement
|
||||||
|
*
|
||||||
|
* @return The returned value from the method invocation
|
||||||
|
*/
|
||||||
|
public Object invoke(JoinPoint jp, AspectJCallback advisorProceed) {
|
||||||
|
Object result = null;
|
||||||
|
InterceptorStatusToken token = super.beforeInvocation(new MethodInvocationAdapter(jp));
|
||||||
|
|
||||||
|
try {
|
||||||
|
result = advisorProceed.proceedWithObject();
|
||||||
|
} finally {
|
||||||
|
result = super.afterInvocation(token, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
+2
@@ -37,7 +37,9 @@ import org.aspectj.lang.JoinPoint;
|
|||||||
* Refer to {@link AbstractSecurityInterceptor} for details on the workflow.
|
* Refer to {@link AbstractSecurityInterceptor} for details on the workflow.
|
||||||
*
|
*
|
||||||
* @author Ben Alex
|
* @author Ben Alex
|
||||||
|
* @deprecated Use AspectJMethodSecurityInterceptor instead
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public class AspectJSecurityInterceptor extends AbstractSecurityInterceptor {
|
public class AspectJSecurityInterceptor extends AbstractSecurityInterceptor {
|
||||||
//~ Instance fields ================================================================================================
|
//~ Instance fields ================================================================================================
|
||||||
|
|
||||||
|
|||||||
+61
@@ -0,0 +1,61 @@
|
|||||||
|
package org.springframework.security.access.intercept.aspectj;
|
||||||
|
|
||||||
|
import java.lang.reflect.AccessibleObject;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
|
import org.aopalliance.intercept.MethodInvocation;
|
||||||
|
import org.aspectj.lang.JoinPoint;
|
||||||
|
import org.aspectj.lang.ProceedingJoinPoint;
|
||||||
|
import org.aspectj.lang.reflect.CodeSignature;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.util.ClassUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decorates a JoinPoint to allow it to be used with method-security infrastructure
|
||||||
|
* classes which support {@code MethodInvocation} instances.
|
||||||
|
*
|
||||||
|
* @author Luke Taylor
|
||||||
|
* @since 3.0.3
|
||||||
|
*/
|
||||||
|
public final class MethodInvocationAdapter implements MethodInvocation {
|
||||||
|
private final ProceedingJoinPoint jp;
|
||||||
|
private final Method method;
|
||||||
|
private final Object target;
|
||||||
|
|
||||||
|
MethodInvocationAdapter(JoinPoint jp) {
|
||||||
|
this.jp = (ProceedingJoinPoint)jp;
|
||||||
|
if (jp.getTarget() != null) {
|
||||||
|
target = jp.getTarget();
|
||||||
|
} else {
|
||||||
|
// SEC-1295: target may be null if an ITD is in use
|
||||||
|
target = jp.getSignature().getDeclaringType();
|
||||||
|
}
|
||||||
|
String targetMethodName = jp.getStaticPart().getSignature().getName();
|
||||||
|
Class<?>[] types = ((CodeSignature) jp.getStaticPart().getSignature()).getParameterTypes();
|
||||||
|
Class<?> declaringType = ((CodeSignature) jp.getStaticPart().getSignature()).getDeclaringType();
|
||||||
|
|
||||||
|
method = ClassUtils.getMethodIfAvailable(declaringType, targetMethodName, types);
|
||||||
|
Assert.notNull(method, "Could not obtain target method from JoinPoint: '"+ jp + "'");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public Method getMethod() {
|
||||||
|
return method;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object[] getArguments() {
|
||||||
|
return jp.getArgs();
|
||||||
|
}
|
||||||
|
|
||||||
|
public AccessibleObject getStaticPart() {
|
||||||
|
return method;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getThis() {
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object proceed() throws Throwable {
|
||||||
|
return jp.proceed();
|
||||||
|
}
|
||||||
|
}
|
||||||
+2
-2
@@ -3,8 +3,8 @@ package org.springframework.security.access.method;
|
|||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import org.springframework.aop.support.AopUtils;
|
||||||
import org.springframework.security.access.ConfigAttribute;
|
import org.springframework.security.access.ConfigAttribute;
|
||||||
import org.springframework.util.ClassUtils;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract implementation of {@link MethodSecurityMetadataSource} that supports both Spring AOP and AspectJ and
|
* Abstract implementation of {@link MethodSecurityMetadataSource} that supports both Spring AOP and AspectJ and
|
||||||
@@ -29,7 +29,7 @@ public abstract class AbstractFallbackMethodSecurityMetadataSource extends Abstr
|
|||||||
public Collection<ConfigAttribute> getAttributes(Method method, Class<?> targetClass) {
|
public Collection<ConfigAttribute> getAttributes(Method method, Class<?> targetClass) {
|
||||||
// The method may be on an interface, but we need attributes from the target class.
|
// The method may be on an interface, but we need attributes from the target class.
|
||||||
// If the target class is null, the method will be unchanged.
|
// If the target class is null, the method will be unchanged.
|
||||||
Method specificMethod = ClassUtils.getMostSpecificMethod(method, targetClass);
|
Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);
|
||||||
// First try is the method in the target class.
|
// First try is the method in the target class.
|
||||||
Collection<ConfigAttribute> attr = findAttributes(specificMethod, targetClass);
|
Collection<ConfigAttribute> attr = findAttributes(specificMethod, targetClass);
|
||||||
if (attr != null) {
|
if (attr != null) {
|
||||||
|
|||||||
+7
-1
@@ -49,7 +49,13 @@ public abstract class AbstractMethodSecurityMetadataSource implements MethodSecu
|
|||||||
if (object instanceof MethodInvocation) {
|
if (object instanceof MethodInvocation) {
|
||||||
MethodInvocation mi = (MethodInvocation) object;
|
MethodInvocation mi = (MethodInvocation) object;
|
||||||
Object target = mi.getThis();
|
Object target = mi.getThis();
|
||||||
return getAttributes(mi.getMethod(), target == null ? null : target.getClass());
|
Class<?> targetClass = null;
|
||||||
|
|
||||||
|
if (target != null) {
|
||||||
|
targetClass = target instanceof Class<?> ? (Class<?>)target : target.getClass();
|
||||||
|
}
|
||||||
|
|
||||||
|
return getAttributes(mi.getMethod(), targetClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (object instanceof JoinPoint) {
|
if (object instanceof JoinPoint) {
|
||||||
|
|||||||
+55
-35
@@ -22,6 +22,7 @@ import java.util.Collections;
|
|||||||
|
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
import org.springframework.security.core.GrantedAuthority;
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
|
import org.springframework.security.core.CredentialsContainer;
|
||||||
import org.springframework.security.core.authority.AuthorityUtils;
|
import org.springframework.security.core.authority.AuthorityUtils;
|
||||||
import org.springframework.security.core.userdetails.UserDetails;
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
|
|
||||||
@@ -34,7 +35,7 @@ import org.springframework.security.core.userdetails.UserDetails;
|
|||||||
* @author Ben Alex
|
* @author Ben Alex
|
||||||
* @author Luke Taylor
|
* @author Luke Taylor
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractAuthenticationToken implements Authentication {
|
public abstract class AbstractAuthenticationToken implements Authentication, CredentialsContainer {
|
||||||
//~ Instance fields ================================================================================================
|
//~ Instance fields ================================================================================================
|
||||||
|
|
||||||
private Object details;
|
private Object details;
|
||||||
@@ -49,7 +50,7 @@ public abstract class AbstractAuthenticationToken implements Authentication {
|
|||||||
* @param authorities the collection of <tt>GrantedAuthority</tt>s for the
|
* @param authorities the collection of <tt>GrantedAuthority</tt>s for the
|
||||||
* principal represented by this authentication object.
|
* principal represented by this authentication object.
|
||||||
*/
|
*/
|
||||||
public AbstractAuthenticationToken(Collection<GrantedAuthority> authorities) {
|
public AbstractAuthenticationToken(Collection<? extends GrantedAuthority> authorities) {
|
||||||
if (authorities == null) {
|
if (authorities == null) {
|
||||||
this.authorities = AuthorityUtils.NO_AUTHORITIES;
|
this.authorities = AuthorityUtils.NO_AUTHORITIES;
|
||||||
return;
|
return;
|
||||||
@@ -67,6 +68,55 @@ public abstract class AbstractAuthenticationToken implements Authentication {
|
|||||||
|
|
||||||
//~ Methods ========================================================================================================
|
//~ Methods ========================================================================================================
|
||||||
|
|
||||||
|
public Collection<GrantedAuthority> getAuthorities() {
|
||||||
|
return authorities;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
if (this.getPrincipal() instanceof UserDetails) {
|
||||||
|
return ((UserDetails) this.getPrincipal()).getUsername();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getPrincipal() instanceof Principal) {
|
||||||
|
return ((Principal)getPrincipal()).getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
return (this.getPrincipal() == null) ? "" : this.getPrincipal().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isAuthenticated() {
|
||||||
|
return authenticated;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAuthenticated(boolean authenticated) {
|
||||||
|
this.authenticated = authenticated;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getDetails() {
|
||||||
|
return details;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDetails(Object details) {
|
||||||
|
this.details = details;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks the {@code credentials}, {@code principal} and {@code details} objects, invoking the
|
||||||
|
* {@code eraseCredentials} method on any which implement {@link CredentialsContainer}.
|
||||||
|
*/
|
||||||
|
public void eraseCredentials() {
|
||||||
|
eraseSecret(getCredentials());
|
||||||
|
eraseSecret(getPrincipal());
|
||||||
|
eraseSecret(details);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void eraseSecret(Object secret) {
|
||||||
|
if (secret instanceof CredentialsContainer) {
|
||||||
|
((CredentialsContainer)secret).eraseCredentials();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean equals(Object obj) {
|
public boolean equals(Object obj) {
|
||||||
if (!(obj instanceof AbstractAuthenticationToken)) {
|
if (!(obj instanceof AbstractAuthenticationToken)) {
|
||||||
return false;
|
return false;
|
||||||
@@ -109,26 +159,7 @@ public abstract class AbstractAuthenticationToken implements Authentication {
|
|||||||
return this.isAuthenticated() == test.isAuthenticated();
|
return this.isAuthenticated() == test.isAuthenticated();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection<GrantedAuthority> getAuthorities() {
|
@Override
|
||||||
return authorities;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object getDetails() {
|
|
||||||
return details;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getName() {
|
|
||||||
if (this.getPrincipal() instanceof UserDetails) {
|
|
||||||
return ((UserDetails) this.getPrincipal()).getUsername();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (getPrincipal() instanceof Principal) {
|
|
||||||
return ((Principal)getPrincipal()).getName();
|
|
||||||
}
|
|
||||||
|
|
||||||
return (this.getPrincipal() == null) ? "" : this.getPrincipal().toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
int code = 31;
|
int code = 31;
|
||||||
|
|
||||||
@@ -155,23 +186,12 @@ public abstract class AbstractAuthenticationToken implements Authentication {
|
|||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isAuthenticated() {
|
@Override
|
||||||
return authenticated;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAuthenticated(boolean authenticated) {
|
|
||||||
this.authenticated = authenticated;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDetails(Object details) {
|
|
||||||
this.details = details;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
sb.append(super.toString()).append(": ");
|
sb.append(super.toString()).append(": ");
|
||||||
sb.append("Principal: ").append(this.getPrincipal()).append("; ");
|
sb.append("Principal: ").append(this.getPrincipal()).append("; ");
|
||||||
sb.append("Password: [PROTECTED]; ");
|
sb.append("Credentials: [PROTECTED]; ");
|
||||||
sb.append("Authenticated: ").append(this.isAuthenticated()).append("; ");
|
sb.append("Authenticated: ").append(this.isAuthenticated()).append("; ");
|
||||||
sb.append("Details: ").append(this.getDetails()).append("; ");
|
sb.append("Details: ").append(this.getDetails()).append("; ");
|
||||||
|
|
||||||
|
|||||||
+32
-1
@@ -26,6 +26,7 @@ import org.springframework.context.MessageSourceAware;
|
|||||||
import org.springframework.context.support.MessageSourceAccessor;
|
import org.springframework.context.support.MessageSourceAccessor;
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
import org.springframework.security.core.AuthenticationException;
|
import org.springframework.security.core.AuthenticationException;
|
||||||
|
import org.springframework.security.core.CredentialsContainer;
|
||||||
import org.springframework.security.core.SpringSecurityMessageSource;
|
import org.springframework.security.core.SpringSecurityMessageSource;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
@@ -42,10 +43,17 @@ import org.springframework.util.Assert;
|
|||||||
* <code>AuthenticationException</code>, the last <code>AuthenticationException</code> received will be used.
|
* <code>AuthenticationException</code>, the last <code>AuthenticationException</code> received will be used.
|
||||||
* If no provider returns a non-null response, or indicates it can even process an <code>Authentication</code>,
|
* If no provider returns a non-null response, or indicates it can even process an <code>Authentication</code>,
|
||||||
* the <code>ProviderManager</code> will throw a <code>ProviderNotFoundException</code>.
|
* the <code>ProviderManager</code> will throw a <code>ProviderNotFoundException</code>.
|
||||||
|
* A parent {@code AuthenticationManager} can also be set, and this will also be tried if none of the configured
|
||||||
|
* providers can perform the authentication. This is intended to support namespace configuration options though and
|
||||||
|
* is not a feature that should normally be required.
|
||||||
* <p>
|
* <p>
|
||||||
* The exception to this process is when a provider throws an {@link AccountStatusException}, in which case no
|
* The exception to this process is when a provider throws an {@link AccountStatusException}, in which case no
|
||||||
* further providers in the list will be queried.
|
* further providers in the list will be queried.
|
||||||
*
|
*
|
||||||
|
* Post-authentication, the credentials will be cleared from the returned {@code Authentication} object, if it
|
||||||
|
* implements the {@link CredentialsContainer} interface. This behaviour can be controlled by modifying the
|
||||||
|
* {@link #setEraseCredentialsAfterAuthentication(boolean) eraseCredentialsAfterAuthentication} property.
|
||||||
|
*
|
||||||
* <h2>Event Publishing</h2>
|
* <h2>Event Publishing</h2>
|
||||||
* <p>
|
* <p>
|
||||||
* Authentication event publishing is delegated to the configured {@link AuthenticationEventPublisher} which defaults
|
* Authentication event publishing is delegated to the configured {@link AuthenticationEventPublisher} which defaults
|
||||||
@@ -57,9 +65,10 @@ import org.springframework.util.Assert;
|
|||||||
* the <tt><http></tt> configuration, so you will receive events from the web part of your application automatically.
|
* the <tt><http></tt> configuration, so you will receive events from the web part of your application automatically.
|
||||||
* <p>
|
* <p>
|
||||||
* Note that the implementation also publishes authentication failure events when it obtains an authentication result
|
* Note that the implementation also publishes authentication failure events when it obtains an authentication result
|
||||||
* (or an exception) from the "parent" <tt>AuthenticationManager</tt> if one has been set. So in this situation, the
|
* (or an exception) from the "parent" {@code AuthenticationManager} if one has been set. So in this situation, the
|
||||||
* parent should not generally be configured to publish events or there will be duplicates.
|
* parent should not generally be configured to publish events or there will be duplicates.
|
||||||
*
|
*
|
||||||
|
*
|
||||||
* @author Ben Alex
|
* @author Ben Alex
|
||||||
* @author Luke Taylor
|
* @author Luke Taylor
|
||||||
*
|
*
|
||||||
@@ -76,6 +85,7 @@ public class ProviderManager extends AbstractAuthenticationManager implements Me
|
|||||||
private List<AuthenticationProvider> providers = Collections.emptyList();
|
private List<AuthenticationProvider> providers = Collections.emptyList();
|
||||||
protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();
|
protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();
|
||||||
private AuthenticationManager parent;
|
private AuthenticationManager parent;
|
||||||
|
private boolean eraseCredentialsAfterAuthentication = false;
|
||||||
|
|
||||||
//~ Methods ========================================================================================================
|
//~ Methods ========================================================================================================
|
||||||
|
|
||||||
@@ -145,6 +155,11 @@ public class ProviderManager extends AbstractAuthenticationManager implements Me
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
|
if (eraseCredentialsAfterAuthentication && (result instanceof CredentialsContainer)) {
|
||||||
|
// Authentication is complete. Remove credentials and other secret data from authentication
|
||||||
|
((CredentialsContainer)result).eraseCredentials();
|
||||||
|
}
|
||||||
|
|
||||||
eventPublisher.publishAuthenticationSuccess(result);
|
eventPublisher.publishAuthenticationSuccess(result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -193,6 +208,22 @@ public class ProviderManager extends AbstractAuthenticationManager implements Me
|
|||||||
this.eventPublisher = eventPublisher;
|
this.eventPublisher = eventPublisher;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If set to, a resulting {@code Authentication} which implements the {@code CredentialsContainer} interface
|
||||||
|
* will have its {@link CredentialsContainer#eraseCredentials() eraseCredentials} method called before it is returned
|
||||||
|
* from the {@code authenticate()} method.
|
||||||
|
*
|
||||||
|
* @param eraseSecretData set to {@literal false} to retain the credentials data in memory.
|
||||||
|
* Defaults to {@literal true}.
|
||||||
|
*/
|
||||||
|
public void setEraseCredentialsAfterAuthentication(boolean eraseSecretData) {
|
||||||
|
this.eraseCredentialsAfterAuthentication = eraseSecretData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEraseCredentialsAfterAuthentication() {
|
||||||
|
return eraseCredentialsAfterAuthentication;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the {@link AuthenticationProvider} objects to be used for authentication.
|
* Sets the {@link AuthenticationProvider} objects to be used for authentication.
|
||||||
*
|
*
|
||||||
|
|||||||
+20
-19
@@ -15,7 +15,6 @@
|
|||||||
|
|
||||||
package org.springframework.security.authentication;
|
package org.springframework.security.authentication;
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
import org.springframework.security.core.GrantedAuthority;
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
@@ -28,8 +27,9 @@ import org.springframework.security.core.GrantedAuthority;
|
|||||||
* <code>GrantedAuthority</code>s that apply.
|
* <code>GrantedAuthority</code>s that apply.
|
||||||
*
|
*
|
||||||
* @author Ben Alex
|
* @author Ben Alex
|
||||||
|
* @author Luke Taylor
|
||||||
*/
|
*/
|
||||||
public class RememberMeAuthenticationToken extends AbstractAuthenticationToken implements Serializable {
|
public class RememberMeAuthenticationToken extends AbstractAuthenticationToken {
|
||||||
//~ Instance fields ================================================================================================
|
//~ Instance fields ================================================================================================
|
||||||
|
|
||||||
private final Object principal;
|
private final Object principal;
|
||||||
@@ -46,7 +46,7 @@ public class RememberMeAuthenticationToken extends AbstractAuthenticationToken i
|
|||||||
*
|
*
|
||||||
* @throws IllegalArgumentException if a <code>null</code> was passed
|
* @throws IllegalArgumentException if a <code>null</code> was passed
|
||||||
*/
|
*/
|
||||||
public RememberMeAuthenticationToken(String key, Object principal, Collection<GrantedAuthority> authorities) {
|
public RememberMeAuthenticationToken(String key, Object principal, Collection<? extends GrantedAuthority> authorities) {
|
||||||
super(authorities);
|
super(authorities);
|
||||||
|
|
||||||
if ((key == null) || ("".equals(key)) || (principal == null) || "".equals(principal)) {
|
if ((key == null) || ("".equals(key)) || (principal == null) || "".equals(principal)) {
|
||||||
@@ -60,6 +60,23 @@ public class RememberMeAuthenticationToken extends AbstractAuthenticationToken i
|
|||||||
|
|
||||||
//~ Methods ========================================================================================================
|
//~ Methods ========================================================================================================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Always returns an empty <code>String</code>
|
||||||
|
*
|
||||||
|
* @return an empty String
|
||||||
|
*/
|
||||||
|
public Object getCredentials() {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getKeyHash() {
|
||||||
|
return this.keyHash;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getPrincipal() {
|
||||||
|
return this.principal;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean equals(Object obj) {
|
public boolean equals(Object obj) {
|
||||||
if (!super.equals(obj)) {
|
if (!super.equals(obj)) {
|
||||||
return false;
|
return false;
|
||||||
@@ -78,20 +95,4 @@ public class RememberMeAuthenticationToken extends AbstractAuthenticationToken i
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Always returns an empty <code>String</code>
|
|
||||||
*
|
|
||||||
* @return an empty String
|
|
||||||
*/
|
|
||||||
public Object getCredentials() {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getKeyHash() {
|
|
||||||
return this.keyHash;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object getPrincipal() {
|
|
||||||
return this.principal;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-4
@@ -22,8 +22,8 @@ import org.springframework.security.core.GrantedAuthority;
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An {@link org.springframework.security.core.Authentication} implementation that is designed for simple presentation of a
|
* An {@link org.springframework.security.core.Authentication} implementation that is designed for simple presentation
|
||||||
* username and password.
|
* of a username and password.
|
||||||
* <p>
|
* <p>
|
||||||
* The <code>principal</code> and <code>credentials</code> should be set with an <code>Object</code> that provides
|
* The <code>principal</code> and <code>credentials</code> should be set with an <code>Object</code> that provides
|
||||||
* the respective property via its <code>Object.toString()</code> method. The simplest such <code>Object</code> to use
|
* the respective property via its <code>Object.toString()</code> method. The simplest such <code>Object</code> to use
|
||||||
@@ -34,8 +34,8 @@ import org.springframework.security.core.GrantedAuthority;
|
|||||||
public class UsernamePasswordAuthenticationToken extends AbstractAuthenticationToken {
|
public class UsernamePasswordAuthenticationToken extends AbstractAuthenticationToken {
|
||||||
//~ Instance fields ================================================================================================
|
//~ Instance fields ================================================================================================
|
||||||
|
|
||||||
private final Object credentials;
|
|
||||||
private final Object principal;
|
private final Object principal;
|
||||||
|
private Object credentials;
|
||||||
|
|
||||||
//~ Constructors ===================================================================================================
|
//~ Constructors ===================================================================================================
|
||||||
|
|
||||||
@@ -68,7 +68,7 @@ public class UsernamePasswordAuthenticationToken extends AbstractAuthenticationT
|
|||||||
* @param credentials
|
* @param credentials
|
||||||
* @param authorities
|
* @param authorities
|
||||||
*/
|
*/
|
||||||
public UsernamePasswordAuthenticationToken(Object principal, Object credentials, Collection<GrantedAuthority> authorities) {
|
public UsernamePasswordAuthenticationToken(Object principal, Object credentials, Collection<? extends GrantedAuthority> authorities) {
|
||||||
super(authorities);
|
super(authorities);
|
||||||
this.principal = principal;
|
this.principal = principal;
|
||||||
this.credentials = credentials;
|
this.credentials = credentials;
|
||||||
@@ -94,4 +94,10 @@ public class UsernamePasswordAuthenticationToken extends AbstractAuthenticationT
|
|||||||
|
|
||||||
super.setAuthenticated(false);
|
super.setAuthenticated(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void eraseCredentials() {
|
||||||
|
super.eraseCredentials();
|
||||||
|
credentials = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package org.springframework.security.core;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates that the implementing object contains sensitive data, which can be erased using the
|
||||||
|
* {@code eraseCredentials} method. Implementations are expected to invoke the method on any internal objects
|
||||||
|
* which may also implement this interface.
|
||||||
|
* <p>
|
||||||
|
* For internal framework use only. Users who are writing their own {@code AuthenticationProvider} implementations
|
||||||
|
* should create and return an appropriate {@code Authentication} object there, minus any sensitive data,
|
||||||
|
* rather than using this interface.
|
||||||
|
*
|
||||||
|
* @author Luke Taylor
|
||||||
|
* @since 3.0.3
|
||||||
|
*/
|
||||||
|
public interface CredentialsContainer {
|
||||||
|
void eraseCredentials();
|
||||||
|
}
|
||||||
@@ -25,6 +25,7 @@ import java.util.SortedSet;
|
|||||||
import java.util.TreeSet;
|
import java.util.TreeSet;
|
||||||
|
|
||||||
import org.springframework.security.core.GrantedAuthority;
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
|
import org.springframework.security.core.CredentialsContainer;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -33,12 +34,18 @@ import org.springframework.util.Assert;
|
|||||||
* Implemented with value object semantics (immutable after construction, like a <code>String</code>).
|
* Implemented with value object semantics (immutable after construction, like a <code>String</code>).
|
||||||
* Developers may use this class directly, subclass it, or write their own {@link UserDetails} implementation from
|
* Developers may use this class directly, subclass it, or write their own {@link UserDetails} implementation from
|
||||||
* scratch.
|
* scratch.
|
||||||
|
* <p>
|
||||||
|
* {@code equals} and {@code hashcode} implementations are based on the {@code username} property only, as the
|
||||||
|
* intention is that lookups of the same user principal object (in a user registry, for example) will match
|
||||||
|
* where the objects represent the same user, not just when all the properties (authorities, password for
|
||||||
|
* example) are the same.
|
||||||
*
|
*
|
||||||
* @author Ben Alex
|
* @author Ben Alex
|
||||||
|
* @author Luke Taylor
|
||||||
*/
|
*/
|
||||||
public class User implements UserDetails {
|
public class User implements UserDetails, CredentialsContainer {
|
||||||
//~ Instance fields ================================================================================================
|
//~ Instance fields ================================================================================================
|
||||||
private final String password;
|
private String password;
|
||||||
private final String username;
|
private final String username;
|
||||||
private final Set<GrantedAuthority> authorities;
|
private final Set<GrantedAuthority> authorities;
|
||||||
private final boolean accountNonExpired;
|
private final boolean accountNonExpired;
|
||||||
@@ -81,7 +88,7 @@ public class User implements UserDetails {
|
|||||||
* <code>GrantedAuthority</code> collection
|
* <code>GrantedAuthority</code> collection
|
||||||
*/
|
*/
|
||||||
public User(String username, String password, boolean enabled, boolean accountNonExpired,
|
public User(String username, String password, boolean enabled, boolean accountNonExpired,
|
||||||
boolean credentialsNonExpired, boolean accountNonLocked, Collection<GrantedAuthority> authorities) {
|
boolean credentialsNonExpired, boolean accountNonLocked, Collection<? extends GrantedAuthority> authorities) {
|
||||||
|
|
||||||
if (((username == null) || "".equals(username)) || (password == null)) {
|
if (((username == null) || "".equals(username)) || (password == null)) {
|
||||||
throw new IllegalArgumentException("Cannot pass null or empty values to constructor");
|
throw new IllegalArgumentException("Cannot pass null or empty values to constructor");
|
||||||
@@ -98,27 +105,6 @@ public class User implements UserDetails {
|
|||||||
|
|
||||||
//~ Methods ========================================================================================================
|
//~ Methods ========================================================================================================
|
||||||
|
|
||||||
public boolean equals(Object rhs) {
|
|
||||||
if (!(rhs instanceof User) || (rhs == null)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
User user = (User) rhs;
|
|
||||||
|
|
||||||
// We rely on constructor to guarantee any User has non-null
|
|
||||||
// authorities
|
|
||||||
if (!authorities.equals(user.authorities)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We rely on constructor to guarantee non-null username and password
|
|
||||||
return (this.getPassword().equals(user.getPassword()) && this.getUsername().equals(user.getUsername())
|
|
||||||
&& (this.isAccountNonExpired() == user.isAccountNonExpired())
|
|
||||||
&& (this.isAccountNonLocked() == user.isAccountNonLocked())
|
|
||||||
&& (this.isCredentialsNonExpired() == user.isCredentialsNonExpired())
|
|
||||||
&& (this.isEnabled() == user.isEnabled()));
|
|
||||||
}
|
|
||||||
|
|
||||||
public Collection<GrantedAuthority> getAuthorities() {
|
public Collection<GrantedAuthority> getAuthorities() {
|
||||||
return authorities;
|
return authorities;
|
||||||
}
|
}
|
||||||
@@ -131,38 +117,8 @@ public class User implements UserDetails {
|
|||||||
return username;
|
return username;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int hashCode() {
|
public boolean isEnabled() {
|
||||||
int code = 9792;
|
return enabled;
|
||||||
|
|
||||||
for (GrantedAuthority authority : getAuthorities()) {
|
|
||||||
code = code * (authority.hashCode() % 7);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.getPassword() != null) {
|
|
||||||
code = code * (this.getPassword().hashCode() % 7);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.getUsername() != null) {
|
|
||||||
code = code * (this.getUsername().hashCode() % 7);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.isAccountNonExpired()) {
|
|
||||||
code = code * -2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.isAccountNonLocked()) {
|
|
||||||
code = code * -3;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.isCredentialsNonExpired()) {
|
|
||||||
code = code * -5;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.isEnabled()) {
|
|
||||||
code = code * -7;
|
|
||||||
}
|
|
||||||
|
|
||||||
return code;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isAccountNonExpired() {
|
public boolean isAccountNonExpired() {
|
||||||
@@ -170,18 +126,18 @@ public class User implements UserDetails {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isAccountNonLocked() {
|
public boolean isAccountNonLocked() {
|
||||||
return this.accountNonLocked;
|
return accountNonLocked;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isCredentialsNonExpired() {
|
public boolean isCredentialsNonExpired() {
|
||||||
return credentialsNonExpired;
|
return credentialsNonExpired;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isEnabled() {
|
public void eraseCredentials() {
|
||||||
return enabled;
|
password = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static SortedSet<GrantedAuthority> sortAuthorities(Collection<GrantedAuthority> authorities) {
|
private static SortedSet<GrantedAuthority> sortAuthorities(Collection<? extends GrantedAuthority> authorities) {
|
||||||
Assert.notNull(authorities, "Cannot pass a null GrantedAuthority collection");
|
Assert.notNull(authorities, "Cannot pass a null GrantedAuthority collection");
|
||||||
// Ensure array iteration order is predictable (as per UserDetails.getAuthorities() contract and SEC-717)
|
// Ensure array iteration order is predictable (as per UserDetails.getAuthorities() contract and SEC-717)
|
||||||
SortedSet<GrantedAuthority> sortedAuthorities =
|
SortedSet<GrantedAuthority> sortedAuthorities =
|
||||||
@@ -211,7 +167,30 @@ public class User implements UserDetails {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns {@code true} if the supplied object is a {@code User} instance with the
|
||||||
|
* same {@code username} value.
|
||||||
|
* <p>
|
||||||
|
* In other words, the objects are equal if they have the same username, representing the
|
||||||
|
* same principal.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object rhs) {
|
||||||
|
if (rhs instanceof User) {
|
||||||
|
return username.equals(((User) rhs).username);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the hashcode of the {@code username}.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return username.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
sb.append(super.toString()).append(": ");
|
sb.append(super.toString()).append(": ");
|
||||||
|
|||||||
+5
-1
@@ -29,10 +29,14 @@ import java.util.Properties;
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves user details from an in-memory list created by the bean context.
|
* Retrieves user details from an in-memory list created in the application context.
|
||||||
|
* <p>
|
||||||
|
* Username lookups are case-insensitive.
|
||||||
*
|
*
|
||||||
* @author Ben Alex
|
* @author Ben Alex
|
||||||
|
* @author Luke Taylor
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
public class InMemoryDaoImpl implements UserDetailsService, InitializingBean {
|
public class InMemoryDaoImpl implements UserDetailsService, InitializingBean {
|
||||||
//~ Instance fields ================================================================================================
|
//~ Instance fields ================================================================================================
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,9 @@ import org.springframework.util.Assert;
|
|||||||
* Used by {@link InMemoryDaoImpl} to store a list of users and their corresponding granted authorities.
|
* Used by {@link InMemoryDaoImpl} to store a list of users and their corresponding granted authorities.
|
||||||
*
|
*
|
||||||
* @author Ben Alex
|
* @author Ben Alex
|
||||||
|
* @deprecated Use a plain map instead
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public class UserMap {
|
public class UserMap {
|
||||||
//~ Static fields/initializers =====================================================================================
|
//~ Static fields/initializers =====================================================================================
|
||||||
|
|
||||||
|
|||||||
+1
@@ -41,6 +41,7 @@ import java.util.Properties;
|
|||||||
*
|
*
|
||||||
* @author Ben Alex
|
* @author Ben Alex
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
public class UserMapEditor extends PropertyEditorSupport {
|
public class UserMapEditor extends PropertyEditorSupport {
|
||||||
//~ Methods ========================================================================================================
|
//~ Methods ========================================================================================================
|
||||||
|
|
||||||
|
|||||||
+44
@@ -0,0 +1,44 @@
|
|||||||
|
package org.springframework.security.access.annotation;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.springframework.security.access.AccessDecisionVoter;
|
||||||
|
import org.springframework.security.access.ConfigAttribute;
|
||||||
|
import org.springframework.security.access.SecurityConfig;
|
||||||
|
import org.springframework.security.authentication.TestingAuthenticationToken;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Luke Taylor
|
||||||
|
*/
|
||||||
|
public class Jsr250VoterTests {
|
||||||
|
|
||||||
|
// SEC-1443
|
||||||
|
@Test
|
||||||
|
public void supportsMultipleRolesCorrectly() throws Exception {
|
||||||
|
List<ConfigAttribute> attrs = new ArrayList<ConfigAttribute>();
|
||||||
|
Jsr250Voter voter = new Jsr250Voter();
|
||||||
|
|
||||||
|
attrs.add(new Jsr250SecurityConfig("A"));
|
||||||
|
attrs.add(new Jsr250SecurityConfig("B"));
|
||||||
|
attrs.add(new Jsr250SecurityConfig("C"));
|
||||||
|
|
||||||
|
assertEquals(AccessDecisionVoter.ACCESS_GRANTED,
|
||||||
|
voter.vote(new TestingAuthenticationToken("user", "pwd", "A"), new Object(), attrs));
|
||||||
|
assertEquals(AccessDecisionVoter.ACCESS_GRANTED,
|
||||||
|
voter.vote(new TestingAuthenticationToken("user", "pwd", "B"), new Object(), attrs));
|
||||||
|
assertEquals(AccessDecisionVoter.ACCESS_GRANTED,
|
||||||
|
voter.vote(new TestingAuthenticationToken("user", "pwd", "C"), new Object(), attrs));
|
||||||
|
|
||||||
|
assertEquals(AccessDecisionVoter.ACCESS_DENIED,
|
||||||
|
voter.vote(new TestingAuthenticationToken("user", "pwd", "NONE"), new Object(), attrs));
|
||||||
|
|
||||||
|
assertEquals(AccessDecisionVoter.ACCESS_ABSTAIN,
|
||||||
|
voter.vote(new TestingAuthenticationToken("user", "pwd", "A"), new Object(),
|
||||||
|
SecurityConfig.createList("A","B","C")));
|
||||||
|
}
|
||||||
|
}
|
||||||
+26
-34
@@ -15,26 +15,28 @@
|
|||||||
|
|
||||||
package org.springframework.security.access.intercept.aspectj;
|
package org.springframework.security.access.intercept.aspectj;
|
||||||
|
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
import static org.mockito.Matchers.any;
|
||||||
|
import static org.mockito.Mockito.*;
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.List;
|
import java.util.Collection;
|
||||||
|
|
||||||
import org.aspectj.lang.JoinPoint;
|
import org.aspectj.lang.JoinPoint;
|
||||||
import org.jmock.Expectations;
|
|
||||||
import org.jmock.Mockery;
|
|
||||||
import org.jmock.integration.junit4.JUnit4Mockery;
|
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.MockitoAnnotations;
|
||||||
import org.springframework.security.MockJoinPoint;
|
import org.springframework.security.MockJoinPoint;
|
||||||
import org.springframework.security.TargetObject;
|
import org.springframework.security.TargetObject;
|
||||||
import org.springframework.security.access.AccessDecisionManager;
|
import org.springframework.security.access.AccessDecisionManager;
|
||||||
import org.springframework.security.access.AccessDeniedException;
|
import org.springframework.security.access.AccessDeniedException;
|
||||||
import org.springframework.security.access.SecurityConfig;
|
import org.springframework.security.access.SecurityConfig;
|
||||||
import org.springframework.security.access.intercept.aspectj.AspectJCallback;
|
|
||||||
import org.springframework.security.access.intercept.aspectj.AspectJSecurityInterceptor;
|
|
||||||
import org.springframework.security.access.method.MethodSecurityMetadataSource;
|
import org.springframework.security.access.method.MethodSecurityMetadataSource;
|
||||||
import org.springframework.security.authentication.AuthenticationManager;
|
import org.springframework.security.authentication.AuthenticationManager;
|
||||||
import org.springframework.security.authentication.TestingAuthenticationToken;
|
import org.springframework.security.authentication.TestingAuthenticationToken;
|
||||||
|
import org.springframework.security.core.Authentication;
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
|
|
||||||
|
|
||||||
@@ -42,33 +44,33 @@ import org.springframework.security.core.context.SecurityContextHolder;
|
|||||||
* Tests {@link AspectJSecurityInterceptor}.
|
* Tests {@link AspectJSecurityInterceptor}.
|
||||||
*
|
*
|
||||||
* @author Ben Alex
|
* @author Ben Alex
|
||||||
|
* @author Luke Taylor
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
public class AspectJSecurityInterceptorTests {
|
public class AspectJSecurityInterceptorTests {
|
||||||
private Mockery jmock = new JUnit4Mockery();
|
|
||||||
private TestingAuthenticationToken token;
|
private TestingAuthenticationToken token;
|
||||||
private AspectJSecurityInterceptor interceptor;
|
private AspectJSecurityInterceptor interceptor;
|
||||||
private AccessDecisionManager adm;
|
private @Mock AccessDecisionManager adm;
|
||||||
private MethodSecurityMetadataSource mds;
|
private @Mock MethodSecurityMetadataSource mds;
|
||||||
private AuthenticationManager authman;
|
private @Mock AuthenticationManager authman;
|
||||||
private AspectJCallback aspectJCallback;
|
private @Mock AspectJCallback aspectJCallback;
|
||||||
private JoinPoint joinPoint;
|
private JoinPoint joinPoint;
|
||||||
|
|
||||||
//~ Methods ========================================================================================================
|
//~ Methods ========================================================================================================
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public final void setUp() throws Exception {
|
public final void setUp() throws Exception {
|
||||||
|
MockitoAnnotations.initMocks(this);
|
||||||
SecurityContextHolder.clearContext();
|
SecurityContextHolder.clearContext();
|
||||||
token = new TestingAuthenticationToken("Test", "Password");
|
token = new TestingAuthenticationToken("Test", "Password");
|
||||||
interceptor = new AspectJSecurityInterceptor();
|
interceptor = new AspectJSecurityInterceptor();
|
||||||
adm = jmock.mock(AccessDecisionManager.class);
|
|
||||||
authman = jmock.mock(AuthenticationManager.class);
|
|
||||||
mds = jmock.mock(MethodSecurityMetadataSource.class);
|
|
||||||
interceptor.setAccessDecisionManager(adm);
|
interceptor.setAccessDecisionManager(adm);
|
||||||
interceptor.setAuthenticationManager(authman);
|
interceptor.setAuthenticationManager(authman);
|
||||||
interceptor.setSecurityMetadataSource(mds);
|
interceptor.setSecurityMetadataSource(mds);
|
||||||
Method method = TargetObject.class.getMethod("countLength", new Class[] {String.class});
|
Method method = TargetObject.class.getMethod("countLength", new Class[] {String.class});
|
||||||
joinPoint = new MockJoinPoint(new TargetObject(), method);
|
joinPoint = new MockJoinPoint(new TargetObject(), method);
|
||||||
aspectJCallback = jmock.mock(AspectJCallback.class);
|
when(mds.getAttributes(any(JoinPoint.class))).thenReturn(SecurityConfig.createList("ROLE_USER"));
|
||||||
|
when(authman.authenticate(token)).thenReturn(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
@@ -77,33 +79,23 @@ public class AspectJSecurityInterceptorTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public void callbackIsInvokedWhenPermissionGranted() throws Exception {
|
public void callbackIsInvokedWhenPermissionGranted() throws Exception {
|
||||||
jmock.checking(new Expectations() {{
|
|
||||||
oneOf(mds).getAttributes(with(any(JoinPoint.class))); will (returnValue(SecurityConfig.createList("ROLE_USER")));
|
|
||||||
oneOf(authman).authenticate(token); will(returnValue(token));
|
|
||||||
oneOf(adm).decide(with(token), with(aNonNull(JoinPoint.class)), with(aNonNull(List.class)));
|
|
||||||
oneOf(aspectJCallback).proceedWithObject();
|
|
||||||
}});
|
|
||||||
|
|
||||||
SecurityContextHolder.getContext().setAuthentication(token);
|
SecurityContextHolder.getContext().setAuthentication(token);
|
||||||
interceptor.invoke(joinPoint, aspectJCallback);
|
interceptor.invoke(joinPoint, aspectJCallback);
|
||||||
jmock.assertIsSatisfied();
|
verify(aspectJCallback).proceedWithObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Test(expected=AccessDeniedException.class)
|
@Test
|
||||||
public void callbackIsNotInvokedWhenPermissionDenied() throws Exception {
|
public void callbackIsNotInvokedWhenPermissionDenied() throws Exception {
|
||||||
jmock.checking(new Expectations() {{
|
doThrow(new AccessDeniedException("denied")).when(adm).decide(any(Authentication.class), any(), any(Collection.class));
|
||||||
oneOf(mds).getAttributes(with(any(JoinPoint.class))); will (returnValue(SecurityConfig.createList("ROLE_USER")));
|
|
||||||
oneOf(authman).authenticate(token); will(returnValue(token));
|
|
||||||
oneOf(adm).decide(with(token), with(aNonNull(JoinPoint.class)), with(aNonNull(List.class)));
|
|
||||||
will(throwException(new AccessDeniedException("denied")));
|
|
||||||
never(aspectJCallback).proceedWithObject();
|
|
||||||
}});
|
|
||||||
|
|
||||||
SecurityContextHolder.getContext().setAuthentication(token);
|
SecurityContextHolder.getContext().setAuthentication(token);
|
||||||
interceptor.invoke(joinPoint, aspectJCallback);
|
try {
|
||||||
jmock.assertIsSatisfied();
|
interceptor.invoke(joinPoint, aspectJCallback);
|
||||||
|
fail("Expected AccessDeniedException");
|
||||||
|
} catch (AccessDeniedException expected) {
|
||||||
|
}
|
||||||
|
verify(aspectJCallback, never()).proceedWithObject();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+24
-4
@@ -28,7 +28,6 @@ import org.springframework.context.MessageSource;
|
|||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
import org.springframework.security.core.AuthenticationException;
|
import org.springframework.security.core.AuthenticationException;
|
||||||
import org.springframework.security.core.GrantedAuthority;
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
import org.springframework.security.core.authority.AuthorityUtils;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests {@link ProviderManager}.
|
* Tests {@link ProviderManager}.
|
||||||
@@ -40,14 +39,33 @@ public class ProviderManagerTests {
|
|||||||
|
|
||||||
@Test(expected=ProviderNotFoundException.class)
|
@Test(expected=ProviderNotFoundException.class)
|
||||||
public void authenticationFailsWithUnsupportedToken() throws Exception {
|
public void authenticationFailsWithUnsupportedToken() throws Exception {
|
||||||
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password",
|
Authentication token = new AbstractAuthenticationToken (null) {
|
||||||
AuthorityUtils.createAuthorityList("ROLE_ONE", "ROLE_TWO"));
|
public Object getCredentials() {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getPrincipal() {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
};
|
||||||
ProviderManager mgr = makeProviderManager();
|
ProviderManager mgr = makeProviderManager();
|
||||||
mgr.setMessageSource(mock(MessageSource.class));
|
mgr.setMessageSource(mock(MessageSource.class));
|
||||||
mgr.authenticate(token);
|
mgr.authenticate(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void credentialsAreNotClearedByDefault() throws Exception {
|
||||||
|
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password");
|
||||||
|
ProviderManager mgr = makeProviderManager();
|
||||||
|
Authentication result = mgr.authenticate(token);
|
||||||
|
assertNotNull(result.getCredentials());
|
||||||
|
|
||||||
|
mgr.setEraseCredentialsAfterAuthentication(true);
|
||||||
|
token = new UsernamePasswordAuthenticationToken("Test", "Password");
|
||||||
|
result = mgr.authenticate(token);
|
||||||
|
assertNull(result.getCredentials());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void authenticationSucceedsWithSupportedTokenAndReturnsExpectedObject() throws Exception {
|
public void authenticationSucceedsWithSupportedTokenAndReturnsExpectedObject() throws Exception {
|
||||||
final Authentication a = mock(Authentication.class);
|
final Authentication a = mock(Authentication.class);
|
||||||
@@ -126,6 +144,7 @@ public class ProviderManagerTests {
|
|||||||
request.setDetails(details);
|
request.setDetails(details);
|
||||||
|
|
||||||
Authentication result = authMgr.authenticate(request);
|
Authentication result = authMgr.authenticate(request);
|
||||||
|
assertNotNull(result.getCredentials());
|
||||||
assertSame(details, result.getDetails());
|
assertSame(details, result.getDetails());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -278,7 +297,8 @@ public class ProviderManagerTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean supports(Class<? extends Object> authentication) {
|
public boolean supports(Class<? extends Object> authentication) {
|
||||||
if (TestingAuthenticationToken.class.isAssignableFrom(authentication)) {
|
if (TestingAuthenticationToken.class.isAssignableFrom(authentication) ||
|
||||||
|
UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication)) {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -19,7 +19,9 @@ import static org.junit.Assert.*;
|
|||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.ObjectOutputStream;
|
import java.io.ObjectOutputStream;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.springframework.security.core.GrantedAuthority;
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
@@ -37,24 +39,24 @@ public class UserTests {
|
|||||||
//~ Methods ========================================================================================================
|
//~ Methods ========================================================================================================
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEquals() {
|
public void equalsReturnsTrueIfUsernamesAreTheSame() {
|
||||||
User user1 = new User("rod", "koala", true, true, true, true,ROLE_12);
|
User user1 = new User("rod", "koala", true, true, true, true, ROLE_12);
|
||||||
|
|
||||||
assertFalse(user1.equals(null));
|
assertFalse(user1.equals(null));
|
||||||
assertFalse(user1.equals("A STRING"));
|
assertFalse(user1.equals("A STRING"));
|
||||||
assertTrue(user1.equals(user1));
|
assertTrue(user1.equals(user1));
|
||||||
assertTrue(user1.equals(new User("rod", "koala", true, true, true, true,ROLE_12)));
|
assertTrue(user1.equals(new User("rod", "notthesame", true, true, true, true, ROLE_12)));
|
||||||
// Equal as the new User will internally sort the GrantedAuthorities in the correct order, before running equals()
|
}
|
||||||
assertTrue(user1.equals(new User("rod", "koala", true, true, true, true,
|
|
||||||
AuthorityUtils.createAuthorityList("ROLE_TWO","ROLE_ONE"))));
|
@Test
|
||||||
assertFalse(user1.equals(new User("DIFFERENT_USERNAME", "koala", true, true, true, true, ROLE_12)));
|
public void hashLookupOnlyDependsOnUsername() throws Exception {
|
||||||
assertFalse(user1.equals(new User("rod", "DIFFERENT_PASSWORD", true, true, true, true, ROLE_12)));
|
User user1 = new User("rod", "koala", true, true, true, true, ROLE_12);
|
||||||
assertFalse(user1.equals(new User("rod", "koala", false, true, true, true, ROLE_12)));
|
Set<UserDetails> users = new HashSet<UserDetails>();
|
||||||
assertFalse(user1.equals(new User("rod", "koala", true, false, true, true, ROLE_12)));
|
users.add(user1);
|
||||||
assertFalse(user1.equals(new User("rod", "koala", true, true, false, true, ROLE_12)));
|
|
||||||
assertFalse(user1.equals(new User("rod", "koala", true, true, true, false, ROLE_12)));
|
assertTrue(users.contains(new User("rod", "koala", true, true, true, true, ROLE_12)));
|
||||||
assertFalse(user1.equals(new User("rod", "koala", true, true, true, true,
|
assertTrue(users.contains(new User("rod", "anotherpass", false, false, false, false, AuthorityUtils.createAuthorityList("ROLE_X"))));
|
||||||
AuthorityUtils.createAuthorityList("ROLE_ONE"))));
|
assertFalse(users.contains(new User("bod", "koala", true, true, true, true, ROLE_12)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -116,9 +118,9 @@ public class UserTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testUserIsEnabled() throws Exception {
|
public void enabledFlagIsFalseForDisabledAccount() throws Exception {
|
||||||
UserDetails user = new User("rod", "koala", false, true, true, true, ROLE_12);
|
UserDetails user = new User("rod", "koala", false, true, true, true, ROLE_12);
|
||||||
assertTrue(!user.isEnabled());
|
assertFalse(user.isEnabled());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
+2
-14
@@ -30,26 +30,14 @@ import java.util.Properties;
|
|||||||
*
|
*
|
||||||
* @author Ben Alex
|
* @author Ben Alex
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
public class InMemoryDaoTests extends TestCase {
|
public class InMemoryDaoTests extends TestCase {
|
||||||
//~ Constructors ===================================================================================================
|
|
||||||
|
|
||||||
public InMemoryDaoTests() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
public InMemoryDaoTests(String arg0) {
|
|
||||||
super(arg0);
|
|
||||||
}
|
|
||||||
|
|
||||||
//~ Methods ========================================================================================================
|
//~ Methods ========================================================================================================
|
||||||
|
|
||||||
public static void main(String[] args) {
|
|
||||||
junit.textui.TestRunner.run(InMemoryDaoTests.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
private UserMap makeUserMap() {
|
private UserMap makeUserMap() {
|
||||||
UserMapEditor editor = new UserMapEditor();
|
UserMapEditor editor = new UserMapEditor();
|
||||||
editor.setAsText("rod=koala,ROLE_ONE,ROLE_TWO,enabled\r\nscott=wombat,ROLE_ONE,ROLE_TWO,enabled");
|
editor.setAsText("rod=koala,ROLE_ONE,ROLE_TWO,enabled\nScott=wombat,ROLE_ONE,ROLE_TWO,enabled");
|
||||||
|
|
||||||
return (UserMap) editor.getValue();
|
return (UserMap) editor.getValue();
|
||||||
}
|
}
|
||||||
|
|||||||
+1
@@ -27,6 +27,7 @@ import org.springframework.security.core.userdetails.memory.UserMapEditor;
|
|||||||
*
|
*
|
||||||
* @author Ben Alex
|
* @author Ben Alex
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
public class UserMapEditorTests extends TestCase {
|
public class UserMapEditorTests extends TestCase {
|
||||||
//~ Constructors ===================================================================================================
|
//~ Constructors ===================================================================================================
|
||||||
|
|
||||||
|
|||||||
+9
-6
@@ -15,13 +15,13 @@
|
|||||||
|
|
||||||
package org.springframework.security.core.userdetails.memory;
|
package org.springframework.security.core.userdetails.memory;
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
import org.springframework.security.core.authority.AuthorityUtils;
|
import org.springframework.security.core.authority.AuthorityUtils;
|
||||||
import org.springframework.security.core.userdetails.User;
|
import org.springframework.security.core.userdetails.User;
|
||||||
import org.springframework.security.core.userdetails.UserDetails;
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||||
import org.springframework.security.core.userdetails.memory.UserMap;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -29,9 +29,10 @@ import org.springframework.security.core.userdetails.memory.UserMap;
|
|||||||
*
|
*
|
||||||
* @author Ben Alex
|
* @author Ben Alex
|
||||||
*/
|
*/
|
||||||
public class UserMapTests extends TestCase {
|
@SuppressWarnings("deprecation")
|
||||||
|
public class UserMapTests {
|
||||||
|
|
||||||
//~ Methods ========================================================================================================
|
@Test
|
||||||
public void testAddAndRetrieveUser() {
|
public void testAddAndRetrieveUser() {
|
||||||
UserDetails rod = new User("rod", "koala", true, true, true, true,
|
UserDetails rod = new User("rod", "koala", true, true, true, true,
|
||||||
AuthorityUtils.createAuthorityList("ROLE_ONE","ROLE_TWO"));
|
AuthorityUtils.createAuthorityList("ROLE_ONE","ROLE_TWO"));
|
||||||
@@ -50,7 +51,8 @@ public class UserMapTests extends TestCase {
|
|||||||
assertEquals(peter, map.getUser("peter"));
|
assertEquals(peter, map.getUser("peter"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testNullUserCannotBeAdded() {
|
@Test
|
||||||
|
public void nullUserCannotBeAdded() {
|
||||||
UserMap map = new UserMap();
|
UserMap map = new UserMap();
|
||||||
assertEquals(0, map.getUserCount());
|
assertEquals(0, map.getUserCount());
|
||||||
|
|
||||||
@@ -62,7 +64,8 @@ public class UserMapTests extends TestCase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testUnknownUserIsNotRetrieved() {
|
@Test
|
||||||
|
public void unknownUserIsNotRetrieved() {
|
||||||
UserDetails rod = new User("rod", "koala", true, true, true, true,
|
UserDetails rod = new User("rod", "koala", true, true, true, true,
|
||||||
AuthorityUtils.createAuthorityList("ROLE_ONE","ROLE_TWO"));
|
AuthorityUtils.createAuthorityList("ROLE_ONE","ROLE_TWO"));
|
||||||
UserMap map = new UserMap();
|
UserMap map = new UserMap();
|
||||||
|
|||||||
+5
-3
@@ -1,10 +1,12 @@
|
|||||||
apply id: 'base'
|
apply plugin: 'base'
|
||||||
apply id: 'docbook'
|
apply plugin: 'docbook'
|
||||||
|
|
||||||
defaultTasks 'docbookHtmlSingle'
|
defaultTasks 'docbookHtmlSingle'
|
||||||
|
|
||||||
docbookSrcFileName = 'faq.xml'
|
[docbookHtml, docbookFoPdf, docbookHtmlSingle]*.sourceFileName = 'faq.xml'
|
||||||
|
|
||||||
docbookHtmlSingle.stylesheet = new File(projectDir, 'src/xsl/html-single-custom.xsl')
|
docbookHtmlSingle.stylesheet = new File(projectDir, 'src/xsl/html-single-custom.xsl')
|
||||||
|
docbookHtmlSingle.suffix = ''
|
||||||
|
|
||||||
docbookHtmlSingle.doLast {
|
docbookHtmlSingle.doLast {
|
||||||
resourcesDir = new File(projectDir, 'src/resources')
|
resourcesDir = new File(projectDir, 'src/resources')
|
||||||
|
|||||||
@@ -1,101 +1,101 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|
||||||
xmlns:xslthl="http://xslthl.sf.net"
|
xmlns:xslthl="http://xslthl.sf.net"
|
||||||
exclude-result-prefixes="xslthl"
|
exclude-result-prefixes="xslthl"
|
||||||
version='1.0'>
|
version='1.0'>
|
||||||
|
|
||||||
<xsl:import href="http://docbook.sourceforge.net/release/xsl/current/html/docbook.xsl"/>
|
<xsl:import href="http://docbook.sourceforge.net/release/xsl/current/html/docbook.xsl"/>
|
||||||
<xsl:import href="http://docbook.sourceforge.net/release/xsl/current/html/highlight.xsl"/>
|
<xsl:import href="http://docbook.sourceforge.net/release/xsl/current/html/highlight.xsl"/>
|
||||||
|
|
||||||
<!--xsl:param name="use.id.as.filename">'1'</xsl:param-->
|
|
||||||
|
|
||||||
<!-- Use code syntax highlighting -->
|
<!--xsl:param name="use.id.as.filename">'1'</xsl:param-->
|
||||||
<xsl:param name="highlight.source">1</xsl:param>
|
|
||||||
|
|
||||||
<!-- Extensions
|
<!-- Use code syntax highlighting -->
|
||||||
<xsl:param name="use.extensions">1</xsl:param>
|
<xsl:param name="highlight.source">1</xsl:param>
|
||||||
<xsl:param name="tablecolumns.extension">0</xsl:param>
|
|
||||||
<xsl:param name="callout.extensions">1</xsl:param>
|
<!-- Extensions
|
||||||
|
<xsl:param name="use.extensions">1</xsl:param>
|
||||||
|
<xsl:param name="tablecolumns.extension">0</xsl:param>
|
||||||
|
<xsl:param name="callout.extensions">1</xsl:param>
|
||||||
-->
|
-->
|
||||||
<!-- Activate Graphics
|
<!-- Activate Graphics
|
||||||
<xsl:param name="admon.graphics" select="1"/>
|
<xsl:param name="admon.graphics" select="1"/>
|
||||||
<xsl:param name="admon.graphics.path">images/</xsl:param>
|
<xsl:param name="admon.graphics.path">images/</xsl:param>
|
||||||
<xsl:param name="admon.graphics.extension">.gif</xsl:param>
|
<xsl:param name="admon.graphics.extension">.gif</xsl:param>
|
||||||
<xsl:param name="callout.graphics" select="1" />
|
<xsl:param name="callout.graphics" select="1" />
|
||||||
<xsl:param name="callout.defaultcolumn">120</xsl:param>
|
<xsl:param name="callout.defaultcolumn">120</xsl:param>
|
||||||
<xsl:param name="callout.graphics.path">images/callouts/</xsl:param>
|
<xsl:param name="callout.graphics.path">images/callouts/</xsl:param>
|
||||||
<xsl:param name="callout.graphics.extension">.gif</xsl:param>
|
<xsl:param name="callout.graphics.extension">.gif</xsl:param>
|
||||||
-->
|
-->
|
||||||
<xsl:param name="table.borders.with.css" select="1"/>
|
<xsl:param name="table.borders.with.css" select="1"/>
|
||||||
<xsl:param name="html.stylesheet">css/faq.css</xsl:param>
|
<xsl:param name="html.stylesheet">css/faq.css</xsl:param>
|
||||||
<xsl:param name="html.stylesheet.type">text/css</xsl:param>
|
<xsl:param name="html.stylesheet.type">text/css</xsl:param>
|
||||||
|
|
||||||
<!--xsl:param name="generate.toc">book toc,title</xsl:param-->
|
<!--xsl:param name="generate.toc">book toc,title</xsl:param-->
|
||||||
<!--
|
<!--
|
||||||
<xsl:param name="admonition.title.properties">text-align: left</xsl:param>
|
<xsl:param name="admonition.title.properties">text-align: left</xsl:param>
|
||||||
|
|
||||||
<xsl:param name="section.label.includes.component.label" select="1"/>
|
<xsl:param name="section.label.includes.component.label" select="1"/>
|
||||||
<xsl:param name="table.footnote.number.format" select="'1'"/>
|
<xsl:param name="table.footnote.number.format" select="'1'"/>
|
||||||
-->
|
-->
|
||||||
<xsl:template match='xslthl:keyword' mode="xslthl">
|
<xsl:template match='xslthl:keyword' mode="xslthl">
|
||||||
<span class="hl-keyword"><xsl:apply-templates mode="xslthl"/></span>
|
<span class="hl-keyword"><xsl:apply-templates mode="xslthl"/></span>
|
||||||
</xsl:template>
|
</xsl:template>
|
||||||
|
|
||||||
<xsl:template match='xslthl:comment' mode="xslthl">
|
<xsl:template match='xslthl:comment' mode="xslthl">
|
||||||
<span class="hl-comment"><xsl:apply-templates mode="xslthl"/></span>
|
<span class="hl-comment"><xsl:apply-templates mode="xslthl"/></span>
|
||||||
</xsl:template>
|
</xsl:template>
|
||||||
|
|
||||||
<xsl:template match='xslthl:oneline-comment' mode="xslthl">
|
<xsl:template match='xslthl:oneline-comment' mode="xslthl">
|
||||||
<span class="hl-comment"><xsl:apply-templates mode="xslthl"/></span>
|
<span class="hl-comment"><xsl:apply-templates mode="xslthl"/></span>
|
||||||
</xsl:template>
|
</xsl:template>
|
||||||
|
|
||||||
<xsl:template match='xslthl:multiline-comment' mode="xslthl">
|
<xsl:template match='xslthl:multiline-comment' mode="xslthl">
|
||||||
<span class="hl-multiline-comment"><xsl:apply-templates mode="xslthl"/></span>
|
<span class="hl-multiline-comment"><xsl:apply-templates mode="xslthl"/></span>
|
||||||
</xsl:template>
|
</xsl:template>
|
||||||
|
|
||||||
<xsl:template match='xslthl:tag' mode="xslthl">
|
<xsl:template match='xslthl:tag' mode="xslthl">
|
||||||
<span class="hl-tag"><xsl:apply-templates mode="xslthl"/></span>
|
<span class="hl-tag"><xsl:apply-templates mode="xslthl"/></span>
|
||||||
</xsl:template>
|
</xsl:template>
|
||||||
|
|
||||||
<xsl:template match='xslthl:attribute' mode="xslthl">
|
<xsl:template match='xslthl:attribute' mode="xslthl">
|
||||||
<span class="hl-attribute"><xsl:apply-templates mode="xslthl"/></span>
|
<span class="hl-attribute"><xsl:apply-templates mode="xslthl"/></span>
|
||||||
</xsl:template>
|
</xsl:template>
|
||||||
|
|
||||||
<xsl:template match='xslthl:value' mode="xslthl">
|
<xsl:template match='xslthl:value' mode="xslthl">
|
||||||
<span class="hl-value"><xsl:apply-templates mode="xslthl"/></span>
|
<span class="hl-value"><xsl:apply-templates mode="xslthl"/></span>
|
||||||
</xsl:template>
|
</xsl:template>
|
||||||
|
|
||||||
<xsl:template match='xslthl:string' mode="xslthl">
|
|
||||||
<span class="hl-string"><xsl:apply-templates mode="xslthl"/></span>
|
|
||||||
</xsl:template>
|
|
||||||
|
|
||||||
<!-- Google Analytics -->
|
<xsl:template match='xslthl:string' mode="xslthl">
|
||||||
<xsl:template name="user.head.content">
|
<span class="hl-string"><xsl:apply-templates mode="xslthl"/></span>
|
||||||
<xsl:comment>Begin Google Analytics code</xsl:comment>
|
</xsl:template>
|
||||||
<script type="text/javascript">
|
|
||||||
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
|
|
||||||
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
|
|
||||||
</script>
|
|
||||||
<script type="text/javascript">
|
|
||||||
var pageTracker = _gat._getTracker("UA-2728886-3");
|
|
||||||
pageTracker._setDomainName("none");
|
|
||||||
pageTracker._setAllowLinker(true);
|
|
||||||
pageTracker._trackPageview();
|
|
||||||
</script>
|
|
||||||
<xsl:comment>End Google Analytics code</xsl:comment>
|
|
||||||
</xsl:template>
|
|
||||||
|
|
||||||
<!-- Loopfuse -->
|
<!-- Google Analytics -->
|
||||||
<xsl:template name="user.footer.content">
|
<xsl:template name="user.head.content">
|
||||||
<xsl:comment>Begin LoopFuse code</xsl:comment>
|
<xsl:comment>Begin Google Analytics code</xsl:comment>
|
||||||
<script src="http://loopfuse.net/webrecorder/js/listen.js" type="text/javascript">
|
<script type="text/javascript">
|
||||||
</script>
|
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
|
||||||
<script type="text/javascript">
|
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
|
||||||
_lf_cid = "LF_48be82fa";
|
</script>
|
||||||
_lf_remora();
|
<script type="text/javascript">
|
||||||
</script>
|
var pageTracker = _gat._getTracker("UA-2728886-3");
|
||||||
<xsl:comment>End LoopFuse code</xsl:comment>
|
pageTracker._setDomainName("none");
|
||||||
</xsl:template>
|
pageTracker._setAllowLinker(true);
|
||||||
|
pageTracker._trackPageview();
|
||||||
|
</script>
|
||||||
|
<xsl:comment>End Google Analytics code</xsl:comment>
|
||||||
|
</xsl:template>
|
||||||
|
|
||||||
|
<!-- Loopfuse -->
|
||||||
|
<xsl:template name="user.footer.content">
|
||||||
|
<xsl:comment>Begin LoopFuse code</xsl:comment>
|
||||||
|
<script src="http://loopfuse.net/webrecorder/js/listen.js" type="text/javascript">
|
||||||
|
</script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
_lf_cid = "LF_48be82fa";
|
||||||
|
_lf_remora();
|
||||||
|
</script>
|
||||||
|
<xsl:comment>End LoopFuse code</xsl:comment>
|
||||||
|
</xsl:template>
|
||||||
|
|
||||||
</xsl:stylesheet>
|
</xsl:stylesheet>
|
||||||
@@ -1,13 +1,15 @@
|
|||||||
apply id: 'base'
|
apply plugin: 'base'
|
||||||
apply id: 'docbook'
|
apply plugin: 'docbook'
|
||||||
|
|
||||||
|
[docbookHtml, docbookFoPdf, docbookHtmlSingle]*.sourceFileName = 'springsecurity.xml';
|
||||||
|
|
||||||
docbookSrcFileName = 'springsecurity.xml'
|
|
||||||
docbookHtml.stylesheet = new File(projectDir, 'src/xsl/html-custom.xsl')
|
docbookHtml.stylesheet = new File(projectDir, 'src/xsl/html-custom.xsl')
|
||||||
|
docbookHtmlSingle.stylesheet = new File(projectDir, 'src/xsl/html-single-custom.xsl')
|
||||||
docbookFoPdf.stylesheet = new File(projectDir, 'src/xsl/pdf-custom.xsl')
|
docbookFoPdf.stylesheet = new File(projectDir, 'src/xsl/pdf-custom.xsl')
|
||||||
def imagesDir = new File(projectDir, 'src/docbook/images');
|
def imagesDir = new File(projectDir, 'src/docbook/images');
|
||||||
docbookFoPdf.admonGraphicsPath = "${imagesDir}/"
|
docbookFoPdf.admonGraphicsPath = "${imagesDir}/"
|
||||||
|
|
||||||
task doc (dependsOn: [docbookHtml, docbookFoPdf]) << {
|
task doc (dependsOn: [docbookHtml, docbookHtmlSingle, docbookFoPdf]) << {
|
||||||
resourcesDir = new File(projectDir, 'src/resources')
|
resourcesDir = new File(projectDir, 'src/resources')
|
||||||
ant {
|
ant {
|
||||||
docsDir = new File(buildDir, 'docs')
|
docsDir = new File(buildDir, 'docs')
|
||||||
|
|||||||
@@ -459,7 +459,12 @@
|
|||||||
instance for use in your own configuration. Its use is described in the
|
instance for use in your own configuration. Its use is described in the
|
||||||
<link xlink:href="#ns-auth-manager">namespace introduction</link>. All elements which create
|
<link xlink:href="#ns-auth-manager">namespace introduction</link>. All elements which create
|
||||||
<interfacename>AuthenticationProvider</interfacename> instances should be children of this
|
<interfacename>AuthenticationProvider</interfacename> instances should be children of this
|
||||||
element.</para>
|
element.</para>
|
||||||
|
<para>
|
||||||
|
The element also exposes an <literal>erase-credentials</literal> attribute which maps
|
||||||
|
to the <literal>eraseCredentialsAfterAuthentication</literal> property of
|
||||||
|
the <classname>ProviderManager</classname>. This is discussed in the
|
||||||
|
<link xlink:href="#core-services-erasing-credentials">Core Services</link> chapter.</para>
|
||||||
<section>
|
<section>
|
||||||
<title>The <literal><authentication-provider></literal> Element</title>
|
<title>The <literal><authentication-provider></literal> Element</title>
|
||||||
<para> Unless used with a <literal>ref</literal> attribute, this element is shorthand for configuring a
|
<para> Unless used with a <literal>ref</literal> attribute, this element is shorthand for configuring a
|
||||||
|
|||||||
@@ -292,7 +292,7 @@
|
|||||||
</programlisting>
|
</programlisting>
|
||||||
</para>
|
</para>
|
||||||
<para> The <classname>CasAuthenticationEntryPoint</classname> should be selected to drive
|
<para> The <classname>CasAuthenticationEntryPoint</classname> should be selected to drive
|
||||||
authentication using <link xlink:href="ns-entry-point-ref"
|
authentication using <link xlink:href="#ns-entry-point-ref"
|
||||||
><literal>entry-point-ref</literal></link>. </para>
|
><literal>entry-point-ref</literal></link>. </para>
|
||||||
<para>The <classname>CasAuthenticationFilter</classname> has very similar properties to the
|
<para>The <classname>CasAuthenticationFilter</classname> has very similar properties to the
|
||||||
<classname>UsernamePasswordAuthenticationFilter</classname> (used for form-based logins).
|
<classname>UsernamePasswordAuthenticationFilter</classname> (used for form-based logins).
|
||||||
|
|||||||
@@ -35,7 +35,7 @@
|
|||||||
<classname>SecurityContext</classname>. </para>
|
<classname>SecurityContext</classname>. </para>
|
||||||
<para> If you are using the namespace, an instance of
|
<para> If you are using the namespace, an instance of
|
||||||
<classname>ProviderManager</classname> is created and maintained internally, and
|
<classname>ProviderManager</classname> is created and maintained internally, and
|
||||||
you add providers to it by using the namespace authentication provider elements
|
you add providers to it by using the namespace authentication provider elements
|
||||||
(see <link xlink:href="#ns-auth-manager">the namespace chapter</link>). In this
|
(see <link xlink:href="#ns-auth-manager">the namespace chapter</link>). In this
|
||||||
case, you should not declare a <classname>ProviderManager</classname> bean in your
|
case, you should not declare a <classname>ProviderManager</classname> bean in your
|
||||||
application context. However, if you are not using the namespace then you would declare
|
application context. However, if you are not using the namespace then you would declare
|
||||||
@@ -97,7 +97,29 @@
|
|||||||
<interfacename>SaltSource</interfacename> enables the passwords to be populated
|
<interfacename>SaltSource</interfacename> enables the passwords to be populated
|
||||||
with a "salt", which enhances the security of the passwords in the authentication
|
with a "salt", which enhances the security of the passwords in the authentication
|
||||||
repository. These will be discussed in more detail <link
|
repository. These will be discussed in more detail <link
|
||||||
xlink:href="core-services-password-encodin">below</link>. </para>
|
xlink:href="#core-services-password-encoding">below</link>. </para>
|
||||||
|
</section>
|
||||||
|
<section xml:id="core-services-erasing-credentials">
|
||||||
|
<title>Erasing Credentials on Successful Authentication</title>
|
||||||
|
<para>
|
||||||
|
From Spring Security 3.0.3, you can configure the <classname>ProviderManager</classname>
|
||||||
|
will attempt to clear any sensitive credentials information from the
|
||||||
|
<interfacename>Authentication</interfacename> object which is returned by a successful
|
||||||
|
authentication request, to prevent information like passwords being retained longer
|
||||||
|
than necessary. This feature is controlled by the <literal>eraseCredentialsAfterAuthentication</literal>
|
||||||
|
property on <classname>ProviderManager</classname>. It is off by default.
|
||||||
|
See the Javadoc for more information.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
This may cause issues when you are using a cache of user objects, for example, to
|
||||||
|
improve performance in a stateless application. If the <interfacename>Authentication</interfacename>
|
||||||
|
contains a reference to an object in the cache (such as a <interfacename>UserDetails</interfacename>
|
||||||
|
instance) and this has its credentials removed, then it will no longer be possible to authenticate
|
||||||
|
against the cached value. You need to take this into account if you are using a cache. An obvious
|
||||||
|
solution is to make a copy of the object first, either in the cache implementation or in
|
||||||
|
the <interfacename>AuthenticationProvider</interfacename> which creates the returned
|
||||||
|
<interfacename>Authentication</interfacename> object.
|
||||||
|
</para>
|
||||||
</section>
|
</section>
|
||||||
</section>
|
</section>
|
||||||
<section>
|
<section>
|
||||||
|
|||||||
@@ -28,7 +28,8 @@
|
|||||||
that are available. We would recommend that you try out the <link
|
that are available. We would recommend that you try out the <link
|
||||||
xlink:href="http://www.springsource.com/products/sts">SpringSource Tool Suite</link> as it
|
xlink:href="http://www.springsource.com/products/sts">SpringSource Tool Suite</link> as it
|
||||||
has special features for working with standard Spring namespaces. </para>
|
has special features for working with standard Spring namespaces. </para>
|
||||||
<para> To start using the security namespace in your application context, all you need to do is
|
<para> To start using the security namespace in your application context, you first need to make
|
||||||
|
sure that the <literal>spring-security-config</literal> jar is on your classpath. Then all you need to do is
|
||||||
add the schema declaration to your application context file: <programlisting language="xml">
|
add the schema declaration to your application context file: <programlisting language="xml">
|
||||||
<![CDATA[
|
<![CDATA[
|
||||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||||
@@ -37,7 +38,7 @@
|
|||||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||||
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
|
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
|
||||||
http://www.springframework.org/schema/security
|
http://www.springframework.org/schema/security
|
||||||
http://www.springframework.org/schema/security/spring-security-3.0.xsd">
|
http://www.springframework.org/schema/security/spring-security-3.0.3.xsd">
|
||||||
...
|
...
|
||||||
</beans>
|
</beans>
|
||||||
]]></programlisting> In many of the examples you will see (and in the sample) applications, we
|
]]></programlisting> In many of the examples you will see (and in the sample) applications, we
|
||||||
@@ -52,7 +53,7 @@
|
|||||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||||
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
|
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
|
||||||
http://www.springframework.org/schema/security
|
http://www.springframework.org/schema/security
|
||||||
http://www.springframework.org/schema/security/spring-security-3.0.xsd">
|
http://www.springframework.org/schema/security/spring-security-3.0.3.xsd">
|
||||||
...
|
...
|
||||||
</beans:beans>
|
</beans:beans>
|
||||||
]]></programlisting> We'll assume this syntax is being used from now on in this chapter. </para>
|
]]></programlisting> We'll assume this syntax is being used from now on in this chapter. </para>
|
||||||
@@ -329,8 +330,10 @@
|
|||||||
]]>
|
]]>
|
||||||
</programlisting> where <literal>myAuthenticationProvider</literal> is the name of a
|
</programlisting> where <literal>myAuthenticationProvider</literal> is the name of a
|
||||||
bean in your application context which implements
|
bean in your application context which implements
|
||||||
<interfacename>AuthenticationProvider</interfacename>. See <xref linkend="ns-auth-manager"
|
<interfacename>AuthenticationProvider</interfacename>. You can use multiple
|
||||||
/> for more on information on how the Spring Security
|
<literal>authentication-provider</literal> elements, in which case they will be checked
|
||||||
|
in the order they are declared when attempting to authenticated a user. See <xref
|
||||||
|
linkend="ns-auth-manager"/> for more on information on how the Spring Security
|
||||||
<interfacename>AuthenticationManager</interfacename> is configured using the namespace. </para>
|
<interfacename>AuthenticationManager</interfacename> is configured using the namespace. </para>
|
||||||
<section xml:id="ns-password-encoder">
|
<section xml:id="ns-password-encoder">
|
||||||
<title>Adding a Password Encoder</title>
|
<title>Adding a Password Encoder</title>
|
||||||
@@ -516,7 +519,7 @@ List<OpenIDAttribute> attributes = token.getAttributes();</programlisting>The
|
|||||||
<classname>OpenIDAttribute</classname> contains the attribute type and the retrieved
|
<classname>OpenIDAttribute</classname> contains the attribute type and the retrieved
|
||||||
value (or values in the case of multi-valued attributes). We'll see more about how the
|
value (or values in the case of multi-valued attributes). We'll see more about how the
|
||||||
<classname>SecurityContextHolder</classname> class is used when we look at core Spring
|
<classname>SecurityContextHolder</classname> class is used when we look at core Spring
|
||||||
Security components in the <link xlink:href="core-components">technical overview</link>
|
Security components in the <link xlink:href="#core-components">technical overview</link>
|
||||||
chapter.</para>
|
chapter.</para>
|
||||||
</section>
|
</section>
|
||||||
</section>
|
</section>
|
||||||
@@ -622,7 +625,7 @@ List<OpenIDAttribute> attributes = token.getAttributes();</programlisting>The
|
|||||||
<para>From version 2.0 onwards Spring Security has improved support substantially for adding
|
<para>From version 2.0 onwards Spring Security has improved support substantially for adding
|
||||||
security to your service layer methods. It provides support for JSR-250 annotation security as
|
security to your service layer methods. It provides support for JSR-250 annotation security as
|
||||||
well as the framework's original <literal>@Secured</literal> annotation. From 3.0 you can also
|
well as the framework's original <literal>@Secured</literal> annotation. From 3.0 you can also
|
||||||
make use of new <link xlink:href="el-access">expression-based annotations</link>. You can
|
make use of new <link xlink:href="#el-access">expression-based annotations</link>. You can
|
||||||
apply security to a single bean, using the <literal>intercept-methods</literal> element to
|
apply security to a single bean, using the <literal>intercept-methods</literal> element to
|
||||||
decorate the bean declaration, or you can secure multiple beans across the entire service
|
decorate the bean declaration, or you can secure multiple beans across the entire service
|
||||||
layer using the AspectJ style pointcuts. </para>
|
layer using the AspectJ style pointcuts. </para>
|
||||||
|
|||||||
@@ -166,7 +166,7 @@ class="org.springframework.security.web.authentication.preauth.PreAuthenticatedA
|
|||||||
configuration (hence the user of the <literal>custom-filter</literal>,
|
configuration (hence the user of the <literal>custom-filter</literal>,
|
||||||
<literal>authentication-manager</literal> and
|
<literal>authentication-manager</literal> and
|
||||||
<literal>custom-authentication-provider</literal> elements (you can read more about them
|
<literal>custom-authentication-provider</literal> elements (you can read more about them
|
||||||
in the <link xlink:href="ns-config">namespace chapter</link>). You would leave these out
|
in the <link xlink:href="#ns-config">namespace chapter</link>). You would leave these out
|
||||||
of a traditional bean configuration. It's also assumed that you have added a
|
of a traditional bean configuration. It's also assumed that you have added a
|
||||||
<interfacename>UserDetailsService</interfacename> (called
|
<interfacename>UserDetailsService</interfacename> (called
|
||||||
<quote>userDetailsService</quote>) to your configuration to load the user's roles.
|
<quote>userDetailsService</quote>) to your configuration to load the user's roles.
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ Success! Your web filters appear to be properly configured!
|
|||||||
<title>CAS Sample</title>
|
<title>CAS Sample</title>
|
||||||
<para> The CAS sample requires that you run both a CAS server and CAS client. It isn't
|
<para> The CAS sample requires that you run both a CAS server and CAS client. It isn't
|
||||||
included in the distribution so you should check out the project code as described in
|
included in the distribution so you should check out the project code as described in
|
||||||
<link xlink:href="get-source">the introduction</link>. You'll find the relevant
|
<link xlink:href="#get-source">the introduction</link>. You'll find the relevant
|
||||||
files under the <filename>sample/cas</filename> directory. There's also a
|
files under the <filename>sample/cas</filename> directory. There's also a
|
||||||
<filename>Readme.txt</filename> file in there which explains how to run both the
|
<filename>Readme.txt</filename> file in there which explains how to run both the
|
||||||
server and the client directly from the source tree, complete with SSL support. You have
|
server and the client directly from the source tree, complete with SSL support. You have
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
</author>
|
</author>
|
||||||
</authorgroup>
|
</authorgroup>
|
||||||
<productname>Spring Security</productname>
|
<productname>Spring Security</productname>
|
||||||
<releaseinfo>3.0.1.RELEASE</releaseinfo>
|
<releaseinfo>3.0.3.RELEASE</releaseinfo>
|
||||||
</info>
|
</info>
|
||||||
<toc/>
|
<toc/>
|
||||||
<preface xml:id="preface">
|
<preface xml:id="preface">
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
Spring Security 3.0, it can be used in two ways <footnote>
|
Spring Security 3.0, it can be used in two ways <footnote>
|
||||||
<para>The legacy options from Spring Security 2.0 are also supported, but
|
<para>The legacy options from Spring Security 2.0 are also supported, but
|
||||||
discouraged.</para>
|
discouraged.</para>
|
||||||
</footnote>. The first approach uses a <link xlink:href="el-access-we">web-security
|
</footnote>. The first approach uses a <link xlink:href="#el-access-web">web-security
|
||||||
expression</link>, specified in the <literal>access</literal> attribute of the tag.
|
expression</link>, specified in the <literal>access</literal> attribute of the tag.
|
||||||
The expression evaluation will be delegated to the
|
The expression evaluation will be delegated to the
|
||||||
<interfacename>WebSecurityExpressionHandler</interfacename> defined in the
|
<interfacename>WebSecurityExpressionHandler</interfacename> defined in the
|
||||||
|
|||||||
@@ -521,7 +521,7 @@ Successfully authenticated. Security context contains: \
|
|||||||
and should be consumed by Spring Security's <classname>RoleVoter</classname>. This is only
|
and should be consumed by Spring Security's <classname>RoleVoter</classname>. This is only
|
||||||
relevant when a voter-based <interfacename>AccessDecisionManager</interfacename> is in
|
relevant when a voter-based <interfacename>AccessDecisionManager</interfacename> is in
|
||||||
use. We'll see how the <interfacename>AccessDecisionManager</interfacename> is implemented
|
use. We'll see how the <interfacename>AccessDecisionManager</interfacename> is implemented
|
||||||
in the <link xlink:href="authz-arch">authorization chapter</link>.</para>
|
in the <link xlink:href="#authz-arch">authorization chapter</link>.</para>
|
||||||
</section>
|
</section>
|
||||||
<section>
|
<section>
|
||||||
<title>RunAsManager</title>
|
<title>RunAsManager</title>
|
||||||
|
|||||||
@@ -0,0 +1,142 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
or more contributor license agreements. See the NOTICE file
|
||||||
|
distributed with this work for additional information
|
||||||
|
regarding copyright ownership. The ASF licenses this file
|
||||||
|
to you under the Apache License, Version 2.0 (the
|
||||||
|
"License"); you may not use this file except in compliance
|
||||||
|
with the License. You may obtain a copy of the License at
|
||||||
|
|
||||||
|
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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|
||||||
|
xmlns:xslthl="http://xslthl.sf.net"
|
||||||
|
exclude-result-prefixes="xslthl"
|
||||||
|
version='1.0'>
|
||||||
|
|
||||||
|
<xsl:import href="http://docbook.sourceforge.net/release/xsl/current/html/docbook.xsl"/>
|
||||||
|
<xsl:import href="http://docbook.sourceforge.net/release/xsl/current/html/highlight.xsl"/>
|
||||||
|
|
||||||
|
<!-- Only use scaling in FO -->
|
||||||
|
<xsl:param name="ignore.image.scaling">1</xsl:param>
|
||||||
|
|
||||||
|
<!-- Use code syntax highlighting -->
|
||||||
|
<xsl:param name="highlight.source">1</xsl:param>
|
||||||
|
|
||||||
|
<!-- Extensions -->
|
||||||
|
<xsl:param name="use.extensions">1</xsl:param>
|
||||||
|
<xsl:param name="tablecolumns.extension">0</xsl:param>
|
||||||
|
<xsl:param name="callout.extensions">1</xsl:param>
|
||||||
|
|
||||||
|
<!-- Activate Graphics -->
|
||||||
|
<xsl:param name="admon.graphics" select="1"/>
|
||||||
|
<xsl:param name="admon.graphics.path">images/</xsl:param>
|
||||||
|
<xsl:param name="admon.graphics.extension">.png</xsl:param>
|
||||||
|
<xsl:param name="callout.graphics" select="1" />
|
||||||
|
<xsl:param name="callout.defaultcolumn">120</xsl:param>
|
||||||
|
<xsl:param name="callout.graphics.path">images/callouts/</xsl:param>
|
||||||
|
<xsl:param name="callout.graphics.extension">.png</xsl:param>
|
||||||
|
|
||||||
|
<xsl:param name="table.borders.with.css" select="1"/>
|
||||||
|
<xsl:param name="html.stylesheet">css/manual.css</xsl:param>
|
||||||
|
<xsl:param name="html.stylesheet.type">text/css</xsl:param>
|
||||||
|
<xsl:param name="generate.toc">book toc,title</xsl:param>
|
||||||
|
|
||||||
|
<xsl:param name="admonition.title.properties">text-align: left</xsl:param>
|
||||||
|
|
||||||
|
<!-- Leave image paths as relative when navigating XInclude -->
|
||||||
|
<xsl:param name="keep.relative.image.uris" select="1"/>
|
||||||
|
|
||||||
|
<!-- Label Chapters and Sections (numbering) -->
|
||||||
|
<xsl:param name="chapter.autolabel" select="1"/>
|
||||||
|
<xsl:param name="section.autolabel" select="1"/>
|
||||||
|
<xsl:param name="section.autolabel.max.depth" select="2"/>
|
||||||
|
|
||||||
|
<xsl:param name="section.label.includes.component.label" select="1"/>
|
||||||
|
<xsl:param name="table.footnote.number.format" select="'1'"/>
|
||||||
|
|
||||||
|
<!-- Show only Sections up to level 2 in the TOCs -->
|
||||||
|
<xsl:param name="toc.section.depth">2</xsl:param>
|
||||||
|
|
||||||
|
<!-- Remove "Chapter" from the Chapter titles... -->
|
||||||
|
<xsl:param name="local.l10n.xml" select="document('')"/>
|
||||||
|
<l:i18n xmlns:l="http://docbook.sourceforge.net/xmlns/l10n/1.0">
|
||||||
|
<l:l10n language="en">
|
||||||
|
<l:context name="title-numbered">
|
||||||
|
<l:template name="chapter" text="%n. %t"/>
|
||||||
|
<l:template name="section" text="%n %t"/>
|
||||||
|
</l:context>
|
||||||
|
</l:l10n>
|
||||||
|
</l:i18n>
|
||||||
|
|
||||||
|
<xsl:template match='xslthl:keyword' mode="xslthl">
|
||||||
|
<span class="hl-keyword"><xsl:apply-templates mode="xslthl"/></span>
|
||||||
|
</xsl:template>
|
||||||
|
|
||||||
|
<xsl:template match='xslthl:comment' mode="xslthl">
|
||||||
|
<span class="hl-comment"><xsl:apply-templates mode="xslthl"/></span>
|
||||||
|
</xsl:template>
|
||||||
|
|
||||||
|
<xsl:template match='xslthl:oneline-comment' mode="xslthl">
|
||||||
|
<span class="hl-comment"><xsl:apply-templates mode="xslthl"/></span>
|
||||||
|
</xsl:template>
|
||||||
|
|
||||||
|
<xsl:template match='xslthl:multiline-comment' mode="xslthl">
|
||||||
|
<span class="hl-multiline-comment"><xsl:apply-templates mode="xslthl"/></span>
|
||||||
|
</xsl:template>
|
||||||
|
|
||||||
|
<xsl:template match='xslthl:tag' mode="xslthl">
|
||||||
|
<span class="hl-tag"><xsl:apply-templates mode="xslthl"/></span>
|
||||||
|
</xsl:template>
|
||||||
|
|
||||||
|
<xsl:template match='xslthl:attribute' mode="xslthl">
|
||||||
|
<span class="hl-attribute"><xsl:apply-templates mode="xslthl"/></span>
|
||||||
|
</xsl:template>
|
||||||
|
|
||||||
|
<xsl:template match='xslthl:value' mode="xslthl">
|
||||||
|
<span class="hl-value"><xsl:apply-templates mode="xslthl"/></span>
|
||||||
|
</xsl:template>
|
||||||
|
|
||||||
|
<xsl:template match='xslthl:string' mode="xslthl">
|
||||||
|
<span class="hl-string"><xsl:apply-templates mode="xslthl"/></span>
|
||||||
|
</xsl:template>
|
||||||
|
|
||||||
|
<!-- Google Analytics -->
|
||||||
|
<xsl:template name="user.head.content">
|
||||||
|
<xsl:comment>Begin Google Analytics code</xsl:comment>
|
||||||
|
<script type="text/javascript">
|
||||||
|
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
|
||||||
|
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
|
||||||
|
</script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
var pageTracker = _gat._getTracker("UA-2728886-3");
|
||||||
|
pageTracker._setDomainName("none");
|
||||||
|
pageTracker._setAllowLinker(true);
|
||||||
|
pageTracker._trackPageview();
|
||||||
|
</script>
|
||||||
|
<xsl:comment>End Google Analytics code</xsl:comment>
|
||||||
|
</xsl:template>
|
||||||
|
|
||||||
|
<!-- Loopfuse -->
|
||||||
|
<xsl:template name="user.footer.content">
|
||||||
|
<xsl:comment>Begin LoopFuse code</xsl:comment>
|
||||||
|
<script src="http://loopfuse.net/webrecorder/js/listen.js" type="text/javascript">
|
||||||
|
</script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
_lf_cid = "LF_48be82fa";
|
||||||
|
_lf_remora();
|
||||||
|
</script>
|
||||||
|
<xsl:comment>End LoopFuse code</xsl:comment>
|
||||||
|
</xsl:template>
|
||||||
|
|
||||||
|
</xsl:stylesheet>
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
apply plugin: 'java'
|
||||||
|
|
||||||
|
configurations {
|
||||||
|
ajtools
|
||||||
|
aspectpath
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
ajtools "org.aspectj:aspectjtools:$aspectjVersion"
|
||||||
|
compile "org.aspectj:aspectjrt:$aspectjVersion"
|
||||||
|
}
|
||||||
|
|
||||||
|
task compileJava(overwrite: true, description: 'Compiles AspectJ Source', type: Ajc) {
|
||||||
|
dependsOn processResources
|
||||||
|
sourceSet = sourceSets.main
|
||||||
|
aspectPath = configurations.aspectpath
|
||||||
|
}
|
||||||
|
|
||||||
|
task compileTestJava(overwrite: true, description: 'Compiles AspectJ Test Source', type: Ajc) {
|
||||||
|
dependsOn processTestResources, compileJava, jar
|
||||||
|
sourceSet = sourceSets.test
|
||||||
|
aspectPath = files(configurations.aspectpath, jar.archivePath)
|
||||||
|
}
|
||||||
|
|
||||||
|
class Ajc extends DefaultTask {
|
||||||
|
@Input
|
||||||
|
SourceSet sourceSet
|
||||||
|
|
||||||
|
@Input
|
||||||
|
FileCollection aspectPath
|
||||||
|
|
||||||
|
@TaskAction
|
||||||
|
def compile() {
|
||||||
|
println "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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
apply plugin: 'java'
|
||||||
|
|
||||||
|
configurations {
|
||||||
|
bundlor
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
bundlor 'com.springsource.bundlor:com.springsource.bundlor.ant:1.0.0.RELEASE',
|
||||||
|
'com.springsource.bundlor:com.springsource.bundlor:1.0.0.RELEASE',
|
||||||
|
'com.springsource.bundlor:com.springsource.bundlor.blint:1.0.0.RELEASE'
|
||||||
|
}
|
||||||
|
|
||||||
|
task bundlor(dependsOn: compileJava) {
|
||||||
|
onlyIf {
|
||||||
|
dependsOnTaskDidWork()
|
||||||
|
}
|
||||||
|
doFirst {
|
||||||
|
ant.taskdef(resource: 'com/springsource/bundlor/ant/antlib.xml', classpath: configurations.bundlor.asPath)
|
||||||
|
File template = new File(projectDir, 'template.mf')
|
||||||
|
mkdir("$buildDir/bundlor")
|
||||||
|
if (template.exists()) {
|
||||||
|
ant.bundlor(inputPath: sourceSets.main.classesDir, outputPath: "$buildDir/bundlor", manifestTemplatePath: template) {
|
||||||
|
property(name: 'version', value: "$version")
|
||||||
|
property(name: 'spring.version', value: "$springVersion")
|
||||||
|
}
|
||||||
|
jar.manifest.from("$buildDir/bundlor/META-INF/MANIFEST.MF")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
jar.dependsOn bundlor
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
apply plugin: 'java'
|
||||||
|
apply plugin: 'eclipse'
|
||||||
|
|
||||||
|
springVersion = '3.0.3.RELEASE'
|
||||||
|
springLdapVersion = '1.3.0.RELEASE'
|
||||||
|
ehcacheVersion = '1.6.2'
|
||||||
|
aspectjVersion = '1.6.8'
|
||||||
|
apacheDsVersion = '1.5.5'
|
||||||
|
jstlVersion = '1.1.2'
|
||||||
|
jettyVersion = '6.1.22'
|
||||||
|
hsqlVersion = '1.8.0.10'
|
||||||
|
|
||||||
|
configurations {
|
||||||
|
provided
|
||||||
|
compile.extendsFrom provided
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
compile 'commons-logging:commons-logging:1.1.1'
|
||||||
|
|
||||||
|
compile ("org.springframework:spring-core:$springVersion") {
|
||||||
|
exclude(group: 'commons-logging', module: 'commons-logging')
|
||||||
|
}
|
||||||
|
|
||||||
|
testCompile 'junit:junit:4.7',
|
||||||
|
'org.mockito:mockito-core:1.8.3',
|
||||||
|
'org.jmock:jmock:2.5.1',
|
||||||
|
'org.jmock:jmock-junit4:2.5.1',
|
||||||
|
'org.hamcrest:hamcrest-core:1.1',
|
||||||
|
'org.hamcrest:hamcrest-library:1.1',
|
||||||
|
"org.springframework:spring-test:$springVersion"
|
||||||
|
}
|
||||||
|
|
||||||
|
test {
|
||||||
|
onlyIf {
|
||||||
|
!project.hasProperty('skipTests')
|
||||||
|
}
|
||||||
|
jvmArgs = ['-ea', '-Xms128m', '-Xmx500m', '-XX:MaxPermSize=128m']
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
apply plugin: 'maven'
|
||||||
|
|
||||||
|
// Create a source jar for uploading
|
||||||
|
task sourceJar(type: Jar) {
|
||||||
|
classifier = 'sources'
|
||||||
|
from sourceSets.main.java
|
||||||
|
}
|
||||||
|
|
||||||
|
configurations {
|
||||||
|
deployerJars
|
||||||
|
}
|
||||||
|
|
||||||
|
artifacts {
|
||||||
|
archives sourceJar
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
deployerJars "org.springframework.build.aws:org.springframework.build.aws.maven:3.0.0.RELEASE"
|
||||||
|
}
|
||||||
|
|
||||||
|
gradle.taskGraph.whenReady {graph ->
|
||||||
|
if (graph.hasTask(uploadArchives)) {
|
||||||
|
// check properties defined and fail early
|
||||||
|
s3AccessKey
|
||||||
|
s3SecretAccessKey
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def deployer = null
|
||||||
|
|
||||||
|
uploadArchives {
|
||||||
|
deployer = repositories.mavenDeployer {
|
||||||
|
configuration = configurations.deployerJars
|
||||||
|
}
|
||||||
|
doFirst {
|
||||||
|
if (releaseBuild) {
|
||||||
|
// "mavenSyncRepoDir" should be set in properties
|
||||||
|
repository(url: mavenSyncRepoDir)
|
||||||
|
} else {
|
||||||
|
s3credentials = [userName: s3AccessKey, passphrase: s3SecretAccessKey]
|
||||||
|
repository(url: "s3://maven.springframework.org/milestone") {
|
||||||
|
authentication(s3credentials)
|
||||||
|
}
|
||||||
|
snapshotRepository(url: "s3://maven.springframework.org/snapshot") {
|
||||||
|
authentication(s3credentials)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pom Customization
|
||||||
|
|
||||||
|
installer = install.repositories.mavenInstaller
|
||||||
|
|
||||||
|
def optionalDeps = ['commons-logging', 'ehcache', 'log4j', 'apacheds-core', 'jsp-api', 'jsr250-api', 'ldapsdk']
|
||||||
|
|
||||||
|
[installer, deployer]*.pom.collect { pom ->
|
||||||
|
pom.scopeMappings.addMapping(10, configurations.provided, 'provided')
|
||||||
|
}
|
||||||
|
|
||||||
|
[installer, deployer]*.pom*.whenConfigured { pom ->
|
||||||
|
pom.dependencies.findAll { dep ->
|
||||||
|
optionalDeps.contains(dep.artifactId) ||
|
||||||
|
dep.groupId.startsWith('org.apache.directory') ||
|
||||||
|
dep.groupId.startsWith('org.slf4j')
|
||||||
|
}*.optional = true
|
||||||
|
|
||||||
|
if (pom.artifactId == 'spring-security-config') {
|
||||||
|
pom.dependencies.find { dep -> dep.artifactId == 'spring-security-web'}.optional = true
|
||||||
|
pom.dependencies.find { dep -> dep.artifactId == 'spring-web'}.optional = true
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.springframework.security</groupId>
|
<groupId>org.springframework.security</groupId>
|
||||||
<artifactId>spring-security-itest</artifactId>
|
<artifactId>spring-security-itest</artifactId>
|
||||||
<version>3.0.2.RELEASE</version>
|
<version>3.0.3.RELEASE</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>spring-security-itest-context</artifactId>
|
<artifactId>spring-security-itest-context</artifactId>
|
||||||
<name>Spring Security - Miscellaneous Application Context Integration Tests</name>
|
<name>Spring Security - Miscellaneous Application Context Integration Tests</name>
|
||||||
|
|||||||
+1
-1
@@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.springframework.security</groupId>
|
<groupId>org.springframework.security</groupId>
|
||||||
<artifactId>spring-security-itest</artifactId>
|
<artifactId>spring-security-itest</artifactId>
|
||||||
<version>3.0.2.RELEASE</version>
|
<version>3.0.3.RELEASE</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>spring-security-itest-misc</artifactId>
|
<artifactId>spring-security-itest-misc</artifactId>
|
||||||
<name>Spring Security - Miscellaneous Integration Tests</name>
|
<name>Spring Security - Miscellaneous Integration Tests</name>
|
||||||
|
|||||||
+5
-5
@@ -3,12 +3,12 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.springframework.security</groupId>
|
<groupId>org.springframework.security</groupId>
|
||||||
<artifactId>spring-security-parent</artifactId>
|
<artifactId>spring-security-parent</artifactId>
|
||||||
<version>3.0.2.RELEASE</version>
|
<version>3.0.3.RELEASE</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>spring-security-itest</artifactId>
|
<artifactId>spring-security-itest</artifactId>
|
||||||
<name>Spring Security - Integration Tests</name>
|
<name>Spring Security - Integration Tests</name>
|
||||||
<packaging>pom</packaging>
|
<packaging>pom</packaging>
|
||||||
<version>3.0.2.RELEASE</version>
|
<version>3.0.3.RELEASE</version>
|
||||||
<modules>
|
<modules>
|
||||||
<module>web</module>
|
<module>web</module>
|
||||||
<!-- module>webflow</module-->
|
<!-- module>webflow</module-->
|
||||||
@@ -66,19 +66,19 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.slf4j</groupId>
|
<groupId>org.slf4j</groupId>
|
||||||
<artifactId>slf4j-api</artifactId>
|
<artifactId>slf4j-api</artifactId>
|
||||||
<version>1.5.10</version>
|
<version>1.6.0</version>
|
||||||
<scope>runtime</scope>
|
<scope>runtime</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.slf4j</groupId>
|
<groupId>org.slf4j</groupId>
|
||||||
<artifactId>slf4j-log4j12</artifactId>
|
<artifactId>slf4j-log4j12</artifactId>
|
||||||
<version>1.5.10</version>
|
<version>1.6.0</version>
|
||||||
<scope>runtime</scope>
|
<scope>runtime</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.slf4j</groupId>
|
<groupId>org.slf4j</groupId>
|
||||||
<artifactId>jcl-over-slf4j</artifactId>
|
<artifactId>jcl-over-slf4j</artifactId>
|
||||||
<version>1.5.10</version>
|
<version>1.6.0</version>
|
||||||
<scope>runtime</scope>
|
<scope>runtime</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile "org.springframework:spring-context:$springVersion",
|
compile "org.springframework:spring-context:$springVersion",
|
||||||
"org.springframework:spring-web:$springVersion",
|
"org.springframework:spring-web:$springVersion"
|
||||||
'javax.servlet:servlet-api:2.5'
|
|
||||||
|
provided 'javax.servlet:servlet-api:2.5'
|
||||||
|
|
||||||
testCompile project(':spring-security-core'),
|
testCompile project(':spring-security-core'),
|
||||||
project(':spring-security-web'),
|
project(':spring-security-web'),
|
||||||
"org.springframework:spring-core:$springVersion",
|
project(':spring-security-taglibs'),
|
||||||
"org.springframework:spring-beans:$springVersion",
|
"org.springframework:spring-beans:$springVersion",
|
||||||
"org.springframework:spring-webmvc:$springVersion",
|
"org.springframework:spring-webmvc:$springVersion",
|
||||||
"org.mortbay.jetty:jetty:$jettyVersion",
|
"org.mortbay.jetty:jetty:$jettyVersion",
|
||||||
|
|||||||
+6
-1
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.springframework.security</groupId>
|
<groupId>org.springframework.security</groupId>
|
||||||
<artifactId>spring-security-itest</artifactId>
|
<artifactId>spring-security-itest</artifactId>
|
||||||
<version>3.0.2.RELEASE</version>
|
<version>3.0.3.RELEASE</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>spring-security-itest-web</artifactId>
|
<artifactId>spring-security-itest-web</artifactId>
|
||||||
<name>Spring Security - Web Integration Tests</name>
|
<name>Spring Security - Web Integration Tests</name>
|
||||||
@@ -28,6 +28,11 @@
|
|||||||
<groupId>javax.servlet</groupId>
|
<groupId>javax.servlet</groupId>
|
||||||
<artifactId>servlet-api</artifactId>
|
<artifactId>servlet-api</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.security</groupId>
|
||||||
|
<artifactId>spring-security-taglibs</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework</groupId>
|
<groupId>org.springframework</groupId>
|
||||||
<artifactId>spring-webmvc</artifactId>
|
<artifactId>spring-webmvc</artifactId>
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
<user name="miles" password="milespassword" authorities="ROLE_USER,ROLE_JAZZ,ROLE_TRUMPETER"/>
|
<user name="miles" password="milespassword" authorities="ROLE_USER,ROLE_JAZZ,ROLE_TRUMPETER"/>
|
||||||
<user name="johnc" password="johncspassword" authorities="ROLE_USER,ROLE_JAZZ,ROLE_SAXOPHONIST"/>
|
<user name="johnc" password="johncspassword" authorities="ROLE_USER,ROLE_JAZZ,ROLE_SAXOPHONIST"/>
|
||||||
<user name="jimi" password="jimispassword" authorities="ROLE_USER,ROLE_ROCK,ROLE_GUITARIST"/>
|
<user name="jimi" password="jimispassword" authorities="ROLE_USER,ROLE_ROCK,ROLE_GUITARIST"/>
|
||||||
|
<user name="theescapist<>&." password="theescapistspassword" authorities="ROLE_USER"/>
|
||||||
</user-service>
|
</user-service>
|
||||||
</authentication-provider>
|
</authentication-provider>
|
||||||
</authentication-manager>
|
</authentication-manager>
|
||||||
|
|||||||
@@ -0,0 +1,158 @@
|
|||||||
|
<?xml version="1.0" encoding="ISO-8859-1" ?>
|
||||||
|
<!DOCTYPE taglib
|
||||||
|
PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN"
|
||||||
|
"http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">
|
||||||
|
<taglib>
|
||||||
|
<tlib-version>1.0</tlib-version>
|
||||||
|
<jsp-version>1.2</jsp-version>
|
||||||
|
<short-name>security</short-name>
|
||||||
|
<uri>http://www.springframework.org/security/tags</uri>
|
||||||
|
<description>
|
||||||
|
Spring Security Authorization Tag Library
|
||||||
|
$Id$
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<tag>
|
||||||
|
<name>authorize</name>
|
||||||
|
<tag-class>org.springframework.security.taglibs.authz.AuthorizeTag</tag-class>
|
||||||
|
<description>
|
||||||
|
A tag which outputs the body of the tag if the configured access expression
|
||||||
|
evaluates to true for the currently authenticated principal.
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<attribute>
|
||||||
|
<name>access</name>
|
||||||
|
<required>false</required>
|
||||||
|
<rtexprvalue>false</rtexprvalue>
|
||||||
|
<description>
|
||||||
|
A Spring-EL expression which is supported by the WebSecurityExpressionHandler
|
||||||
|
in the application context. The latter will be used to evaluate the expression.
|
||||||
|
</description>
|
||||||
|
</attribute>
|
||||||
|
|
||||||
|
<attribute>
|
||||||
|
<name>url</name>
|
||||||
|
<required>false</required>
|
||||||
|
<rtexprvalue>false</rtexprvalue>
|
||||||
|
<description>
|
||||||
|
A URL within the application. If the user has access to this URL (as determined by
|
||||||
|
the AccessDecisionManager), the tag body will be evaluated. If not, it will
|
||||||
|
be skipped.
|
||||||
|
</description>
|
||||||
|
</attribute>
|
||||||
|
|
||||||
|
<attribute>
|
||||||
|
<name>method</name>
|
||||||
|
<required>false</required>
|
||||||
|
<rtexprvalue>false</rtexprvalue>
|
||||||
|
<description>
|
||||||
|
Can optionally be used to narrow down the HTTP method (typically GET or POST) to which the URL
|
||||||
|
applies to. Only has any meaning when used in combination with the "url" attribute.
|
||||||
|
</description>
|
||||||
|
</attribute>
|
||||||
|
|
||||||
|
|
||||||
|
<attribute>
|
||||||
|
<name>ifNotGranted</name>
|
||||||
|
<required>false</required>
|
||||||
|
<rtexprvalue>true</rtexprvalue>
|
||||||
|
<description>
|
||||||
|
A comma separated list of roles which the user must not have
|
||||||
|
for the body to be output. Deprecated in favour of the access expression.
|
||||||
|
</description>
|
||||||
|
</attribute>
|
||||||
|
|
||||||
|
<attribute>
|
||||||
|
<name>ifAllGranted</name>
|
||||||
|
<required>false</required>
|
||||||
|
<rtexprvalue>true</rtexprvalue>
|
||||||
|
<description>
|
||||||
|
A comma separated list of roles which the user must all
|
||||||
|
possess for the body to be output. Deprecated in favour of the access expression.
|
||||||
|
</description>
|
||||||
|
</attribute>
|
||||||
|
|
||||||
|
<attribute>
|
||||||
|
<name>ifAnyGranted</name>
|
||||||
|
<required>false</required>
|
||||||
|
<rtexprvalue>true</rtexprvalue>
|
||||||
|
<description>
|
||||||
|
A comma separated list of roles, one of which the user must
|
||||||
|
possess for the body to be output. Deprecated in favour of the access expression.
|
||||||
|
</description>
|
||||||
|
</attribute>
|
||||||
|
</tag>
|
||||||
|
|
||||||
|
<tag>
|
||||||
|
<name>authentication</name>
|
||||||
|
<tag-class>org.springframework.security.taglibs.authz.AuthenticationTag</tag-class>
|
||||||
|
<description>
|
||||||
|
Allows access to the current Authentication object.
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<attribute>
|
||||||
|
<name>property</name>
|
||||||
|
<required>true</required>
|
||||||
|
<rtexprvalue>true</rtexprvalue>
|
||||||
|
<description>
|
||||||
|
Property of the Authentication object which should be output. Supports nested
|
||||||
|
properties. For example if the principal object is an instance of UserDetails,
|
||||||
|
the property "principal.username" will return the username. Alternatively, using
|
||||||
|
"name" will call getName method on the Authentication object directly.
|
||||||
|
</description>
|
||||||
|
</attribute>
|
||||||
|
<attribute>
|
||||||
|
<name>var</name>
|
||||||
|
<required>false</required>
|
||||||
|
<rtexprvalue>false</rtexprvalue>
|
||||||
|
<description>
|
||||||
|
Name of the exported scoped variable which will contain the
|
||||||
|
evaluated property of the Authentication object.
|
||||||
|
</description>
|
||||||
|
</attribute>
|
||||||
|
<attribute>
|
||||||
|
<description>Set HTML escaping for this tag, as a boolean value.</description>
|
||||||
|
<name>htmlEscape</name>
|
||||||
|
<required>false</required>
|
||||||
|
<rtexprvalue>true</rtexprvalue>
|
||||||
|
</attribute>
|
||||||
|
<attribute>
|
||||||
|
<name>scope</name>
|
||||||
|
<required>false</required>
|
||||||
|
<rtexprvalue>false</rtexprvalue>
|
||||||
|
<description>
|
||||||
|
Scope for var.
|
||||||
|
</description>
|
||||||
|
</attribute>
|
||||||
|
</tag>
|
||||||
|
|
||||||
|
<tag>
|
||||||
|
<name>accesscontrollist</name>
|
||||||
|
<tag-class>org.springframework.security.taglibs.authz.AccessControlListTag</tag-class>
|
||||||
|
<description>
|
||||||
|
Allows inclusion of a tag body if the current Authentication
|
||||||
|
has one of the specified permissions to the presented
|
||||||
|
domain object instance.
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<attribute>
|
||||||
|
<name>hasPermission</name>
|
||||||
|
<required>true</required>
|
||||||
|
<rtexprvalue>true</rtexprvalue>
|
||||||
|
<description>
|
||||||
|
A comma separated list of permissions, which will be converted to
|
||||||
|
Permission instances by the configured PermissionFactory.
|
||||||
|
</description>
|
||||||
|
</attribute>
|
||||||
|
<attribute>
|
||||||
|
<name>domainObject</name>
|
||||||
|
<required>true</required>
|
||||||
|
<rtexprvalue>true</rtexprvalue>
|
||||||
|
<description>
|
||||||
|
The actual domain object instance for which permissions
|
||||||
|
are being evaluated.
|
||||||
|
</description>
|
||||||
|
</attribute>
|
||||||
|
</tag>
|
||||||
|
|
||||||
|
</taglib>
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<h1>Authentication Tag Test Page</h1>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<ul>
|
||||||
|
<li>This is the authentication name: <sec:authentication property="name"/></li>
|
||||||
|
<li>This is the principal.username: <sec:authentication property="principal.username"/></li>
|
||||||
|
<li>This is the unescaped authentication name: <sec:authentication property="name" htmlEscape="false"/></li>
|
||||||
|
<li>This is the unescaped principal.username: <sec:authentication property="principal.username" htmlEscape="false"/></li>
|
||||||
|
|
||||||
|
</ul
|
||||||
|
</p>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
|
|
||||||
|
|
||||||
+12
@@ -95,4 +95,16 @@ public class InMemoryProviderWebAppTests extends AbstractWebServerIntegrationTes
|
|||||||
tester.assertTextPresent("This session has been expired");
|
tester.assertTextPresent("This session has been expired");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void authenticationTagEscapingWorksCorrectly() {
|
||||||
|
beginAt("secure/authenticationTagTestPage.jsp");
|
||||||
|
login("theescapist<>&.", "theescapistspassword");
|
||||||
|
String response = tester.getServerResponse();
|
||||||
|
assertTrue(response.contains("This is the unescaped authentication name: theescapist<>&."));
|
||||||
|
assertTrue(response.contains("This is the unescaped principal.username: theescapist<>&."));
|
||||||
|
assertTrue(response.contains("This is the authentication name: theescapist<>&."));
|
||||||
|
assertTrue(response.contains("This is the principal.username: theescapist<>&."));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-3
@@ -4,18 +4,22 @@ test.exclude('**/OpenLDAPIntegrationTestSuite.class')
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile project(':spring-security-core'),
|
compile project(':spring-security-core'),
|
||||||
"org.springframework:spring-core:$springVersion",
|
|
||||||
"org.springframework:spring-beans:$springVersion",
|
"org.springframework:spring-beans:$springVersion",
|
||||||
"org.springframework:spring-context:$springVersion",
|
"org.springframework:spring-context:$springVersion",
|
||||||
"org.springframework:spring-tx:$springVersion",
|
"org.springframework:spring-tx:$springVersion",
|
||||||
"org.springframework.ldap:spring-ldap-core:$springLdapVersion",
|
|
||||||
"org.apache.directory.server:apacheds-core:$apacheDsVersion",
|
"org.apache.directory.server:apacheds-core:$apacheDsVersion",
|
||||||
"org.apache.directory.server:apacheds-core-entry:$apacheDsVersion",
|
"org.apache.directory.server:apacheds-core-entry:$apacheDsVersion",
|
||||||
"org.apache.directory.server:apacheds-protocol-shared:$apacheDsVersion",
|
"org.apache.directory.server:apacheds-protocol-shared:$apacheDsVersion",
|
||||||
"org.apache.directory.server:apacheds-protocol-ldap:$apacheDsVersion",
|
"org.apache.directory.server:apacheds-protocol-ldap:$apacheDsVersion",
|
||||||
"org.apache.directory.server:apacheds-server-jndi:$apacheDsVersion",
|
"org.apache.directory.server:apacheds-server-jndi:$apacheDsVersion",
|
||||||
'org.apache.directory.shared:shared-ldap:0.9.15',
|
'org.apache.directory.shared:shared-ldap:0.9.15',
|
||||||
'ldapsdk:ldapsdk:4.1'
|
'ldapsdk:ldapsdk:4.1'
|
||||||
|
compile ("org.springframework.ldap:spring-ldap-core:$springLdapVersion") {
|
||||||
|
exclude(group: 'commons-logging', module: 'commons-logging')
|
||||||
|
exclude(group: 'org.springframework', module: 'spring-core')
|
||||||
|
exclude(group: 'org.springframework', module: 'spring-tx')
|
||||||
|
exclude(group: 'org.springframework', module: 'spring-beans')
|
||||||
|
}
|
||||||
|
|
||||||
runtime 'org.slf4j:slf4j-log4j12:1.4.3'
|
runtime 'org.slf4j:slf4j-log4j12:1.4.3'
|
||||||
}
|
}
|
||||||
+1
-5
@@ -3,7 +3,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.springframework.security</groupId>
|
<groupId>org.springframework.security</groupId>
|
||||||
<artifactId>spring-security-parent</artifactId>
|
<artifactId>spring-security-parent</artifactId>
|
||||||
<version>3.0.2.RELEASE</version>
|
<version>3.0.3.RELEASE</version>
|
||||||
</parent>
|
</parent>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
<artifactId>spring-security-ldap</artifactId>
|
<artifactId>spring-security-ldap</artifactId>
|
||||||
@@ -19,10 +19,6 @@
|
|||||||
<groupId>org.springframework.ldap</groupId>
|
<groupId>org.springframework.ldap</groupId>
|
||||||
<artifactId>spring-ldap-core</artifactId>
|
<artifactId>spring-ldap-core</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>commons-logging</groupId>
|
|
||||||
<artifactId>commons-logging</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>ldapsdk</groupId>
|
<groupId>ldapsdk</groupId>
|
||||||
<artifactId>ldapsdk</artifactId>
|
<artifactId>ldapsdk</artifactId>
|
||||||
|
|||||||
+11
-6
@@ -193,21 +193,26 @@ public class SpringSecurityLdapTemplate extends LdapTemplate {
|
|||||||
public Object executeWithContext(DirContext ctx) throws NamingException {
|
public Object executeWithContext(DirContext ctx) throws NamingException {
|
||||||
DistinguishedName ctxBaseDn = new DistinguishedName(ctx.getNameInNamespace());
|
DistinguishedName ctxBaseDn = new DistinguishedName(ctx.getNameInNamespace());
|
||||||
NamingEnumeration<SearchResult> resultsEnum = ctx.search(base, filter, params, searchControls);
|
NamingEnumeration<SearchResult> resultsEnum = ctx.search(base, filter, params, searchControls);
|
||||||
|
if (logger.isDebugEnabled()) {
|
||||||
|
logger.debug("Searching for entry in under DN '" + ctxBaseDn
|
||||||
|
+ "', base = '" + base + "', filter = '" + filter + "'");
|
||||||
|
}
|
||||||
|
|
||||||
Set<DirContextOperations> results = new HashSet<DirContextOperations>();
|
Set<DirContextOperations> results = new HashSet<DirContextOperations>();
|
||||||
try {
|
try {
|
||||||
while (resultsEnum.hasMore()) {
|
while (resultsEnum.hasMore()) {
|
||||||
|
|
||||||
SearchResult searchResult = resultsEnum.next();
|
SearchResult searchResult = resultsEnum.next();
|
||||||
// Work out the DN of the matched entry
|
// Work out the DN of the matched entry
|
||||||
StringBuilder dn = new StringBuilder(searchResult.getName());
|
DistinguishedName dn = new DistinguishedName(searchResult.getName());
|
||||||
|
|
||||||
if (base.length() > 0) {
|
if (base.length() > 0) {
|
||||||
dn.append(",");
|
dn.prepend(new DistinguishedName(base));
|
||||||
dn.append(base);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
results.add(new DirContextAdapter(searchResult.getAttributes(),
|
if (logger.isDebugEnabled()) {
|
||||||
new DistinguishedName(dn.toString()), ctxBaseDn));
|
logger.debug("Found DN: " + dn);
|
||||||
|
}
|
||||||
|
results.add(new DirContextAdapter(searchResult.getAttributes(), dn, ctxBaseDn));
|
||||||
}
|
}
|
||||||
} catch (PartialResultException e) {
|
} catch (PartialResultException e) {
|
||||||
logger.info("Ignoring PartialResultException");
|
logger.info("Ignoring PartialResultException");
|
||||||
|
|||||||
+4
-4
@@ -99,8 +99,9 @@ public class BindAuthenticator extends AbstractLdapAuthenticator {
|
|||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
|
||||||
private DirContextOperations bindWithDn(String userDn, String username, String password) {
|
private DirContextOperations bindWithDn(String userDnStr, String username, String password) {
|
||||||
BaseLdapPathContextSource ctxSource = (BaseLdapPathContextSource) getContextSource();
|
BaseLdapPathContextSource ctxSource = (BaseLdapPathContextSource) getContextSource();
|
||||||
|
DistinguishedName userDn = new DistinguishedName(userDnStr);
|
||||||
DistinguishedName fullDn = new DistinguishedName(userDn);
|
DistinguishedName fullDn = new DistinguishedName(userDn);
|
||||||
fullDn.prepend(ctxSource.getBaseLdapPath());
|
fullDn.prepend(ctxSource.getBaseLdapPath());
|
||||||
|
|
||||||
@@ -114,8 +115,7 @@ public class BindAuthenticator extends AbstractLdapAuthenticator {
|
|||||||
|
|
||||||
Attributes attrs = ctx.getAttributes(userDn, getUserAttributes());
|
Attributes attrs = ctx.getAttributes(userDn, getUserAttributes());
|
||||||
|
|
||||||
DirContextAdapter result = new DirContextAdapter(attrs, new DistinguishedName(userDn),
|
DirContextAdapter result = new DirContextAdapter(attrs, userDn, ctxSource.getBaseLdapPath());
|
||||||
ctxSource.getBaseLdapPath());
|
|
||||||
|
|
||||||
if (ppolicy != null) {
|
if (ppolicy != null) {
|
||||||
result.setAttributeValue(ppolicy.getID(), ppolicy);
|
result.setAttributeValue(ppolicy.getID(), ppolicy);
|
||||||
@@ -128,7 +128,7 @@ public class BindAuthenticator extends AbstractLdapAuthenticator {
|
|||||||
// unless a subclass wishes to implement more specialized behaviour.
|
// unless a subclass wishes to implement more specialized behaviour.
|
||||||
if ((e instanceof org.springframework.ldap.AuthenticationException)
|
if ((e instanceof org.springframework.ldap.AuthenticationException)
|
||||||
|| (e instanceof org.springframework.ldap.OperationNotSupportedException)) {
|
|| (e instanceof org.springframework.ldap.OperationNotSupportedException)) {
|
||||||
handleBindException(userDn, username, e);
|
handleBindException(userDnStr, username, e);
|
||||||
} else {
|
} else {
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
|
|||||||
+19
-3
@@ -34,11 +34,13 @@ import org.springframework.util.Assert;
|
|||||||
* distinguished name and a set of attributes that have been retrieved from the Ldap server.
|
* distinguished name and a set of attributes that have been retrieved from the Ldap server.
|
||||||
* <p>
|
* <p>
|
||||||
* An instance may be created as the result of a search, or when user information is retrieved during authentication.
|
* An instance may be created as the result of a search, or when user information is retrieved during authentication.
|
||||||
* </p>
|
|
||||||
* <p>
|
* <p>
|
||||||
* An instance of this class will be used by the <tt>LdapAuthenticationProvider</tt> to construct the final user details
|
* An instance of this class will be used by the <tt>LdapAuthenticationProvider</tt> to construct the final user details
|
||||||
* object that it returns.
|
* object that it returns.
|
||||||
* </p>
|
* <p>
|
||||||
|
* The {@code equals} and {@code hashcode} methods are implemented using the {@code Dn} property and do not consider
|
||||||
|
* additional state, so it is not possible two store two instances with the same DN in the same set, or use them as
|
||||||
|
* keys in a map.
|
||||||
*
|
*
|
||||||
* @author Luke Taylor
|
* @author Luke Taylor
|
||||||
*/
|
*/
|
||||||
@@ -104,14 +106,28 @@ public class LdapUserDetailsImpl implements LdapUserDetails, PasswordPolicyData
|
|||||||
return graceLoginsRemaining;
|
return graceLoginsRemaining;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (obj instanceof LdapUserDetailsImpl) {
|
||||||
|
return dn.equals(((LdapUserDetailsImpl)obj).dn);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return dn.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
sb.append(super.toString()).append(": ");
|
sb.append(super.toString()).append(": ");
|
||||||
|
sb.append("Dn: ").append(dn).append("; ");
|
||||||
sb.append("Username: ").append(this.username).append("; ");
|
sb.append("Username: ").append(this.username).append("; ");
|
||||||
sb.append("Password: [PROTECTED]; ");
|
sb.append("Password: [PROTECTED]; ");
|
||||||
sb.append("Enabled: ").append(this.enabled).append("; ");
|
sb.append("Enabled: ").append(this.enabled).append("; ");
|
||||||
sb.append("AccountNonExpired: ").append(this.accountNonExpired).append("; ");
|
sb.append("AccountNonExpired: ").append(this.accountNonExpired).append("; ");
|
||||||
sb.append("credentialsNonExpired: ").append(this.credentialsNonExpired).append("; ");
|
sb.append("CredentialsNonExpired: ").append(this.credentialsNonExpired).append("; ");
|
||||||
sb.append("AccountNonLocked: ").append(this.accountNonLocked).append("; ");
|
sb.append("AccountNonLocked: ").append(this.accountNonLocked).append("; ");
|
||||||
|
|
||||||
if (this.getAuthorities() != null) {
|
if (this.getAuthorities() != null) {
|
||||||
|
|||||||
+12
-3
@@ -1,10 +1,13 @@
|
|||||||
package org.springframework.security.ldap.userdetails;
|
package org.springframework.security.ldap.userdetails;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
import org.springframework.ldap.core.DirContextOperations;
|
import org.springframework.ldap.core.DirContextOperations;
|
||||||
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
|
import org.springframework.security.core.authority.AuthorityUtils;
|
||||||
import org.springframework.security.core.userdetails.UserDetails;
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||||
import org.springframework.security.ldap.authentication.NullLdapAuthoritiesPopulator;
|
|
||||||
import org.springframework.security.ldap.search.LdapUserSearch;
|
import org.springframework.security.ldap.search.LdapUserSearch;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
@@ -16,8 +19,8 @@ import org.springframework.util.Assert;
|
|||||||
* @author Luke Taylor
|
* @author Luke Taylor
|
||||||
*/
|
*/
|
||||||
public class LdapUserDetailsService implements UserDetailsService {
|
public class LdapUserDetailsService implements UserDetailsService {
|
||||||
private LdapUserSearch userSearch;
|
private final LdapUserSearch userSearch;
|
||||||
private LdapAuthoritiesPopulator authoritiesPopulator;
|
private final LdapAuthoritiesPopulator authoritiesPopulator;
|
||||||
private UserDetailsContextMapper userDetailsMapper = new LdapUserDetailsMapper();
|
private UserDetailsContextMapper userDetailsMapper = new LdapUserDetailsMapper();
|
||||||
|
|
||||||
public LdapUserDetailsService(LdapUserSearch userSearch) {
|
public LdapUserDetailsService(LdapUserSearch userSearch) {
|
||||||
@@ -42,4 +45,10 @@ public class LdapUserDetailsService implements UserDetailsService {
|
|||||||
Assert.notNull(userDetailsMapper, "userDetailsMapper must not be null");
|
Assert.notNull(userDetailsMapper, "userDetailsMapper must not be null");
|
||||||
this.userDetailsMapper = userDetailsMapper;
|
this.userDetailsMapper = userDetailsMapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final class NullLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator {
|
||||||
|
public Collection<GrantedAuthority> getGrantedAuthorities(DirContextOperations userDetails, String username) {
|
||||||
|
return AuthorityUtils.NO_AUTHORITIES;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-7
@@ -18,14 +18,13 @@ package org.springframework.security.ldap.authentication;
|
|||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.springframework.ldap.core.DirContextAdapter;
|
|
||||||
import org.springframework.ldap.core.DirContextOperations;
|
import org.springframework.ldap.core.DirContextOperations;
|
||||||
import org.springframework.ldap.core.DistinguishedName;
|
|
||||||
import org.springframework.security.authentication.BadCredentialsException;
|
import org.springframework.security.authentication.BadCredentialsException;
|
||||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
import org.springframework.security.core.SpringSecurityMessageSource;
|
import org.springframework.security.core.SpringSecurityMessageSource;
|
||||||
import org.springframework.security.ldap.AbstractLdapIntegrationTests;
|
import org.springframework.security.ldap.AbstractLdapIntegrationTests;
|
||||||
|
import org.springframework.security.ldap.search.FilterBasedLdapUserSearch;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests for {@link BindAuthenticator}.
|
* Tests for {@link BindAuthenticator}.
|
||||||
@@ -37,7 +36,6 @@ public class BindAuthenticatorTests extends AbstractLdapIntegrationTests {
|
|||||||
|
|
||||||
private BindAuthenticator authenticator;
|
private BindAuthenticator authenticator;
|
||||||
private Authentication bob;
|
private Authentication bob;
|
||||||
// private Authentication ben;
|
|
||||||
|
|
||||||
|
|
||||||
//~ Methods ========================================================================================================
|
//~ Methods ========================================================================================================
|
||||||
@@ -46,7 +44,6 @@ public class BindAuthenticatorTests extends AbstractLdapIntegrationTests {
|
|||||||
authenticator = new BindAuthenticator(getContextSource());
|
authenticator = new BindAuthenticator(getContextSource());
|
||||||
authenticator.setMessageSource(new SpringSecurityMessageSource());
|
authenticator.setMessageSource(new SpringSecurityMessageSource());
|
||||||
bob = new UsernamePasswordAuthenticationToken("bob", "bobspassword");
|
bob = new UsernamePasswordAuthenticationToken("bob", "bobspassword");
|
||||||
// ben = new UsernamePasswordAuthenticationToken("ben", "benspassword");
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,11 +72,14 @@ public class BindAuthenticatorTests extends AbstractLdapIntegrationTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAuthenticationWithUserSearch() throws Exception {
|
public void testAuthenticationWithUserSearch() throws Exception {
|
||||||
DirContextAdapter ctx = new DirContextAdapter(new DistinguishedName("uid=bob,ou=people"));
|
//DirContextAdapter ctx = new DirContextAdapter(new DistinguishedName("uid=bob,ou=people"));
|
||||||
|
authenticator.setUserSearch(new FilterBasedLdapUserSearch("ou=people", "(uid={0})", getContextSource()));
|
||||||
authenticator.setUserSearch(new MockUserSearch(ctx));
|
|
||||||
authenticator.afterPropertiesSet();
|
authenticator.afterPropertiesSet();
|
||||||
authenticator.authenticate(bob);
|
authenticator.authenticate(bob);
|
||||||
|
// SEC-1444
|
||||||
|
authenticator.setUserSearch(new FilterBasedLdapUserSearch("ou=people", "(cn={0})", getContextSource()));
|
||||||
|
authenticator.authenticate(new UsernamePasswordAuthenticationToken("mouse, jerry", "jerryspassword"));
|
||||||
|
authenticator.authenticate(new UsernamePasswordAuthenticationToken("slash/guy", "slashguyspassword"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
+1
-3
@@ -70,13 +70,11 @@ public class FilterBasedLdapUserSearchTests extends AbstractLdapIntegrationTests
|
|||||||
@Test
|
@Test
|
||||||
public void extraFilterPartToExcludeBob() throws Exception {
|
public void extraFilterPartToExcludeBob() throws Exception {
|
||||||
FilterBasedLdapUserSearch locator = new FilterBasedLdapUserSearch("ou=people",
|
FilterBasedLdapUserSearch locator = new FilterBasedLdapUserSearch("ou=people",
|
||||||
"(&(cn=*)(!(|(uid={0})(uid=rod)(uid=jerry))))", dirCtxFactory);
|
"(&(cn=*)(!(|(uid={0})(uid=rod)(uid=jerry)(uid=slashguy))))", dirCtxFactory);
|
||||||
|
|
||||||
// Search for bob, get back ben...
|
// Search for bob, get back ben...
|
||||||
DirContextOperations ben = locator.searchForUser("bob");
|
DirContextOperations ben = locator.searchForUser("bob");
|
||||||
assertEquals("Ben Alex", ben.getStringAttribute("cn"));
|
assertEquals("Ben Alex", ben.getStringAttribute("cn"));
|
||||||
|
|
||||||
// assertEquals("uid=ben,ou=people,"+ROOT_DN, ben.getDn());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected=IncorrectResultSizeDataAccessException.class)
|
@Test(expected=IncorrectResultSizeDataAccessException.class)
|
||||||
|
|||||||
+27
-7
@@ -1,16 +1,20 @@
|
|||||||
package org.springframework.security.ldap.userdetails;
|
package org.springframework.security.ldap.userdetails;
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
import org.springframework.ldap.core.DirContextAdapter;
|
import org.springframework.ldap.core.DirContextAdapter;
|
||||||
import org.springframework.ldap.core.DistinguishedName;
|
import org.springframework.ldap.core.DistinguishedName;
|
||||||
import org.springframework.security.ldap.userdetails.InetOrgPerson;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Luke Taylor
|
* @author Luke Taylor
|
||||||
*/
|
*/
|
||||||
public class InetOrgPersonTests extends TestCase {
|
public class InetOrgPersonTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
public void testUsernameIsMappedFromContextUidIfNotSet() {
|
public void testUsernameIsMappedFromContextUidIfNotSet() {
|
||||||
InetOrgPerson.Essence essence = new InetOrgPerson.Essence(createUserContext());
|
InetOrgPerson.Essence essence = new InetOrgPerson.Essence(createUserContext());
|
||||||
InetOrgPerson p = (InetOrgPerson) essence.createUserDetails();
|
InetOrgPerson p = (InetOrgPerson) essence.createUserDetails();
|
||||||
@@ -18,7 +22,19 @@ public class InetOrgPersonTests extends TestCase {
|
|||||||
assertEquals("ghengis", p.getUsername());
|
assertEquals("ghengis", p.getUsername());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testUsernameIsDifferentFromContextUidIfSet() {
|
@Test
|
||||||
|
public void hashLookupViaEqualObjectRetrievesOriginal() throws Exception {
|
||||||
|
InetOrgPerson.Essence essence = new InetOrgPerson.Essence(createUserContext());
|
||||||
|
InetOrgPerson p = (InetOrgPerson) essence.createUserDetails();
|
||||||
|
essence = new InetOrgPerson.Essence(createUserContext());
|
||||||
|
InetOrgPerson p2 = (InetOrgPerson) essence.createUserDetails();
|
||||||
|
Set<InetOrgPerson> set = new HashSet<InetOrgPerson>();
|
||||||
|
set.add(p);
|
||||||
|
assertTrue(set.contains(p2));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void usernameIsDifferentFromContextUidIfSet() {
|
||||||
InetOrgPerson.Essence essence = new InetOrgPerson.Essence(createUserContext());
|
InetOrgPerson.Essence essence = new InetOrgPerson.Essence(createUserContext());
|
||||||
essence.setUsername("joe");
|
essence.setUsername("joe");
|
||||||
InetOrgPerson p = (InetOrgPerson) essence.createUserDetails();
|
InetOrgPerson p = (InetOrgPerson) essence.createUserDetails();
|
||||||
@@ -27,7 +43,8 @@ public class InetOrgPersonTests extends TestCase {
|
|||||||
assertEquals("ghengis", p.getUid());
|
assertEquals("ghengis", p.getUid());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testAttributesMapCorrectlyFromContext() {
|
@Test
|
||||||
|
public void attributesMapCorrectlyFromContext() {
|
||||||
InetOrgPerson.Essence essence = new InetOrgPerson.Essence(createUserContext());
|
InetOrgPerson.Essence essence = new InetOrgPerson.Essence(createUserContext());
|
||||||
InetOrgPerson p = (InetOrgPerson) essence.createUserDetails();
|
InetOrgPerson p = (InetOrgPerson) essence.createUserDetails();
|
||||||
|
|
||||||
@@ -50,6 +67,7 @@ public class InetOrgPersonTests extends TestCase {
|
|||||||
assertEquals("G", p.getInitials());
|
assertEquals("G", p.getInitials());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
public void testPasswordIsSetFromContextUserPassword() {
|
public void testPasswordIsSetFromContextUserPassword() {
|
||||||
InetOrgPerson.Essence essence = new InetOrgPerson.Essence(createUserContext());
|
InetOrgPerson.Essence essence = new InetOrgPerson.Essence(createUserContext());
|
||||||
InetOrgPerson p = (InetOrgPerson) essence.createUserDetails();
|
InetOrgPerson p = (InetOrgPerson) essence.createUserDetails();
|
||||||
@@ -57,7 +75,8 @@ public class InetOrgPersonTests extends TestCase {
|
|||||||
assertEquals("pillage", p.getPassword());
|
assertEquals("pillage", p.getPassword());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testMappingBackToContextMatchesOriginalData() {
|
@Test
|
||||||
|
public void mappingBackToContextMatchesOriginalData() {
|
||||||
DirContextAdapter ctx1 = createUserContext();
|
DirContextAdapter ctx1 = createUserContext();
|
||||||
DirContextAdapter ctx2 = new DirContextAdapter();
|
DirContextAdapter ctx2 = new DirContextAdapter();
|
||||||
ctx1.setAttributeValues("objectclass", new String[] {"top", "person", "organizationalPerson", "inetOrgPerson"});
|
ctx1.setAttributeValues("objectclass", new String[] {"top", "person", "organizationalPerson", "inetOrgPerson"});
|
||||||
@@ -68,7 +87,8 @@ public class InetOrgPersonTests extends TestCase {
|
|||||||
assertEquals(ctx1, ctx2);
|
assertEquals(ctx1, ctx2);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testCopyMatchesOriginalData() {
|
@Test
|
||||||
|
public void copyMatchesOriginalData() {
|
||||||
DirContextAdapter ctx1 = createUserContext();
|
DirContextAdapter ctx1 = createUserContext();
|
||||||
DirContextAdapter ctx2 = new DirContextAdapter();
|
DirContextAdapter ctx2 = new DirContextAdapter();
|
||||||
ctx2.setDn(new DistinguishedName("ignored=ignored"));
|
ctx2.setDn(new DistinguishedName("ignored=ignored"));
|
||||||
|
|||||||
@@ -58,6 +58,16 @@ sn: Mouse
|
|||||||
uid: jerry
|
uid: jerry
|
||||||
userPassword: jerryspassword
|
userPassword: jerryspassword
|
||||||
|
|
||||||
|
dn: cn=slash/guy,ou=people,dc=springframework,dc=org
|
||||||
|
objectclass: top
|
||||||
|
objectclass: person
|
||||||
|
objectclass: organizationalPerson
|
||||||
|
objectclass: inetOrgPerson
|
||||||
|
cn: slash/guy
|
||||||
|
sn: Slash
|
||||||
|
uid: slashguy
|
||||||
|
userPassword: slashguyspassword
|
||||||
|
|
||||||
dn: cn=developers,ou=groups,dc=springframework,dc=org
|
dn: cn=developers,ou=groups,dc=springframework,dc=org
|
||||||
objectclass: top
|
objectclass: top
|
||||||
objectclass: groupOfNames
|
objectclass: groupOfNames
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user