Compare commits
103 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8e9f7e2f10 | |||
| bf5a3a1aee | |||
| 201690ceba | |||
| e1f33d577f | |||
| 879adcae5f | |||
| eed8538071 | |||
| 3df9ad1e8f | |||
| dac46dc57c | |||
| b5b2e2c50e | |||
| 72c99af0d4 | |||
| 742e5fd7a9 | |||
| 795c073f48 | |||
| 58c9cbb471 | |||
| e40bc262bb | |||
| b0d865e28f | |||
| 0f7f0042ac | |||
| e0f1121d5b | |||
| ea93ed4165 | |||
| 96acf33019 | |||
| 35dbc0e6a8 | |||
| 0526c5233c | |||
| 60c011a976 | |||
| 916a19ccbd | |||
| 8138fac3f9 | |||
| 62fadfd28a | |||
| 166f48e6ab | |||
| 0f97086c86 | |||
| fe5c6d6621 | |||
| c642de537a | |||
| fd27c07b55 | |||
| e0d95c7c8a | |||
| 9d76c98791 | |||
| e923371724 | |||
| 216512bc54 | |||
| 8445e91b22 | |||
| 13ccb83d6f | |||
| 127d9eece9 | |||
| 7891787a53 | |||
| 2d8b6650db | |||
| 78995ff0a9 | |||
| 7974f3161d | |||
| c35c1c0643 | |||
| 2162221589 | |||
| 040fb6aa3c | |||
| b152218ee0 | |||
| 544e421157 | |||
| 0f612bf637 | |||
| c683bc10bf | |||
| 11ab23f4f4 | |||
| 0065b55a75 | |||
| d6f9d2e34a | |||
| 5dedbb6283 | |||
| 4cad151b57 | |||
| 72080bb5fe | |||
| 5854f00977 | |||
| 93118f4e91 | |||
| 8796850816 | |||
| cee2ea9c60 | |||
| 1159c9f302 | |||
| 6c5ce1237d | |||
| f81b58112b | |||
| 0e02b489c8 | |||
| d1669b909f | |||
| cb8041ba67 | |||
| 6f74162a1f | |||
| 99a0baadfa | |||
| 1f9a0e579f | |||
| 9e7d08c9e7 | |||
| 82168faf9d | |||
| 9d0f8977a9 | |||
| 5ae615f3b4 | |||
| d2b0077392 | |||
| 092c5aecf7 | |||
| a5d56d8724 | |||
| 7c0da854da | |||
| 0f546dcb07 | |||
| cb576d16e1 | |||
| 3b4df40f47 | |||
| 6cbf71bd72 | |||
| cd63329b63 | |||
| cc7f504f96 | |||
| a094563052 | |||
| da19435f21 | |||
| be50cd8ada | |||
| 21efbb6ba7 | |||
| c7cf6fdd73 | |||
| 8129bf2ce0 | |||
| d48079eb19 | |||
| 45f1179b52 | |||
| e11dfa7578 | |||
| 6cc0f6c054 | |||
| 22ea835643 | |||
| 9f51d68e92 | |||
| 32af1884f7 | |||
| a88035196a | |||
| 0db94b1d36 | |||
| 9e8994a2b7 | |||
| 8b2faff7ad | |||
| 469bc20e6d | |||
| 947d11f433 | |||
| b3a60a83f6 | |||
| 5bc7e4171c | |||
| 80e96b0f7b |
+1
-1
@@ -1,4 +1,3 @@
|
||||
classes/
|
||||
target/
|
||||
*/src/*/java/META-INF
|
||||
*/src/META-INF/
|
||||
@@ -22,4 +21,5 @@ build/
|
||||
atlassian-ide-plugin.xml
|
||||
!etc/eclipse/.checkstyle
|
||||
.checkstyle
|
||||
classes/
|
||||
s101plugin.state
|
||||
|
||||
+1
-1
@@ -13,4 +13,4 @@ cache:
|
||||
- $HOME/.gradle/caches/
|
||||
- $HOME/.gradle/wrapper/
|
||||
|
||||
script: ./gradlew build --refresh-dependencies --no-daemon
|
||||
script: ./gradlew build
|
||||
|
||||
Vendored
-119
@@ -1,119 +0,0 @@
|
||||
def projectProperties = [
|
||||
[$class: 'BuildDiscarderProperty',
|
||||
strategy: [$class: 'LogRotator', numToKeepStr: '5']],
|
||||
pipelineTriggers([cron('@daily')])
|
||||
]
|
||||
properties(projectProperties)
|
||||
|
||||
def SUCCESS = hudson.model.Result.SUCCESS.toString()
|
||||
currentBuild.result = SUCCESS
|
||||
|
||||
try {
|
||||
parallel check: {
|
||||
stage('Check') {
|
||||
node {
|
||||
checkout scm
|
||||
try {
|
||||
sh "./gradlew clean check --refresh-dependencies --no-daemon"
|
||||
} catch(Exception e) {
|
||||
currentBuild.result = 'FAILED: check'
|
||||
throw e
|
||||
} finally {
|
||||
junit '**/build/*-results/*.xml'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
sonar: {
|
||||
stage('Sonar') {
|
||||
node {
|
||||
checkout scm
|
||||
withCredentials([string(credentialsId: 'spring-sonar.login', variable: 'SONAR_LOGIN')]) {
|
||||
try {
|
||||
sh "./gradlew clean sonarqube -PexcludeProjects='**/samples/**' -Dsonar.host.url=$SPRING_SONAR_HOST_URL -Dsonar.login=$SONAR_LOGIN --refresh-dependencies --no-daemon"
|
||||
} catch(Exception e) {
|
||||
currentBuild.result = 'FAILED: sonar'
|
||||
throw e
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
springio: {
|
||||
stage('Spring IO') {
|
||||
node {
|
||||
checkout scm
|
||||
try {
|
||||
sh "./gradlew clean springIoCheck -PplatformVersion=Cairo-BUILD-SNAPSHOT -PexcludeProjects='**/samples/**' --refresh-dependencies --no-daemon --stacktrace"
|
||||
} catch(Exception e) {
|
||||
currentBuild.result = 'FAILED: springio'
|
||||
throw e
|
||||
} finally {
|
||||
junit '**/build/spring-io*-results/*.xml'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(currentBuild.result == 'SUCCESS') {
|
||||
parallel artifacts: {
|
||||
stage('Deploy Artifacts') {
|
||||
node {
|
||||
checkout scm
|
||||
withCredentials([file(credentialsId: 'spring-signing-secring.gpg', variable: 'SIGNING_KEYRING_FILE')]) {
|
||||
withCredentials([string(credentialsId: 'spring-gpg-passphrase', variable: 'SIGNING_PASSWORD')]) {
|
||||
withCredentials([usernamePassword(credentialsId: 'oss-token', passwordVariable: 'OSSRH_PASSWORD', usernameVariable: 'OSSRH_USERNAME')]) {
|
||||
withCredentials([usernamePassword(credentialsId: '02bd1690-b54f-4c9f-819d-a77cb7a9822c', usernameVariable: 'ARTIFACTORY_USERNAME', passwordVariable: 'ARTIFACTORY_PASSWORD')]) {
|
||||
sh "./gradlew deployArtifacts finalizeDeployArtifacts -Psigning.secretKeyRingFile=$SIGNING_KEYRING_FILE -Psigning.keyId=$SPRING_SIGNING_KEYID -Psigning.password='$SIGNING_PASSWORD' -PossrhUsername=$OSSRH_USERNAME -PossrhPassword=$OSSRH_PASSWORD -PartifactoryUsername=$ARTIFACTORY_USERNAME -PartifactoryPassword=$ARTIFACTORY_PASSWORD --refresh-dependencies --no-daemon --stacktrace"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
docs: {
|
||||
stage('Deploy Docs') {
|
||||
node {
|
||||
checkout scm
|
||||
withCredentials([file(credentialsId: 'docs.spring.io-jenkins_private_ssh_key', variable: 'DEPLOY_SSH_KEY')]) {
|
||||
sh "./gradlew deployDocs -PdeployDocsSshKeyPath=$DEPLOY_SSH_KEY -PdeployDocsSshUsername=$SPRING_DOCS_USERNAME --refresh-dependencies --no-daemon --stacktrace"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
schema: {
|
||||
stage('Deploy Schema') {
|
||||
node {
|
||||
checkout scm
|
||||
withCredentials([file(credentialsId: 'docs.spring.io-jenkins_private_ssh_key', variable: 'DEPLOY_SSH_KEY')]) {
|
||||
sh "./gradlew deploySchema -PdeployDocsSshKeyPath=$DEPLOY_SSH_KEY -PdeployDocsSshUsername=$SPRING_DOCS_USERNAME --refresh-dependencies --no-daemon --stacktrace"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
def buildStatus = currentBuild.result
|
||||
def buildNotSuccess = !SUCCESS.equals(buildStatus)
|
||||
def lastBuildNotSuccess = !SUCCESS.equals(currentBuild.previousBuild?.result)
|
||||
|
||||
if(buildNotSuccess || lastBuildNotSuccess) {
|
||||
|
||||
stage('Notifiy') {
|
||||
node {
|
||||
final def RECIPIENTS = [[$class: 'DevelopersRecipientProvider'], [$class: 'RequesterRecipientProvider']]
|
||||
|
||||
def subject = "${buildStatus}: Build ${env.JOB_NAME} ${env.BUILD_NUMBER} status is now ${buildStatus}"
|
||||
def details = """The build status changed to ${buildStatus}. For details see ${env.BUILD_URL}"""
|
||||
|
||||
emailext (
|
||||
subject: subject,
|
||||
body: details,
|
||||
recipientProviders: RECIPIENTS,
|
||||
to: "$SPRING_SECURITY_TEAM_EMAILS"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -4,8 +4,8 @@ image:https://travis-ci.org/spring-projects/spring-security.svg?branch=master["B
|
||||
|
||||
= Spring Security
|
||||
|
||||
Spring Security provides security services for the http://docs.spring.io[Spring IO Platform]. Spring Security 5.0 requires Spring 5.0 as
|
||||
a minimum and also requires Java 8.
|
||||
Spring Security provides security services for the http://docs.spring.io[Spring IO Platform]. Spring Security 3.1 requires Spring 3.0.3 as
|
||||
a minimum and also requires Java 5.
|
||||
|
||||
For a detailed list of features and access to the latest release, please visit http://spring.io/projects[Spring projects].
|
||||
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
// Acl Module build file
|
||||
|
||||
dependencies {
|
||||
compile project(':spring-security-core'),
|
||||
springCoreDependency,
|
||||
'aopalliance:aopalliance:1.0',
|
||||
"org.springframework:spring-aop:$springVersion",
|
||||
"org.springframework:spring-context:$springVersion",
|
||||
"org.springframework:spring-tx:$springVersion",
|
||||
"org.springframework:spring-jdbc:$springVersion"
|
||||
|
||||
optional "net.sf.ehcache:ehcache:$ehcacheVersion"
|
||||
|
||||
testCompile "org.springframework:spring-beans:$springVersion",
|
||||
"org.springframework:spring-context-support:$springVersion",
|
||||
"org.springframework:spring-test:$springVersion"
|
||||
|
||||
testRuntime "org.hsqldb:hsqldb:$hsqlVersion"
|
||||
}
|
||||
+165
@@ -0,0 +1,165 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-acl</artifactId>
|
||||
<version>4.2.9.RELEASE</version>
|
||||
<name>spring-security-acl</name>
|
||||
<description>spring-security-acl</description>
|
||||
<url>http://spring.io/spring-security</url>
|
||||
<organization>
|
||||
<name>spring.io</name>
|
||||
<url>http://spring.io/</url>
|
||||
</organization>
|
||||
<licenses>
|
||||
<license>
|
||||
<name>The Apache Software License, Version 2.0</name>
|
||||
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
|
||||
<distribution>repo</distribution>
|
||||
</license>
|
||||
</licenses>
|
||||
<developers>
|
||||
<developer>
|
||||
<id>rwinch</id>
|
||||
<name>Rob Winch</name>
|
||||
<email>rwinch@gopivotal.com</email>
|
||||
</developer>
|
||||
</developers>
|
||||
<scm>
|
||||
<connection>scm:git:git://github.com/spring-projects/spring-security</connection>
|
||||
<developerConnection>scm:git:git://github.com/spring-projects/spring-security</developerConnection>
|
||||
<url>https://github.com/spring-projects/spring-security</url>
|
||||
</scm>
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-framework-bom</artifactId>
|
||||
<version>4.3.19.RELEASE</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>aopalliance</groupId>
|
||||
<artifactId>aopalliance</artifactId>
|
||||
<version>1.0</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-core</artifactId>
|
||||
<version>4.2.9.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-aop</artifactId>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-core</artifactId>
|
||||
<scope>compile</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
<groupId>commons-logging</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-jdbc</artifactId>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-tx</artifactId>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-logging</groupId>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
<version>1.2</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.sf.ehcache</groupId>
|
||||
<artifactId>ehcache</artifactId>
|
||||
<version>2.10.5</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
<version>1.1.11</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.12</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.assertj</groupId>
|
||||
<artifactId>assertj-core</artifactId>
|
||||
<version>2.2.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hsqldb</groupId>
|
||||
<artifactId>hsqldb</artifactId>
|
||||
<version>2.3.6</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<version>1.10.19</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>jcl-over-slf4j</artifactId>
|
||||
<version>1.7.25</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-beans</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context-support</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>1.7</source>
|
||||
<target>1.7</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@@ -1,18 +0,0 @@
|
||||
apply plugin: 'io.spring.convention.spring-module'
|
||||
|
||||
dependencies {
|
||||
compile project(':spring-security-core')
|
||||
compile 'org.springframework:spring-aop'
|
||||
compile 'org.springframework:spring-context'
|
||||
compile 'org.springframework:spring-core'
|
||||
compile 'org.springframework:spring-jdbc'
|
||||
compile 'org.springframework:spring-tx'
|
||||
|
||||
optional 'net.sf.ehcache:ehcache'
|
||||
|
||||
testCompile 'org.springframework:spring-beans'
|
||||
testCompile 'org.springframework:spring-context-support'
|
||||
testCompile 'org.springframework:spring-test'
|
||||
|
||||
testRuntime 'org.hsqldb:hsqldb'
|
||||
}
|
||||
-21
@@ -64,7 +64,6 @@ public class AccessControlEntryImpl implements AccessControlEntry,
|
||||
// ~ Methods
|
||||
// ========================================================================================================
|
||||
|
||||
@Override
|
||||
public boolean equals(Object arg0) {
|
||||
if (!(arg0 instanceof AccessControlEntryImpl)) {
|
||||
return false;
|
||||
@@ -129,49 +128,30 @@ public class AccessControlEntryImpl implements AccessControlEntry,
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = this.acl.hashCode();
|
||||
result = 31 * result + this.permission.hashCode();
|
||||
result = 31 * result + (this.id != null ? this.id.hashCode() : 0);
|
||||
result = 31 * result + this.sid.hashCode();
|
||||
result = 31 * result + (this.auditFailure ? 1 : 0);
|
||||
result = 31 * result + (this.auditSuccess ? 1 : 0);
|
||||
result = 31 * result + (this.granting ? 1 : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Acl getAcl() {
|
||||
return acl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Serializable getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Permission getPermission() {
|
||||
return permission;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Sid getSid() {
|
||||
return sid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAuditFailure() {
|
||||
return auditFailure;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAuditSuccess() {
|
||||
return auditSuccess;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isGranting() {
|
||||
return granting;
|
||||
}
|
||||
@@ -189,7 +169,6 @@ public class AccessControlEntryImpl implements AccessControlEntry,
|
||||
this.permission = permission;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("AccessControlEntryImpl[");
|
||||
|
||||
@@ -123,7 +123,6 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
|
||||
// ~ Methods
|
||||
// ========================================================================================================
|
||||
|
||||
@Override
|
||||
public void deleteAce(int aceIndex) throws NotFoundException {
|
||||
aclAuthorizationStrategy.securityCheck(this,
|
||||
AclAuthorizationStrategy.CHANGE_GENERAL);
|
||||
@@ -145,7 +144,6 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void insertAce(int atIndexLocation, Permission permission, Sid sid,
|
||||
boolean granting) throws NotFoundException {
|
||||
aclAuthorizationStrategy.securityCheck(this,
|
||||
@@ -169,24 +167,20 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AccessControlEntry> getEntries() {
|
||||
// Can safely return AccessControlEntry directly, as they're immutable outside the
|
||||
// ACL package
|
||||
return new ArrayList<AccessControlEntry>(aces);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Serializable getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectIdentity getObjectIdentity() {
|
||||
return objectIdentity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEntriesInheriting() {
|
||||
return entriesInheriting;
|
||||
}
|
||||
@@ -198,7 +192,6 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
|
||||
* ACL was only loaded for a subset of SIDs
|
||||
* @see DefaultPermissionGrantingStrategy
|
||||
*/
|
||||
@Override
|
||||
public boolean isGranted(List<Permission> permission, List<Sid> sids,
|
||||
boolean administrativeMode) throws NotFoundException, UnloadedSidException {
|
||||
Assert.notEmpty(permission, "Permissions required");
|
||||
@@ -212,7 +205,6 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
|
||||
administrativeMode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSidLoaded(List<Sid> sids) {
|
||||
// If loadedSides is null, this indicates all SIDs were loaded
|
||||
// Also return true if the caller didn't specify a SID to find
|
||||
@@ -241,14 +233,12 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEntriesInheriting(boolean entriesInheriting) {
|
||||
aclAuthorizationStrategy.securityCheck(this,
|
||||
AclAuthorizationStrategy.CHANGE_GENERAL);
|
||||
this.entriesInheriting = entriesInheriting;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOwner(Sid newOwner) {
|
||||
aclAuthorizationStrategy.securityCheck(this,
|
||||
AclAuthorizationStrategy.CHANGE_OWNERSHIP);
|
||||
@@ -256,12 +246,10 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
|
||||
this.owner = newOwner;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Sid getOwner() {
|
||||
return this.owner;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setParent(Acl newParent) {
|
||||
aclAuthorizationStrategy.securityCheck(this,
|
||||
AclAuthorizationStrategy.CHANGE_GENERAL);
|
||||
@@ -270,12 +258,10 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
|
||||
this.parentAcl = newParent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Acl getParentAcl() {
|
||||
return parentAcl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateAce(int aceIndex, Permission permission) throws NotFoundException {
|
||||
aclAuthorizationStrategy.securityCheck(this,
|
||||
AclAuthorizationStrategy.CHANGE_GENERAL);
|
||||
@@ -287,7 +273,6 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateAuditing(int aceIndex, boolean auditSuccess, boolean auditFailure) {
|
||||
aclAuthorizationStrategy.securityCheck(this,
|
||||
AclAuthorizationStrategy.CHANGE_AUDITING);
|
||||
@@ -300,7 +285,6 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof AclImpl) {
|
||||
AclImpl rhs = (AclImpl) obj;
|
||||
@@ -341,23 +325,6 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = this.parentAcl != null ? this.parentAcl.hashCode() : 0;
|
||||
result = 31 * result + this.aclAuthorizationStrategy.hashCode();
|
||||
result = 31 * result + (this.permissionGrantingStrategy != null ?
|
||||
this.permissionGrantingStrategy.hashCode() :
|
||||
0);
|
||||
result = 31 * result + (this.aces != null ? this.aces.hashCode() : 0);
|
||||
result = 31 * result + this.objectIdentity.hashCode();
|
||||
result = 31 * result + this.id.hashCode();
|
||||
result = 31 * result + (this.owner != null ? this.owner.hashCode() : 0);
|
||||
result = 31 * result + (this.loadedSids != null ? this.loadedSids.hashCode() : 0);
|
||||
result = 31 * result + (this.entriesInheriting ? 1 : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("AclImpl[");
|
||||
|
||||
@@ -55,7 +55,6 @@ public class GrantedAuthoritySid implements Sid {
|
||||
// ~ Methods
|
||||
// ========================================================================================================
|
||||
|
||||
@Override
|
||||
public boolean equals(Object object) {
|
||||
if ((object == null) || !(object instanceof GrantedAuthoritySid)) {
|
||||
return false;
|
||||
@@ -67,7 +66,6 @@ public class GrantedAuthoritySid implements Sid {
|
||||
this.getGrantedAuthority());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return this.getGrantedAuthority().hashCode();
|
||||
}
|
||||
@@ -76,7 +74,6 @@ public class GrantedAuthoritySid implements Sid {
|
||||
return grantedAuthority;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "GrantedAuthoritySid[" + this.grantedAuthority + "]";
|
||||
}
|
||||
|
||||
@@ -110,7 +110,6 @@ public class ObjectIdentityImpl implements ObjectIdentity {
|
||||
*
|
||||
* @return <code>true</code> if the presented object matches this object
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object arg0) {
|
||||
if (arg0 == null || !(arg0 instanceof ObjectIdentityImpl)) {
|
||||
return false;
|
||||
@@ -135,12 +134,10 @@ public class ObjectIdentityImpl implements ObjectIdentity {
|
||||
return type.equals(other.type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Serializable getIdentifier() {
|
||||
return identifier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
@@ -150,7 +147,6 @@ public class ObjectIdentityImpl implements ObjectIdentity {
|
||||
*
|
||||
* @return the hash
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int code = 31;
|
||||
code ^= this.type.hashCode();
|
||||
@@ -159,7 +155,6 @@ public class ObjectIdentityImpl implements ObjectIdentity {
|
||||
return code;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(this.getClass().getName()).append("[");
|
||||
|
||||
@@ -60,7 +60,6 @@ public class PrincipalSid implements Sid {
|
||||
// ~ Methods
|
||||
// ========================================================================================================
|
||||
|
||||
@Override
|
||||
public boolean equals(Object object) {
|
||||
if ((object == null) || !(object instanceof PrincipalSid)) {
|
||||
return false;
|
||||
@@ -71,7 +70,6 @@ public class PrincipalSid implements Sid {
|
||||
return ((PrincipalSid) object).getPrincipal().equals(this.getPrincipal());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return this.getPrincipal().hashCode();
|
||||
}
|
||||
@@ -80,7 +78,6 @@ public class PrincipalSid implements Sid {
|
||||
return principal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PrincipalSid[" + this.principal + "]";
|
||||
}
|
||||
|
||||
@@ -1,125 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.security.acls.jdbc;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.security.acls.model.ObjectIdentity;
|
||||
|
||||
/**
|
||||
* Utility class for helping convert database representations of {@link ObjectIdentity#getIdentifier()} into
|
||||
* the correct Java type as specified by <code>acl_class.class_id_type</code>.
|
||||
* @author paulwheeler
|
||||
*/
|
||||
class AclClassIdUtils {
|
||||
private static final String DEFAULT_CLASS_ID_TYPE_COLUMN_NAME = "class_id_type";
|
||||
private static final Log log = LogFactory.getLog(AclClassIdUtils.class);
|
||||
|
||||
private ConversionService conversionService;
|
||||
|
||||
public AclClassIdUtils() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the raw type from the database into the right Java type. For most applications the 'raw type' will be Long, for some applications
|
||||
* it could be String.
|
||||
* @param identifier The identifier from the database
|
||||
* @param resultSet Result set of the query
|
||||
* @return The identifier in the appropriate target Java type. Typically Long or UUID.
|
||||
* @throws SQLException
|
||||
*/
|
||||
Serializable identifierFrom(Serializable identifier, ResultSet resultSet) throws SQLException {
|
||||
if (isString(identifier) && hasValidClassIdType(resultSet)
|
||||
&& canConvertFromStringTo(classIdTypeFrom(resultSet))) {
|
||||
|
||||
identifier = convertFromStringTo((String) identifier, classIdTypeFrom(resultSet));
|
||||
} else {
|
||||
// Assume it should be a Long type
|
||||
identifier = convertToLong(identifier);
|
||||
}
|
||||
|
||||
return identifier;
|
||||
}
|
||||
|
||||
private boolean hasValidClassIdType(ResultSet resultSet) throws SQLException {
|
||||
boolean hasClassIdType = false;
|
||||
try {
|
||||
hasClassIdType = classIdTypeFrom(resultSet) != null;
|
||||
} catch (SQLException e) {
|
||||
log.debug("Unable to obtain the class id type", e);
|
||||
}
|
||||
return hasClassIdType;
|
||||
}
|
||||
|
||||
private <T extends Serializable> Class<T> classIdTypeFrom(ResultSet resultSet) throws SQLException {
|
||||
return classIdTypeFrom(resultSet.getString(DEFAULT_CLASS_ID_TYPE_COLUMN_NAME));
|
||||
}
|
||||
|
||||
private <T extends Serializable> Class<T> classIdTypeFrom(String className) {
|
||||
Class targetType = null;
|
||||
if (className != null) {
|
||||
try {
|
||||
targetType = Class.forName(className);
|
||||
} catch (ClassNotFoundException e) {
|
||||
log.debug("Unable to find class id type on classpath", e);
|
||||
}
|
||||
}
|
||||
return targetType;
|
||||
}
|
||||
|
||||
private <T> boolean canConvertFromStringTo(Class<T> targetType) {
|
||||
return hasConversionService() && conversionService.canConvert(String.class, targetType);
|
||||
}
|
||||
|
||||
private <T extends Serializable> T convertFromStringTo(String identifier, Class<T> targetType) {
|
||||
return conversionService.convert(identifier, targetType);
|
||||
}
|
||||
|
||||
private boolean hasConversionService() {
|
||||
return conversionService != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts to a {@link Long}, attempting to use the {@link ConversionService} if available.
|
||||
* @param identifier The identifier
|
||||
* @return Long version of the identifier
|
||||
* @throws NumberFormatException if the string cannot be parsed to a long.
|
||||
* @throws org.springframework.core.convert.ConversionException if a conversion exception occurred
|
||||
* @throws IllegalArgumentException if targetType is null
|
||||
*/
|
||||
private Long convertToLong(Serializable identifier) {
|
||||
Long idAsLong;
|
||||
if (hasConversionService()) {
|
||||
idAsLong = conversionService.convert(identifier, Long.class);
|
||||
} else {
|
||||
idAsLong = Long.valueOf(identifier.toString());
|
||||
}
|
||||
return idAsLong;
|
||||
}
|
||||
|
||||
private boolean isString(Serializable object) {
|
||||
return object.getClass().isAssignableFrom(String.class);
|
||||
}
|
||||
|
||||
public void setConversionService(ConversionService conversionService) {
|
||||
this.conversionService = conversionService;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2004, 2005, 2006, 2017 Acegi Technology Pty Limited
|
||||
* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -30,7 +30,6 @@ import java.util.Set;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.springframework.core.convert.ConversionException;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.core.PreparedStatementSetter;
|
||||
import org.springframework.jdbc.core.ResultSetExtractor;
|
||||
@@ -79,7 +78,7 @@ import org.springframework.util.Assert;
|
||||
*/
|
||||
public class BasicLookupStrategy implements LookupStrategy {
|
||||
|
||||
private final static String DEFAULT_SELECT_CLAUSE_COLUMNS = "select acl_object_identity.object_id_identity, "
|
||||
public final static String DEFAULT_SELECT_CLAUSE = "select acl_object_identity.object_id_identity, "
|
||||
+ "acl_entry.ace_order, "
|
||||
+ "acl_object_identity.id as acl_id, "
|
||||
+ "acl_object_identity.parent_object, "
|
||||
@@ -93,19 +92,13 @@ public class BasicLookupStrategy implements LookupStrategy {
|
||||
+ "acl_sid.sid as ace_sid, "
|
||||
+ "acli_sid.principal as acl_principal, "
|
||||
+ "acli_sid.sid as acl_sid, "
|
||||
+ "acl_class.class ";
|
||||
private final static String DEFAULT_SELECT_CLAUSE_ACL_CLASS_ID_TYPE_COLUMN = ", acl_class.class_id_type ";
|
||||
private final static String DEFAULT_SELECT_CLAUSE_FROM = "from acl_object_identity "
|
||||
+ "acl_class.class "
|
||||
+ "from acl_object_identity "
|
||||
+ "left join acl_sid acli_sid on acli_sid.id = acl_object_identity.owner_sid "
|
||||
+ "left join acl_class on acl_class.id = acl_object_identity.object_id_class "
|
||||
+ "left join acl_entry on acl_object_identity.id = acl_entry.acl_object_identity "
|
||||
+ "left join acl_sid on acl_entry.sid = acl_sid.id " + "where ( ";
|
||||
|
||||
public final static String DEFAULT_SELECT_CLAUSE = DEFAULT_SELECT_CLAUSE_COLUMNS + DEFAULT_SELECT_CLAUSE_FROM;
|
||||
|
||||
public final static String DEFAULT_ACL_CLASS_ID_SELECT_CLAUSE = DEFAULT_SELECT_CLAUSE_COLUMNS +
|
||||
DEFAULT_SELECT_CLAUSE_ACL_CLASS_ID_TYPE_COLUMN + DEFAULT_SELECT_CLAUSE_FROM;
|
||||
|
||||
private final static String DEFAULT_LOOKUP_KEYS_WHERE_CLAUSE = "(acl_object_identity.id = ?)";
|
||||
|
||||
private final static String DEFAULT_LOOKUP_IDENTITIES_WHERE_CLAUSE = "(acl_object_identity.object_id_identity = ? and acl_class.class = ?)";
|
||||
@@ -133,8 +126,6 @@ public class BasicLookupStrategy implements LookupStrategy {
|
||||
private String lookupObjectIdentitiesWhereClause = DEFAULT_LOOKUP_IDENTITIES_WHERE_CLAUSE;
|
||||
private String orderByClause = DEFAULT_ORDER_BY_CLAUSE;
|
||||
|
||||
private AclClassIdUtils aclClassIdUtils;
|
||||
|
||||
// ~ Constructors
|
||||
// ===================================================================================================
|
||||
|
||||
@@ -170,9 +161,9 @@ public class BasicLookupStrategy implements LookupStrategy {
|
||||
this.aclCache = aclCache;
|
||||
this.aclAuthorizationStrategy = aclAuthorizationStrategy;
|
||||
this.grantingStrategy = grantingStrategy;
|
||||
this.aclClassIdUtils = new AclClassIdUtils();
|
||||
fieldAces.setAccessible(true);
|
||||
fieldAcl.setAccessible(true);
|
||||
|
||||
}
|
||||
|
||||
// ~ Methods
|
||||
@@ -392,9 +383,10 @@ public class BasicLookupStrategy implements LookupStrategy {
|
||||
// No need to check for nulls, as guaranteed non-null by
|
||||
// ObjectIdentity.getIdentifier() interface contract
|
||||
String identifier = oid.getIdentifier().toString();
|
||||
long id = (Long.valueOf(identifier)).longValue();
|
||||
|
||||
// Inject values
|
||||
ps.setString((2 * i) + 1, identifier);
|
||||
ps.setLong((2 * i) + 1, id);
|
||||
ps.setString((2 * i) + 2, type);
|
||||
i++;
|
||||
}
|
||||
@@ -545,18 +537,6 @@ public class BasicLookupStrategy implements LookupStrategy {
|
||||
this.orderByClause = orderByClause;
|
||||
}
|
||||
|
||||
public final void setAclClassIdSupported(boolean aclClassIdSupported) {
|
||||
if (aclClassIdSupported) {
|
||||
Assert.isTrue(this.selectClause.equals(DEFAULT_SELECT_CLAUSE), "Cannot set aclClassIdSupported and override the select clause; "
|
||||
+ "just override the select clause");
|
||||
this.selectClause = DEFAULT_ACL_CLASS_ID_SELECT_CLAUSE;
|
||||
}
|
||||
}
|
||||
|
||||
public final void setAclClassIdUtils(AclClassIdUtils aclClassIdUtils) {
|
||||
this.aclClassIdUtils = aclClassIdUtils;
|
||||
}
|
||||
|
||||
// ~ Inner Classes
|
||||
// ==================================================================================================
|
||||
|
||||
@@ -622,7 +602,6 @@ public class BasicLookupStrategy implements LookupStrategy {
|
||||
* @param rs the ResultSet focused on a current row
|
||||
*
|
||||
* @throws SQLException if something goes wrong converting values
|
||||
* @throws ConversionException if can't convert to the desired Java type
|
||||
*/
|
||||
private void convertCurrentResultIntoObject(Map<Serializable, Acl> acls,
|
||||
ResultSet rs) throws SQLException {
|
||||
@@ -633,12 +612,9 @@ public class BasicLookupStrategy implements LookupStrategy {
|
||||
|
||||
if (acl == null) {
|
||||
// Make an AclImpl and pop it into the Map
|
||||
|
||||
// If the Java type is a String, check to see if we can convert it to the target id type, e.g. UUID.
|
||||
Serializable identifier = (Serializable) rs.getObject("object_id_identity");
|
||||
identifier = aclClassIdUtils.identifierFrom(identifier, rs);
|
||||
ObjectIdentity objectIdentity = new ObjectIdentityImpl(
|
||||
rs.getString("class"), identifier);
|
||||
rs.getString("class"), Long.valueOf(rs
|
||||
.getLong("object_id_identity")));
|
||||
|
||||
Acl parentAcl = null;
|
||||
long parentAclId = rs.getLong("parent_object");
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2004, 2005, 2006, 2017 Acegi Technology Pty Limited
|
||||
* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package org.springframework.security.acls.jdbc;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Arrays;
|
||||
@@ -50,15 +49,8 @@ public class JdbcAclService implements AclService {
|
||||
// =====================================================================================
|
||||
|
||||
protected static final Log log = LogFactory.getLog(JdbcAclService.class);
|
||||
private static final String DEFAULT_SELECT_ACL_CLASS_COLUMNS = "class.class as class";
|
||||
private static final String DEFAULT_SELECT_ACL_CLASS_COLUMNS_WITH_ID_TYPE = DEFAULT_SELECT_ACL_CLASS_COLUMNS + ", class.class_id_type as class_id_type";
|
||||
private static final String DEFAULT_SELECT_ACL_WITH_PARENT_SQL = "select obj.object_id_identity as obj_id, " + DEFAULT_SELECT_ACL_CLASS_COLUMNS
|
||||
+ " from acl_object_identity obj, acl_object_identity parent, acl_class class "
|
||||
+ "where obj.parent_object = parent.id and obj.object_id_class = class.id "
|
||||
+ "and parent.object_id_identity = ? and parent.object_id_class = ("
|
||||
+ "select id FROM acl_class where acl_class.class = ?)";
|
||||
private static final String DEFAULT_SELECT_ACL_WITH_PARENT_SQL_WITH_CLASS_ID_TYPE = "select obj.object_id_identity as obj_id, " + DEFAULT_SELECT_ACL_CLASS_COLUMNS_WITH_ID_TYPE
|
||||
+ " from acl_object_identity obj, acl_object_identity parent, acl_class class "
|
||||
private static final String DEFAULT_SELECT_ACL_WITH_PARENT_SQL = "select obj.object_id_identity as obj_id, class.class as class "
|
||||
+ "from acl_object_identity obj, acl_object_identity parent, acl_class class "
|
||||
+ "where obj.parent_object = parent.id and obj.object_id_class = class.id "
|
||||
+ "and parent.object_id_identity = ? and parent.object_id_class = ("
|
||||
+ "select id FROM acl_class where acl_class.class = ?)";
|
||||
@@ -68,9 +60,7 @@ public class JdbcAclService implements AclService {
|
||||
|
||||
protected final JdbcTemplate jdbcTemplate;
|
||||
private final LookupStrategy lookupStrategy;
|
||||
private boolean aclClassIdSupported;
|
||||
private String findChildrenSql = DEFAULT_SELECT_ACL_WITH_PARENT_SQL;
|
||||
private AclClassIdUtils aclClassIdUtils;
|
||||
|
||||
// ~ Constructors
|
||||
// ===================================================================================================
|
||||
@@ -80,7 +70,6 @@ public class JdbcAclService implements AclService {
|
||||
Assert.notNull(lookupStrategy, "LookupStrategy required");
|
||||
this.jdbcTemplate = new JdbcTemplate(dataSource);
|
||||
this.lookupStrategy = lookupStrategy;
|
||||
this.aclClassIdUtils = new AclClassIdUtils();
|
||||
}
|
||||
|
||||
// ~ Methods
|
||||
@@ -93,8 +82,7 @@ public class JdbcAclService implements AclService {
|
||||
public ObjectIdentity mapRow(ResultSet rs, int rowNum)
|
||||
throws SQLException {
|
||||
String javaType = rs.getString("class");
|
||||
Serializable identifier = (Serializable) rs.getObject("obj_id");
|
||||
identifier = aclClassIdUtils.identifierFrom(identifier, rs);
|
||||
Long identifier = new Long(rs.getLong("obj_id"));
|
||||
|
||||
return new ObjectIdentityImpl(javaType, identifier);
|
||||
}
|
||||
@@ -150,24 +138,4 @@ public class JdbcAclService implements AclService {
|
||||
public void setFindChildrenQuery(String findChildrenSql) {
|
||||
this.findChildrenSql = findChildrenSql;
|
||||
}
|
||||
|
||||
public void setAclClassIdSupported(boolean aclClassIdSupported) {
|
||||
this.aclClassIdSupported = aclClassIdSupported;
|
||||
if (aclClassIdSupported) {
|
||||
// Change the default insert if it hasn't been overridden
|
||||
if (this.findChildrenSql.equals(DEFAULT_SELECT_ACL_WITH_PARENT_SQL)) {
|
||||
this.findChildrenSql = DEFAULT_SELECT_ACL_WITH_PARENT_SQL_WITH_CLASS_ID_TYPE;
|
||||
} else {
|
||||
log.debug("Find children statement has already been overridden, so not overridding the default");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setAclClassIdUtils(AclClassIdUtils aclClassIdUtils) {
|
||||
this.aclClassIdUtils = aclClassIdUtils;
|
||||
}
|
||||
|
||||
protected boolean isAclClassIdSupported() {
|
||||
return aclClassIdSupported;
|
||||
}
|
||||
}
|
||||
|
||||
+5
-24
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2004, 2005, 2006, 2017 Acegi Technology Pty Limited
|
||||
* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -58,8 +58,6 @@ import org.springframework.util.Assert;
|
||||
* @author Johannes Zlattinger
|
||||
*/
|
||||
public class JdbcMutableAclService extends JdbcAclService implements MutableAclService {
|
||||
private static final String DEFAULT_INSERT_INTO_ACL_CLASS = "insert into acl_class (class) values (?)";
|
||||
private static final String DEFAULT_INSERT_INTO_ACL_CLASS_WITH_ID = "insert into acl_class (class, class_id_type) values (?, ?)";
|
||||
// ~ Instance fields
|
||||
// ================================================================================================
|
||||
|
||||
@@ -69,7 +67,7 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
|
||||
private String deleteObjectIdentityByPrimaryKey = "delete from acl_object_identity where id=?";
|
||||
private String classIdentityQuery = "call identity()";
|
||||
private String sidIdentityQuery = "call identity()";
|
||||
private String insertClass = DEFAULT_INSERT_INTO_ACL_CLASS;
|
||||
private String insertClass = "insert into acl_class (class) values (?)";
|
||||
private String insertEntry = "insert into acl_entry "
|
||||
+ "(acl_object_identity, ace_order, sid, mask, granting, audit_success, audit_failure)"
|
||||
+ "values (?, ?, ?, ?, ?, ?, ?)";
|
||||
@@ -169,7 +167,7 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
|
||||
*/
|
||||
protected void createObjectIdentity(ObjectIdentity object, Sid owner) {
|
||||
Long sidId = createOrRetrieveSidPrimaryKey(owner, true);
|
||||
Long classId = createOrRetrieveClassPrimaryKey(object.getType(), true, object.getIdentifier().getClass());
|
||||
Long classId = createOrRetrieveClassPrimaryKey(object.getType(), true);
|
||||
jdbcTemplate.update(insertObjectIdentity, classId, object.getIdentifier(), sidId,
|
||||
Boolean.TRUE);
|
||||
}
|
||||
@@ -183,7 +181,7 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
|
||||
*
|
||||
* @return the primary key or null if not found
|
||||
*/
|
||||
protected Long createOrRetrieveClassPrimaryKey(String type, boolean allowCreate, Class idType) {
|
||||
protected Long createOrRetrieveClassPrimaryKey(String type, boolean allowCreate) {
|
||||
List<Long> classIds = jdbcTemplate.queryForList(selectClassPrimaryKey,
|
||||
new Object[] { type }, Long.class);
|
||||
|
||||
@@ -192,11 +190,7 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
|
||||
}
|
||||
|
||||
if (allowCreate) {
|
||||
if (!isAclClassIdSupported()) {
|
||||
jdbcTemplate.update(insertClass, type);
|
||||
} else {
|
||||
jdbcTemplate.update(insertClass, type, idType.getCanonicalName());
|
||||
}
|
||||
jdbcTemplate.update(insertClass, type);
|
||||
Assert.isTrue(TransactionSynchronizationManager.isSynchronizationActive(),
|
||||
"Transaction must be running");
|
||||
return jdbcTemplate.queryForObject(classIdentityQuery, Long.class);
|
||||
@@ -491,17 +485,4 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
|
||||
public void setForeignKeysInDatabase(boolean foreignKeysInDatabase) {
|
||||
this.foreignKeysInDatabase = foreignKeysInDatabase;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAclClassIdSupported(boolean aclClassIdSupported) {
|
||||
super.setAclClassIdSupported(aclClassIdSupported);
|
||||
if (aclClassIdSupported) {
|
||||
// Change the default insert if it hasn't been overridden
|
||||
if (this.insertClass.equals(DEFAULT_INSERT_INTO_ACL_CLASS)) {
|
||||
this.insertClass = DEFAULT_INSERT_INTO_ACL_CLASS_WITH_ID;
|
||||
} else {
|
||||
log.debug("Insert class statement has already been overridden, so not overridding the default");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ CREATE TABLE acl_class (
|
||||
CREATE TABLE acl_object_identity (
|
||||
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
object_id_class BIGINT UNSIGNED NOT NULL,
|
||||
object_id_identity VARCHAR(36) NOT NULL,
|
||||
object_id_identity BIGINT NOT NULL,
|
||||
parent_object BIGINT UNSIGNED,
|
||||
owner_sid BIGINT UNSIGNED,
|
||||
entries_inheriting BOOLEAN NOT NULL,
|
||||
|
||||
@@ -43,7 +43,7 @@ END;
|
||||
CREATE TABLE acl_object_identity (
|
||||
id NUMBER(38) NOT NULL PRIMARY KEY,
|
||||
object_id_class NUMBER(38) NOT NULL,
|
||||
object_id_identity NVARCHAR2(36) NOT NULL,
|
||||
object_id_identity NUMBER(38) NOT NULL,
|
||||
parent_object NUMBER(38),
|
||||
owner_sid NUMBER(38),
|
||||
entries_inheriting NUMBER(1) NOT NULL CHECK (entries_inheriting in (0, 1)),
|
||||
|
||||
@@ -15,14 +15,13 @@ create table acl_sid(
|
||||
create table acl_class(
|
||||
id bigserial not null primary key,
|
||||
class varchar(100) not null,
|
||||
class_id_type varchar(100),
|
||||
constraint unique_uk_2 unique(class)
|
||||
);
|
||||
|
||||
create table acl_object_identity(
|
||||
id bigserial primary key,
|
||||
object_id_class bigint not null,
|
||||
object_id_identity varchar(36) not null,
|
||||
object_id_identity bigint not null,
|
||||
parent_object bigint,
|
||||
owner_sid bigint,
|
||||
entries_inheriting boolean not null,
|
||||
|
||||
@@ -21,7 +21,7 @@ CREATE TABLE acl_class (
|
||||
CREATE TABLE acl_object_identity (
|
||||
id BIGINT NOT NULL IDENTITY PRIMARY KEY,
|
||||
object_id_class BIGINT NOT NULL,
|
||||
object_id_identity VARCHAR(36) NOT NULL,
|
||||
object_id_identity BIGINT NOT NULL,
|
||||
parent_object BIGINT,
|
||||
owner_sid BIGINT,
|
||||
entries_inheriting BIT NOT NULL,
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
-- ACL schema sql used in HSQLDB
|
||||
|
||||
-- drop table acl_entry;
|
||||
-- drop table acl_object_identity;
|
||||
-- drop table acl_class;
|
||||
-- drop table acl_sid;
|
||||
|
||||
create table acl_sid(
|
||||
id bigint generated by default as identity(start with 100) not null primary key,
|
||||
principal boolean not null,
|
||||
sid varchar_ignorecase(100) not null,
|
||||
constraint unique_uk_1 unique(sid,principal)
|
||||
);
|
||||
|
||||
create table acl_class(
|
||||
id bigint generated by default as identity(start with 100) not null primary key,
|
||||
class varchar_ignorecase(100) not null,
|
||||
class_id_type varchar_ignorecase(100),
|
||||
constraint unique_uk_2 unique(class)
|
||||
);
|
||||
|
||||
create table acl_object_identity(
|
||||
id bigint generated by default as identity(start with 100) not null primary key,
|
||||
object_id_class bigint not null,
|
||||
object_id_identity varchar_ignorecase(36) not null,
|
||||
parent_object bigint,
|
||||
owner_sid bigint,
|
||||
entries_inheriting boolean not null,
|
||||
constraint unique_uk_3 unique(object_id_class,object_id_identity),
|
||||
constraint foreign_fk_1 foreign key(parent_object)references acl_object_identity(id),
|
||||
constraint foreign_fk_2 foreign key(object_id_class)references acl_class(id),
|
||||
constraint foreign_fk_3 foreign key(owner_sid)references acl_sid(id)
|
||||
);
|
||||
|
||||
create table acl_entry(
|
||||
id bigint generated by default as identity(start with 100) not null primary key,
|
||||
acl_object_identity bigint not null,
|
||||
ace_order int not null,
|
||||
sid bigint not null,
|
||||
mask integer not null,
|
||||
granting boolean not null,
|
||||
audit_success boolean not null,
|
||||
audit_failure boolean not null,
|
||||
constraint unique_uk_4 unique(acl_object_identity,ace_order),
|
||||
constraint foreign_fk_4 foreign key(acl_object_identity) references acl_object_identity(id),
|
||||
constraint foreign_fk_5 foreign key(sid) references acl_sid(id)
|
||||
);
|
||||
+3
-3
@@ -40,9 +40,9 @@ public class AclEntryAfterInvocationCollectionFilteringProviderTests {
|
||||
public void objectsAreRemovedIfPermissionDenied() throws Exception {
|
||||
AclService service = mock(AclService.class);
|
||||
Acl acl = mock(Acl.class);
|
||||
when(acl.isGranted(any(), any(), anyBoolean())).thenReturn(
|
||||
when(acl.isGranted(any(List.class), any(List.class), anyBoolean())).thenReturn(
|
||||
false);
|
||||
when(service.readAclById(any(), any())).thenReturn(
|
||||
when(service.readAclById(any(ObjectIdentity.class), any(List.class))).thenReturn(
|
||||
acl);
|
||||
AclEntryAfterInvocationCollectionFilteringProvider provider = new AclEntryAfterInvocationCollectionFilteringProvider(
|
||||
service, Arrays.asList(mock(Permission.class)));
|
||||
@@ -82,7 +82,7 @@ public class AclEntryAfterInvocationCollectionFilteringProviderTests {
|
||||
|
||||
assertThat(provider.decide(mock(Authentication.class), new Object(),
|
||||
SecurityConfig.createList("AFTER_ACL_COLLECTION_READ"), null))
|
||||
.isNull();
|
||||
.isNull();;
|
||||
verify(service, never()).readAclById(any(ObjectIdentity.class), any(List.class));
|
||||
}
|
||||
|
||||
|
||||
+4
-4
@@ -54,7 +54,7 @@ public class AclEntryAfterInvocationProviderTests {
|
||||
Acl acl = mock(Acl.class);
|
||||
when(acl.isGranted(any(List.class), any(List.class), anyBoolean())).thenReturn(
|
||||
true);
|
||||
when(service.readAclById(any(), any())).thenReturn(
|
||||
when(service.readAclById(any(ObjectIdentity.class), any(List.class))).thenReturn(
|
||||
acl);
|
||||
AclEntryAfterInvocationProvider provider = new AclEntryAfterInvocationProvider(
|
||||
service, Arrays.asList(mock(Permission.class)));
|
||||
@@ -106,9 +106,9 @@ public class AclEntryAfterInvocationProviderTests {
|
||||
when(acl.isGranted(any(List.class), any(List.class), anyBoolean())).thenReturn(
|
||||
false);
|
||||
// Try a second time with no permissions found
|
||||
when(acl.isGranted(any(), any(List.class), anyBoolean())).thenThrow(
|
||||
when(acl.isGranted(any(List.class), any(List.class), anyBoolean())).thenThrow(
|
||||
new NotFoundException(""));
|
||||
when(service.readAclById(any(), any())).thenReturn(
|
||||
when(service.readAclById(any(ObjectIdentity.class), any(List.class))).thenReturn(
|
||||
acl);
|
||||
AclEntryAfterInvocationProvider provider = new AclEntryAfterInvocationProvider(
|
||||
service, Arrays.asList(mock(Permission.class)));
|
||||
@@ -138,7 +138,7 @@ public class AclEntryAfterInvocationProviderTests {
|
||||
|
||||
assertThat(provider.decide(mock(Authentication.class), new Object(),
|
||||
SecurityConfig.createList("AFTER_ACL_COLLECTION_READ"), null))
|
||||
.isNull();
|
||||
.isNull();;
|
||||
verify(service, never()).readAclById(any(ObjectIdentity.class), any(List.class));
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -23,7 +23,7 @@ import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.security.acls.model.Acl;
|
||||
import org.springframework.security.authentication.TestingAuthenticationToken;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
|
||||
@@ -495,7 +495,7 @@ public class AclImplTests {
|
||||
assertThat(acl.isSidLoaded(Arrays.asList(new GrantedAuthoritySid("ROLE_IGNORED"),
|
||||
new PrincipalSid("ben"))))
|
||||
.isTrue();
|
||||
assertThat(acl.isSidLoaded(Arrays.asList((Sid) new GrantedAuthoritySid(
|
||||
assertThat(acl.isSidLoaded(Arrays.asList((Sid)new GrantedAuthoritySid(
|
||||
"ROLE_IGNORED"))))
|
||||
.isTrue();
|
||||
assertThat(acl.isSidLoaded(BEN)).isTrue();
|
||||
@@ -507,7 +507,7 @@ public class AclImplTests {
|
||||
assertThat(acl.isSidLoaded(Arrays.asList((Sid) new GrantedAuthoritySid(
|
||||
"ROLE_GENERAL"), new GrantedAuthoritySid("ROLE_IGNORED"))))
|
||||
.isFalse();
|
||||
assertThat(acl.isSidLoaded(Arrays.asList((Sid) new GrantedAuthoritySid(
|
||||
assertThat(acl.isSidLoaded(Arrays.asList((Sid)new GrantedAuthoritySid(
|
||||
"ROLE_IGNORED"), new GrantedAuthoritySid("ROLE_GENERAL"))))
|
||||
.isFalse();
|
||||
}
|
||||
|
||||
-341
@@ -1,341 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.security.acls.jdbc;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import net.sf.ehcache.Cache;
|
||||
import net.sf.ehcache.CacheManager;
|
||||
import net.sf.ehcache.Ehcache;
|
||||
|
||||
import org.junit.*;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.security.acls.TargetObject;
|
||||
import org.springframework.security.acls.TargetObjectWithUUID;
|
||||
import org.springframework.security.acls.domain.*;
|
||||
import org.springframework.security.acls.model.Acl;
|
||||
import org.springframework.security.acls.model.AuditableAccessControlEntry;
|
||||
import org.springframework.security.acls.model.MutableAcl;
|
||||
import org.springframework.security.acls.model.NotFoundException;
|
||||
import org.springframework.security.acls.model.ObjectIdentity;
|
||||
import org.springframework.security.acls.model.Permission;
|
||||
import org.springframework.security.acls.model.Sid;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
/**
|
||||
* Tests {@link BasicLookupStrategy}
|
||||
*
|
||||
* @author Andrei Stefan
|
||||
*/
|
||||
public abstract class AbstractBasicLookupStrategyTests {
|
||||
|
||||
protected static final Sid BEN_SID = new PrincipalSid("ben");
|
||||
protected static final String TARGET_CLASS = TargetObject.class.getName();
|
||||
protected static final String TARGET_CLASS_WITH_UUID = TargetObjectWithUUID.class.getName();
|
||||
protected static final UUID OBJECT_IDENTITY_UUID = UUID.randomUUID();
|
||||
protected static final Long OBJECT_IDENTITY_LONG_AS_UUID = 110L;
|
||||
|
||||
// ~ Instance fields
|
||||
// ================================================================================================
|
||||
|
||||
private BasicLookupStrategy strategy;
|
||||
private static CacheManager cacheManager;
|
||||
|
||||
// ~ Methods
|
||||
// ========================================================================================================
|
||||
|
||||
public abstract JdbcTemplate getJdbcTemplate();
|
||||
|
||||
public abstract DataSource getDataSource();
|
||||
|
||||
@BeforeClass
|
||||
public static void initCacheManaer() {
|
||||
cacheManager = CacheManager.create();
|
||||
cacheManager.addCache(new Cache("basiclookuptestcache", 500, false, false, 30, 30));
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void shutdownCacheManager() {
|
||||
cacheManager.removalAll();
|
||||
cacheManager.shutdown();
|
||||
}
|
||||
|
||||
@Before
|
||||
public void populateDatabase() {
|
||||
String query = "INSERT INTO acl_sid(ID,PRINCIPAL,SID) VALUES (1,1,'ben');"
|
||||
+ "INSERT INTO acl_class(ID,CLASS) VALUES (2,'" + TARGET_CLASS + "');"
|
||||
+ "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (1,2,100,null,1,1);"
|
||||
+ "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (2,2,101,1,1,1);"
|
||||
+ "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (3,2,102,2,1,1);"
|
||||
+ "INSERT INTO acl_entry(ID,ACL_OBJECT_IDENTITY,ACE_ORDER,SID,MASK,GRANTING,AUDIT_SUCCESS,AUDIT_FAILURE) VALUES (1,1,0,1,1,1,0,0);"
|
||||
+ "INSERT INTO acl_entry(ID,ACL_OBJECT_IDENTITY,ACE_ORDER,SID,MASK,GRANTING,AUDIT_SUCCESS,AUDIT_FAILURE) VALUES (2,1,1,1,2,0,0,0);"
|
||||
+ "INSERT INTO acl_entry(ID,ACL_OBJECT_IDENTITY,ACE_ORDER,SID,MASK,GRANTING,AUDIT_SUCCESS,AUDIT_FAILURE) VALUES (3,2,0,1,8,1,0,0);"
|
||||
+ "INSERT INTO acl_entry(ID,ACL_OBJECT_IDENTITY,ACE_ORDER,SID,MASK,GRANTING,AUDIT_SUCCESS,AUDIT_FAILURE) VALUES (4,3,0,1,8,0,0,0);";
|
||||
getJdbcTemplate().execute(query);
|
||||
}
|
||||
|
||||
@Before
|
||||
public void initializeBeans() {
|
||||
strategy = new BasicLookupStrategy(getDataSource(), aclCache(), aclAuthStrategy(),
|
||||
new DefaultPermissionGrantingStrategy(new ConsoleAuditLogger()));
|
||||
strategy.setPermissionFactory(new DefaultPermissionFactory());
|
||||
}
|
||||
|
||||
protected AclAuthorizationStrategy aclAuthStrategy() {
|
||||
return new AclAuthorizationStrategyImpl(
|
||||
new SimpleGrantedAuthority("ROLE_ADMINISTRATOR"));
|
||||
}
|
||||
|
||||
protected EhCacheBasedAclCache aclCache() {
|
||||
return new EhCacheBasedAclCache(getCache(),
|
||||
new DefaultPermissionGrantingStrategy(new ConsoleAuditLogger()),
|
||||
new AclAuthorizationStrategyImpl(new SimpleGrantedAuthority("ROLE_USER")));
|
||||
}
|
||||
|
||||
|
||||
@After
|
||||
public void emptyDatabase() {
|
||||
String query = "DELETE FROM acl_entry;" + "DELETE FROM acl_object_identity WHERE ID = 9;"
|
||||
+ "DELETE FROM acl_object_identity WHERE ID = 8;" + "DELETE FROM acl_object_identity WHERE ID = 7;"
|
||||
+ "DELETE FROM acl_object_identity WHERE ID = 6;" + "DELETE FROM acl_object_identity WHERE ID = 5;"
|
||||
+ "DELETE FROM acl_object_identity WHERE ID = 4;" + "DELETE FROM acl_object_identity WHERE ID = 3;"
|
||||
+ "DELETE FROM acl_object_identity WHERE ID = 2;" + "DELETE FROM acl_object_identity WHERE ID = 1;"
|
||||
+ "DELETE FROM acl_class;" + "DELETE FROM acl_sid;";
|
||||
getJdbcTemplate().execute(query);
|
||||
}
|
||||
|
||||
protected Ehcache getCache() {
|
||||
Ehcache cache = cacheManager.getCache("basiclookuptestcache");
|
||||
cache.removeAll();
|
||||
return cache;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAclsRetrievalWithDefaultBatchSize() throws Exception {
|
||||
ObjectIdentity topParentOid = new ObjectIdentityImpl(TARGET_CLASS, new Long(100));
|
||||
ObjectIdentity middleParentOid = new ObjectIdentityImpl(TARGET_CLASS, new Long(101));
|
||||
// Deliberately use an integer for the child, to reproduce bug report in SEC-819
|
||||
ObjectIdentity childOid = new ObjectIdentityImpl(TARGET_CLASS, Integer.valueOf(102));
|
||||
|
||||
Map<ObjectIdentity, Acl> map = this.strategy
|
||||
.readAclsById(Arrays.asList(topParentOid, middleParentOid, childOid), null);
|
||||
checkEntries(topParentOid, middleParentOid, childOid, map);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAclsRetrievalFromCacheOnly() throws Exception {
|
||||
ObjectIdentity topParentOid = new ObjectIdentityImpl(TARGET_CLASS, Integer.valueOf(100));
|
||||
ObjectIdentity middleParentOid = new ObjectIdentityImpl(TARGET_CLASS, new Long(101));
|
||||
ObjectIdentity childOid = new ObjectIdentityImpl(TARGET_CLASS, new Long(102));
|
||||
|
||||
// Objects were put in cache
|
||||
strategy.readAclsById(Arrays.asList(topParentOid, middleParentOid, childOid), null);
|
||||
|
||||
// Let's empty the database to force acls retrieval from cache
|
||||
emptyDatabase();
|
||||
Map<ObjectIdentity, Acl> map = this.strategy
|
||||
.readAclsById(Arrays.asList(topParentOid, middleParentOid, childOid), null);
|
||||
|
||||
checkEntries(topParentOid, middleParentOid, childOid, map);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAclsRetrievalWithCustomBatchSize() throws Exception {
|
||||
ObjectIdentity topParentOid = new ObjectIdentityImpl(TARGET_CLASS, new Long(100));
|
||||
ObjectIdentity middleParentOid = new ObjectIdentityImpl(TARGET_CLASS, Integer.valueOf(101));
|
||||
ObjectIdentity childOid = new ObjectIdentityImpl(TARGET_CLASS, new Long(102));
|
||||
|
||||
// Set a batch size to allow multiple database queries in order to retrieve all
|
||||
// acls
|
||||
this.strategy.setBatchSize(1);
|
||||
Map<ObjectIdentity, Acl> map = this.strategy
|
||||
.readAclsById(Arrays.asList(topParentOid, middleParentOid, childOid), null);
|
||||
checkEntries(topParentOid, middleParentOid, childOid, map);
|
||||
}
|
||||
|
||||
private void checkEntries(ObjectIdentity topParentOid, ObjectIdentity middleParentOid, ObjectIdentity childOid,
|
||||
Map<ObjectIdentity, Acl> map) throws Exception {
|
||||
assertThat(map).hasSize(3);
|
||||
|
||||
MutableAcl topParent = (MutableAcl) map.get(topParentOid);
|
||||
MutableAcl middleParent = (MutableAcl) map.get(middleParentOid);
|
||||
MutableAcl child = (MutableAcl) map.get(childOid);
|
||||
|
||||
// Check the retrieved versions has IDs
|
||||
assertThat(topParent.getId()).isNotNull();
|
||||
assertThat(middleParent.getId()).isNotNull();
|
||||
assertThat(child.getId()).isNotNull();
|
||||
|
||||
// Check their parents were correctly retrieved
|
||||
assertThat(topParent.getParentAcl()).isNull();
|
||||
assertThat(middleParent.getParentAcl().getObjectIdentity()).isEqualTo(topParentOid);
|
||||
assertThat(child.getParentAcl().getObjectIdentity()).isEqualTo(middleParentOid);
|
||||
|
||||
// Check their ACEs were correctly retrieved
|
||||
assertThat(topParent.getEntries()).hasSize(2);
|
||||
assertThat(middleParent.getEntries()).hasSize(1);
|
||||
assertThat(child.getEntries()).hasSize(1);
|
||||
|
||||
// Check object identities were correctly retrieved
|
||||
assertThat(topParent.getObjectIdentity()).isEqualTo(topParentOid);
|
||||
assertThat(middleParent.getObjectIdentity()).isEqualTo(middleParentOid);
|
||||
assertThat(child.getObjectIdentity()).isEqualTo(childOid);
|
||||
|
||||
// Check each entry
|
||||
assertThat(topParent.isEntriesInheriting()).isTrue();
|
||||
assertThat(Long.valueOf(1)).isEqualTo(topParent.getId());
|
||||
assertThat(new PrincipalSid("ben")).isEqualTo(topParent.getOwner());
|
||||
assertThat(Long.valueOf(1)).isEqualTo(topParent.getEntries().get(0).getId());
|
||||
assertThat(topParent.getEntries().get(0).getPermission()).isEqualTo(BasePermission.READ);
|
||||
assertThat(topParent.getEntries().get(0).getSid()).isEqualTo(new PrincipalSid("ben"));
|
||||
assertThat(((AuditableAccessControlEntry) topParent.getEntries().get(0)).isAuditFailure()).isFalse();
|
||||
assertThat(((AuditableAccessControlEntry) topParent.getEntries().get(0)).isAuditSuccess()).isFalse();
|
||||
assertThat((topParent.getEntries().get(0)).isGranting()).isTrue();
|
||||
|
||||
assertThat(Long.valueOf(2)).isEqualTo(topParent.getEntries().get(1).getId());
|
||||
assertThat(topParent.getEntries().get(1).getPermission()).isEqualTo(BasePermission.WRITE);
|
||||
assertThat(topParent.getEntries().get(1).getSid()).isEqualTo(new PrincipalSid("ben"));
|
||||
assertThat(((AuditableAccessControlEntry) topParent.getEntries().get(1)).isAuditFailure()).isFalse();
|
||||
assertThat(((AuditableAccessControlEntry) topParent.getEntries().get(1)).isAuditSuccess()).isFalse();
|
||||
assertThat(topParent.getEntries().get(1).isGranting()).isFalse();
|
||||
|
||||
assertThat(middleParent.isEntriesInheriting()).isTrue();
|
||||
assertThat(Long.valueOf(2)).isEqualTo(middleParent.getId());
|
||||
assertThat(new PrincipalSid("ben")).isEqualTo(middleParent.getOwner());
|
||||
assertThat(Long.valueOf(3)).isEqualTo(middleParent.getEntries().get(0).getId());
|
||||
assertThat(middleParent.getEntries().get(0).getPermission()).isEqualTo(BasePermission.DELETE);
|
||||
assertThat(middleParent.getEntries().get(0).getSid()).isEqualTo(new PrincipalSid("ben"));
|
||||
assertThat(((AuditableAccessControlEntry) middleParent.getEntries().get(0)).isAuditFailure()).isFalse();
|
||||
assertThat(((AuditableAccessControlEntry) middleParent.getEntries().get(0)).isAuditSuccess()).isFalse();
|
||||
assertThat(middleParent.getEntries().get(0).isGranting()).isTrue();
|
||||
|
||||
assertThat(child.isEntriesInheriting()).isTrue();
|
||||
assertThat(Long.valueOf(3)).isEqualTo(child.getId());
|
||||
assertThat(new PrincipalSid("ben")).isEqualTo(child.getOwner());
|
||||
assertThat(Long.valueOf(4)).isEqualTo(child.getEntries().get(0).getId());
|
||||
assertThat(child.getEntries().get(0).getPermission()).isEqualTo(BasePermission.DELETE);
|
||||
assertThat(new PrincipalSid("ben")).isEqualTo(child.getEntries().get(0).getSid());
|
||||
assertThat(((AuditableAccessControlEntry) child.getEntries().get(0)).isAuditFailure()).isFalse();
|
||||
assertThat(((AuditableAccessControlEntry) child.getEntries().get(0)).isAuditSuccess()).isFalse();
|
||||
assertThat((child.getEntries().get(0)).isGranting()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAllParentsAreRetrievedWhenChildIsLoaded() throws Exception {
|
||||
String query = "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (6,2,103,1,1,1);";
|
||||
getJdbcTemplate().execute(query);
|
||||
|
||||
ObjectIdentity topParentOid = new ObjectIdentityImpl(TARGET_CLASS, Long.valueOf(100));
|
||||
ObjectIdentity middleParentOid = new ObjectIdentityImpl(TARGET_CLASS, Long.valueOf(101));
|
||||
ObjectIdentity childOid = new ObjectIdentityImpl(TARGET_CLASS, Long.valueOf(102));
|
||||
ObjectIdentity middleParent2Oid = new ObjectIdentityImpl(TARGET_CLASS, Long.valueOf(103));
|
||||
|
||||
// Retrieve the child
|
||||
Map<ObjectIdentity, Acl> map = this.strategy.readAclsById(Arrays.asList(childOid), null);
|
||||
|
||||
// Check that the child and all its parents were retrieved
|
||||
assertThat(map.get(childOid)).isNotNull();
|
||||
assertThat(map.get(childOid).getObjectIdentity()).isEqualTo(childOid);
|
||||
assertThat(map.get(middleParentOid)).isNotNull();
|
||||
assertThat(map.get(middleParentOid).getObjectIdentity()).isEqualTo(middleParentOid);
|
||||
assertThat(map.get(topParentOid)).isNotNull();
|
||||
assertThat(map.get(topParentOid).getObjectIdentity()).isEqualTo(topParentOid);
|
||||
|
||||
// The second parent shouldn't have been retrieved
|
||||
assertThat(map.get(middleParent2Oid)).isNull();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test created from SEC-590.
|
||||
*/
|
||||
@Test
|
||||
public void testReadAllObjectIdentitiesWhenLastElementIsAlreadyCached() throws Exception {
|
||||
String query = "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (6,2,105,null,1,1);"
|
||||
+ "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (7,2,106,6,1,1);"
|
||||
+ "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (8,2,107,6,1,1);"
|
||||
+ "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (9,2,108,7,1,1);"
|
||||
+ "INSERT INTO acl_entry(ID,ACL_OBJECT_IDENTITY,ACE_ORDER,SID,MASK,GRANTING,AUDIT_SUCCESS,AUDIT_FAILURE) VALUES (7,6,0,1,1,1,0,0)";
|
||||
getJdbcTemplate().execute(query);
|
||||
|
||||
ObjectIdentity grandParentOid = new ObjectIdentityImpl(TARGET_CLASS, new Long(104));
|
||||
ObjectIdentity parent1Oid = new ObjectIdentityImpl(TARGET_CLASS, new Long(105));
|
||||
ObjectIdentity parent2Oid = new ObjectIdentityImpl(TARGET_CLASS, Integer.valueOf(106));
|
||||
ObjectIdentity childOid = new ObjectIdentityImpl(TARGET_CLASS, Integer.valueOf(107));
|
||||
|
||||
// First lookup only child, thus populating the cache with grandParent,
|
||||
// parent1
|
||||
// and child
|
||||
List<Permission> checkPermission = Arrays.asList(BasePermission.READ);
|
||||
List<Sid> sids = Arrays.asList(BEN_SID);
|
||||
List<ObjectIdentity> childOids = Arrays.asList(childOid);
|
||||
|
||||
strategy.setBatchSize(6);
|
||||
Map<ObjectIdentity, Acl> foundAcls = strategy.readAclsById(childOids, sids);
|
||||
|
||||
Acl foundChildAcl = foundAcls.get(childOid);
|
||||
assertThat(foundChildAcl).isNotNull();
|
||||
assertThat(foundChildAcl.isGranted(checkPermission, sids, false)).isTrue();
|
||||
|
||||
// Search for object identities has to be done in the following order:
|
||||
// last
|
||||
// element have to be one which
|
||||
// is already in cache and the element before it must not be stored in
|
||||
// cache
|
||||
List<ObjectIdentity> allOids = Arrays.asList(grandParentOid, parent1Oid, parent2Oid, childOid);
|
||||
try {
|
||||
foundAcls = strategy.readAclsById(allOids, sids);
|
||||
|
||||
} catch (NotFoundException notExpected) {
|
||||
fail("It shouldn't have thrown NotFoundException");
|
||||
}
|
||||
|
||||
Acl foundParent2Acl = foundAcls.get(parent2Oid);
|
||||
assertThat(foundParent2Acl).isNotNull();
|
||||
assertThat(foundParent2Acl.isGranted(checkPermission, sids, false)).isTrue();
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void nullOwnerIsNotSupported() {
|
||||
String query = "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (6,2,104,null,null,1);";
|
||||
|
||||
getJdbcTemplate().execute(query);
|
||||
|
||||
ObjectIdentity oid = new ObjectIdentityImpl(TARGET_CLASS, new Long(104));
|
||||
|
||||
strategy.readAclsById(Arrays.asList(oid), Arrays.asList(BEN_SID));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreatePrincipalSid() {
|
||||
Sid result = strategy.createSid(true, "sid");
|
||||
|
||||
assertThat(result.getClass()).isEqualTo(PrincipalSid.class);
|
||||
assertThat(((PrincipalSid) result).getPrincipal()).isEqualTo("sid");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateGrantedAuthority() {
|
||||
Sid result = strategy.createSid(false, "sid");
|
||||
|
||||
assertThat(result.getClass()).isEqualTo(GrantedAuthoritySid.class);
|
||||
assertThat(((GrantedAuthoritySid) result).getGrantedAuthority()).isEqualTo("sid");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,160 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.security.acls.jdbc;
|
||||
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
|
||||
/**
|
||||
* Tests for {@link AclClassIdUtils}.
|
||||
* @author paulwheeler
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class AclClassIdUtilsTest {
|
||||
|
||||
private static final Long DEFAULT_IDENTIFIER = 999L;
|
||||
private static final String DEFAULT_IDENTIFIER_AS_STRING = DEFAULT_IDENTIFIER.toString();
|
||||
|
||||
@Mock
|
||||
private ResultSet resultSet;
|
||||
@Mock
|
||||
private ConversionService conversionService;
|
||||
@InjectMocks
|
||||
private AclClassIdUtils aclClassIdUtils;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
given(conversionService.canConvert(String.class, Long.class)).willReturn(true);
|
||||
given(conversionService.convert(DEFAULT_IDENTIFIER, Long.class)).willReturn(new Long(DEFAULT_IDENTIFIER));
|
||||
given(conversionService.convert(DEFAULT_IDENTIFIER_AS_STRING, Long.class)).willReturn(new Long(DEFAULT_IDENTIFIER));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldReturnLongIfIdentifierIsNotStringAndNoConversionService() throws SQLException {
|
||||
// given
|
||||
AclClassIdUtils aclClassIdUtilsWithoutConversionSvc = new AclClassIdUtils();
|
||||
|
||||
// when
|
||||
Serializable newIdentifier = aclClassIdUtilsWithoutConversionSvc.identifierFrom(DEFAULT_IDENTIFIER, resultSet);
|
||||
|
||||
// then
|
||||
assertThat(newIdentifier).isEqualTo(DEFAULT_IDENTIFIER);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldReturnLongIfIdentifierIsNotString() throws SQLException {
|
||||
// given
|
||||
Long prevIdentifier = 999L;
|
||||
|
||||
// when
|
||||
Serializable newIdentifier = aclClassIdUtils.identifierFrom(prevIdentifier, resultSet);
|
||||
|
||||
// then
|
||||
assertThat(newIdentifier).isEqualTo(prevIdentifier);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldReturnLongIfClassIdTypeIsNull() throws SQLException {
|
||||
// given
|
||||
given(resultSet.getString("class_id_type")).willReturn(null);
|
||||
|
||||
// when
|
||||
Serializable newIdentifier = aclClassIdUtils.identifierFrom(DEFAULT_IDENTIFIER_AS_STRING, resultSet);
|
||||
|
||||
// then
|
||||
assertThat(newIdentifier).isEqualTo(DEFAULT_IDENTIFIER);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldReturnLongIfNoClassIdTypeColumn() throws SQLException {
|
||||
// given
|
||||
given(resultSet.getString("class_id_type")).willThrow(SQLException.class);
|
||||
|
||||
// when
|
||||
Serializable newIdentifier = aclClassIdUtils.identifierFrom(DEFAULT_IDENTIFIER_AS_STRING, resultSet);
|
||||
|
||||
// then
|
||||
assertThat(newIdentifier).isEqualTo(DEFAULT_IDENTIFIER);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldReturnLongIfTypeClassNotFound() throws SQLException {
|
||||
// given
|
||||
given(resultSet.getString("class_id_type")).willReturn("com.example.UnknownType");
|
||||
|
||||
// when
|
||||
Serializable newIdentifier = aclClassIdUtils.identifierFrom(DEFAULT_IDENTIFIER_AS_STRING, resultSet);
|
||||
|
||||
// then
|
||||
assertThat(newIdentifier).isEqualTo(DEFAULT_IDENTIFIER);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldReturnLongIfTypeClassCannotBeConverted() throws SQLException {
|
||||
// given
|
||||
given(resultSet.getString("class_id_type")).willReturn("java.lang.Long");
|
||||
given(conversionService.canConvert(String.class, Long.class)).willReturn(false);
|
||||
|
||||
// when
|
||||
Serializable newIdentifier = aclClassIdUtils.identifierFrom(DEFAULT_IDENTIFIER_AS_STRING, resultSet);
|
||||
|
||||
// then
|
||||
assertThat(newIdentifier).isEqualTo(DEFAULT_IDENTIFIER);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldReturnLongWhenLongClassIdType() throws SQLException {
|
||||
// given
|
||||
given(resultSet.getString("class_id_type")).willReturn("java.lang.Long");
|
||||
|
||||
// when
|
||||
Serializable newIdentifier = aclClassIdUtils.identifierFrom(DEFAULT_IDENTIFIER_AS_STRING, resultSet);
|
||||
|
||||
// then
|
||||
assertThat(newIdentifier).isEqualTo(DEFAULT_IDENTIFIER);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldReturnUUIDWhenUUIDClassIdType() throws SQLException {
|
||||
// given
|
||||
UUID identifier = UUID.randomUUID();
|
||||
String identifierAsString = identifier.toString();
|
||||
given(resultSet.getString("class_id_type")).willReturn("java.util.UUID");
|
||||
given(conversionService.canConvert(String.class, UUID.class)).willReturn(true);
|
||||
given(conversionService.convert(identifierAsString, UUID.class)).willReturn(UUID.fromString(identifierAsString));
|
||||
|
||||
// when
|
||||
Serializable newIdentifier = aclClassIdUtils.identifierFrom(identifier.toString(), resultSet);
|
||||
|
||||
// then
|
||||
assertThat(newIdentifier).isEqualTo(identifier);
|
||||
}
|
||||
|
||||
}
|
||||
+307
-16
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,39 +15,330 @@
|
||||
*/
|
||||
package org.springframework.security.acls.jdbc;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import net.sf.ehcache.Cache;
|
||||
import net.sf.ehcache.CacheManager;
|
||||
import net.sf.ehcache.Ehcache;
|
||||
import org.junit.*;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.datasource.SingleConnectionDataSource;
|
||||
import org.springframework.security.acls.domain.*;
|
||||
import org.springframework.security.acls.model.Acl;
|
||||
import org.springframework.security.acls.model.AuditableAccessControlEntry;
|
||||
import org.springframework.security.acls.model.MutableAcl;
|
||||
import org.springframework.security.acls.model.NotFoundException;
|
||||
import org.springframework.security.acls.model.ObjectIdentity;
|
||||
import org.springframework.security.acls.model.Permission;
|
||||
import org.springframework.security.acls.model.Sid;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.util.FileCopyUtils;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Tests {@link BasicLookupStrategy} with Acl Class type id not specified.
|
||||
* Tests {@link BasicLookupStrategy}
|
||||
*
|
||||
* @author Andrei Stefan
|
||||
* @author Paul Wheeler
|
||||
*/
|
||||
public class BasicLookupStrategyTests extends AbstractBasicLookupStrategyTests {
|
||||
private static final BasicLookupStrategyTestsDbHelper DATABASE_HELPER = new BasicLookupStrategyTestsDbHelper();
|
||||
public class BasicLookupStrategyTests {
|
||||
|
||||
private static final Sid BEN_SID = new PrincipalSid("ben");
|
||||
private static final String TARGET_CLASS = "org.springframework.security.acls.TargetObject";
|
||||
|
||||
// ~ Instance fields
|
||||
// ================================================================================================
|
||||
|
||||
private static JdbcTemplate jdbcTemplate;
|
||||
private BasicLookupStrategy strategy;
|
||||
private static SingleConnectionDataSource dataSource;
|
||||
private static CacheManager cacheManager;
|
||||
|
||||
// ~ Methods
|
||||
// ========================================================================================================
|
||||
@BeforeClass
|
||||
public static void initCacheManaer() {
|
||||
cacheManager = CacheManager.create();
|
||||
cacheManager.addCache(new Cache("basiclookuptestcache", 500, false, false, 30, 30));
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void createDatabase() throws Exception {
|
||||
DATABASE_HELPER.createDatabase();
|
||||
dataSource = new SingleConnectionDataSource("jdbc:hsqldb:mem:lookupstrategytest", "sa", "", true);
|
||||
dataSource.setDriverClassName("org.hsqldb.jdbcDriver");
|
||||
jdbcTemplate = new JdbcTemplate(dataSource);
|
||||
|
||||
Resource resource = new ClassPathResource("createAclSchema.sql");
|
||||
String sql = new String(FileCopyUtils.copyToByteArray(resource.getInputStream()));
|
||||
jdbcTemplate.execute(sql);
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void dropDatabase() throws Exception {
|
||||
DATABASE_HELPER.getDataSource().destroy();
|
||||
dataSource.destroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JdbcTemplate getJdbcTemplate() {
|
||||
return DATABASE_HELPER.getJdbcTemplate();
|
||||
@AfterClass
|
||||
public static void shutdownCacheManager() {
|
||||
cacheManager.removalAll();
|
||||
cacheManager.shutdown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataSource getDataSource() {
|
||||
return DATABASE_HELPER.getDataSource();
|
||||
@Before
|
||||
public void populateDatabase() {
|
||||
String query = "INSERT INTO acl_sid(ID,PRINCIPAL,SID) VALUES (1,1,'ben');"
|
||||
+ "INSERT INTO acl_class(ID,CLASS) VALUES (2,'" + TARGET_CLASS + "');"
|
||||
+ "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (1,2,100,null,1,1);"
|
||||
+ "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (2,2,101,1,1,1);"
|
||||
+ "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (3,2,102,2,1,1);"
|
||||
+ "INSERT INTO acl_entry(ID,ACL_OBJECT_IDENTITY,ACE_ORDER,SID,MASK,GRANTING,AUDIT_SUCCESS,AUDIT_FAILURE) VALUES (1,1,0,1,1,1,0,0);"
|
||||
+ "INSERT INTO acl_entry(ID,ACL_OBJECT_IDENTITY,ACE_ORDER,SID,MASK,GRANTING,AUDIT_SUCCESS,AUDIT_FAILURE) VALUES (2,1,1,1,2,0,0,0);"
|
||||
+ "INSERT INTO acl_entry(ID,ACL_OBJECT_IDENTITY,ACE_ORDER,SID,MASK,GRANTING,AUDIT_SUCCESS,AUDIT_FAILURE) VALUES (3,2,0,1,8,1,0,0);"
|
||||
+ "INSERT INTO acl_entry(ID,ACL_OBJECT_IDENTITY,ACE_ORDER,SID,MASK,GRANTING,AUDIT_SUCCESS,AUDIT_FAILURE) VALUES (4,3,0,1,8,0,0,0);";
|
||||
jdbcTemplate.execute(query);
|
||||
}
|
||||
|
||||
@Before
|
||||
public void initializeBeans() {
|
||||
EhCacheBasedAclCache cache = new EhCacheBasedAclCache(getCache(),
|
||||
new DefaultPermissionGrantingStrategy(new ConsoleAuditLogger()),
|
||||
new AclAuthorizationStrategyImpl(new SimpleGrantedAuthority("ROLE_USER")));
|
||||
AclAuthorizationStrategy authorizationStrategy = new AclAuthorizationStrategyImpl(
|
||||
new SimpleGrantedAuthority("ROLE_ADMINISTRATOR"));
|
||||
strategy = new BasicLookupStrategy(dataSource, cache, authorizationStrategy,
|
||||
new DefaultPermissionGrantingStrategy(new ConsoleAuditLogger()));
|
||||
strategy.setPermissionFactory(new DefaultPermissionFactory());
|
||||
}
|
||||
|
||||
@After
|
||||
public void emptyDatabase() {
|
||||
String query = "DELETE FROM acl_entry;" + "DELETE FROM acl_object_identity WHERE ID = 7;"
|
||||
+ "DELETE FROM acl_object_identity WHERE ID = 6;" + "DELETE FROM acl_object_identity WHERE ID = 5;"
|
||||
+ "DELETE FROM acl_object_identity WHERE ID = 4;" + "DELETE FROM acl_object_identity WHERE ID = 3;"
|
||||
+ "DELETE FROM acl_object_identity WHERE ID = 2;" + "DELETE FROM acl_object_identity WHERE ID = 1;"
|
||||
+ "DELETE FROM acl_class;" + "DELETE FROM acl_sid;";
|
||||
jdbcTemplate.execute(query);
|
||||
}
|
||||
|
||||
private Ehcache getCache() {
|
||||
Ehcache cache = cacheManager.getCache("basiclookuptestcache");
|
||||
cache.removeAll();
|
||||
return cache;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAclsRetrievalWithDefaultBatchSize() throws Exception {
|
||||
ObjectIdentity topParentOid = new ObjectIdentityImpl(TARGET_CLASS, new Long(100));
|
||||
ObjectIdentity middleParentOid = new ObjectIdentityImpl(TARGET_CLASS, new Long(101));
|
||||
// Deliberately use an integer for the child, to reproduce bug report in
|
||||
// SEC-819
|
||||
ObjectIdentity childOid = new ObjectIdentityImpl(TARGET_CLASS, Integer.valueOf(102));
|
||||
|
||||
Map<ObjectIdentity, Acl> map = this.strategy
|
||||
.readAclsById(Arrays.asList(topParentOid, middleParentOid, childOid), null);
|
||||
checkEntries(topParentOid, middleParentOid, childOid, map);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAclsRetrievalFromCacheOnly() throws Exception {
|
||||
ObjectIdentity topParentOid = new ObjectIdentityImpl(TARGET_CLASS, Integer.valueOf(100));
|
||||
ObjectIdentity middleParentOid = new ObjectIdentityImpl(TARGET_CLASS, new Long(101));
|
||||
ObjectIdentity childOid = new ObjectIdentityImpl(TARGET_CLASS, new Long(102));
|
||||
|
||||
// Objects were put in cache
|
||||
strategy.readAclsById(Arrays.asList(topParentOid, middleParentOid, childOid), null);
|
||||
|
||||
// Let's empty the database to force acls retrieval from cache
|
||||
emptyDatabase();
|
||||
Map<ObjectIdentity, Acl> map = this.strategy
|
||||
.readAclsById(Arrays.asList(topParentOid, middleParentOid, childOid), null);
|
||||
|
||||
checkEntries(topParentOid, middleParentOid, childOid, map);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAclsRetrievalWithCustomBatchSize() throws Exception {
|
||||
ObjectIdentity topParentOid = new ObjectIdentityImpl(TARGET_CLASS, new Long(100));
|
||||
ObjectIdentity middleParentOid = new ObjectIdentityImpl(TARGET_CLASS, Integer.valueOf(101));
|
||||
ObjectIdentity childOid = new ObjectIdentityImpl(TARGET_CLASS, new Long(102));
|
||||
|
||||
// Set a batch size to allow multiple database queries in order to
|
||||
// retrieve all
|
||||
// acls
|
||||
this.strategy.setBatchSize(1);
|
||||
Map<ObjectIdentity, Acl> map = this.strategy
|
||||
.readAclsById(Arrays.asList(topParentOid, middleParentOid, childOid), null);
|
||||
checkEntries(topParentOid, middleParentOid, childOid, map);
|
||||
}
|
||||
|
||||
private void checkEntries(ObjectIdentity topParentOid, ObjectIdentity middleParentOid, ObjectIdentity childOid,
|
||||
Map<ObjectIdentity, Acl> map) throws Exception {
|
||||
assertThat(map).hasSize(3);
|
||||
|
||||
MutableAcl topParent = (MutableAcl) map.get(topParentOid);
|
||||
MutableAcl middleParent = (MutableAcl) map.get(middleParentOid);
|
||||
MutableAcl child = (MutableAcl) map.get(childOid);
|
||||
|
||||
// Check the retrieved versions has IDs
|
||||
assertThat(topParent.getId()).isNotNull();
|
||||
assertThat(middleParent.getId()).isNotNull();
|
||||
assertThat(child.getId()).isNotNull();
|
||||
|
||||
// Check their parents were correctly retrieved
|
||||
assertThat(topParent.getParentAcl()).isNull();
|
||||
assertThat(middleParent.getParentAcl().getObjectIdentity()).isEqualTo(topParentOid);
|
||||
assertThat(child.getParentAcl().getObjectIdentity()).isEqualTo(middleParentOid);
|
||||
|
||||
// Check their ACEs were correctly retrieved
|
||||
assertThat(topParent.getEntries()).hasSize(2);
|
||||
assertThat(middleParent.getEntries()).hasSize(1);
|
||||
assertThat(child.getEntries()).hasSize(1);
|
||||
|
||||
// Check object identities were correctly retrieved
|
||||
assertThat(topParent.getObjectIdentity()).isEqualTo(topParentOid);
|
||||
assertThat(middleParent.getObjectIdentity()).isEqualTo(middleParentOid);
|
||||
assertThat(child.getObjectIdentity()).isEqualTo(childOid);
|
||||
|
||||
// Check each entry
|
||||
assertThat(topParent.isEntriesInheriting()).isTrue();
|
||||
assertThat(Long.valueOf(1)).isEqualTo(topParent.getId());
|
||||
assertThat(new PrincipalSid("ben")).isEqualTo(topParent.getOwner());
|
||||
assertThat(Long.valueOf(1)).isEqualTo(topParent.getEntries().get(0).getId());
|
||||
assertThat(topParent.getEntries().get(0).getPermission()).isEqualTo(BasePermission.READ);
|
||||
assertThat(topParent.getEntries().get(0).getSid()).isEqualTo(new PrincipalSid("ben"));
|
||||
assertThat(((AuditableAccessControlEntry) topParent.getEntries().get(0)).isAuditFailure()).isFalse();
|
||||
assertThat(((AuditableAccessControlEntry) topParent.getEntries().get(0)).isAuditSuccess()).isFalse();
|
||||
assertThat((topParent.getEntries().get(0)).isGranting()).isTrue();
|
||||
|
||||
assertThat(Long.valueOf(2)).isEqualTo(topParent.getEntries().get(1).getId());
|
||||
assertThat(topParent.getEntries().get(1).getPermission()).isEqualTo(BasePermission.WRITE);
|
||||
assertThat(topParent.getEntries().get(1).getSid()).isEqualTo(new PrincipalSid("ben"));
|
||||
assertThat(((AuditableAccessControlEntry) topParent.getEntries().get(1)).isAuditFailure()).isFalse();
|
||||
assertThat(((AuditableAccessControlEntry) topParent.getEntries().get(1)).isAuditSuccess()).isFalse();
|
||||
assertThat(topParent.getEntries().get(1).isGranting()).isFalse();
|
||||
|
||||
assertThat(middleParent.isEntriesInheriting()).isTrue();
|
||||
assertThat(Long.valueOf(2)).isEqualTo(middleParent.getId());
|
||||
assertThat(new PrincipalSid("ben")).isEqualTo(middleParent.getOwner());
|
||||
assertThat(Long.valueOf(3)).isEqualTo(middleParent.getEntries().get(0).getId());
|
||||
assertThat(middleParent.getEntries().get(0).getPermission()).isEqualTo(BasePermission.DELETE);
|
||||
assertThat(middleParent.getEntries().get(0).getSid()).isEqualTo(new PrincipalSid("ben"));
|
||||
assertThat(((AuditableAccessControlEntry) middleParent.getEntries().get(0)).isAuditFailure()).isFalse();
|
||||
assertThat(((AuditableAccessControlEntry) middleParent.getEntries().get(0)).isAuditSuccess()).isFalse();
|
||||
assertThat(middleParent.getEntries().get(0).isGranting()).isTrue();
|
||||
|
||||
assertThat(child.isEntriesInheriting()).isTrue();
|
||||
assertThat(Long.valueOf(3)).isEqualTo(child.getId());
|
||||
assertThat(new PrincipalSid("ben")).isEqualTo(child.getOwner());
|
||||
assertThat(Long.valueOf(4)).isEqualTo(child.getEntries().get(0).getId());
|
||||
assertThat(child.getEntries().get(0).getPermission()).isEqualTo(BasePermission.DELETE);
|
||||
assertThat(new PrincipalSid("ben")).isEqualTo(child.getEntries().get(0).getSid());
|
||||
assertThat(((AuditableAccessControlEntry) child.getEntries().get(0)).isAuditFailure()).isFalse();
|
||||
assertThat(((AuditableAccessControlEntry) child.getEntries().get(0)).isAuditSuccess()).isFalse();
|
||||
assertThat((child.getEntries().get(0)).isGranting()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAllParentsAreRetrievedWhenChildIsLoaded() throws Exception {
|
||||
String query = "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (4,2,103,1,1,1);";
|
||||
jdbcTemplate.execute(query);
|
||||
|
||||
ObjectIdentity topParentOid = new ObjectIdentityImpl(TARGET_CLASS, Long.valueOf(100));
|
||||
ObjectIdentity middleParentOid = new ObjectIdentityImpl(TARGET_CLASS, Long.valueOf(101));
|
||||
ObjectIdentity childOid = new ObjectIdentityImpl(TARGET_CLASS, Long.valueOf(102));
|
||||
ObjectIdentity middleParent2Oid = new ObjectIdentityImpl(TARGET_CLASS, Long.valueOf(103));
|
||||
|
||||
// Retrieve the child
|
||||
Map<ObjectIdentity, Acl> map = this.strategy.readAclsById(Arrays.asList(childOid), null);
|
||||
|
||||
// Check that the child and all its parents were retrieved
|
||||
assertThat(map.get(childOid)).isNotNull();
|
||||
assertThat(map.get(childOid).getObjectIdentity()).isEqualTo(childOid);
|
||||
assertThat(map.get(middleParentOid)).isNotNull();
|
||||
assertThat(map.get(middleParentOid).getObjectIdentity()).isEqualTo(middleParentOid);
|
||||
assertThat(map.get(topParentOid)).isNotNull();
|
||||
assertThat(map.get(topParentOid).getObjectIdentity()).isEqualTo(topParentOid);
|
||||
|
||||
// The second parent shouldn't have been retrieved
|
||||
assertThat(map.get(middleParent2Oid)).isNull();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test created from SEC-590.
|
||||
*/
|
||||
@Test
|
||||
public void testReadAllObjectIdentitiesWhenLastElementIsAlreadyCached() throws Exception {
|
||||
String query = "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (4,2,104,null,1,1);"
|
||||
+ "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (5,2,105,4,1,1);"
|
||||
+ "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (6,2,106,4,1,1);"
|
||||
+ "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (7,2,107,5,1,1);"
|
||||
+ "INSERT INTO acl_entry(ID,ACL_OBJECT_IDENTITY,ACE_ORDER,SID,MASK,GRANTING,AUDIT_SUCCESS,AUDIT_FAILURE) VALUES (5,4,0,1,1,1,0,0)";
|
||||
jdbcTemplate.execute(query);
|
||||
|
||||
ObjectIdentity grandParentOid = new ObjectIdentityImpl(TARGET_CLASS, new Long(104));
|
||||
ObjectIdentity parent1Oid = new ObjectIdentityImpl(TARGET_CLASS, new Long(105));
|
||||
ObjectIdentity parent2Oid = new ObjectIdentityImpl(TARGET_CLASS, Integer.valueOf(106));
|
||||
ObjectIdentity childOid = new ObjectIdentityImpl(TARGET_CLASS, Integer.valueOf(107));
|
||||
|
||||
// First lookup only child, thus populating the cache with grandParent,
|
||||
// parent1
|
||||
// and child
|
||||
List<Permission> checkPermission = Arrays.asList(BasePermission.READ);
|
||||
List<Sid> sids = Arrays.asList(BEN_SID);
|
||||
List<ObjectIdentity> childOids = Arrays.asList(childOid);
|
||||
|
||||
strategy.setBatchSize(6);
|
||||
Map<ObjectIdentity, Acl> foundAcls = strategy.readAclsById(childOids, sids);
|
||||
|
||||
Acl foundChildAcl = foundAcls.get(childOid);
|
||||
assertThat(foundChildAcl).isNotNull();
|
||||
assertThat(foundChildAcl.isGranted(checkPermission, sids, false)).isTrue();
|
||||
|
||||
// Search for object identities has to be done in the following order:
|
||||
// last
|
||||
// element have to be one which
|
||||
// is already in cache and the element before it must not be stored in
|
||||
// cache
|
||||
List<ObjectIdentity> allOids = Arrays.asList(grandParentOid, parent1Oid, parent2Oid, childOid);
|
||||
try {
|
||||
foundAcls = strategy.readAclsById(allOids, sids);
|
||||
|
||||
} catch (NotFoundException notExpected) {
|
||||
fail("It shouldn't have thrown NotFoundException");
|
||||
}
|
||||
|
||||
Acl foundParent2Acl = foundAcls.get(parent2Oid);
|
||||
assertThat(foundParent2Acl).isNotNull();
|
||||
assertThat(foundParent2Acl.isGranted(checkPermission, sids, false)).isTrue();
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void nullOwnerIsNotSupported() {
|
||||
String query = "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (4,2,104,null,null,1);";
|
||||
|
||||
jdbcTemplate.execute(query);
|
||||
|
||||
ObjectIdentity oid = new ObjectIdentityImpl(TARGET_CLASS, new Long(104));
|
||||
|
||||
strategy.readAclsById(Arrays.asList(oid), Arrays.asList(BEN_SID));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreatePrincipalSid() {
|
||||
Sid result = strategy.createSid(true, "sid");
|
||||
|
||||
assertThat(result.getClass()).isEqualTo(PrincipalSid.class);
|
||||
assertThat(((PrincipalSid) result).getPrincipal()).isEqualTo("sid");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateGrantedAuthority() {
|
||||
Sid result = strategy.createSid(false, "sid");
|
||||
|
||||
assertThat(result.getClass()).isEqualTo(GrantedAuthoritySid.class);
|
||||
assertThat(((GrantedAuthoritySid) result).getGrantedAuthority()).isEqualTo("sid");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
-72
@@ -1,72 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.security.acls.jdbc;
|
||||
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.datasource.SingleConnectionDataSource;
|
||||
import org.springframework.util.FileCopyUtils;
|
||||
|
||||
/**
|
||||
* Helper class to initialize the database for BasicLookupStrategyTests.
|
||||
* @author Andrei Stefan
|
||||
* @author Paul Wheeler
|
||||
*/
|
||||
public class BasicLookupStrategyTestsDbHelper {
|
||||
private static final String ACL_SCHEMA_SQL_FILE = "createAclSchema.sql";
|
||||
private static final String ACL_SCHEMA_SQL_FILE_WITH_ACL_CLASS_ID = "createAclSchemaWithAclClassIdType.sql";
|
||||
|
||||
private SingleConnectionDataSource dataSource;
|
||||
private JdbcTemplate jdbcTemplate;
|
||||
private boolean withAclClassIdType;
|
||||
|
||||
public BasicLookupStrategyTestsDbHelper() {
|
||||
}
|
||||
|
||||
public BasicLookupStrategyTestsDbHelper(boolean withAclClassIdType) {
|
||||
this.withAclClassIdType = withAclClassIdType;
|
||||
}
|
||||
|
||||
public void createDatabase() throws Exception {
|
||||
// Use a different connection url so the tests can run in parallel
|
||||
String connectionUrl;
|
||||
String sqlClassPathResource;
|
||||
if (!withAclClassIdType) {
|
||||
connectionUrl = "jdbc:hsqldb:mem:lookupstrategytest";
|
||||
sqlClassPathResource = ACL_SCHEMA_SQL_FILE;
|
||||
} else {
|
||||
connectionUrl = "jdbc:hsqldb:mem:lookupstrategytestWithAclClassIdType";
|
||||
sqlClassPathResource = ACL_SCHEMA_SQL_FILE_WITH_ACL_CLASS_ID;
|
||||
|
||||
}
|
||||
dataSource = new SingleConnectionDataSource(connectionUrl, "sa", "", true);
|
||||
dataSource.setDriverClassName("org.hsqldb.jdbcDriver");
|
||||
jdbcTemplate = new JdbcTemplate(dataSource);
|
||||
|
||||
Resource resource = new ClassPathResource(sqlClassPathResource);
|
||||
String sql = new String(FileCopyUtils.copyToByteArray(resource.getInputStream()));
|
||||
jdbcTemplate.execute(sql);
|
||||
}
|
||||
|
||||
public JdbcTemplate getJdbcTemplate() {
|
||||
return jdbcTemplate;
|
||||
}
|
||||
|
||||
public SingleConnectionDataSource getDataSource() {
|
||||
return dataSource;
|
||||
}
|
||||
}
|
||||
-117
@@ -1,117 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.security.acls.jdbc;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.springframework.core.convert.ConversionFailedException;
|
||||
import org.springframework.core.convert.support.DefaultConversionService;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.security.acls.domain.ConsoleAuditLogger;
|
||||
import org.springframework.security.acls.domain.DefaultPermissionFactory;
|
||||
import org.springframework.security.acls.domain.DefaultPermissionGrantingStrategy;
|
||||
import org.springframework.security.acls.domain.ObjectIdentityImpl;
|
||||
import org.springframework.security.acls.model.Acl;
|
||||
import org.springframework.security.acls.model.ObjectIdentity;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
/**
|
||||
* Tests {@link BasicLookupStrategy} with Acl Class type id set to UUID.
|
||||
*
|
||||
* @author Paul Wheeler
|
||||
*/
|
||||
public class BasicLookupStrategyWithAclClassTypeTests extends AbstractBasicLookupStrategyTests {
|
||||
|
||||
private static final BasicLookupStrategyTestsDbHelper DATABASE_HELPER = new BasicLookupStrategyTestsDbHelper(true);
|
||||
|
||||
private BasicLookupStrategy uuidEnabledStrategy;
|
||||
|
||||
@Override
|
||||
public JdbcTemplate getJdbcTemplate() {
|
||||
return DATABASE_HELPER.getJdbcTemplate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataSource getDataSource() {
|
||||
return DATABASE_HELPER.getDataSource();
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void createDatabase() throws Exception {
|
||||
DATABASE_HELPER.createDatabase();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void dropDatabase() throws Exception {
|
||||
DATABASE_HELPER.getDataSource().destroy();
|
||||
}
|
||||
|
||||
@Before
|
||||
public void initializeBeans() {
|
||||
super.initializeBeans();
|
||||
AclClassIdUtils aclClassIdUtils = new AclClassIdUtils();
|
||||
aclClassIdUtils.setConversionService(new DefaultConversionService());
|
||||
uuidEnabledStrategy = new BasicLookupStrategy(getDataSource(), aclCache(), aclAuthStrategy(),
|
||||
new DefaultPermissionGrantingStrategy(new ConsoleAuditLogger()));
|
||||
uuidEnabledStrategy.setPermissionFactory(new DefaultPermissionFactory());
|
||||
uuidEnabledStrategy.setAclClassIdSupported(true);
|
||||
uuidEnabledStrategy.setAclClassIdUtils(aclClassIdUtils);
|
||||
}
|
||||
|
||||
@Before
|
||||
public void populateDatabaseForAclClassTypeTests() {
|
||||
String query = "INSERT INTO acl_class(ID,CLASS,CLASS_ID_TYPE) VALUES (3,'"
|
||||
+ TARGET_CLASS_WITH_UUID
|
||||
+ "', 'java.util.UUID');"
|
||||
+ "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (4,3,'"
|
||||
+ OBJECT_IDENTITY_UUID.toString() + "',null,1,1);"
|
||||
+ "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (5,3,'"
|
||||
+ OBJECT_IDENTITY_LONG_AS_UUID + "',null,1,1);"
|
||||
+ "INSERT INTO acl_entry(ID,ACL_OBJECT_IDENTITY,ACE_ORDER,SID,MASK,GRANTING,AUDIT_SUCCESS,AUDIT_FAILURE) VALUES (5,4,0,1,8,0,0,0);"
|
||||
+ "INSERT INTO acl_entry(ID,ACL_OBJECT_IDENTITY,ACE_ORDER,SID,MASK,GRANTING,AUDIT_SUCCESS,AUDIT_FAILURE) VALUES (6,5,0,1,8,0,0,0);";
|
||||
DATABASE_HELPER.getJdbcTemplate().execute(query);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadObjectIdentityUsingUuidType() {
|
||||
ObjectIdentity oid = new ObjectIdentityImpl(TARGET_CLASS_WITH_UUID, OBJECT_IDENTITY_UUID);
|
||||
Map<ObjectIdentity, Acl> foundAcls = uuidEnabledStrategy.readAclsById(Arrays.asList(oid), Arrays.asList(BEN_SID));
|
||||
Assert.assertEquals(1, foundAcls.size());
|
||||
Assert.assertNotNull(foundAcls.get(oid));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadObjectIdentityUsingLongTypeWithConversionServiceEnabled() {
|
||||
ObjectIdentity oid = new ObjectIdentityImpl(TARGET_CLASS, new Long(100));
|
||||
Map<ObjectIdentity, Acl> foundAcls = uuidEnabledStrategy.readAclsById(Arrays.asList(oid), Arrays.asList(BEN_SID));
|
||||
Assert.assertEquals(1, foundAcls.size());
|
||||
Assert.assertNotNull(foundAcls.get(oid));
|
||||
}
|
||||
|
||||
@Test(expected = ConversionFailedException.class)
|
||||
public void testReadObjectIdentityUsingNonUuidInDatabase() {
|
||||
ObjectIdentity oid = new ObjectIdentityImpl(TARGET_CLASS_WITH_UUID, OBJECT_IDENTITY_LONG_AS_UUID);
|
||||
uuidEnabledStrategy.readAclsById(Arrays.asList(oid), Arrays.asList(BEN_SID));
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -36,7 +36,7 @@ import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Captor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.security.acls.domain.*;
|
||||
import org.springframework.security.acls.model.MutableAcl;
|
||||
import org.springframework.security.acls.model.ObjectIdentity;
|
||||
|
||||
@@ -29,7 +29,7 @@ import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.security.acls.domain.ObjectIdentityImpl;
|
||||
import org.springframework.security.acls.domain.PrincipalSid;
|
||||
import org.springframework.security.acls.model.Acl;
|
||||
@@ -64,4 +64,4 @@ public class JdbcAclServiceTests {
|
||||
|
||||
aclService.readAclById(objectIdentity, sids);
|
||||
}
|
||||
}
|
||||
}
|
||||
+30
-57
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2004, 2005, 2006, 2017 Acegi Technology Pty Limited
|
||||
* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -98,30 +98,10 @@ public class JdbcMutableAclServiceTests extends
|
||||
// ~ Methods
|
||||
// ========================================================================================================
|
||||
|
||||
protected String getSqlClassPathResource() {
|
||||
return "createAclSchema.sql";
|
||||
}
|
||||
|
||||
protected ObjectIdentity getTopParentOid() {
|
||||
return topParentOid;
|
||||
}
|
||||
|
||||
protected ObjectIdentity getMiddleParentOid() {
|
||||
return middleParentOid;
|
||||
}
|
||||
|
||||
protected ObjectIdentity getChildOid() {
|
||||
return childOid;
|
||||
}
|
||||
|
||||
protected String getTargetClass() {
|
||||
return TARGET_CLASS;
|
||||
}
|
||||
|
||||
@BeforeTransaction
|
||||
public void createTables() throws Exception {
|
||||
try {
|
||||
new DatabaseSeeder(dataSource, new ClassPathResource(getSqlClassPathResource()));
|
||||
new DatabaseSeeder(dataSource, new ClassPathResource("createAclSchema.sql"));
|
||||
// new DatabaseSeeder(dataSource, new
|
||||
// ClassPathResource("createAclSchemaPostgres.sql"));
|
||||
}
|
||||
@@ -146,9 +126,9 @@ public class JdbcMutableAclServiceTests extends
|
||||
public void testLifecycle() {
|
||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||
|
||||
MutableAcl topParent = jdbcMutableAclService.createAcl(getTopParentOid());
|
||||
MutableAcl middleParent = jdbcMutableAclService.createAcl(getMiddleParentOid());
|
||||
MutableAcl child = jdbcMutableAclService.createAcl(getChildOid());
|
||||
MutableAcl topParent = jdbcMutableAclService.createAcl(topParentOid);
|
||||
MutableAcl middleParent = jdbcMutableAclService.createAcl(middleParentOid);
|
||||
MutableAcl child = jdbcMutableAclService.createAcl(childOid);
|
||||
|
||||
// Specify the inheritance hierarchy
|
||||
middleParent.setParent(topParent);
|
||||
@@ -167,13 +147,13 @@ public class JdbcMutableAclServiceTests extends
|
||||
|
||||
// Let's check if we can read them back correctly
|
||||
Map<ObjectIdentity, Acl> map = jdbcMutableAclService.readAclsById(Arrays.asList(
|
||||
getTopParentOid(), getMiddleParentOid(), getChildOid()));
|
||||
topParentOid, middleParentOid, childOid));
|
||||
assertThat(map).hasSize(3);
|
||||
|
||||
// Replace our current objects with their retrieved versions
|
||||
topParent = (MutableAcl) map.get(getTopParentOid());
|
||||
middleParent = (MutableAcl) map.get(getMiddleParentOid());
|
||||
child = (MutableAcl) map.get(getChildOid());
|
||||
topParent = (MutableAcl) map.get(topParentOid);
|
||||
middleParent = (MutableAcl) map.get(middleParentOid);
|
||||
child = (MutableAcl) map.get(childOid);
|
||||
|
||||
// Check the retrieved versions has IDs
|
||||
assertThat(topParent.getId()).isNotNull();
|
||||
@@ -182,8 +162,8 @@ public class JdbcMutableAclServiceTests extends
|
||||
|
||||
// Check their parents were correctly persisted
|
||||
assertThat(topParent.getParentAcl()).isNull();
|
||||
assertThat(middleParent.getParentAcl().getObjectIdentity()).isEqualTo(getTopParentOid());
|
||||
assertThat(child.getParentAcl().getObjectIdentity()).isEqualTo(getMiddleParentOid());
|
||||
assertThat(middleParent.getParentAcl().getObjectIdentity()).isEqualTo(topParentOid);
|
||||
assertThat(child.getParentAcl().getObjectIdentity()).isEqualTo(middleParentOid);
|
||||
|
||||
// Check their ACEs were correctly persisted
|
||||
assertThat(topParent.getEntries()).hasSize(2);
|
||||
@@ -217,7 +197,7 @@ public class JdbcMutableAclServiceTests extends
|
||||
// Next change the child so it doesn't inherit permissions from above
|
||||
child.setEntriesInheriting(false);
|
||||
jdbcMutableAclService.updateAcl(child);
|
||||
child = (MutableAcl) jdbcMutableAclService.readAclById(getChildOid());
|
||||
child = (MutableAcl) jdbcMutableAclService.readAclById(childOid);
|
||||
assertThat(child.isEntriesInheriting()).isFalse();
|
||||
|
||||
// Check the child permissions no longer inherit
|
||||
@@ -248,7 +228,7 @@ public class JdbcMutableAclServiceTests extends
|
||||
|
||||
// Save the changed child
|
||||
jdbcMutableAclService.updateAcl(child);
|
||||
child = (MutableAcl) jdbcMutableAclService.readAclById(getChildOid());
|
||||
child = (MutableAcl) jdbcMutableAclService.readAclById(childOid);
|
||||
assertThat(child.getEntries()).hasSize(3);
|
||||
|
||||
// Output permissions
|
||||
@@ -288,38 +268,38 @@ public class JdbcMutableAclServiceTests extends
|
||||
public void deleteAclAlsoDeletesChildren() throws Exception {
|
||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||
|
||||
jdbcMutableAclService.createAcl(getTopParentOid());
|
||||
MutableAcl middleParent = jdbcMutableAclService.createAcl(getMiddleParentOid());
|
||||
MutableAcl child = jdbcMutableAclService.createAcl(getChildOid());
|
||||
jdbcMutableAclService.createAcl(topParentOid);
|
||||
MutableAcl middleParent = jdbcMutableAclService.createAcl(middleParentOid);
|
||||
MutableAcl child = jdbcMutableAclService.createAcl(childOid);
|
||||
child.setParent(middleParent);
|
||||
jdbcMutableAclService.updateAcl(middleParent);
|
||||
jdbcMutableAclService.updateAcl(child);
|
||||
// Check the childOid really is a child of middleParentOid
|
||||
Acl childAcl = jdbcMutableAclService.readAclById(getChildOid());
|
||||
Acl childAcl = jdbcMutableAclService.readAclById(childOid);
|
||||
|
||||
assertThat(childAcl.getParentAcl().getObjectIdentity()).isEqualTo(getMiddleParentOid());
|
||||
assertThat(childAcl.getParentAcl().getObjectIdentity()).isEqualTo(middleParentOid);
|
||||
|
||||
// Delete the mid-parent and test if the child was deleted, as well
|
||||
jdbcMutableAclService.deleteAcl(getMiddleParentOid(), true);
|
||||
jdbcMutableAclService.deleteAcl(middleParentOid, true);
|
||||
|
||||
try {
|
||||
jdbcMutableAclService.readAclById(getMiddleParentOid());
|
||||
jdbcMutableAclService.readAclById(middleParentOid);
|
||||
fail("It should have thrown NotFoundException");
|
||||
}
|
||||
catch (NotFoundException expected) {
|
||||
|
||||
}
|
||||
try {
|
||||
jdbcMutableAclService.readAclById(getChildOid());
|
||||
jdbcMutableAclService.readAclById(childOid);
|
||||
fail("It should have thrown NotFoundException");
|
||||
}
|
||||
catch (NotFoundException expected) {
|
||||
|
||||
}
|
||||
|
||||
Acl acl = jdbcMutableAclService.readAclById(getTopParentOid());
|
||||
Acl acl = jdbcMutableAclService.readAclById(topParentOid);
|
||||
assertThat(acl).isNotNull();
|
||||
assertThat(getTopParentOid()).isEqualTo(((MutableAcl) acl).getObjectIdentity());
|
||||
assertThat(topParentOid).isEqualTo(((MutableAcl) acl).getObjectIdentity());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -387,8 +367,8 @@ public class JdbcMutableAclServiceTests extends
|
||||
@Transactional
|
||||
public void deleteAclWithChildrenThrowsException() throws Exception {
|
||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||
MutableAcl parent = jdbcMutableAclService.createAcl(getTopParentOid());
|
||||
MutableAcl child = jdbcMutableAclService.createAcl(getMiddleParentOid());
|
||||
MutableAcl parent = jdbcMutableAclService.createAcl(topParentOid);
|
||||
MutableAcl child = jdbcMutableAclService.createAcl(middleParentOid);
|
||||
|
||||
// Specify the inheritance hierarchy
|
||||
child.setParent(parent);
|
||||
@@ -398,7 +378,7 @@ public class JdbcMutableAclServiceTests extends
|
||||
jdbcMutableAclService.setForeignKeysInDatabase(false); // switch on FK
|
||||
// checking in the
|
||||
// class, not database
|
||||
jdbcMutableAclService.deleteAcl(getTopParentOid(), false);
|
||||
jdbcMutableAclService.deleteAcl(topParentOid, false);
|
||||
fail("It should have thrown ChildrenExistException");
|
||||
}
|
||||
catch (ChildrenExistException expected) {
|
||||
@@ -413,21 +393,21 @@ public class JdbcMutableAclServiceTests extends
|
||||
@Transactional
|
||||
public void deleteAclRemovesRowsFromDatabase() throws Exception {
|
||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||
MutableAcl child = jdbcMutableAclService.createAcl(getChildOid());
|
||||
MutableAcl child = jdbcMutableAclService.createAcl(childOid);
|
||||
child.insertAce(0, BasePermission.DELETE, new PrincipalSid(auth), false);
|
||||
jdbcMutableAclService.updateAcl(child);
|
||||
|
||||
// Remove the child and check all related database rows were removed accordingly
|
||||
jdbcMutableAclService.deleteAcl(getChildOid(), false);
|
||||
jdbcMutableAclService.deleteAcl(childOid, false);
|
||||
assertThat(
|
||||
jdbcTemplate.queryForList(SELECT_ALL_CLASSES,
|
||||
new Object[] { getTargetClass() })).hasSize(1);
|
||||
new Object[] { TARGET_CLASS })).hasSize(1);
|
||||
assertThat(jdbcTemplate.queryForList("select * from acl_object_identity")
|
||||
).isEmpty();
|
||||
assertThat(jdbcTemplate.queryForList("select * from acl_entry")).isEmpty();
|
||||
|
||||
// Check the cache
|
||||
assertThat(aclCache.getFromCache(getChildOid())).isNull();
|
||||
assertThat(aclCache.getFromCache(childOid)).isNull();
|
||||
assertThat(aclCache.getFromCache(Long.valueOf(102))).isNull();
|
||||
}
|
||||
|
||||
@@ -593,11 +573,4 @@ public class JdbcMutableAclServiceTests extends
|
||||
}
|
||||
}
|
||||
|
||||
protected Authentication getAuth() {
|
||||
return auth;
|
||||
}
|
||||
|
||||
protected JdbcMutableAclService getJdbcMutableAclService() {
|
||||
return jdbcMutableAclService;
|
||||
}
|
||||
}
|
||||
|
||||
-83
@@ -1,83 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.security.acls.jdbc;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.security.acls.TargetObjectWithUUID;
|
||||
import org.springframework.security.acls.domain.ObjectIdentityImpl;
|
||||
import org.springframework.security.acls.model.ObjectIdentity;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
* Integration tests the ACL system using ACL class id type of UUID and using an in-memory database.
|
||||
* @author Paul Wheeler
|
||||
*/
|
||||
@ContextConfiguration(locations = {"/jdbcMutableAclServiceTestsWithAclClass-context.xml"})
|
||||
public class JdbcMutableAclServiceTestsWithAclClassId extends JdbcMutableAclServiceTests {
|
||||
|
||||
private static final String TARGET_CLASS_WITH_UUID = TargetObjectWithUUID.class.getName();
|
||||
|
||||
private final ObjectIdentity topParentOid = new ObjectIdentityImpl(TARGET_CLASS_WITH_UUID,
|
||||
UUID.randomUUID());
|
||||
private final ObjectIdentity middleParentOid = new ObjectIdentityImpl(TARGET_CLASS_WITH_UUID,
|
||||
UUID.randomUUID());
|
||||
private final ObjectIdentity childOid = new ObjectIdentityImpl(TARGET_CLASS_WITH_UUID,
|
||||
UUID.randomUUID());
|
||||
|
||||
@Override
|
||||
protected String getSqlClassPathResource() {
|
||||
return "createAclSchemaWithAclClassIdType.sql";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ObjectIdentity getTopParentOid() {
|
||||
return topParentOid;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ObjectIdentity getMiddleParentOid() {
|
||||
return middleParentOid;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ObjectIdentity getChildOid() {
|
||||
return childOid;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getTargetClass() {
|
||||
return TARGET_CLASS_WITH_UUID;
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void identityWithUuidIdIsSupportedByCreateAcl() throws Exception {
|
||||
SecurityContextHolder.getContext().setAuthentication(getAuth());
|
||||
|
||||
UUID id = UUID.randomUUID();
|
||||
ObjectIdentity oid = new ObjectIdentityImpl(TARGET_CLASS_WITH_UUID, id);
|
||||
getJdbcMutableAclService().createAcl(oid);
|
||||
|
||||
assertThat(getJdbcMutableAclService().readAclById(new ObjectIdentityImpl(
|
||||
TARGET_CLASS_WITH_UUID, id))).isNotNull();
|
||||
}
|
||||
}
|
||||
@@ -17,10 +17,7 @@
|
||||
<constructor-arg>
|
||||
<bean class="org.springframework.cache.ehcache.EhCacheFactoryBean">
|
||||
<property name="cacheManager">
|
||||
<bean class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
|
||||
<!-- This context is used in two tests so accept existing cache manager as the context will be reused -->
|
||||
<property name="acceptExisting" value="true"/>
|
||||
</bean>
|
||||
<bean class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"/>
|
||||
</property>
|
||||
<property name="cacheName" value="aclCache"/>
|
||||
</bean>
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||
|
||||
<import resource="jdbcMutableAclServiceTests-context.xml"/>
|
||||
|
||||
<bean id="aclClassIdUtils" class="org.springframework.security.acls.jdbc.AclClassIdUtils">
|
||||
<property name="conversionService">
|
||||
<bean class="org.springframework.core.convert.support.DefaultConversionService"/>
|
||||
</property>
|
||||
</bean>
|
||||
<!-- Overridden bean definitions -->
|
||||
|
||||
<bean id="aclService" class="org.springframework.security.acls.jdbc.JdbcMutableAclService">
|
||||
<constructor-arg ref="dataSource"/>
|
||||
<constructor-arg ref="lookupStrategy"/>
|
||||
<constructor-arg ref="aclCache"/>
|
||||
<property name="aclClassIdSupported" value="true"/>
|
||||
<property name="aclClassIdUtils" ref="aclClassIdUtils"/>
|
||||
</bean>
|
||||
|
||||
<bean id="lookupStrategy" class="org.springframework.security.acls.jdbc.BasicLookupStrategy">
|
||||
<constructor-arg ref="dataSource"/>
|
||||
<constructor-arg ref="aclCache"/>
|
||||
<constructor-arg ref="aclAuthorizationStrategy"/>
|
||||
<constructor-arg>
|
||||
<bean class="org.springframework.security.acls.domain.ConsoleAuditLogger"/>
|
||||
</constructor-arg>
|
||||
<property name="aclClassIdSupported" value="true"/>
|
||||
<property name="aclClassIdUtils" ref="aclClassIdUtils"/>
|
||||
</bean>
|
||||
</beans>
|
||||
@@ -1,15 +1,14 @@
|
||||
<configuration>
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
|
||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
</appender>
|
||||
|
||||
<logger name="org.springframework.security" level="${sec.log.level:-WARN}"/>
|
||||
<logger name="org.springframework.security" level="${sec.log.level}:-WARN"/>
|
||||
|
||||
|
||||
<root level="${root.level:-WARN}">
|
||||
<root level="${root.level}:-WARN">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</root>
|
||||
</root>
|
||||
|
||||
</configuration>
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
|
||||
dependencies {
|
||||
compile project(':spring-security-core'),
|
||||
springCoreDependency,
|
||||
"org.springframework:spring-beans:$springVersion",
|
||||
"org.springframework:spring-context:$springVersion"
|
||||
|
||||
testCompile 'aopalliance:aopalliance:1.0',
|
||||
"org.springframework:spring-aop:$springVersion"
|
||||
}
|
||||
+144
@@ -0,0 +1,144 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-aspects</artifactId>
|
||||
<version>4.2.9.RELEASE</version>
|
||||
<name>spring-security-aspects</name>
|
||||
<description>spring-security-aspects</description>
|
||||
<url>http://spring.io/spring-security</url>
|
||||
<organization>
|
||||
<name>spring.io</name>
|
||||
<url>http://spring.io/</url>
|
||||
</organization>
|
||||
<licenses>
|
||||
<license>
|
||||
<name>The Apache Software License, Version 2.0</name>
|
||||
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
|
||||
<distribution>repo</distribution>
|
||||
</license>
|
||||
</licenses>
|
||||
<developers>
|
||||
<developer>
|
||||
<id>rwinch</id>
|
||||
<name>Rob Winch</name>
|
||||
<email>rwinch@gopivotal.com</email>
|
||||
</developer>
|
||||
</developers>
|
||||
<scm>
|
||||
<connection>scm:git:git://github.com/spring-projects/spring-security</connection>
|
||||
<developerConnection>scm:git:git://github.com/spring-projects/spring-security</developerConnection>
|
||||
<url>https://github.com/spring-projects/spring-security</url>
|
||||
</scm>
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-framework-bom</artifactId>
|
||||
<version>4.3.19.RELEASE</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-core</artifactId>
|
||||
<version>4.2.9.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-beans</artifactId>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-core</artifactId>
|
||||
<scope>compile</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
<groupId>commons-logging</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-logging</groupId>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
<version>1.2</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.aspectj</groupId>
|
||||
<artifactId>aspectjrt</artifactId>
|
||||
<version>1.8.13</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>aopalliance</groupId>
|
||||
<artifactId>aopalliance</artifactId>
|
||||
<version>1.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
<version>1.1.11</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.12</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.assertj</groupId>
|
||||
<artifactId>assertj-core</artifactId>
|
||||
<version>2.2.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<version>1.10.19</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>jcl-over-slf4j</artifactId>
|
||||
<version>1.7.25</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-aop</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>1.7</source>
|
||||
<target>1.7</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@@ -1,11 +0,0 @@
|
||||
apply plugin: 'io.spring.convention.spring-module'
|
||||
apply plugin: 'aspectj'
|
||||
|
||||
dependencies {
|
||||
compile project(':spring-security-core')
|
||||
compile 'org.springframework:spring-beans'
|
||||
compile 'org.springframework:spring-context'
|
||||
compile 'org.springframework:spring-core'
|
||||
|
||||
testCompile 'org.springframework:spring-aop'
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
<configuration>
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<logger name="org.springframework.security" level="${sec.log.level:-WARN}"/>
|
||||
|
||||
|
||||
<root level="${root.level:-WARN}">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</root>
|
||||
|
||||
</configuration>
|
||||
@@ -0,0 +1,9 @@
|
||||
apply plugin: 'maven-bom'
|
||||
apply from: "$rootDir/gradle/maven-deployment.gradle"
|
||||
|
||||
generatePom.enabled = false
|
||||
sonarqube.skipProject = true
|
||||
|
||||
mavenBom {
|
||||
projects = coreModuleProjects
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
apply plugin: 'maven-bom'
|
||||
apply plugin: 'io.spring.convention.artifactory'
|
||||
|
||||
sonarqube.skipProject = true
|
||||
|
||||
project.rootProject.allprojects.each { p ->
|
||||
p.plugins.withType(io.spring.gradle.convention.SpringMavenPlugin) {
|
||||
project.mavenBom.projects.add(p)
|
||||
}
|
||||
}
|
||||
+187
-11
@@ -1,19 +1,195 @@
|
||||
buildscript {
|
||||
dependencies {
|
||||
classpath 'io.spring.gradle:spring-build-conventions:0.0.8.RELEASE'
|
||||
classpath "org.springframework.boot:spring-boot-gradle-plugin:$springBootVersion"
|
||||
}
|
||||
repositories {
|
||||
maven { url 'https://repo.spring.io/plugins-snapshot' }
|
||||
maven { url "https://repo.spring.io/plugins-release" }
|
||||
maven { url "https://repo.spring.io/plugins-snapshot" }
|
||||
}
|
||||
dependencies {
|
||||
classpath "com.github.ben-manes:gradle-versions-plugin:0.17.0"
|
||||
classpath("org.springframework.build.gradle:propdeps-plugin:0.0.7")
|
||||
classpath("io.spring.gradle:spring-io-plugin:0.0.6.RELEASE")
|
||||
classpath("com.bmuschko:gradle-tomcat-plugin:2.2.4")
|
||||
classpath('me.champeau.gradle:gradle-javadoc-hotfix-plugin:0.1')
|
||||
classpath('org.asciidoctor:asciidoctor-gradle-plugin:1.5.1')
|
||||
classpath("io.spring.gradle:docbook-reference-plugin:0.3.1")
|
||||
classpath("org.springframework.boot:spring-boot-gradle-plugin:1.5.2.RELEASE")
|
||||
}
|
||||
}
|
||||
apply plugin: 'io.spring.convention.root'
|
||||
|
||||
group = 'org.springframework.security'
|
||||
plugins {
|
||||
id "org.sonarqube" version "2.1-rc1"
|
||||
}
|
||||
|
||||
apply plugin: 'base'
|
||||
|
||||
description = 'Spring Security'
|
||||
|
||||
ext.snapshotBuild = version.contains("SNAPSHOT")
|
||||
ext.releaseBuild = version.contains("SNAPSHOT")
|
||||
ext.milestoneBuild = !(snapshotBuild || releaseBuild)
|
||||
allprojects {
|
||||
apply plugin: 'idea'
|
||||
apply plugin: 'eclipse'
|
||||
apply plugin: "com.github.ben-manes.versions"
|
||||
|
||||
dependencyManagementExport.projects = subprojects.findAll { !it.name.contains('-boot') }
|
||||
ext.releaseBuild = version.endsWith('RELEASE')
|
||||
ext.snapshotBuild = version.endsWith('SNAPSHOT')
|
||||
ext.springVersion = '4.3.19.RELEASE'
|
||||
ext.springLdapVersion = '2.3.2.RELEASE'
|
||||
|
||||
group = 'org.springframework.security'
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven { url "https://repo.spring.io/libs-snapshot" }
|
||||
maven { url "https://repo.spring.io/plugins-release" }
|
||||
maven { url "http://repo.terracotta.org/maven2/" }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
sonarqube {
|
||||
properties {
|
||||
property "sonar.java.coveragePlugin", "jacoco"
|
||||
property "sonar.projectName", "Spring Security"
|
||||
property "sonar.jacoco.reportPath", "${buildDir.name}/jacoco.exec"
|
||||
property "sonar.links.homepage", 'https://www.springsource.org/spring-security'
|
||||
property "sonar.links.ci", 'https://build.springsource.org/browse/SEC-B32X'
|
||||
property "sonar.links.issue", 'https://jira.springsource.org/browse/SEC'
|
||||
property "sonar.links.scm", 'https://github.com/SpringSource/spring-security'
|
||||
property "sonar.links.scm_dev", 'https://github.com/SpringSource/spring-security.git'
|
||||
property "sonar.java.coveragePlugin", "jacoco"
|
||||
}
|
||||
}
|
||||
|
||||
// Set up different subproject lists for individual configuration
|
||||
ext.javaProjects = subprojects.findAll { project -> project.name != 'docs' && project.name != 'manual' && project.name != 'guides' && project.name != 'spring-security-bom' }
|
||||
ext.sampleProjects = subprojects.findAll { project -> project.name.startsWith('spring-security-samples') }
|
||||
ext.itestProjects = subprojects.findAll { project -> project.name.startsWith('itest') }
|
||||
ext.coreModuleProjects = javaProjects - sampleProjects - itestProjects
|
||||
ext.aspectjProjects = [project(':spring-security-aspects'), project(':spring-security-samples-xml-aspectj'), project(':spring-security-samples-javaconfig-aspectj')]
|
||||
|
||||
configure(allprojects - javaProjects) {
|
||||
task afterEclipseImport {
|
||||
ext.srcFile = file('.classpath')
|
||||
inputs.file srcFile
|
||||
outputs.dir srcFile
|
||||
|
||||
onlyIf { !srcFile.exists() }
|
||||
|
||||
doLast {
|
||||
srcFile << """<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
||||
"""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
configure(subprojects - coreModuleProjects - project(':spring-security-samples-javaconfig-messages') - project(':spring-security-bom')) {
|
||||
tasks.findByPath("artifactoryPublish")?.enabled = false
|
||||
sonarqube {
|
||||
skipProject = true
|
||||
}
|
||||
}
|
||||
|
||||
configure(javaProjects) {
|
||||
ext.TOMCAT_GRADLE = "$rootDir/gradle/tomcat.gradle"
|
||||
ext.WAR_SAMPLE_GRADLE = "$rootDir/gradle/war-sample.gradle"
|
||||
ext.BOOT_SAMPLE_GRADLE = "$rootDir/gradle/boot-sample.gradle"
|
||||
apply from: "$rootDir/gradle/javaprojects.gradle"
|
||||
if(!project.name.contains('gae')) {
|
||||
apply from: "$rootDir/gradle/checkstyle.gradle"
|
||||
}
|
||||
apply from: "$rootDir/gradle/ide.gradle"
|
||||
apply from: "$rootDir/gradle/release-checks.gradle"
|
||||
apply from: "$rootDir/gradle/maven-deployment.gradle"
|
||||
}
|
||||
|
||||
configure(coreModuleProjects) {
|
||||
apply plugin: 'emma'
|
||||
apply plugin: 'spring-io'
|
||||
|
||||
ext.springIoVersion = project.hasProperty('platformVersion') ? platformVersion : 'Brussels-SR9'
|
||||
|
||||
configurations {
|
||||
jacoco //Configuration Group used by Sonar to provide Code Coverage using JaCoCo
|
||||
}
|
||||
|
||||
dependencyManagement {
|
||||
springIoTestRuntime {
|
||||
imports {
|
||||
mavenBom("io.spring.platform:platform-bom:${springIoVersion}") {
|
||||
bomProperties([
|
||||
'assertj.version': '2.2.0',
|
||||
'mockito.version': '1.10.19'
|
||||
])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
dependencies {
|
||||
jacoco "org.jacoco:org.jacoco.agent:0.7.9:runtime"
|
||||
}
|
||||
test {
|
||||
jvmArgs "-javaagent:${configurations.jacoco.asPath}=destfile=${buildDir}/jacoco.exec,includes=${project.group}.*"
|
||||
}
|
||||
integrationTest {
|
||||
jvmArgs "-javaagent:${configurations.jacoco.asPath}=destfile=${buildDir}/jacoco.exec,includes=${project.group}.*"
|
||||
}
|
||||
}
|
||||
|
||||
configure (aspectjProjects) {
|
||||
apply plugin: 'java'
|
||||
apply plugin: 'aspectj'
|
||||
}
|
||||
|
||||
task coreBuild {
|
||||
dependsOn coreModuleProjects*.tasks*.matching { task -> task.name == 'build' }
|
||||
}
|
||||
|
||||
task coreInstall {
|
||||
dependsOn coreModuleProjects*.tasks*.matching { task -> task.name == 'install' }
|
||||
}
|
||||
|
||||
// Task for creating the distro zip
|
||||
|
||||
task dist(type: Zip) {
|
||||
dependsOn { subprojects*.tasks*.matching { task -> task.name.endsWith('generatePom') } }
|
||||
classifier = 'dist'
|
||||
|
||||
evaluationDependsOn(':docs')
|
||||
evaluationDependsOn(':docs:manual')
|
||||
|
||||
def zipRootDir = "${project.name}-$version"
|
||||
into(zipRootDir) {
|
||||
from(rootDir) {
|
||||
include '*.adoc'
|
||||
include '*.txt'
|
||||
}
|
||||
into('docs') {
|
||||
with(project(':docs').apiSpec)
|
||||
with(project(':docs:manual').spec)
|
||||
with(project(':docs:guides').spec)
|
||||
}
|
||||
project.coreModuleProjects*.tasks*.withType(AbstractArchiveTask).flatten().each{ archiveTask ->
|
||||
if(archiveTask!=dist){
|
||||
into("$zipRootDir/dist") {
|
||||
from archiveTask.outputs.files
|
||||
}
|
||||
}
|
||||
}
|
||||
sampleProjects.each { project->
|
||||
into("$zipRootDir/samples/$project.name") {
|
||||
from(project.projectDir) {
|
||||
include "src/main/**"
|
||||
include "pom.xml"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
artifacts {
|
||||
archives dist
|
||||
archives project(':docs').docsZip
|
||||
archives project(':docs').schemaZip
|
||||
}
|
||||
|
||||
@@ -13,9 +13,7 @@ public class MavenBomPlugin implements Plugin<Project> {
|
||||
public void apply(Project project) {
|
||||
project.plugins.apply(JavaPlugin)
|
||||
project.plugins.apply(MavenPlugin)
|
||||
|
||||
project.group = project.rootProject.group
|
||||
project.task(MAVEN_BOM_TASK_NAME, type: MavenBomTask, group: 'Generate', description: 'Configures the pom as a Maven Build of Materials (BOM)')
|
||||
project.install.dependsOn project.mavenBom
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@ import org.gradle.api.tasks.*
|
||||
|
||||
public class MavenBomTask extends DefaultTask {
|
||||
|
||||
Set<Project> projects = []
|
||||
Set<Project> projects
|
||||
|
||||
File bomFile
|
||||
|
||||
@@ -52,4 +52,4 @@ public class MavenBomTask extends DefaultTask {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -26,11 +26,15 @@ class AspectJPlugin implements Plugin<Project> {
|
||||
void apply(Project project) {
|
||||
project.plugins.apply(JavaPlugin)
|
||||
|
||||
if (!project.hasProperty('aspectjVersion')) {
|
||||
throw new GradleException("You must set the property 'aspectjVersion' before applying the aspectj plugin")
|
||||
}
|
||||
|
||||
if (project.configurations.findByName('ajtools') == null) {
|
||||
project.configurations.create('ajtools')
|
||||
project.dependencies {
|
||||
ajtools "org.aspectj:aspectjtools"
|
||||
optional "org.aspectj:aspectjrt"
|
||||
ajtools "org.aspectj:aspectjtools:${project.aspectjVersion}"
|
||||
optional "org.aspectj:aspectjrt:${project.aspectjVersion}"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,12 +42,6 @@ class AspectJPlugin implements Plugin<Project> {
|
||||
project.configurations.create('aspectpath')
|
||||
}
|
||||
|
||||
project.afterEvaluate {
|
||||
setupAspectJ(project)
|
||||
}
|
||||
}
|
||||
|
||||
void setupAspectJ(Project project) {
|
||||
project.tasks.withType(JavaCompile) { javaCompileTask ->
|
||||
def javaCompileTaskName = javaCompileTask.name
|
||||
def ajCompileTask = project.tasks.create(name: javaCompileTaskName + 'Aspect', overwrite: true, description: 'Compiles AspectJ Source', type: Ajc) {
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
|
||||
dependencies {
|
||||
compile project(':spring-security-core'),
|
||||
project(':spring-security-web'),
|
||||
springCoreDependency,
|
||||
"org.springframework:spring-context:$springVersion",
|
||||
"org.springframework:spring-beans:$springVersion",
|
||||
"org.springframework:spring-web:$springVersion",
|
||||
"org.jasig.cas.client:cas-client-core:$casClientVersion"
|
||||
|
||||
optional "net.sf.ehcache:ehcache:$ehcacheVersion",
|
||||
"com.fasterxml.jackson.core:jackson-databind:$jacksonDatabindVersion"
|
||||
|
||||
testCompile "org.skyscreamer:jsonassert:$jsonassertVersion"
|
||||
|
||||
provided "javax.servlet:javax.servlet-api:$servletApiVersion"
|
||||
}
|
||||
+169
@@ -0,0 +1,169 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-cas</artifactId>
|
||||
<version>4.2.9.RELEASE</version>
|
||||
<name>spring-security-cas</name>
|
||||
<description>spring-security-cas</description>
|
||||
<url>http://spring.io/spring-security</url>
|
||||
<organization>
|
||||
<name>spring.io</name>
|
||||
<url>http://spring.io/</url>
|
||||
</organization>
|
||||
<licenses>
|
||||
<license>
|
||||
<name>The Apache Software License, Version 2.0</name>
|
||||
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
|
||||
<distribution>repo</distribution>
|
||||
</license>
|
||||
</licenses>
|
||||
<developers>
|
||||
<developer>
|
||||
<id>rwinch</id>
|
||||
<name>Rob Winch</name>
|
||||
<email>rwinch@gopivotal.com</email>
|
||||
</developer>
|
||||
</developers>
|
||||
<scm>
|
||||
<connection>scm:git:git://github.com/spring-projects/spring-security</connection>
|
||||
<developerConnection>scm:git:git://github.com/spring-projects/spring-security</developerConnection>
|
||||
<url>https://github.com/spring-projects/spring-security</url>
|
||||
</scm>
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-framework-bom</artifactId>
|
||||
<version>4.3.19.RELEASE</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.jasig.cas.client</groupId>
|
||||
<artifactId>cas-client-core</artifactId>
|
||||
<version>3.4.1</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-core</artifactId>
|
||||
<version>4.2.9.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-web</artifactId>
|
||||
<version>4.2.9.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-beans</artifactId>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-core</artifactId>
|
||||
<scope>compile</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
<groupId>commons-logging</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-web</artifactId>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>2.8.11.2</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-logging</groupId>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
<version>1.2</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.sf.ehcache</groupId>
|
||||
<artifactId>ehcache</artifactId>
|
||||
<version>2.10.5</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
<version>1.1.11</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.12</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.assertj</groupId>
|
||||
<artifactId>assertj-core</artifactId>
|
||||
<version>2.2.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<version>1.10.19</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.skyscreamer</groupId>
|
||||
<artifactId>jsonassert</artifactId>
|
||||
<version>1.4.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>jcl-over-slf4j</artifactId>
|
||||
<version>1.7.25</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>1.7</source>
|
||||
<target>1.7</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@@ -1,18 +0,0 @@
|
||||
apply plugin: 'io.spring.convention.spring-module'
|
||||
|
||||
dependencies {
|
||||
compile project(':spring-security-core')
|
||||
compile project(':spring-security-web')
|
||||
compile 'org.jasig.cas.client:cas-client-core'
|
||||
compile 'org.springframework:spring-beans'
|
||||
compile 'org.springframework:spring-context'
|
||||
compile 'org.springframework:spring-core'
|
||||
compile 'org.springframework:spring-web'
|
||||
|
||||
optional 'com.fasterxml.jackson.core:jackson-databind'
|
||||
optional 'net.sf.ehcache:ehcache'
|
||||
|
||||
provided 'javax.servlet:javax.servlet-api'
|
||||
|
||||
testCompile 'org.skyscreamer:jsonassert'
|
||||
}
|
||||
-15
@@ -122,7 +122,6 @@ public class CasAuthenticationToken extends AbstractAuthenticationToken implemen
|
||||
return key.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object obj) {
|
||||
if (!super.equals(obj)) {
|
||||
return false;
|
||||
@@ -145,18 +144,6 @@ public class CasAuthenticationToken extends AbstractAuthenticationToken implemen
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = super.hashCode();
|
||||
result = 31 * result + this.credentials.hashCode();
|
||||
result = 31 * result + this.principal.hashCode();
|
||||
result = 31 * result + this.userDetails.hashCode();
|
||||
result = 31 * result + this.keyHash;
|
||||
result = 31 * result + (this.assertion != null ? this.assertion.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getCredentials() {
|
||||
return this.credentials;
|
||||
}
|
||||
@@ -165,7 +152,6 @@ public class CasAuthenticationToken extends AbstractAuthenticationToken implemen
|
||||
return this.keyHash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getPrincipal() {
|
||||
return this.principal;
|
||||
}
|
||||
@@ -178,7 +164,6 @@ public class CasAuthenticationToken extends AbstractAuthenticationToken implemen
|
||||
return userDetails;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(super.toString());
|
||||
|
||||
+4
-4
@@ -55,7 +55,7 @@ public class CasAuthenticationTokenMixinTests {
|
||||
|
||||
public static final String AUTHORITIES_SET_JSON = "[\"java.util.Collections$UnmodifiableSet\", [" + AUTHORITY_JSON + "]]";
|
||||
|
||||
public static final String AUTHORITIES_ARRAYLIST_JSON = "[\"java.util.ArrayList\", [" + AUTHORITY_JSON + "]]";
|
||||
public static final String AUTHORITIES_ARRAYLIST_JSON = "[\"java.util.Collections$UnmodifiableRandomAccessList\", [" + AUTHORITY_JSON + "]]";
|
||||
|
||||
// @formatter:off
|
||||
public static final String USER_JSON = "{"
|
||||
@@ -84,14 +84,14 @@ public class CasAuthenticationTokenMixinTests {
|
||||
+ "\"principal\": {"
|
||||
+ "\"@class\": \"org.jasig.cas.client.authentication.AttributePrincipalImpl\", "
|
||||
+ "\"name\": \"assertName\", "
|
||||
+ "\"attributes\": {\"@class\": \"java.util.Collections$EmptyMap\"}, "
|
||||
+ "\"attributes\": {\"@class\": \"java.util.HashMap\"}, "
|
||||
+ "\"proxyGrantingTicket\": null, "
|
||||
+ "\"proxyRetriever\": null"
|
||||
+ "}, "
|
||||
+ "\"validFromDate\": [\"java.util.Date\", " + START_DATE.getTime() + "], "
|
||||
+ "\"validUntilDate\": [\"java.util.Date\", " + END_DATE.getTime() + "],"
|
||||
+ "\"authenticationDate\": [\"java.util.Date\", " + START_DATE.getTime() + "], "
|
||||
+ "\"attributes\": {\"@class\": \"java.util.Collections$EmptyMap\"}" +
|
||||
+ "\"attributes\": {\"@class\": \"java.util.HashMap\"}" +
|
||||
"}"
|
||||
+ "}";
|
||||
|
||||
@@ -124,7 +124,7 @@ public class CasAuthenticationTokenMixinTests {
|
||||
@Test
|
||||
public void deserializeCasAuthenticationTestAfterEraseCredentialInvoked() throws Exception {
|
||||
CasAuthenticationToken token = mapper.readValue(CAS_TOKEN_CLEARED_JSON, CasAuthenticationToken.class);
|
||||
assertThat(((UserDetails) token.getPrincipal()).getPassword()).isNull();
|
||||
assertThat(((UserDetails)token.getPrincipal()).getPassword()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+1
-1
@@ -57,7 +57,7 @@ public class GrantedAuthorityFromAssertionAttributesUserDetailsServiceTests {
|
||||
assertion, "ticket");
|
||||
UserDetails user = uds.loadUserDetails(token);
|
||||
Set<String> roles = AuthorityUtils.authorityListToSet(user.getAuthorities());
|
||||
assertThat(roles).containsExactlyInAnyOrder(
|
||||
assertThat(roles).containsOnly(
|
||||
"role_a1", "role_a2", "role_b", "role_c");
|
||||
}
|
||||
}
|
||||
|
||||
+6
-8
@@ -16,11 +16,6 @@
|
||||
|
||||
package org.springframework.security.cas.web;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
|
||||
import org.jasig.cas.client.proxy.ProxyGrantingTicketStorage;
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
@@ -35,9 +30,13 @@ import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
|
||||
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
/**
|
||||
* Tests {@link CasAuthenticationFilter}.
|
||||
*
|
||||
@@ -146,8 +145,7 @@ public class CasAuthenticationFilterTests {
|
||||
.createAuthorityList("ROLE_ANONYMOUS")));
|
||||
assertThat(filter.requiresAuthentication(request, response)).isTrue();
|
||||
SecurityContextHolder.getContext().setAuthentication(
|
||||
new TestingAuthenticationToken("un", "principal", AuthorityUtils
|
||||
.createAuthorityList("ROLE_ANONYMOUS")));
|
||||
new TestingAuthenticationToken("un", "principal"));
|
||||
assertThat(filter.requiresAuthentication(request, response)).isTrue();
|
||||
SecurityContextHolder.getContext().setAuthentication(
|
||||
new TestingAuthenticationToken("un", "principal", "ROLE_ANONYMOUS"));
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
<configuration>
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<logger name="org.springframework.security" level="${sec.log.level:-WARN}"/>
|
||||
|
||||
|
||||
<root level="${root.level:-WARN}">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</root>
|
||||
|
||||
</configuration>
|
||||
@@ -0,0 +1,77 @@
|
||||
import javax.security.auth.login.ConfigurationSpi;
|
||||
|
||||
// Config Module build file
|
||||
|
||||
apply plugin: 'groovy'
|
||||
apply plugin: 'trang'
|
||||
|
||||
compileTestJava.dependsOn(':spring-security-core:compileTestJava')
|
||||
|
||||
dependencies {
|
||||
// NB: Don't add other compile time dependencies to the config module as this breaks tooling
|
||||
compile project(':spring-security-core'),
|
||||
springCoreDependency,
|
||||
'aopalliance:aopalliance:1.0',
|
||||
"org.springframework:spring-aop:$springVersion",
|
||||
"org.springframework:spring-context:$springVersion",
|
||||
"org.springframework:spring-beans:$springVersion"
|
||||
|
||||
optional project(':spring-security-web'),
|
||||
project(':spring-security-ldap'),
|
||||
project(':spring-security-openid'),
|
||||
project(':spring-security-messaging'),
|
||||
"org.springframework:spring-web:$springVersion",
|
||||
"org.springframework:spring-websocket:$springVersion",
|
||||
"org.springframework:spring-webmvc:$springVersion",
|
||||
"org.aspectj:aspectjweaver:$aspectjVersion",
|
||||
"org.springframework:spring-jdbc:$springVersion",
|
||||
"org.springframework:spring-tx:$springVersion"
|
||||
|
||||
provided "javax.servlet:javax.servlet-api:$servletApiVersion"
|
||||
|
||||
testCompile project(':spring-security-cas'),
|
||||
project(':spring-security-core').sourceSets.test.output,
|
||||
project(':spring-security-aspects'),
|
||||
'javax.annotation:jsr250-api:1.0',
|
||||
"org.springframework.ldap:spring-ldap-core:$springLdapVersion",
|
||||
"org.springframework:spring-expression:$springVersion",
|
||||
"org.springframework:spring-jdbc:$springVersion",
|
||||
"org.springframework:spring-orm:$springVersion",
|
||||
"org.springframework:spring-tx:$springVersion",
|
||||
"org.slf4j:jcl-over-slf4j:$slf4jVersion",
|
||||
"org.eclipse.persistence:javax.persistence:$javaPersistenceVersion",
|
||||
"org.hibernate:hibernate-entitymanager:$hibernateVersion",
|
||||
"org.codehaus.groovy:groovy-all:$groovyVersion",
|
||||
"org.apache.directory.server:apacheds-core:$apacheDsVersion",
|
||||
"org.apache.directory.server:apacheds-core-entry:$apacheDsVersion",
|
||||
"org.apache.directory.server:apacheds-protocol-shared:$apacheDsVersion",
|
||||
"org.apache.directory.server:apacheds-protocol-ldap:$apacheDsVersion",
|
||||
"org.apache.directory.server:apacheds-server-jndi:$apacheDsVersion",
|
||||
'org.apache.directory.shared:shared-ldap:0.9.15',
|
||||
'ldapsdk:ldapsdk:4.1',
|
||||
powerMockDependencies,
|
||||
"org.hsqldb:hsqldb:$hsqlVersion",
|
||||
spockDependencies
|
||||
|
||||
testCompile('org.openid4java:openid4java-nodeps:0.9.6') {
|
||||
exclude group: 'com.google.code.guice', module: 'guice'
|
||||
}
|
||||
testCompile("org.springframework.data:spring-data-jpa:$springDataJpaVersion") {
|
||||
exclude group: 'org.aspectj', module: 'aspectjrt'
|
||||
}
|
||||
|
||||
testRuntime "org.hsqldb:hsqldb:$hsqlVersion",
|
||||
"cglib:cglib-nodep:$cglibVersion"
|
||||
}
|
||||
|
||||
test {
|
||||
inputs.file file("$rootDir/docs/manual/src/docbook/appendix-namespace.xml")
|
||||
}
|
||||
|
||||
rncToXsd {
|
||||
rncDir = file('src/main/resources/org/springframework/security/config/')
|
||||
xsdDir = rncDir
|
||||
xslFile = new File(rncDir, 'spring-security.xsl')
|
||||
}
|
||||
|
||||
build.dependsOn rncToXsd
|
||||
+404
@@ -0,0 +1,404 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-config</artifactId>
|
||||
<version>4.2.9.RELEASE</version>
|
||||
<name>spring-security-config</name>
|
||||
<description>spring-security-config</description>
|
||||
<url>http://spring.io/spring-security</url>
|
||||
<organization>
|
||||
<name>spring.io</name>
|
||||
<url>http://spring.io/</url>
|
||||
</organization>
|
||||
<licenses>
|
||||
<license>
|
||||
<name>The Apache Software License, Version 2.0</name>
|
||||
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
|
||||
<distribution>repo</distribution>
|
||||
</license>
|
||||
</licenses>
|
||||
<developers>
|
||||
<developer>
|
||||
<id>rwinch</id>
|
||||
<name>Rob Winch</name>
|
||||
<email>rwinch@gopivotal.com</email>
|
||||
</developer>
|
||||
</developers>
|
||||
<scm>
|
||||
<connection>scm:git:git://github.com/spring-projects/spring-security</connection>
|
||||
<developerConnection>scm:git:git://github.com/spring-projects/spring-security</developerConnection>
|
||||
<url>https://github.com/spring-projects/spring-security</url>
|
||||
</scm>
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-framework-bom</artifactId>
|
||||
<version>4.3.19.RELEASE</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>aopalliance</groupId>
|
||||
<artifactId>aopalliance</artifactId>
|
||||
<version>1.0</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-core</artifactId>
|
||||
<version>4.2.9.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-aop</artifactId>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-beans</artifactId>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-core</artifactId>
|
||||
<scope>compile</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
<groupId>commons-logging</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-logging</groupId>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
<version>1.2</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.aspectj</groupId>
|
||||
<artifactId>aspectjweaver</artifactId>
|
||||
<version>1.8.13</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-ldap</artifactId>
|
||||
<version>4.2.9.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-messaging</artifactId>
|
||||
<version>4.2.9.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-openid</artifactId>
|
||||
<version>4.2.9.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-web</artifactId>
|
||||
<version>4.2.9.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-jdbc</artifactId>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-tx</artifactId>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-web</artifactId>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-webmvc</artifactId>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-websocket</artifactId>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cglib</groupId>
|
||||
<artifactId>cglib-nodep</artifactId>
|
||||
<version>3.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
<version>1.1.11</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.annotation</groupId>
|
||||
<artifactId>jsr250-api</artifactId>
|
||||
<version>1.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.12</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ldapsdk</groupId>
|
||||
<artifactId>ldapsdk</artifactId>
|
||||
<version>4.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.directory.server</groupId>
|
||||
<artifactId>apacheds-core</artifactId>
|
||||
<version>1.5.5</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.directory.server</groupId>
|
||||
<artifactId>apacheds-core-entry</artifactId>
|
||||
<version>1.5.5</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.directory.server</groupId>
|
||||
<artifactId>apacheds-protocol-ldap</artifactId>
|
||||
<version>1.5.5</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.directory.server</groupId>
|
||||
<artifactId>apacheds-protocol-shared</artifactId>
|
||||
<version>1.5.5</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.directory.server</groupId>
|
||||
<artifactId>apacheds-server-jndi</artifactId>
|
||||
<version>1.5.5</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.directory.shared</groupId>
|
||||
<artifactId>shared-ldap</artifactId>
|
||||
<version>0.9.15</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.assertj</groupId>
|
||||
<artifactId>assertj-core</artifactId>
|
||||
<version>2.2.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.codehaus.groovy</groupId>
|
||||
<artifactId>groovy-all</artifactId>
|
||||
<version>2.4.4</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.persistence</groupId>
|
||||
<artifactId>javax.persistence</artifactId>
|
||||
<version>2.1.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-entitymanager</artifactId>
|
||||
<version>5.0.12.Final</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hsqldb</groupId>
|
||||
<artifactId>hsqldb</artifactId>
|
||||
<version>2.3.6</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<version>1.10.19</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openid4java</groupId>
|
||||
<artifactId>openid4java-nodeps</artifactId>
|
||||
<version>0.9.6</version>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>guice</artifactId>
|
||||
<groupId>com.google.code.guice</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.powermock</groupId>
|
||||
<artifactId>powermock-api-mockito</artifactId>
|
||||
<version>1.6.5</version>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>mockito-all</artifactId>
|
||||
<groupId>org.mockito</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.powermock</groupId>
|
||||
<artifactId>powermock-api-support</artifactId>
|
||||
<version>1.6.5</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.powermock</groupId>
|
||||
<artifactId>powermock-core</artifactId>
|
||||
<version>1.6.5</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.powermock</groupId>
|
||||
<artifactId>powermock-module-junit4</artifactId>
|
||||
<version>1.6.5</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.powermock</groupId>
|
||||
<artifactId>powermock-module-junit4-common</artifactId>
|
||||
<version>1.6.5</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.powermock</groupId>
|
||||
<artifactId>powermock-reflect</artifactId>
|
||||
<version>1.6.5</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>jcl-over-slf4j</artifactId>
|
||||
<version>1.7.25</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.spockframework</groupId>
|
||||
<artifactId>spock-core</artifactId>
|
||||
<version>0.7-groovy-2.0</version>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>junit-dep</artifactId>
|
||||
<groupId>junit</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.spockframework</groupId>
|
||||
<artifactId>spock-spring</artifactId>
|
||||
<version>0.7-groovy-2.0</version>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>junit-dep</artifactId>
|
||||
<groupId>junit</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-jpa</artifactId>
|
||||
<version>1.11.16.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>aspectjrt</artifactId>
|
||||
<groupId>org.aspectj</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.ldap</groupId>
|
||||
<artifactId>spring-ldap-core</artifactId>
|
||||
<version>2.3.2.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-aspects</artifactId>
|
||||
<version>4.2.9.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-cas</artifactId>
|
||||
<version>4.2.9.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-expression</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-orm</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>1.7</source>
|
||||
<target>1.7</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@@ -1,81 +0,0 @@
|
||||
apply plugin: 'io.spring.convention.spring-module'
|
||||
apply plugin: 'trang'
|
||||
|
||||
dependencies {
|
||||
// NB: Don't add other compile time dependencies to the config module as this breaks tooling
|
||||
compile project(':spring-security-core')
|
||||
compile 'org.springframework:spring-aop'
|
||||
compile 'org.springframework:spring-beans'
|
||||
compile 'org.springframework:spring-context'
|
||||
compile 'org.springframework:spring-core'
|
||||
|
||||
optional project(':spring-security-ldap')
|
||||
optional project(':spring-security-messaging')
|
||||
optional project(':spring-security-oauth2-client')
|
||||
optional project(':spring-security-oauth2-jose')
|
||||
optional project(':spring-security-openid')
|
||||
optional project(':spring-security-web')
|
||||
optional 'io.projectreactor:reactor-core'
|
||||
optional 'org.aspectj:aspectjweaver'
|
||||
optional 'org.springframework:spring-jdbc'
|
||||
optional 'org.springframework:spring-tx'
|
||||
optional 'org.springframework:spring-webmvc'
|
||||
optional'org.springframework:spring-web'
|
||||
optional'org.springframework:spring-webflux'
|
||||
optional'org.springframework:spring-websocket'
|
||||
|
||||
provided 'javax.servlet:javax.servlet-api'
|
||||
|
||||
testCompile project(':spring-security-aspects')
|
||||
testCompile project(':spring-security-cas')
|
||||
testCompile project(':spring-security-test')
|
||||
testCompile project(path : ':spring-security-core', configuration : 'tests')
|
||||
testCompile project(path : ':spring-security-web', configuration : 'tests')
|
||||
testCompile apachedsDependencies
|
||||
testCompile powerMock2Dependencies
|
||||
testCompile spockDependencies
|
||||
testCompile 'ch.qos.logback:logback-classic'
|
||||
testCompile 'javax.annotation:jsr250-api:1.0'
|
||||
testCompile 'ldapsdk:ldapsdk:4.1'
|
||||
testCompile('net.sourceforge.htmlunit:htmlunit') {
|
||||
exclude group: 'commons-logging', module: 'commons-logging'
|
||||
}
|
||||
testCompile 'org.codehaus.groovy:groovy-all'
|
||||
testCompile 'org.eclipse.persistence:javax.persistence'
|
||||
testCompile 'org.hibernate:hibernate-entitymanager'
|
||||
testCompile 'org.hsqldb:hsqldb'
|
||||
testCompile ('org.openid4java:openid4java-nodeps') {
|
||||
exclude group: 'com.google.code.guice', module: 'guice'
|
||||
}
|
||||
testCompile('org.seleniumhq.selenium:htmlunit-driver') {
|
||||
exclude group: 'commons-logging', module: 'commons-logging'
|
||||
}
|
||||
testCompile('org.seleniumhq.selenium:selenium-java') {
|
||||
exclude group: 'commons-logging', module: 'commons-logging'
|
||||
exclude group: 'io.netty', module: 'netty'
|
||||
}
|
||||
testCompile 'org.slf4j:jcl-over-slf4j'
|
||||
testCompile 'org.springframework.ldap:spring-ldap-core'
|
||||
testCompile 'org.springframework:spring-expression'
|
||||
testCompile 'org.springframework:spring-jdbc'
|
||||
testCompile 'org.springframework:spring-orm'
|
||||
testCompile 'org.springframework:spring-tx'
|
||||
testCompile ('org.springframework.data:spring-data-jpa') {
|
||||
exclude group: 'org.aspectj', module: 'aspectjrt'
|
||||
}
|
||||
|
||||
testRuntime 'cglib:cglib-nodep'
|
||||
testRuntime 'org.hsqldb:hsqldb'
|
||||
}
|
||||
|
||||
test {
|
||||
inputs.file file("$rootDir/docs/manual/src/docbook/appendix-namespace.xml")
|
||||
}
|
||||
|
||||
rncToXsd {
|
||||
rncDir = file('src/main/resources/org/springframework/security/config/')
|
||||
xsdDir = rncDir
|
||||
xslFile = new File(rncDir, 'spring-security.xsl')
|
||||
}
|
||||
|
||||
build.dependsOn rncToXsd
|
||||
+20
-3
@@ -1,6 +1,5 @@
|
||||
package org.springframework.security.config.ldap
|
||||
|
||||
import org.springframework.security.crypto.password.NoOpPasswordEncoder
|
||||
|
||||
import static org.mockito.Mockito.*
|
||||
|
||||
@@ -89,16 +88,34 @@ class LdapProviderBeanDefinitionParserTests extends AbstractXmlConfigTests {
|
||||
notThrown(AuthenticationException)
|
||||
}
|
||||
|
||||
def supportsPasswordComparisonAuthenticationWithHashAttribute() {
|
||||
xml.'ldap-server'(ldif:'test-server.ldif')
|
||||
xml.'authentication-manager'{
|
||||
'ldap-authentication-provider'('user-dn-pattern': 'uid={0},ou=people') {
|
||||
'password-compare'('password-attribute': 'uid', hash: 'plaintext')
|
||||
}
|
||||
}
|
||||
createAppContext('')
|
||||
def am = appContext.getBean(BeanIds.AUTHENTICATION_MANAGER)
|
||||
|
||||
when:
|
||||
def auth = am.authenticate(new UsernamePasswordAuthenticationToken("ben", "ben"))
|
||||
|
||||
then:
|
||||
auth != null
|
||||
notThrown(AuthenticationException)
|
||||
|
||||
}
|
||||
|
||||
def supportsPasswordComparisonAuthenticationWithPasswordEncoder() {
|
||||
xml.'ldap-server'(ldif:'test-server.ldif')
|
||||
xml.'authentication-manager'{
|
||||
'ldap-authentication-provider'('user-dn-pattern': 'uid={0},ou=people') {
|
||||
'password-compare'('password-attribute': 'uid') {
|
||||
'password-encoder'(ref: 'passwordEncoder')
|
||||
'password-encoder'(hash: 'plaintext')
|
||||
}
|
||||
}
|
||||
}
|
||||
xml.'b:bean'(id: 'passwordEncoder', 'class' : NoOpPasswordEncoder.name, 'factory-method': 'getInstance')
|
||||
|
||||
createAppContext('')
|
||||
def am = appContext.getBean(BeanIds.AUTHENTICATION_MANAGER)
|
||||
|
||||
+2
-2
@@ -15,10 +15,10 @@
|
||||
*/
|
||||
package org.springframework.security.config.annotation.authentication.ldap;
|
||||
|
||||
import org.springframework.security.authentication.encoding.PlaintextPasswordEncoder;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
|
||||
import org.springframework.security.ldap.userdetails.LdapAuthoritiesPopulator;
|
||||
import org.springframework.security.ldap.userdetails.PersonContextMapper;
|
||||
|
||||
@@ -90,7 +90,7 @@ public class NamespaceLdapAuthenticationProviderTestsConfigs {
|
||||
.groupSearchBase("ou=groups")
|
||||
.userSearchFilter("(uid={0})")
|
||||
.passwordCompare()
|
||||
.passwordEncoder(NoOpPasswordEncoder.getInstance()) // ldap-authentication-provider/password-compare/password-encoder@ref
|
||||
.passwordEncoder(new PlaintextPasswordEncoder()) // ldap-authentication-provider/password-compare/password-encoder@ref
|
||||
.passwordAttribute("userPassword"); // ldap-authentication-provider/password-compare@password-attribute
|
||||
}
|
||||
// @formatter:on
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
<configuration>
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
|
||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
</appender>
|
||||
|
||||
<logger name="org.springframework.security" level="${sec.log.level:-WARN}"/>
|
||||
<logger name="org.springframework.security" level="${sec.log.level}:-WARN"/>
|
||||
|
||||
<logger name="org.apache.directory" level="ERROR"/>
|
||||
<logger name="JdbmTable" level="INFO"/>
|
||||
<logger name="JdbmIndex" level="INFO"/>
|
||||
<logger name="org.apache.mina" level="WARN"/>
|
||||
<logger name="org.apache.directory" level="ERROR"/>
|
||||
<logger name="JdbmTable" level="INFO"/>
|
||||
<logger name="JdbmIndex" level="INFO"/>
|
||||
<logger name="org.apache.mina" level="WARN"/>
|
||||
|
||||
<root level="${root.level:-WARN}">
|
||||
<root level="${root.level}:-WARN">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</root>
|
||||
</root>
|
||||
|
||||
</configuration>
|
||||
|
||||
@@ -55,6 +55,7 @@ public abstract class Elements {
|
||||
public static final String FILTER_CHAIN = "filter-chain";
|
||||
public static final String GLOBAL_METHOD_SECURITY = "global-method-security";
|
||||
public static final String PASSWORD_ENCODER = "password-encoder";
|
||||
public static final String SALT_SOURCE = "salt-source";
|
||||
public static final String PORT_MAPPINGS = "port-mappings";
|
||||
public static final String PORT_MAPPING = "port-mapping";
|
||||
public static final String CUSTOM_FILTER = "custom-filter";
|
||||
|
||||
+5
-93
@@ -27,7 +27,6 @@ import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.aop.framework.ProxyFactoryBean;
|
||||
import org.springframework.aop.target.LazyInitTargetSource;
|
||||
import org.springframework.beans.factory.BeanFactoryUtils;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@@ -37,15 +36,10 @@ import org.springframework.core.annotation.AnnotationAwareOrderComparator;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.config.annotation.ObjectPostProcessor;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.config.annotation.authentication.configurers.provisioning.InMemoryUserDetailsManagerConfigurer;
|
||||
import org.springframework.security.config.annotation.authentication.configurers.provisioning.JdbcUserDetailsManagerConfigurer;
|
||||
import org.springframework.security.config.annotation.authentication.configurers.userdetails.DaoAuthenticationConfigurer;
|
||||
import org.springframework.security.config.annotation.authentication.configurers.GlobalAuthenticationConfigurerAdapter;
|
||||
import org.springframework.security.config.annotation.configuration.ObjectPostProcessorConfiguration;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -74,9 +68,8 @@ public class AuthenticationConfiguration {
|
||||
|
||||
@Bean
|
||||
public AuthenticationManagerBuilder authenticationManagerBuilder(
|
||||
ObjectPostProcessor<Object> objectPostProcessor, ApplicationContext context) {
|
||||
LazyPasswordEncoder defaultPasswordEncoder = new LazyPasswordEncoder(context);
|
||||
return new DefaultPasswordEncoderAuthenticationManagerBuilder(objectPostProcessor, defaultPasswordEncoder);
|
||||
ObjectPostProcessor<Object> objectPostProcessor) {
|
||||
return new AuthenticationManagerBuilder(objectPostProcessor);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@@ -100,7 +93,7 @@ public class AuthenticationConfiguration {
|
||||
return this.authenticationManager;
|
||||
}
|
||||
AuthenticationManagerBuilder authBuilder = authenticationManagerBuilder(
|
||||
this.objectPostProcessor, this.applicationContext);
|
||||
this.objectPostProcessor);
|
||||
if (this.buildingAuthenticationManager.getAndSet(true)) {
|
||||
return new AuthenticationManagerDelegator(authBuilder);
|
||||
}
|
||||
@@ -218,85 +211,4 @@ public class AuthenticationConfiguration {
|
||||
return "AuthenticationManagerDelegator [delegate=" + this.delegate + "]";
|
||||
}
|
||||
}
|
||||
|
||||
static class DefaultPasswordEncoderAuthenticationManagerBuilder extends AuthenticationManagerBuilder {
|
||||
private PasswordEncoder defaultPasswordEncoder;
|
||||
|
||||
/**
|
||||
* Creates a new instance
|
||||
*
|
||||
* @param objectPostProcessor the {@link ObjectPostProcessor} instance to use.
|
||||
*/
|
||||
DefaultPasswordEncoderAuthenticationManagerBuilder(
|
||||
ObjectPostProcessor<Object> objectPostProcessor, PasswordEncoder defaultPasswordEncoder) {
|
||||
super(objectPostProcessor);
|
||||
this.defaultPasswordEncoder = defaultPasswordEncoder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InMemoryUserDetailsManagerConfigurer<AuthenticationManagerBuilder> inMemoryAuthentication()
|
||||
throws Exception {
|
||||
return super.inMemoryAuthentication()
|
||||
.passwordEncoder(this.defaultPasswordEncoder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JdbcUserDetailsManagerConfigurer<AuthenticationManagerBuilder> jdbcAuthentication()
|
||||
throws Exception {
|
||||
return super.jdbcAuthentication()
|
||||
.passwordEncoder(this.defaultPasswordEncoder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends UserDetailsService> DaoAuthenticationConfigurer<AuthenticationManagerBuilder, T> userDetailsService(
|
||||
T userDetailsService) throws Exception {
|
||||
return super.userDetailsService(userDetailsService)
|
||||
.passwordEncoder(this.defaultPasswordEncoder);
|
||||
}
|
||||
}
|
||||
|
||||
static class LazyPasswordEncoder implements PasswordEncoder {
|
||||
private ApplicationContext applicationContext;
|
||||
private PasswordEncoder passwordEncoder;
|
||||
|
||||
LazyPasswordEncoder(ApplicationContext applicationContext) {
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String encode(CharSequence rawPassword) {
|
||||
return getPasswordEncoder().encode(rawPassword);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(CharSequence rawPassword,
|
||||
String encodedPassword) {
|
||||
return getPasswordEncoder().matches(rawPassword, encodedPassword);
|
||||
}
|
||||
|
||||
private PasswordEncoder getPasswordEncoder() {
|
||||
if (this.passwordEncoder != null) {
|
||||
return this.passwordEncoder;
|
||||
}
|
||||
PasswordEncoder passwordEncoder = getBeanOrNull(PasswordEncoder.class);
|
||||
if (passwordEncoder == null) {
|
||||
passwordEncoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
|
||||
}
|
||||
this.passwordEncoder = passwordEncoder;
|
||||
return passwordEncoder;
|
||||
}
|
||||
|
||||
private <T> T getBeanOrNull(Class<T> type) {
|
||||
try {
|
||||
return this.applicationContext.getBean(type);
|
||||
} catch(NoSuchBeanDefinitionException notFound) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getPasswordEncoder().toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
@@ -19,6 +19,7 @@ import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.security.authentication.AuthenticationProvider;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.config.annotation.authentication.configurers.GlobalAuthenticationConfigurerAdapter;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
|
||||
|
||||
+1
-1
@@ -20,6 +20,7 @@ import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.config.annotation.authentication.configurers.GlobalAuthenticationConfigurerAdapter;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
|
||||
@@ -71,7 +72,6 @@ class InitializeUserDetailsBeanManagerConfigurer
|
||||
if (passwordEncoder != null) {
|
||||
provider.setPasswordEncoder(passwordEncoder);
|
||||
}
|
||||
provider.afterPropertiesSet();
|
||||
|
||||
auth.authenticationProvider(provider);
|
||||
}
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.security.config.annotation.authentication.configuration;
|
||||
package org.springframework.security.config.annotation.authentication.configurers;
|
||||
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
@@ -39,4 +39,4 @@ public abstract class GlobalAuthenticationConfigurerAdapter implements
|
||||
|
||||
public void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
}
|
||||
}
|
||||
}
|
||||
+26
-18
@@ -21,14 +21,15 @@ import java.net.ServerSocket;
|
||||
import org.springframework.ldap.core.support.BaseLdapPathContextSource;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.AuthenticationProvider;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.security.authentication.encoding.PasswordEncoder;
|
||||
import org.springframework.security.authentication.encoding.PlaintextPasswordEncoder;
|
||||
import org.springframework.security.config.annotation.ObjectPostProcessor;
|
||||
import org.springframework.security.config.annotation.SecurityConfigurerAdapter;
|
||||
import org.springframework.security.config.annotation.authentication.ProviderManagerBuilder;
|
||||
import org.springframework.security.config.annotation.web.configurers.ChannelSecurityConfigurer;
|
||||
import org.springframework.security.config.core.GrantedAuthorityDefaults;
|
||||
import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
|
||||
import org.springframework.security.core.authority.mapping.SimpleAuthorityMapper;
|
||||
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
|
||||
import org.springframework.security.ldap.DefaultSpringSecurityContextSource;
|
||||
import org.springframework.security.ldap.authentication.AbstractLdapAuthenticator;
|
||||
import org.springframework.security.ldap.authentication.BindAuthenticator;
|
||||
@@ -38,7 +39,6 @@ import org.springframework.security.ldap.authentication.PasswordComparisonAuthen
|
||||
import org.springframework.security.ldap.search.FilterBasedLdapUserSearch;
|
||||
import org.springframework.security.ldap.search.LdapUserSearch;
|
||||
import org.springframework.security.ldap.server.ApacheDSContainer;
|
||||
import org.springframework.security.ldap.server.UnboundIdContainer;
|
||||
import org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator;
|
||||
import org.springframework.security.ldap.userdetails.InetOrgPersonContextMapper;
|
||||
import org.springframework.security.ldap.userdetails.LdapAuthoritiesPopulator;
|
||||
@@ -46,7 +46,6 @@ import org.springframework.security.ldap.userdetails.LdapUserDetailsMapper;
|
||||
import org.springframework.security.ldap.userdetails.PersonContextMapper;
|
||||
import org.springframework.security.ldap.userdetails.UserDetailsContextMapper;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* Configures LDAP {@link AuthenticationProvider} in the {@link ProviderManagerBuilder}.
|
||||
@@ -64,12 +63,12 @@ public class LdapAuthenticationProviderConfigurer<B extends ProviderManagerBuild
|
||||
private String groupSearchFilter = "(uniqueMember={0})";
|
||||
private String rolePrefix = "ROLE_";
|
||||
private String userSearchBase = ""; // only for search
|
||||
private String userSearchFilter = null; // "uid={0}"; // only for search
|
||||
private String userSearchFilter = null;// "uid={0}"; // only for search
|
||||
private String[] userDnPatterns;
|
||||
private BaseLdapPathContextSource contextSource;
|
||||
private ContextSourceBuilder contextSourceBuilder = new ContextSourceBuilder();
|
||||
private UserDetailsContextMapper userDetailsContextMapper;
|
||||
private PasswordEncoder passwordEncoder;
|
||||
private Object passwordEncoder;
|
||||
private String passwordAttribute;
|
||||
private LdapAuthoritiesPopulator ldapAuthoritiesPopulator;
|
||||
private GrantedAuthoritiesMapper authoritiesMapper;
|
||||
@@ -249,6 +248,22 @@ public class LdapAuthenticationProviderConfigurer<B extends ProviderManagerBuild
|
||||
return contextSourceBuilder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies the {@link PasswordEncoder} to be used when authenticating with password
|
||||
* comparison.
|
||||
*
|
||||
* @param passwordEncoder the {@link PasswordEncoder} to use
|
||||
* @return the {@link LdapAuthenticationProviderConfigurer} for further customization
|
||||
* @deprecated Use
|
||||
* {@link #passwordEncoder(org.springframework.security.crypto.password.PasswordEncoder)}
|
||||
* instead
|
||||
*/
|
||||
public LdapAuthenticationProviderConfigurer<B> passwordEncoder(
|
||||
PasswordEncoder passwordEncoder) {
|
||||
this.passwordEncoder = passwordEncoder;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies the {@link org.springframework.security.crypto.password.PasswordEncoder}
|
||||
* to be used when authenticating with password comparison.
|
||||
@@ -386,7 +401,7 @@ public class LdapAuthenticationProviderConfigurer<B extends ProviderManagerBuild
|
||||
|
||||
/**
|
||||
* Allows specifying the {@link PasswordEncoder} to use. The default is
|
||||
* {@link org.springframework.security.crypto.password.NoOpPasswordEncoder}.
|
||||
* {@link PlaintextPasswordEncoder}.
|
||||
* @param passwordEncoder the {@link PasswordEncoder} to use
|
||||
* @return the {@link PasswordEncoder} to use
|
||||
*/
|
||||
@@ -536,16 +551,9 @@ public class LdapAuthenticationProviderConfigurer<B extends ProviderManagerBuild
|
||||
if (url != null) {
|
||||
return contextSource;
|
||||
}
|
||||
if (ClassUtils.isPresent("org.apache.directory.server.core.DefaultDirectoryService", getClass().getClassLoader())) {
|
||||
ApacheDSContainer apacheDsContainer = new ApacheDSContainer(root, ldif);
|
||||
apacheDsContainer.setPort(getPort());
|
||||
postProcess(apacheDsContainer);
|
||||
}
|
||||
else if (ClassUtils.isPresent("com.unboundid.ldap.listener.InMemoryDirectoryServer", getClass().getClassLoader())) {
|
||||
UnboundIdContainer unboundIdContainer = new UnboundIdContainer(root, ldif);
|
||||
unboundIdContainer.setPort(getPort());
|
||||
postProcess(unboundIdContainer);
|
||||
}
|
||||
ApacheDSContainer apacheDsContainer = new ApacheDSContainer(root, ldif);
|
||||
apacheDsContainer.setPort(getPort());
|
||||
postProcess(apacheDsContainer);
|
||||
return contextSource;
|
||||
}
|
||||
|
||||
@@ -606,6 +614,6 @@ public class LdapAuthenticationProviderConfigurer<B extends ProviderManagerBuild
|
||||
*/
|
||||
public PasswordCompareConfigurer passwordCompare() {
|
||||
return new PasswordCompareConfigurer().passwordAttribute("password")
|
||||
.passwordEncoder(NoOpPasswordEncoder.getInstance());
|
||||
.passwordEncoder(new PlaintextPasswordEncoder());
|
||||
}
|
||||
}
|
||||
|
||||
-31
@@ -43,8 +43,6 @@ public class UserDetailsManagerConfigurer<B extends ProviderManagerBuilder<B>, C
|
||||
|
||||
private final List<UserDetailsBuilder> userBuilders = new ArrayList<UserDetailsBuilder>();
|
||||
|
||||
private final List<UserDetails> users = new ArrayList<>();
|
||||
|
||||
protected UserDetailsManagerConfigurer(UserDetailsManager userDetailsManager) {
|
||||
super(userDetailsManager);
|
||||
}
|
||||
@@ -59,35 +57,6 @@ public class UserDetailsManagerConfigurer<B extends ProviderManagerBuilder<B>, C
|
||||
for (UserDetailsBuilder userBuilder : userBuilders) {
|
||||
getUserDetailsService().createUser(userBuilder.build());
|
||||
}
|
||||
for (UserDetails userDetails : this.users) {
|
||||
getUserDetailsService().createUser(userDetails);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows adding a user to the {@link UserDetailsManager} that is being created. This
|
||||
* method can be invoked multiple times to add multiple users.
|
||||
*
|
||||
* @param userDetails the user to add. Cannot be null.
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public final C withUser(UserDetails userDetails) {
|
||||
this.users.add(userDetails);
|
||||
return (C) this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows adding a user to the {@link UserDetailsManager} that is being created. This
|
||||
* method can be invoked multiple times to add multiple users.
|
||||
*
|
||||
* @param userBuilder the user to add. Cannot be null.
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public final C withUser(User.UserBuilder userBuilder) {
|
||||
this.users.add(userBuilder.build());
|
||||
return (C) this;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+18
@@ -18,6 +18,7 @@ package org.springframework.security.config.annotation.authentication.configurer
|
||||
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
|
||||
import org.springframework.security.config.annotation.ObjectPostProcessor;
|
||||
import org.springframework.security.config.annotation.SecurityBuilder;
|
||||
import org.springframework.security.config.annotation.SecurityConfigurer;
|
||||
import org.springframework.security.config.annotation.authentication.ProviderManagerBuilder;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
@@ -73,6 +74,23 @@ abstract class AbstractDaoAuthenticationConfigurer<B extends ProviderManagerBuil
|
||||
return (C) this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows specifying the
|
||||
* {@link org.springframework.security.authentication.encoding.PasswordEncoder} to use
|
||||
* with the {@link DaoAuthenticationProvider}. The default is to use plain text.
|
||||
*
|
||||
* @param passwordEncoder The
|
||||
* {@link org.springframework.security.authentication.encoding.PasswordEncoder} to
|
||||
* use.
|
||||
* @return the {@link SecurityConfigurer} for further customizations
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public C passwordEncoder(
|
||||
org.springframework.security.authentication.encoding.PasswordEncoder passwordEncoder) {
|
||||
provider.setPasswordEncoder(passwordEncoder);
|
||||
return (C) this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(B builder) throws Exception {
|
||||
provider = postProcess(provider);
|
||||
|
||||
-69
@@ -1,69 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.config.annotation.method.configuration;
|
||||
|
||||
import org.springframework.context.annotation.AdviceMode;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.core.Ordered;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @since 5.0
|
||||
*/
|
||||
@Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME)
|
||||
@Target(value = { java.lang.annotation.ElementType.TYPE })
|
||||
@Documented
|
||||
@Import({ ReactiveMethodSecuritySelector.class })
|
||||
@Configuration
|
||||
public @interface EnableReactiveMethodSecurity {
|
||||
/**
|
||||
* Indicate whether subclass-based (CGLIB) proxies are to be created as opposed
|
||||
* to standard Java interface-based proxies. The default is {@code false}. <strong>
|
||||
* Applicable only if {@link #mode()} is set to {@link AdviceMode#PROXY}</strong>.
|
||||
* <p>Note that setting this attribute to {@code true} will affect <em>all</em>
|
||||
* Spring-managed beans requiring proxying, not just those marked with {@code @Cacheable}.
|
||||
* For example, other beans marked with Spring's {@code @Transactional} annotation will
|
||||
* be upgraded to subclass proxying at the same time. This approach has no negative
|
||||
* impact in practice unless one is explicitly expecting one type of proxy vs another,
|
||||
* e.g. in tests.
|
||||
*/
|
||||
boolean proxyTargetClass() default false;
|
||||
|
||||
/**
|
||||
* Indicate how security advice should be applied. The default is
|
||||
* {@link AdviceMode#PROXY}.
|
||||
* @see AdviceMode
|
||||
*
|
||||
* @return the {@link AdviceMode} to use
|
||||
*/
|
||||
AdviceMode mode() default AdviceMode.PROXY;
|
||||
|
||||
/**
|
||||
* Indicate the ordering of the execution of the security advisor when multiple
|
||||
* advices are applied at a specific joinpoint. The default is
|
||||
* {@link Ordered#LOWEST_PRECEDENCE}.
|
||||
*
|
||||
* @return the order the security advisor should be applied
|
||||
*/
|
||||
int order() default Ordered.LOWEST_PRECEDENCE;
|
||||
}
|
||||
+2
-2
@@ -50,7 +50,7 @@ class MethodSecurityMetadataSourceAdvisorRegistrar implements
|
||||
advisor.addConstructorArgReference("methodSecurityMetadataSource");
|
||||
advisor.addConstructorArgValue("methodSecurityMetadataSource");
|
||||
|
||||
MultiValueMap<String, Object> attributes = importingClassMetadata.getAllAnnotationAttributes(EnableGlobalMethodSecurity.class.getName());
|
||||
MultiValueMap<String,Object> attributes = importingClassMetadata.getAllAnnotationAttributes(EnableGlobalMethodSecurity.class.getName());
|
||||
Integer order = (Integer) attributes.getFirst("order");
|
||||
if(order != null) {
|
||||
advisor.addPropertyValue("order", order);
|
||||
@@ -59,4 +59,4 @@ class MethodSecurityMetadataSourceAdvisorRegistrar implements
|
||||
registry.registerBeanDefinition("metaDataSourceAdvisor",
|
||||
advisor.getBeanDefinition());
|
||||
}
|
||||
}
|
||||
}
|
||||
-80
@@ -1,80 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.config.annotation.method.configuration;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.ImportAware;
|
||||
import org.springframework.context.annotation.Role;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
import org.springframework.security.access.expression.method.*;
|
||||
import org.springframework.security.access.intercept.aopalliance.MethodSecurityMetadataSourceAdvisor;
|
||||
import org.springframework.security.access.method.AbstractMethodSecurityMetadataSource;
|
||||
import org.springframework.security.access.method.DelegatingMethodSecurityMetadataSource;
|
||||
import org.springframework.security.access.prepost.PrePostAdviceReactiveMethodInterceptor;
|
||||
import org.springframework.security.access.prepost.PrePostAnnotationSecurityMetadataSource;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* @author Rob Winch
|
||||
* @since 5.0
|
||||
*/
|
||||
@Configuration
|
||||
class ReactiveMethodSecurityConfiguration implements ImportAware {
|
||||
private int advisorOrder;
|
||||
|
||||
@Bean
|
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
public MethodSecurityMetadataSourceAdvisor methodSecurityInterceptor(AbstractMethodSecurityMetadataSource source) throws Exception {
|
||||
MethodSecurityMetadataSourceAdvisor advisor = new MethodSecurityMetadataSourceAdvisor(
|
||||
"securityMethodInterceptor", source, "methodMetadataSource");
|
||||
advisor.setOrder(advisorOrder);
|
||||
return advisor;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public DelegatingMethodSecurityMetadataSource methodMetadataSource() {
|
||||
ExpressionBasedAnnotationAttributeFactory attributeFactory = new ExpressionBasedAnnotationAttributeFactory(
|
||||
new DefaultMethodSecurityExpressionHandler());
|
||||
PrePostAnnotationSecurityMetadataSource prePostSource = new PrePostAnnotationSecurityMetadataSource(
|
||||
attributeFactory);
|
||||
return new DelegatingMethodSecurityMetadataSource(Arrays.asList(prePostSource));
|
||||
}
|
||||
|
||||
@Bean
|
||||
public PrePostAdviceReactiveMethodInterceptor securityMethodInterceptor(AbstractMethodSecurityMetadataSource source, MethodSecurityExpressionHandler handler) {
|
||||
|
||||
ExpressionBasedPostInvocationAdvice postAdvice = new ExpressionBasedPostInvocationAdvice(
|
||||
handler);
|
||||
ExpressionBasedPreInvocationAdvice preAdvice = new ExpressionBasedPreInvocationAdvice();
|
||||
preAdvice.setExpressionHandler(handler);
|
||||
|
||||
return new PrePostAdviceReactiveMethodInterceptor(source, preAdvice, postAdvice);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public DefaultMethodSecurityExpressionHandler methodSecurityExpressionHandler() {
|
||||
return new DefaultMethodSecurityExpressionHandler();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setImportMetadata(AnnotationMetadata importMetadata) {
|
||||
this.advisorOrder = (int) importMetadata.getAnnotationAttributes(EnableReactiveMethodSecurity.class.getName()).get("order");
|
||||
}
|
||||
}
|
||||
-53
@@ -1,53 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.config.annotation.method.configuration;
|
||||
|
||||
import org.springframework.context.annotation.AdviceMode;
|
||||
import org.springframework.context.annotation.AdviceModeImportSelector;
|
||||
import org.springframework.context.annotation.AutoProxyRegistrar;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Rob Winch
|
||||
* @since 5.0
|
||||
*/
|
||||
class ReactiveMethodSecuritySelector extends
|
||||
AdviceModeImportSelector<EnableReactiveMethodSecurity> {
|
||||
|
||||
@Override
|
||||
protected String[] selectImports(AdviceMode adviceMode) {
|
||||
switch (adviceMode) {
|
||||
case PROXY:
|
||||
return getProxyImports();
|
||||
default:
|
||||
throw new IllegalStateException("AdviceMode " + adviceMode + " is not supported");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the imports to use if the {@link AdviceMode} is set to {@link AdviceMode#PROXY}.
|
||||
* <p>Take care of adding the necessary JSR-107 import if it is available.
|
||||
*/
|
||||
private String[] getProxyImports() {
|
||||
List<String> result = new ArrayList<>();
|
||||
result.add(AutoProxyRegistrar.class.getName());
|
||||
result.add(ReactiveMethodSecurityConfiguration.class.getName());
|
||||
return result.toArray(new String[result.size()]);
|
||||
}
|
||||
}
|
||||
-8
@@ -77,10 +77,6 @@ final class FilterComparator implements Comparator<Filter>, Serializable {
|
||||
order += STEP;
|
||||
put(LogoutFilter.class, order);
|
||||
order += STEP;
|
||||
filterToOrder.put(
|
||||
"org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestRedirectFilter",
|
||||
order);
|
||||
order += STEP;
|
||||
put(X509AuthenticationFilter.class, order);
|
||||
order += STEP;
|
||||
put(AbstractPreAuthenticatedProcessingFilter.class, order);
|
||||
@@ -88,10 +84,6 @@ final class FilterComparator implements Comparator<Filter>, Serializable {
|
||||
filterToOrder.put("org.springframework.security.cas.web.CasAuthenticationFilter",
|
||||
order);
|
||||
order += STEP;
|
||||
filterToOrder.put(
|
||||
"org.springframework.security.oauth2.client.web.OAuth2LoginAuthenticationFilter",
|
||||
order);
|
||||
order += STEP;
|
||||
put(UsernamePasswordAuthenticationFilter.class, order);
|
||||
order += STEP;
|
||||
put(ConcurrentSessionFilter.class, order);
|
||||
|
||||
+3
-98
@@ -61,7 +61,6 @@ import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.config.annotation.web.configurers.oauth2.client.OAuth2LoginConfigurer;
|
||||
import org.springframework.security.web.DefaultSecurityFilterChain;
|
||||
import org.springframework.security.web.PortMapper;
|
||||
import org.springframework.security.web.PortMapperImpl;
|
||||
@@ -604,7 +603,7 @@ public final class HttpSecurity extends
|
||||
* @Override
|
||||
* protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
* auth.inMemoryAuthentication().withUser("user").password("password").roles("USER")
|
||||
* .and().withUser("admin").password("password").roles("ADMIN", "USER");
|
||||
* .and().withUser("adminr").password("password").roles("ADMIN", "USER");
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
@@ -627,7 +626,7 @@ public final class HttpSecurity extends
|
||||
* @Override
|
||||
* protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
* auth.inMemoryAuthentication().withUser("user").password("password").roles("USER")
|
||||
* .and().withUser("admin").password("password").roles("ADMIN", "USER");
|
||||
* .and().withUser("adminr").password("password").roles("ADMIN", "USER");
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
@@ -897,100 +896,6 @@ public final class HttpSecurity extends
|
||||
return getOrApply(new FormLoginConfigurer<HttpSecurity>());
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures authentication support using an OAuth 2.0 and/or OpenID Connect 1.0 Provider.
|
||||
* <br>
|
||||
* <br>
|
||||
*
|
||||
* The "authentication flow" is implemented using the <b>Authorization Code Grant</b>, as specified in the
|
||||
* <a target="_blank" href="https://tools.ietf.org/html/rfc6749#section-4.1">OAuth 2.0 Authorization Framework</a>
|
||||
* and <a target="_blank" href="http://openid.net/specs/openid-connect-core-1_0.html#CodeFlowAuth">OpenID Connect Core 1.0</a>
|
||||
* specification.
|
||||
* <br>
|
||||
* <br>
|
||||
*
|
||||
* As a prerequisite to using this feature, you must register a client with a provider.
|
||||
* The client registration information may than be used for configuring
|
||||
* a {@link org.springframework.security.oauth2.client.registration.ClientRegistration} using a
|
||||
* {@link org.springframework.security.oauth2.client.registration.ClientRegistration.Builder}.
|
||||
* <br>
|
||||
* <br>
|
||||
*
|
||||
* {@link org.springframework.security.oauth2.client.registration.ClientRegistration}(s) are composed within a
|
||||
* {@link org.springframework.security.oauth2.client.registration.ClientRegistrationRepository},
|
||||
* which is <b>required</b> and must be registered with the {@link ApplicationContext} or
|
||||
* configured via <code>oauth2Login().clientRegistrationRepository(..)</code>.
|
||||
* <br>
|
||||
* <br>
|
||||
*
|
||||
* The default configuration provides an auto-generated login page at <code>"/login"</code> and
|
||||
* redirects to <code>"/login?error"</code> when an authentication error occurs.
|
||||
* The login page will display each of the clients with a link
|
||||
* that is capable of initiating the "authentication flow".
|
||||
* <br>
|
||||
* <br>
|
||||
*
|
||||
* <p>
|
||||
* <h2>Example Configuration</h2>
|
||||
*
|
||||
* The following example shows the minimal configuration required, using Google as the Authentication Provider.
|
||||
*
|
||||
* <pre>
|
||||
* @Configuration
|
||||
* public class OAuth2LoginConfig {
|
||||
*
|
||||
* @EnableWebSecurity
|
||||
* public static class OAuth2LoginSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
* @Override
|
||||
* protected void configure(HttpSecurity http) throws Exception {
|
||||
* http
|
||||
* .authorizeRequests()
|
||||
* .anyRequest().authenticated()
|
||||
* .and()
|
||||
* .oauth2Login();
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* @Bean
|
||||
* public ClientRegistrationRepository clientRegistrationRepository() {
|
||||
* return new InMemoryClientRegistrationRepository(this.googleClientRegistration());
|
||||
* }
|
||||
*
|
||||
* private ClientRegistration googleClientRegistration() {
|
||||
* return ClientRegistration.withRegistrationId("google")
|
||||
* .clientId("google-client-id")
|
||||
* .clientSecret("google-client-secret")
|
||||
* .clientAuthenticationMethod(ClientAuthenticationMethod.BASIC)
|
||||
* .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
|
||||
* .redirectUriTemplate("{baseUrl}/login/oauth2/code/{registrationId}")
|
||||
* .scope("openid", "profile", "email", "address", "phone")
|
||||
* .authorizationUri("https://accounts.google.com/o/oauth2/v2/auth")
|
||||
* .tokenUri("https://www.googleapis.com/oauth2/v4/token")
|
||||
* .userInfoUri("https://www.googleapis.com/oauth2/v3/userinfo")
|
||||
* .userNameAttributeName(IdTokenClaimNames.SUB)
|
||||
* .jwkSetUri("https://www.googleapis.com/oauth2/v3/certs")
|
||||
* .clientName("Google")
|
||||
* .build();
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* <p>
|
||||
* For more advanced configuration, see {@link OAuth2LoginConfigurer} for available options to customize the defaults.
|
||||
*
|
||||
* @author Joe Grandja
|
||||
* @since 5.0
|
||||
* @see <a target="_blank" href="https://tools.ietf.org/html/rfc6749#section-4.1">Section 4.1 Authorization Code Grant</a>
|
||||
* @see <a target="_blank" href="http://openid.net/specs/openid-connect-core-1_0.html#CodeFlowAuth">Section 3.1 Authorization Code Flow</a>
|
||||
* @see org.springframework.security.oauth2.client.registration.ClientRegistration
|
||||
* @see org.springframework.security.oauth2.client.registration.ClientRegistrationRepository
|
||||
* @return the {@link OAuth2LoginConfigurer} for further customizations
|
||||
* @throws Exception
|
||||
*/
|
||||
public OAuth2LoginConfigurer<HttpSecurity> oauth2Login() throws Exception {
|
||||
return getOrApply(new OAuth2LoginConfigurer<HttpSecurity>());
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures channel security. In order for this configuration to be useful at least
|
||||
* one mapping to a required channel must be provided.
|
||||
@@ -1038,7 +943,7 @@ public final class HttpSecurity extends
|
||||
* <h2>Example Configuration</h2>
|
||||
*
|
||||
* The example below demonstrates how to configure HTTP Basic authentication for an
|
||||
* application. The default realm is "Realm", but can be
|
||||
* application. The default realm is "Spring Security Application", but can be
|
||||
* customized using {@link HttpBasicConfigurer#realmName(String)}.
|
||||
*
|
||||
* <pre>
|
||||
|
||||
+6
-2
@@ -25,6 +25,7 @@ import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.http.HttpMethod;
|
||||
@@ -47,7 +48,7 @@ import org.springframework.security.web.access.WebInvocationPrivilegeEvaluator;
|
||||
import org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler;
|
||||
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
|
||||
import org.springframework.security.web.debug.DebugFilter;
|
||||
import org.springframework.security.web.firewall.DefaultHttpFirewall;
|
||||
import org.springframework.security.web.firewall.StrictHttpFirewall;
|
||||
import org.springframework.security.web.firewall.HttpFirewall;
|
||||
import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
@@ -159,7 +160,7 @@ public final class WebSecurity extends
|
||||
|
||||
/**
|
||||
* Allows customizing the {@link HttpFirewall}. The default is
|
||||
* {@link DefaultHttpFirewall}.
|
||||
* {@link StrictHttpFirewall}.
|
||||
*
|
||||
* @param httpFirewall the custom {@link HttpFirewall}
|
||||
* @return the {@link WebSecurity} for further customizations
|
||||
@@ -382,5 +383,8 @@ public final class WebSecurity extends
|
||||
this.defaultWebSecurityExpressionHandler
|
||||
.setApplicationContext(applicationContext);
|
||||
this.ignoredRequestRegistry = new IgnoredRequestConfigurer(applicationContext);
|
||||
try {
|
||||
this.httpFirewall = applicationContext.getBean(HttpFirewall.class);
|
||||
} catch(NoSuchBeanDefinitionException e) {}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -28,7 +28,7 @@ import org.springframework.security.web.method.annotation.CsrfTokenArgumentResol
|
||||
import org.springframework.security.web.servlet.support.csrf.CsrfRequestDataValueProcessor;
|
||||
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
|
||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
|
||||
import org.springframework.web.servlet.support.RequestDataValueProcessor;
|
||||
|
||||
/**
|
||||
@@ -41,7 +41,7 @@ import org.springframework.web.servlet.support.RequestDataValueProcessor;
|
||||
* @author Rob Winch
|
||||
* @since 3.2
|
||||
*/
|
||||
class WebMvcSecurityConfiguration implements WebMvcConfigurer, ApplicationContextAware {
|
||||
class WebMvcSecurityConfiguration extends WebMvcConfigurerAdapter implements ApplicationContextAware {
|
||||
private BeanResolver beanResolver;
|
||||
|
||||
@Override
|
||||
@@ -64,4 +64,4 @@ class WebMvcSecurityConfiguration implements WebMvcConfigurer, ApplicationContex
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
this.beanResolver = new BeanFactoryResolver(applicationContext.getAutowireCapableBeanFactory());
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -160,7 +160,7 @@ public class WebSecurityConfiguration implements ImportAware, BeanClassLoaderAwa
|
||||
}
|
||||
|
||||
@Bean
|
||||
public static AutowiredWebSecurityConfigurersIgnoreParents autowiredWebSecurityConfigurersIgnoreParents(
|
||||
public AutowiredWebSecurityConfigurersIgnoreParents autowiredWebSecurityConfigurersIgnoreParents(
|
||||
ConfigurableListableBeanFactory beanFactory) {
|
||||
return new AutowiredWebSecurityConfigurersIgnoreParents(beanFactory);
|
||||
}
|
||||
|
||||
+11
-99
@@ -31,7 +31,6 @@ import org.springframework.aop.framework.Advised;
|
||||
import org.springframework.aop.target.LazyInitTargetSource;
|
||||
import org.springframework.beans.FatalBeanException;
|
||||
import org.springframework.beans.factory.BeanFactoryUtils;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.core.annotation.Order;
|
||||
@@ -43,9 +42,6 @@ import org.springframework.security.authentication.DefaultAuthenticationEventPub
|
||||
import org.springframework.security.config.annotation.ObjectPostProcessor;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
|
||||
import org.springframework.security.config.annotation.authentication.configurers.provisioning.InMemoryUserDetailsManagerConfigurer;
|
||||
import org.springframework.security.config.annotation.authentication.configurers.provisioning.JdbcUserDetailsManagerConfigurer;
|
||||
import org.springframework.security.config.annotation.authentication.configurers.userdetails.DaoAuthenticationConfigurer;
|
||||
import org.springframework.security.config.annotation.web.WebSecurityConfigurer;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.builders.WebSecurity;
|
||||
@@ -57,8 +53,6 @@ import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
|
||||
import org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -371,19 +365,6 @@ public abstract class WebSecurityConfigurerAdapter implements
|
||||
@Autowired
|
||||
public void setApplicationContext(ApplicationContext context) {
|
||||
this.context = context;
|
||||
|
||||
ObjectPostProcessor<Object> objectPostProcessor = context.getBean(ObjectPostProcessor.class);
|
||||
LazyPasswordEncoder passwordEncoder = new LazyPasswordEncoder(context);
|
||||
|
||||
authenticationBuilder = new DefaultPasswordEncoderAuthenticationManagerBuilder(objectPostProcessor, passwordEncoder);
|
||||
localConfigureAuthenticationBldr = new DefaultPasswordEncoderAuthenticationManagerBuilder(objectPostProcessor, passwordEncoder) {
|
||||
@Override
|
||||
public AuthenticationManagerBuilder eraseCredentials(boolean eraseCredentials) {
|
||||
authenticationBuilder.eraseCredentials(eraseCredentials);
|
||||
return super.eraseCredentials(eraseCredentials);
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
@Autowired(required = false)
|
||||
@@ -400,6 +381,17 @@ public abstract class WebSecurityConfigurerAdapter implements
|
||||
@Autowired
|
||||
public void setObjectPostProcessor(ObjectPostProcessor<Object> objectPostProcessor) {
|
||||
this.objectPostProcessor = objectPostProcessor;
|
||||
|
||||
authenticationBuilder = new AuthenticationManagerBuilder(objectPostProcessor);
|
||||
localConfigureAuthenticationBldr = new AuthenticationManagerBuilder(
|
||||
objectPostProcessor) {
|
||||
@Override
|
||||
public AuthenticationManagerBuilder eraseCredentials(boolean eraseCredentials) {
|
||||
authenticationBuilder.eraseCredentials(eraseCredentials);
|
||||
return super.eraseCredentials(eraseCredentials);
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
@Autowired
|
||||
@@ -538,84 +530,4 @@ public abstract class WebSecurityConfigurerAdapter implements
|
||||
}
|
||||
}
|
||||
|
||||
static class DefaultPasswordEncoderAuthenticationManagerBuilder extends AuthenticationManagerBuilder {
|
||||
private PasswordEncoder defaultPasswordEncoder;
|
||||
|
||||
/**
|
||||
* Creates a new instance
|
||||
*
|
||||
* @param objectPostProcessor the {@link ObjectPostProcessor} instance to use.
|
||||
*/
|
||||
DefaultPasswordEncoderAuthenticationManagerBuilder(
|
||||
ObjectPostProcessor<Object> objectPostProcessor, PasswordEncoder defaultPasswordEncoder) {
|
||||
super(objectPostProcessor);
|
||||
this.defaultPasswordEncoder = defaultPasswordEncoder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InMemoryUserDetailsManagerConfigurer<AuthenticationManagerBuilder> inMemoryAuthentication()
|
||||
throws Exception {
|
||||
return super.inMemoryAuthentication()
|
||||
.passwordEncoder(this.defaultPasswordEncoder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JdbcUserDetailsManagerConfigurer<AuthenticationManagerBuilder> jdbcAuthentication()
|
||||
throws Exception {
|
||||
return super.jdbcAuthentication()
|
||||
.passwordEncoder(this.defaultPasswordEncoder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends UserDetailsService> DaoAuthenticationConfigurer<AuthenticationManagerBuilder, T> userDetailsService(
|
||||
T userDetailsService) throws Exception {
|
||||
return super.userDetailsService(userDetailsService)
|
||||
.passwordEncoder(this.defaultPasswordEncoder);
|
||||
}
|
||||
}
|
||||
|
||||
static class LazyPasswordEncoder implements PasswordEncoder {
|
||||
private ApplicationContext applicationContext;
|
||||
private PasswordEncoder passwordEncoder;
|
||||
|
||||
LazyPasswordEncoder(ApplicationContext applicationContext) {
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String encode(CharSequence rawPassword) {
|
||||
return getPasswordEncoder().encode(rawPassword);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(CharSequence rawPassword,
|
||||
String encodedPassword) {
|
||||
return getPasswordEncoder().matches(rawPassword, encodedPassword);
|
||||
}
|
||||
|
||||
private PasswordEncoder getPasswordEncoder() {
|
||||
if (this.passwordEncoder != null) {
|
||||
return this.passwordEncoder;
|
||||
}
|
||||
PasswordEncoder passwordEncoder = getBeanOrNull(PasswordEncoder.class);
|
||||
if (passwordEncoder == null) {
|
||||
passwordEncoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
|
||||
}
|
||||
this.passwordEncoder = passwordEncoder;
|
||||
return passwordEncoder;
|
||||
}
|
||||
|
||||
private <T> T getBeanOrNull(Class<T> type) {
|
||||
try {
|
||||
return this.applicationContext.getBean(type);
|
||||
} catch(NoSuchBeanDefinitionException notFound) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getPasswordEncoder().toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+10
-25
@@ -15,6 +15,11 @@
|
||||
*/
|
||||
package org.springframework.security.config.annotation.web.configurers;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.security.authentication.AuthenticationDetailsSource;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
@@ -32,20 +37,16 @@ import org.springframework.security.web.authentication.SavedRequestAwareAuthenti
|
||||
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
|
||||
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
|
||||
import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.AndRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.MediaTypeRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.NegatedRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.RequestHeaderRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
import org.springframework.web.accept.ContentNegotiationStrategy;
|
||||
import org.springframework.web.accept.HeaderContentNegotiationStrategy;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
/**
|
||||
* Base class for configuring {@link AbstractAuthenticationFilterConfigurer}. This is
|
||||
* Base class for confuring {@link AbstractAuthenticationFilterConfigurer}. This is
|
||||
* intended for internal use only.
|
||||
*
|
||||
* @see FormLoginConfigurer
|
||||
@@ -61,7 +62,7 @@ import java.util.Collections;
|
||||
public abstract class AbstractAuthenticationFilterConfigurer<B extends HttpSecurityBuilder<B>, T extends AbstractAuthenticationFilterConfigurer<B, T, F>, F extends AbstractAuthenticationProcessingFilter>
|
||||
extends AbstractHttpConfigurer<T, B> {
|
||||
|
||||
private F authFilter;
|
||||
private final F authFilter;
|
||||
|
||||
private AuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource;
|
||||
|
||||
@@ -79,13 +80,6 @@ public abstract class AbstractAuthenticationFilterConfigurer<B extends HttpSecur
|
||||
|
||||
private String failureUrl;
|
||||
|
||||
/**
|
||||
* Creates a new instance with minimal defaults
|
||||
*/
|
||||
protected AbstractAuthenticationFilterConfigurer() {
|
||||
setLoginPage("/login");
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance
|
||||
* @param authenticationFilter the {@link AbstractAuthenticationProcessingFilter} to
|
||||
@@ -95,8 +89,8 @@ public abstract class AbstractAuthenticationFilterConfigurer<B extends HttpSecur
|
||||
*/
|
||||
protected AbstractAuthenticationFilterConfigurer(F authenticationFilter,
|
||||
String defaultLoginProcessingUrl) {
|
||||
this();
|
||||
this.authFilter = authenticationFilter;
|
||||
setLoginPage("/login");
|
||||
if (defaultLoginProcessingUrl != null) {
|
||||
loginProcessingUrl(defaultLoginProcessingUrl);
|
||||
}
|
||||
@@ -327,21 +321,12 @@ public abstract class AbstractAuthenticationFilterConfigurer<B extends HttpSecur
|
||||
/**
|
||||
* Gets the Authentication Filter
|
||||
*
|
||||
* @return the Authentication Filter
|
||||
* @return
|
||||
*/
|
||||
protected final F getAuthenticationFilter() {
|
||||
return authFilter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Authentication Filter
|
||||
*
|
||||
* @param authFilter the Authentication Filter
|
||||
*/
|
||||
protected final void setAuthenticationFilter(F authFilter) {
|
||||
this.authFilter = authFilter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the login page
|
||||
*
|
||||
|
||||
-10
@@ -19,9 +19,6 @@ import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||
import org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter;
|
||||
import org.springframework.security.web.csrf.CsrfToken;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
/**
|
||||
* Adds a Filter that will generate a login page if one is not specified otherwise when
|
||||
@@ -68,13 +65,6 @@ public final class DefaultLoginPageConfigurer<H extends HttpSecurityBuilder<H>>
|
||||
|
||||
@Override
|
||||
public void init(H http) throws Exception {
|
||||
this.loginPageGeneratingFilter.setResolveHiddenInputs( request -> {
|
||||
CsrfToken token = (CsrfToken) request.getAttribute(CsrfToken.class.getName());
|
||||
if(token == null) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
return Collections.singletonMap(token.getParameterName(), token.getToken());
|
||||
});
|
||||
http.setSharedObject(DefaultLoginPageGeneratingFilter.class,
|
||||
loginPageGeneratingFilter);
|
||||
}
|
||||
|
||||
-6
@@ -24,7 +24,6 @@ import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.security.access.AccessDecisionVoter;
|
||||
import org.springframework.security.access.ConfigAttribute;
|
||||
import org.springframework.security.access.PermissionEvaluator;
|
||||
import org.springframework.security.access.SecurityConfig;
|
||||
import org.springframework.security.access.expression.SecurityExpressionHandler;
|
||||
import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
|
||||
@@ -223,11 +222,6 @@ public final class ExpressionUrlAuthorizationConfigurer<H extends HttpSecurityBu
|
||||
GrantedAuthorityDefaults grantedAuthorityDefaults = context.getBean(grantedAuthorityDefaultsBeanNames[0], GrantedAuthorityDefaults.class);
|
||||
defaultHandler.setDefaultRolePrefix(grantedAuthorityDefaults.getRolePrefix());
|
||||
}
|
||||
String[] permissionEvaluatorBeanNames = context.getBeanNamesForType(PermissionEvaluator.class);
|
||||
if(permissionEvaluatorBeanNames.length == 1) {
|
||||
PermissionEvaluator permissionEvaluator = context.getBean(permissionEvaluatorBeanNames[0], PermissionEvaluator.class);
|
||||
defaultHandler.setPermissionEvaluator(permissionEvaluator);
|
||||
}
|
||||
}
|
||||
|
||||
expressionHandler = postProcess(defaultHandler);
|
||||
|
||||
+2
-2
@@ -213,7 +213,7 @@ public final class FormLoginConfigurer<H extends HttpSecurityBuilder<H>> extends
|
||||
* Forward Authentication Failure Handler
|
||||
*
|
||||
* @param forwardUrl the target URL in case of failure
|
||||
* @return the {@link FormLoginConfigurer} for additional customization
|
||||
* @return he {@link FormLoginConfigurer} for additional customization
|
||||
*/
|
||||
public FormLoginConfigurer<H> failureForwardUrl(String forwardUrl) {
|
||||
failureHandler(new ForwardAuthenticationFailureHandler(forwardUrl));
|
||||
@@ -224,7 +224,7 @@ public final class FormLoginConfigurer<H extends HttpSecurityBuilder<H>> extends
|
||||
* Forward Authentication Success Handler
|
||||
*
|
||||
* @param forwardUrl the target URL in case of success
|
||||
* @return the {@link FormLoginConfigurer} for additional customization
|
||||
* @return he {@link FormLoginConfigurer} for additional customization
|
||||
*/
|
||||
public FormLoginConfigurer<H> successForwardUrl(String forwardUrl) {
|
||||
successHandler(new ForwardAuthenticationSuccessHandler(forwardUrl));
|
||||
|
||||
+2
-2
@@ -227,7 +227,7 @@ public class HeadersConfigurer<H extends HttpSecurityBuilder<H>> extends
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows completing configuration of X-XSS-Protection and continuing
|
||||
* Allows completing configuration of Strict Transport Security and continuing
|
||||
* configuration of headers.
|
||||
*
|
||||
* @return the {@link HeadersConfigurer} for additional configuration
|
||||
@@ -282,7 +282,7 @@ public class HeadersConfigurer<H extends HttpSecurityBuilder<H>> extends
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows completing configuration of Cache Control and continuing
|
||||
* Allows completing configuration of Strict Transport Security and continuing
|
||||
* configuration of headers.
|
||||
*
|
||||
* @return the {@link HeadersConfigurer} for additional configuration
|
||||
|
||||
+3
-6
@@ -125,7 +125,7 @@ public final class HttpBasicConfigurer<B extends HttpSecurityBuilder<B>> extends
|
||||
* The {@link AuthenticationEntryPoint} to be populated on
|
||||
* {@link BasicAuthenticationFilter} in the event that authentication fails. The
|
||||
* default to use {@link BasicAuthenticationEntryPoint} with the realm
|
||||
* "Realm".
|
||||
* "Spring Security Application".
|
||||
*
|
||||
* @param authenticationEntryPoint the {@link AuthenticationEntryPoint} to use
|
||||
* @return {@link HttpBasicConfigurer} for additional customization
|
||||
@@ -169,16 +169,13 @@ public final class HttpBasicConfigurer<B extends HttpSecurityBuilder<B>> extends
|
||||
MediaType.MULTIPART_FORM_DATA, MediaType.TEXT_XML);
|
||||
restMatcher.setIgnoredMediaTypes(Collections.singleton(MediaType.ALL));
|
||||
|
||||
MediaTypeRequestMatcher allMatcher = new MediaTypeRequestMatcher(contentNegotiationStrategy, MediaType.ALL);
|
||||
allMatcher.setUseEquals(true);
|
||||
|
||||
RequestMatcher notHtmlMatcher = new NegatedRequestMatcher(
|
||||
new MediaTypeRequestMatcher(contentNegotiationStrategy,
|
||||
MediaType.TEXT_HTML));
|
||||
RequestMatcher restNotHtmlMatcher = new AndRequestMatcher(
|
||||
Arrays.<RequestMatcher>asList(notHtmlMatcher, restMatcher));
|
||||
|
||||
RequestMatcher preferredMatcher = new OrRequestMatcher(Arrays.asList(X_REQUESTED_WITH, restNotHtmlMatcher, allMatcher));
|
||||
RequestMatcher preferredMatcher = new OrRequestMatcher(Arrays.asList(X_REQUESTED_WITH, restNotHtmlMatcher));
|
||||
|
||||
registerDefaultEntryPoint(http, preferredMatcher);
|
||||
registerDefaultLogoutSuccessHandler(http, preferredMatcher);
|
||||
@@ -221,4 +218,4 @@ public final class HttpBasicConfigurer<B extends HttpSecurityBuilder<B>> extends
|
||||
basicAuthenticationFilter = postProcess(basicAuthenticationFilter);
|
||||
http.addFilter(basicAuthenticationFilter);
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -201,7 +201,7 @@ public final class JeeConfigurer<H extends HttpSecurityBuilder<H>> extends
|
||||
// @formatter:off
|
||||
http
|
||||
.authenticationProvider(authenticationProvider)
|
||||
.setSharedObject(AuthenticationEntryPoint.class, new Http403ForbiddenEntryPoint());
|
||||
.setSharedObject(AuthenticationEntryPoint.class,new Http403ForbiddenEntryPoint());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@@ -259,4 +259,4 @@ public final class JeeConfigurer<H extends HttpSecurityBuilder<H>> extends
|
||||
detailsSource = postProcess(detailsSource);
|
||||
return detailsSource;
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -163,7 +163,7 @@ public final class X509Configurer<H extends HttpSecurityBuilder<H>> extends
|
||||
|
||||
http
|
||||
.authenticationProvider(authenticationProvider)
|
||||
.setSharedObject(AuthenticationEntryPoint.class, new Http403ForbiddenEntryPoint());
|
||||
.setSharedObject(AuthenticationEntryPoint.class,new Http403ForbiddenEntryPoint());
|
||||
}
|
||||
// @formatter:on
|
||||
|
||||
@@ -201,4 +201,4 @@ public final class X509Configurer<H extends HttpSecurityBuilder<H>> extends
|
||||
return authenticationUserDetailsService;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
-73
@@ -1,73 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.security.config.annotation.web.configurers.oauth2.client;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
|
||||
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
|
||||
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
|
||||
import org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestRedirectFilter;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A security configurer for the Implicit Grant type.
|
||||
*
|
||||
* @author Joe Grandja
|
||||
* @since 5.0
|
||||
*/
|
||||
public final class ImplicitGrantConfigurer<B extends HttpSecurityBuilder<B>> extends
|
||||
AbstractHttpConfigurer<ImplicitGrantConfigurer<B>, B> {
|
||||
|
||||
private String authorizationRequestBaseUri;
|
||||
|
||||
public ImplicitGrantConfigurer<B> authorizationRequestBaseUri(String authorizationRequestBaseUri) {
|
||||
Assert.hasText(authorizationRequestBaseUri, "authorizationRequestBaseUri cannot be empty");
|
||||
this.authorizationRequestBaseUri = authorizationRequestBaseUri;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ImplicitGrantConfigurer<B> clientRegistrationRepository(ClientRegistrationRepository clientRegistrationRepository) {
|
||||
Assert.notNull(clientRegistrationRepository, "clientRegistrationRepository cannot be null");
|
||||
this.getBuilder().setSharedObject(ClientRegistrationRepository.class, clientRegistrationRepository);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(B http) throws Exception {
|
||||
OAuth2AuthorizationRequestRedirectFilter authorizationRequestFilter = new OAuth2AuthorizationRequestRedirectFilter(
|
||||
this.getClientRegistrationRepository(), this.getAuthorizationRequestBaseUri());
|
||||
http.addFilter(this.postProcess(authorizationRequestFilter));
|
||||
}
|
||||
|
||||
private String getAuthorizationRequestBaseUri() {
|
||||
return this.authorizationRequestBaseUri != null ?
|
||||
this.authorizationRequestBaseUri :
|
||||
OAuth2AuthorizationRequestRedirectFilter.DEFAULT_AUTHORIZATION_REQUEST_BASE_URI;
|
||||
}
|
||||
|
||||
private ClientRegistrationRepository getClientRegistrationRepository() {
|
||||
ClientRegistrationRepository clientRegistrationRepository = this.getBuilder().getSharedObject(ClientRegistrationRepository.class);
|
||||
if (clientRegistrationRepository == null) {
|
||||
clientRegistrationRepository = this.getClientRegistrationRepositoryBean();
|
||||
this.getBuilder().setSharedObject(ClientRegistrationRepository.class, clientRegistrationRepository);
|
||||
}
|
||||
return clientRegistrationRepository;
|
||||
}
|
||||
|
||||
private ClientRegistrationRepository getClientRegistrationRepositoryBean() {
|
||||
return this.getBuilder().getSharedObject(ApplicationContext.class).getBean(ClientRegistrationRepository.class);
|
||||
}
|
||||
}
|
||||
-407
@@ -1,407 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.security.config.annotation.web.configurers.oauth2.client;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactoryUtils;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.security.authentication.AuthenticationProvider;
|
||||
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
|
||||
import org.springframework.security.config.annotation.web.configurers.AbstractAuthenticationFilterConfigurer;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
|
||||
import org.springframework.security.oauth2.client.InMemoryOAuth2AuthorizedClientService;
|
||||
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService;
|
||||
import org.springframework.security.oauth2.client.authentication.OAuth2LoginAuthenticationProvider;
|
||||
import org.springframework.security.oauth2.client.authentication.OAuth2LoginAuthenticationToken;
|
||||
import org.springframework.security.oauth2.client.endpoint.NimbusAuthorizationCodeTokenResponseClient;
|
||||
import org.springframework.security.oauth2.client.endpoint.OAuth2AccessTokenResponseClient;
|
||||
import org.springframework.security.oauth2.client.endpoint.OAuth2AuthorizationCodeGrantRequest;
|
||||
import org.springframework.security.oauth2.client.oidc.authentication.OidcAuthorizationCodeAuthenticationProvider;
|
||||
import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserRequest;
|
||||
import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserService;
|
||||
import org.springframework.security.oauth2.client.registration.ClientRegistration;
|
||||
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
|
||||
import org.springframework.security.oauth2.client.userinfo.CustomUserTypesOAuth2UserService;
|
||||
import org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService;
|
||||
import org.springframework.security.oauth2.client.userinfo.DelegatingOAuth2UserService;
|
||||
import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest;
|
||||
import org.springframework.security.oauth2.client.userinfo.OAuth2UserService;
|
||||
import org.springframework.security.oauth2.client.web.AuthorizationRequestRepository;
|
||||
import org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestRedirectFilter;
|
||||
import org.springframework.security.oauth2.client.web.OAuth2LoginAuthenticationFilter;
|
||||
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
|
||||
import org.springframework.security.oauth2.core.OAuth2Error;
|
||||
import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest;
|
||||
import org.springframework.security.oauth2.core.oidc.OidcScopes;
|
||||
import org.springframework.security.oauth2.core.oidc.user.OidcUser;
|
||||
import org.springframework.security.oauth2.core.user.OAuth2User;
|
||||
import org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter;
|
||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A security configurer for OAuth 2.0 / OpenID Connect 1.0 login.
|
||||
*
|
||||
* @author Joe Grandja
|
||||
* @since 5.0
|
||||
*/
|
||||
public final class OAuth2LoginConfigurer<B extends HttpSecurityBuilder<B>> extends
|
||||
AbstractAuthenticationFilterConfigurer<B, OAuth2LoginConfigurer<B>, OAuth2LoginAuthenticationFilter> {
|
||||
|
||||
private final AuthorizationEndpointConfig authorizationEndpointConfig = new AuthorizationEndpointConfig();
|
||||
private final TokenEndpointConfig tokenEndpointConfig = new TokenEndpointConfig();
|
||||
private final RedirectionEndpointConfig redirectionEndpointConfig = new RedirectionEndpointConfig();
|
||||
private final UserInfoEndpointConfig userInfoEndpointConfig = new UserInfoEndpointConfig();
|
||||
private String loginPage;
|
||||
|
||||
public OAuth2LoginConfigurer() {
|
||||
super();
|
||||
}
|
||||
|
||||
public OAuth2LoginConfigurer<B> clientRegistrationRepository(ClientRegistrationRepository clientRegistrationRepository) {
|
||||
Assert.notNull(clientRegistrationRepository, "clientRegistrationRepository cannot be null");
|
||||
this.getBuilder().setSharedObject(ClientRegistrationRepository.class, clientRegistrationRepository);
|
||||
return this;
|
||||
}
|
||||
|
||||
public OAuth2LoginConfigurer<B> authorizedClientService(OAuth2AuthorizedClientService authorizedClientService) {
|
||||
Assert.notNull(authorizedClientService, "authorizedClientService cannot be null");
|
||||
this.getBuilder().setSharedObject(OAuth2AuthorizedClientService.class, authorizedClientService);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OAuth2LoginConfigurer<B> loginPage(String loginPage) {
|
||||
Assert.hasText(loginPage, "loginPage cannot be empty");
|
||||
this.loginPage = loginPage;
|
||||
return this;
|
||||
}
|
||||
|
||||
public AuthorizationEndpointConfig authorizationEndpoint() {
|
||||
return this.authorizationEndpointConfig;
|
||||
}
|
||||
|
||||
public class AuthorizationEndpointConfig {
|
||||
private String authorizationRequestBaseUri;
|
||||
private AuthorizationRequestRepository<OAuth2AuthorizationRequest> authorizationRequestRepository;
|
||||
|
||||
private AuthorizationEndpointConfig() {
|
||||
}
|
||||
|
||||
public AuthorizationEndpointConfig baseUri(String authorizationRequestBaseUri) {
|
||||
Assert.hasText(authorizationRequestBaseUri, "authorizationRequestBaseUri cannot be empty");
|
||||
this.authorizationRequestBaseUri = authorizationRequestBaseUri;
|
||||
return this;
|
||||
}
|
||||
|
||||
public AuthorizationEndpointConfig authorizationRequestRepository(AuthorizationRequestRepository<OAuth2AuthorizationRequest> authorizationRequestRepository) {
|
||||
Assert.notNull(authorizationRequestRepository, "authorizationRequestRepository cannot be null");
|
||||
this.authorizationRequestRepository = authorizationRequestRepository;
|
||||
return this;
|
||||
}
|
||||
|
||||
public OAuth2LoginConfigurer<B> and() {
|
||||
return OAuth2LoginConfigurer.this;
|
||||
}
|
||||
}
|
||||
|
||||
public TokenEndpointConfig tokenEndpoint() {
|
||||
return this.tokenEndpointConfig;
|
||||
}
|
||||
|
||||
public class TokenEndpointConfig {
|
||||
private OAuth2AccessTokenResponseClient<OAuth2AuthorizationCodeGrantRequest> accessTokenResponseClient;
|
||||
|
||||
private TokenEndpointConfig() {
|
||||
}
|
||||
|
||||
public TokenEndpointConfig accessTokenResponseClient(
|
||||
OAuth2AccessTokenResponseClient<OAuth2AuthorizationCodeGrantRequest> accessTokenResponseClient) {
|
||||
|
||||
Assert.notNull(accessTokenResponseClient, "accessTokenResponseClient cannot be null");
|
||||
this.accessTokenResponseClient = accessTokenResponseClient;
|
||||
return this;
|
||||
}
|
||||
|
||||
public OAuth2LoginConfigurer<B> and() {
|
||||
return OAuth2LoginConfigurer.this;
|
||||
}
|
||||
}
|
||||
|
||||
public RedirectionEndpointConfig redirectionEndpoint() {
|
||||
return this.redirectionEndpointConfig;
|
||||
}
|
||||
|
||||
public class RedirectionEndpointConfig {
|
||||
private String authorizationResponseBaseUri;
|
||||
|
||||
private RedirectionEndpointConfig() {
|
||||
}
|
||||
|
||||
public RedirectionEndpointConfig baseUri(String authorizationResponseBaseUri) {
|
||||
Assert.hasText(authorizationResponseBaseUri, "authorizationResponseBaseUri cannot be empty");
|
||||
this.authorizationResponseBaseUri = authorizationResponseBaseUri;
|
||||
return this;
|
||||
}
|
||||
|
||||
public OAuth2LoginConfigurer<B> and() {
|
||||
return OAuth2LoginConfigurer.this;
|
||||
}
|
||||
}
|
||||
|
||||
public UserInfoEndpointConfig userInfoEndpoint() {
|
||||
return this.userInfoEndpointConfig;
|
||||
}
|
||||
|
||||
public class UserInfoEndpointConfig {
|
||||
private OAuth2UserService<OAuth2UserRequest, OAuth2User> userService;
|
||||
private OAuth2UserService<OidcUserRequest, OidcUser> oidcUserService;
|
||||
private Map<String, Class<? extends OAuth2User>> customUserTypes = new HashMap<>();
|
||||
private GrantedAuthoritiesMapper userAuthoritiesMapper;
|
||||
|
||||
private UserInfoEndpointConfig() {
|
||||
}
|
||||
|
||||
public UserInfoEndpointConfig userService(OAuth2UserService<OAuth2UserRequest, OAuth2User> userService) {
|
||||
Assert.notNull(userService, "userService cannot be null");
|
||||
this.userService = userService;
|
||||
return this;
|
||||
}
|
||||
|
||||
public UserInfoEndpointConfig oidcUserService(OAuth2UserService<OidcUserRequest, OidcUser> oidcUserService) {
|
||||
Assert.notNull(oidcUserService, "oidcUserService cannot be null");
|
||||
this.oidcUserService = oidcUserService;
|
||||
return this;
|
||||
}
|
||||
|
||||
public UserInfoEndpointConfig customUserType(Class<? extends OAuth2User> customUserType, String clientRegistrationId) {
|
||||
Assert.notNull(customUserType, "customUserType cannot be null");
|
||||
Assert.hasText(clientRegistrationId, "clientRegistrationId cannot be empty");
|
||||
this.customUserTypes.put(clientRegistrationId, customUserType);
|
||||
return this;
|
||||
}
|
||||
|
||||
public UserInfoEndpointConfig userAuthoritiesMapper(GrantedAuthoritiesMapper userAuthoritiesMapper) {
|
||||
Assert.notNull(userAuthoritiesMapper, "userAuthoritiesMapper cannot be null");
|
||||
this.userAuthoritiesMapper = userAuthoritiesMapper;
|
||||
return this;
|
||||
}
|
||||
|
||||
public OAuth2LoginConfigurer<B> and() {
|
||||
return OAuth2LoginConfigurer.this;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(B http) throws Exception {
|
||||
OAuth2LoginAuthenticationFilter authenticationFilter =
|
||||
new OAuth2LoginAuthenticationFilter(
|
||||
this.getClientRegistrationRepository(),
|
||||
this.getAuthorizedClientService(),
|
||||
OAuth2LoginAuthenticationFilter.DEFAULT_FILTER_PROCESSES_URI);
|
||||
this.setAuthenticationFilter(authenticationFilter);
|
||||
this.loginProcessingUrl(OAuth2LoginAuthenticationFilter.DEFAULT_FILTER_PROCESSES_URI);
|
||||
if (this.loginPage != null) {
|
||||
super.loginPage(this.loginPage);
|
||||
}
|
||||
super.init(http);
|
||||
|
||||
OAuth2AccessTokenResponseClient<OAuth2AuthorizationCodeGrantRequest> accessTokenResponseClient =
|
||||
this.tokenEndpointConfig.accessTokenResponseClient;
|
||||
if (accessTokenResponseClient == null) {
|
||||
accessTokenResponseClient = new NimbusAuthorizationCodeTokenResponseClient();
|
||||
}
|
||||
|
||||
OAuth2UserService<OAuth2UserRequest, OAuth2User> oauth2UserService = this.userInfoEndpointConfig.userService;
|
||||
if (oauth2UserService == null) {
|
||||
if (!this.userInfoEndpointConfig.customUserTypes.isEmpty()) {
|
||||
List<OAuth2UserService<OAuth2UserRequest, OAuth2User>> userServices = new ArrayList<>();
|
||||
userServices.add(new CustomUserTypesOAuth2UserService(this.userInfoEndpointConfig.customUserTypes));
|
||||
userServices.add(new DefaultOAuth2UserService());
|
||||
oauth2UserService = new DelegatingOAuth2UserService<>(userServices);
|
||||
} else {
|
||||
oauth2UserService = new DefaultOAuth2UserService();
|
||||
}
|
||||
}
|
||||
|
||||
OAuth2LoginAuthenticationProvider oauth2LoginAuthenticationProvider =
|
||||
new OAuth2LoginAuthenticationProvider(accessTokenResponseClient, oauth2UserService);
|
||||
if (this.userInfoEndpointConfig.userAuthoritiesMapper != null) {
|
||||
oauth2LoginAuthenticationProvider.setAuthoritiesMapper(
|
||||
this.userInfoEndpointConfig.userAuthoritiesMapper);
|
||||
}
|
||||
http.authenticationProvider(this.postProcess(oauth2LoginAuthenticationProvider));
|
||||
|
||||
boolean oidcAuthenticationProviderEnabled = ClassUtils.isPresent(
|
||||
"org.springframework.security.oauth2.jwt.JwtDecoder", this.getClass().getClassLoader());
|
||||
|
||||
if (oidcAuthenticationProviderEnabled) {
|
||||
OAuth2UserService<OidcUserRequest, OidcUser> oidcUserService = this.userInfoEndpointConfig.oidcUserService;
|
||||
if (oidcUserService == null) {
|
||||
oidcUserService = new OidcUserService();
|
||||
}
|
||||
|
||||
OidcAuthorizationCodeAuthenticationProvider oidcAuthorizationCodeAuthenticationProvider =
|
||||
new OidcAuthorizationCodeAuthenticationProvider(accessTokenResponseClient, oidcUserService);
|
||||
if (this.userInfoEndpointConfig.userAuthoritiesMapper != null) {
|
||||
oidcAuthorizationCodeAuthenticationProvider.setAuthoritiesMapper(
|
||||
this.userInfoEndpointConfig.userAuthoritiesMapper);
|
||||
}
|
||||
http.authenticationProvider(this.postProcess(oidcAuthorizationCodeAuthenticationProvider));
|
||||
} else {
|
||||
http.authenticationProvider(new OidcAuthenticationRequestChecker());
|
||||
}
|
||||
|
||||
this.initDefaultLoginFilter(http);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(B http) throws Exception {
|
||||
String authorizationRequestBaseUri = this.authorizationEndpointConfig.authorizationRequestBaseUri;
|
||||
if (authorizationRequestBaseUri == null) {
|
||||
authorizationRequestBaseUri = OAuth2AuthorizationRequestRedirectFilter.DEFAULT_AUTHORIZATION_REQUEST_BASE_URI;
|
||||
}
|
||||
|
||||
OAuth2AuthorizationRequestRedirectFilter authorizationRequestFilter = new OAuth2AuthorizationRequestRedirectFilter(
|
||||
this.getClientRegistrationRepository(), authorizationRequestBaseUri);
|
||||
|
||||
if (this.authorizationEndpointConfig.authorizationRequestRepository != null) {
|
||||
authorizationRequestFilter.setAuthorizationRequestRepository(
|
||||
this.authorizationEndpointConfig.authorizationRequestRepository);
|
||||
}
|
||||
http.addFilter(this.postProcess(authorizationRequestFilter));
|
||||
|
||||
OAuth2LoginAuthenticationFilter authenticationFilter = this.getAuthenticationFilter();
|
||||
if (this.redirectionEndpointConfig.authorizationResponseBaseUri != null) {
|
||||
authenticationFilter.setFilterProcessesUrl(this.redirectionEndpointConfig.authorizationResponseBaseUri);
|
||||
}
|
||||
if (this.authorizationEndpointConfig.authorizationRequestRepository != null) {
|
||||
authenticationFilter.setAuthorizationRequestRepository(
|
||||
this.authorizationEndpointConfig.authorizationRequestRepository);
|
||||
}
|
||||
super.configure(http);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RequestMatcher createLoginProcessingUrlMatcher(String loginProcessingUrl) {
|
||||
return new AntPathRequestMatcher(loginProcessingUrl);
|
||||
}
|
||||
|
||||
private ClientRegistrationRepository getClientRegistrationRepository() {
|
||||
ClientRegistrationRepository clientRegistrationRepository =
|
||||
this.getBuilder().getSharedObject(ClientRegistrationRepository.class);
|
||||
if (clientRegistrationRepository == null) {
|
||||
clientRegistrationRepository = this.getClientRegistrationRepositoryBean();
|
||||
this.getBuilder().setSharedObject(ClientRegistrationRepository.class, clientRegistrationRepository);
|
||||
}
|
||||
return clientRegistrationRepository;
|
||||
}
|
||||
|
||||
private ClientRegistrationRepository getClientRegistrationRepositoryBean() {
|
||||
return this.getBuilder().getSharedObject(ApplicationContext.class).getBean(ClientRegistrationRepository.class);
|
||||
}
|
||||
|
||||
private OAuth2AuthorizedClientService getAuthorizedClientService() {
|
||||
OAuth2AuthorizedClientService authorizedClientService =
|
||||
this.getBuilder().getSharedObject(OAuth2AuthorizedClientService.class);
|
||||
if (authorizedClientService == null) {
|
||||
authorizedClientService = this.getAuthorizedClientServiceBean();
|
||||
if (authorizedClientService == null) {
|
||||
authorizedClientService = new InMemoryOAuth2AuthorizedClientService(this.getClientRegistrationRepository());
|
||||
}
|
||||
this.getBuilder().setSharedObject(OAuth2AuthorizedClientService.class, authorizedClientService);
|
||||
}
|
||||
return authorizedClientService;
|
||||
}
|
||||
|
||||
private OAuth2AuthorizedClientService getAuthorizedClientServiceBean() {
|
||||
Map<String, OAuth2AuthorizedClientService> authorizedClientServiceMap =
|
||||
BeanFactoryUtils.beansOfTypeIncludingAncestors(
|
||||
this.getBuilder().getSharedObject(ApplicationContext.class),
|
||||
OAuth2AuthorizedClientService.class);
|
||||
return (!authorizedClientServiceMap.isEmpty() ? authorizedClientServiceMap.values().iterator().next() : null);
|
||||
}
|
||||
|
||||
private void initDefaultLoginFilter(B http) {
|
||||
DefaultLoginPageGeneratingFilter loginPageGeneratingFilter = http.getSharedObject(DefaultLoginPageGeneratingFilter.class);
|
||||
if (loginPageGeneratingFilter == null || this.isCustomLoginPage()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Iterable<ClientRegistration> clientRegistrations = null;
|
||||
ClientRegistrationRepository clientRegistrationRepository = this.getClientRegistrationRepository();
|
||||
ResolvableType type = ResolvableType.forInstance(clientRegistrationRepository).as(Iterable.class);
|
||||
if (type != ResolvableType.NONE && ClientRegistration.class.isAssignableFrom(type.resolveGenerics()[0])) {
|
||||
clientRegistrations = (Iterable<ClientRegistration>) clientRegistrationRepository;
|
||||
}
|
||||
if (clientRegistrations == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
String authorizationRequestBaseUri = this.authorizationEndpointConfig.authorizationRequestBaseUri != null ?
|
||||
this.authorizationEndpointConfig.authorizationRequestBaseUri :
|
||||
OAuth2AuthorizationRequestRedirectFilter.DEFAULT_AUTHORIZATION_REQUEST_BASE_URI;
|
||||
Map<String, String> authenticationUrlToClientName = new HashMap<>();
|
||||
|
||||
clientRegistrations.forEach(registration -> authenticationUrlToClientName.put(
|
||||
authorizationRequestBaseUri + "/" + registration.getRegistrationId(),
|
||||
registration.getClientName()));
|
||||
loginPageGeneratingFilter.setOauth2LoginEnabled(true);
|
||||
loginPageGeneratingFilter.setOauth2AuthenticationUrlToClientName(authenticationUrlToClientName);
|
||||
loginPageGeneratingFilter.setLoginPageUrl(this.getLoginPage());
|
||||
loginPageGeneratingFilter.setFailureUrl(this.getFailureUrl());
|
||||
}
|
||||
|
||||
private static class OidcAuthenticationRequestChecker implements AuthenticationProvider {
|
||||
|
||||
@Override
|
||||
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
|
||||
OAuth2LoginAuthenticationToken authorizationCodeAuthentication =
|
||||
(OAuth2LoginAuthenticationToken) authentication;
|
||||
|
||||
// Section 3.1.2.1 Authentication Request - http://openid.net/specs/openid-connect-core-1_0.html#AuthRequest
|
||||
// scope
|
||||
// REQUIRED. OpenID Connect requests MUST contain the "openid" scope value.
|
||||
if (authorizationCodeAuthentication.getAuthorizationExchange()
|
||||
.getAuthorizationRequest().getScopes().contains(OidcScopes.OPENID)) {
|
||||
|
||||
OAuth2Error oauth2Error = new OAuth2Error(
|
||||
"oidc_provider_not_configured",
|
||||
"An OpenID Connect Authentication Provider has not been configured. " +
|
||||
"Check to ensure you include the dependency 'spring-security-oauth2-jose'.",
|
||||
null);
|
||||
throw new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(Class<?> authentication) {
|
||||
return OAuth2LoginAuthenticationToken.class.isAssignableFrom(authentication);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+1
-1
@@ -99,7 +99,7 @@ import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
* <ul>
|
||||
* <li>{@link AuthenticationEntryPoint} is populated with a
|
||||
* {@link LoginUrlAuthenticationEntryPoint}</li>
|
||||
* <li>An {@link OpenIDAuthenticationProvider} is populated into
|
||||
* <li>A {@link OpenIDAuthenticationProvider} is populated into
|
||||
* {@link HttpSecurity#authenticationProvider(org.springframework.security.authentication.AuthenticationProvider)}
|
||||
* </li>
|
||||
* </ul>
|
||||
|
||||
-88
@@ -1,88 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.config.annotation.web.reactive;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.security.config.web.server.ServerHttpSecurity;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Add this annotation to a {@code Configuration} class to have Spring Security WebFlux
|
||||
* support added. User's can then create one or more {@link ServerHttpSecurity}
|
||||
* {@code Bean} instances.
|
||||
*
|
||||
* A minimal configuration can be found below:
|
||||
*
|
||||
* <pre class="code">
|
||||
* @EnableWebFluxSecurity
|
||||
* public class MyMinimalSecurityConfiguration {
|
||||
*
|
||||
* @Bean
|
||||
* public MapReactiveUserDetailsService userDetailsRepository() {
|
||||
* UserDetails user = User.withDefaultPasswordEncoder()
|
||||
* .username("user")
|
||||
* .password("password")
|
||||
* .roles("USER")
|
||||
* .build();
|
||||
* return new MapReactiveUserDetailsService(user);
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* Below is the same as our minimal configuration, but explicitly declaring the
|
||||
* {@code ServerHttpSecurity}.
|
||||
*
|
||||
* <pre class="code">
|
||||
* @EnableWebFluxSecurity
|
||||
* public class MyExplicitSecurityConfiguration {
|
||||
* @Bean
|
||||
* SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
|
||||
* http
|
||||
* .authorizeExchange()
|
||||
* .anyExchange().authenticated()
|
||||
* .and()
|
||||
* .httpBasic().and()
|
||||
* .formLogin();
|
||||
* return http.build();
|
||||
* }
|
||||
*
|
||||
* @Bean
|
||||
* public MapReactiveUserDetailsService userDetailsRepository() {
|
||||
* UserDetails user = User.withDefaultPasswordEncoder()
|
||||
* .username("user")
|
||||
* .password("password")
|
||||
* .roles("USER")
|
||||
* .build();
|
||||
* return new MapReactiveUserDetailsService(user);
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @since 5.0
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
@Documented
|
||||
@Import({ServerHttpSecurityConfiguration.class, WebFluxSecurityConfiguration.class})
|
||||
@Configuration
|
||||
public @interface EnableWebFluxSecurity {
|
||||
}
|
||||
-87
@@ -1,87 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.config.annotation.web.reactive;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.core.ReactiveAdapterRegistry;
|
||||
import org.springframework.security.authentication.ReactiveAuthenticationManager;
|
||||
import org.springframework.security.authentication.UserDetailsRepositoryReactiveAuthenticationManager;
|
||||
import org.springframework.security.config.web.server.ServerHttpSecurity;
|
||||
import org.springframework.security.core.userdetails.ReactiveUserDetailsService;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.security.web.reactive.result.method.annotation.AuthenticationPrincipalArgumentResolver;
|
||||
import org.springframework.web.reactive.config.WebFluxConfigurer;
|
||||
import org.springframework.web.reactive.result.method.annotation.ArgumentResolverConfigurer;
|
||||
|
||||
import static org.springframework.security.config.web.server.ServerHttpSecurity.http;
|
||||
|
||||
/**
|
||||
* @author Rob Winch
|
||||
* @since 5.0
|
||||
*/
|
||||
class ServerHttpSecurityConfiguration implements WebFluxConfigurer {
|
||||
private static final String BEAN_NAME_PREFIX = "org.springframework.security.config.annotation.web.reactive.HttpSecurityConfiguration.";
|
||||
private static final String HTTPSECURITY_BEAN_NAME = BEAN_NAME_PREFIX + "httpSecurity";
|
||||
|
||||
@Autowired(required = false)
|
||||
private ReactiveAdapterRegistry adapterRegistry = new ReactiveAdapterRegistry();
|
||||
|
||||
@Autowired(required = false)
|
||||
private ReactiveAuthenticationManager authenticationManager;
|
||||
|
||||
@Autowired(required = false)
|
||||
private ReactiveUserDetailsService reactiveUserDetailsService;
|
||||
|
||||
@Autowired(required = false)
|
||||
private PasswordEncoder passwordEncoder;
|
||||
|
||||
@Override
|
||||
public void configureArgumentResolvers(ArgumentResolverConfigurer configurer) {
|
||||
configurer.addCustomResolver(authenticationPrincipalArgumentResolver());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public AuthenticationPrincipalArgumentResolver authenticationPrincipalArgumentResolver() {
|
||||
return new AuthenticationPrincipalArgumentResolver(this.adapterRegistry);
|
||||
}
|
||||
|
||||
@Bean(HTTPSECURITY_BEAN_NAME)
|
||||
@Scope("prototype")
|
||||
public ServerHttpSecurity httpSecurity() {
|
||||
return http()
|
||||
.authenticationManager(authenticationManager())
|
||||
.headers().and()
|
||||
.logout().and();
|
||||
}
|
||||
|
||||
private ReactiveAuthenticationManager authenticationManager() {
|
||||
if(this.authenticationManager != null) {
|
||||
return this.authenticationManager;
|
||||
}
|
||||
if(this.reactiveUserDetailsService != null) {
|
||||
UserDetailsRepositoryReactiveAuthenticationManager manager =
|
||||
new UserDetailsRepositoryReactiveAuthenticationManager(this.reactiveUserDetailsService);
|
||||
if(this.passwordEncoder != null) {
|
||||
manager.setPasswordEncoder(this.passwordEncoder);
|
||||
}
|
||||
return manager;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
-90
@@ -1,90 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.config.annotation.web.reactive;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.security.config.web.server.ServerHttpSecurity;
|
||||
import org.springframework.security.web.reactive.result.view.CsrfRequestDataValueProcessor;
|
||||
import org.springframework.security.web.server.SecurityWebFilterChain;
|
||||
import org.springframework.security.web.server.WebFilterChainProxy;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.web.reactive.result.view.AbstractView;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Rob Winch
|
||||
* @since 5.0
|
||||
*/
|
||||
@Configuration
|
||||
class WebFluxSecurityConfiguration {
|
||||
public static final int WEB_FILTER_CHAIN_FILTER_ORDER = 0 - 100;
|
||||
|
||||
private static final String BEAN_NAME_PREFIX = "org.springframework.security.config.annotation.web.reactive.WebFluxSecurityConfiguration.";
|
||||
|
||||
private static final String SPRING_SECURITY_WEBFILTERCHAINFILTER_BEAN_NAME = BEAN_NAME_PREFIX + "WebFilterChainFilter";
|
||||
|
||||
@Autowired(required = false)
|
||||
private List<SecurityWebFilterChain> securityWebFilterChains;
|
||||
|
||||
@Autowired
|
||||
ApplicationContext context;
|
||||
|
||||
@Bean(SPRING_SECURITY_WEBFILTERCHAINFILTER_BEAN_NAME)
|
||||
@Order(value = WEB_FILTER_CHAIN_FILTER_ORDER)
|
||||
public WebFilterChainProxy springSecurityWebFilterChainFilter() {
|
||||
return new WebFilterChainProxy(getSecurityWebFilterChains());
|
||||
}
|
||||
|
||||
@Bean(name = AbstractView.REQUEST_DATA_VALUE_PROCESSOR_BEAN_NAME)
|
||||
public CsrfRequestDataValueProcessor requestDataValueProcessor() {
|
||||
return new CsrfRequestDataValueProcessor();
|
||||
}
|
||||
|
||||
private List<SecurityWebFilterChain> getSecurityWebFilterChains() {
|
||||
List<SecurityWebFilterChain> result = this.securityWebFilterChains;
|
||||
if(ObjectUtils.isEmpty(result)) {
|
||||
return Arrays.asList(springSecurityFilterChain());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private SecurityWebFilterChain springSecurityFilterChain() {
|
||||
ServerHttpSecurity http = this.context.getBean(ServerHttpSecurity.class);
|
||||
return springSecurityFilterChain(http);
|
||||
}
|
||||
|
||||
/**
|
||||
* The default {@link ServerHttpSecurity} configuration.
|
||||
* @param http
|
||||
* @return
|
||||
*/
|
||||
private SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
|
||||
http
|
||||
.authorizeExchange()
|
||||
.anyExchange().authenticated()
|
||||
.and()
|
||||
.httpBasic().and()
|
||||
.formLogin();
|
||||
return http.build();
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -23,7 +23,7 @@ import org.springframework.security.web.method.annotation.AuthenticationPrincipa
|
||||
import org.springframework.security.web.servlet.support.csrf.CsrfRequestDataValueProcessor;
|
||||
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
|
||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
|
||||
import org.springframework.web.servlet.support.RequestDataValueProcessor;
|
||||
|
||||
/**
|
||||
@@ -38,7 +38,7 @@ import org.springframework.web.servlet.support.RequestDataValueProcessor;
|
||||
* @since 3.2
|
||||
*/
|
||||
@EnableWebSecurity
|
||||
public class WebMvcSecurityConfiguration implements WebMvcConfigurer {
|
||||
public class WebMvcSecurityConfiguration extends WebMvcConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("deprecation")
|
||||
@@ -52,4 +52,4 @@ public class WebMvcSecurityConfiguration implements WebMvcConfigurer {
|
||||
public RequestDataValueProcessor requestDataValueProcessor() {
|
||||
return new CsrfRequestDataValueProcessor();
|
||||
}
|
||||
}
|
||||
}
|
||||
+13
-24
@@ -26,7 +26,6 @@ import org.springframework.security.authentication.ProviderManager;
|
||||
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
|
||||
import org.springframework.security.config.BeanIds;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
@@ -50,24 +49,21 @@ public class AuthenticationManagerFactoryBean implements
|
||||
return (AuthenticationManager) bf.getBean(BeanIds.AUTHENTICATION_MANAGER);
|
||||
}
|
||||
catch (NoSuchBeanDefinitionException e) {
|
||||
if (!BeanIds.AUTHENTICATION_MANAGER.equals(e.getBeanName())) {
|
||||
throw e;
|
||||
}
|
||||
|
||||
UserDetailsService uds = getBeanOrNull(UserDetailsService.class);
|
||||
if(uds == null) {
|
||||
if (BeanIds.AUTHENTICATION_MANAGER.equals(e.getBeanName())) {
|
||||
try {
|
||||
UserDetailsService uds = bf.getBean(UserDetailsService.class);
|
||||
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
|
||||
provider.setUserDetailsService(uds);
|
||||
provider.afterPropertiesSet();
|
||||
return new ProviderManager(
|
||||
Arrays.<AuthenticationProvider> asList(provider));
|
||||
}
|
||||
catch (NoSuchBeanDefinitionException noUds) {
|
||||
}
|
||||
throw new NoSuchBeanDefinitionException(BeanIds.AUTHENTICATION_MANAGER,
|
||||
MISSING_BEAN_ERROR_MESSAGE);
|
||||
MISSING_BEAN_ERROR_MESSAGE);
|
||||
}
|
||||
|
||||
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
|
||||
provider.setUserDetailsService(uds);
|
||||
PasswordEncoder passwordEncoder = getBeanOrNull(PasswordEncoder.class);
|
||||
if (passwordEncoder != null) {
|
||||
provider.setPasswordEncoder(passwordEncoder);
|
||||
}
|
||||
provider.afterPropertiesSet();
|
||||
return new ProviderManager(Arrays.<AuthenticationProvider> asList(provider));
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,11 +79,4 @@ public class AuthenticationManagerFactoryBean implements
|
||||
bf = beanFactory;
|
||||
}
|
||||
|
||||
private <T> T getBeanOrNull(Class<T> type) {
|
||||
try {
|
||||
return this.bf.getBean(type);
|
||||
} catch (NoSuchBeanDefinitionException noUds) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+13
-8
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package org.springframework.security.config.authentication;
|
||||
|
||||
import org.springframework.beans.BeanMetadataElement;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
@@ -37,16 +36,22 @@ public class AuthenticationProviderBeanDefinitionParser implements BeanDefinitio
|
||||
private static final String ATT_USER_DETAILS_REF = "user-service-ref";
|
||||
|
||||
public BeanDefinition parse(Element element, ParserContext pc) {
|
||||
RootBeanDefinition authProvider = new RootBeanDefinition(DaoAuthenticationProvider.class);
|
||||
RootBeanDefinition authProvider = new RootBeanDefinition(
|
||||
DaoAuthenticationProvider.class);
|
||||
authProvider.setSource(pc.extractSource(element));
|
||||
|
||||
Element passwordEncoderElt = DomUtils.getChildElementByTagName(element, Elements.PASSWORD_ENCODER);
|
||||
Element passwordEncoderElt = DomUtils.getChildElementByTagName(element,
|
||||
Elements.PASSWORD_ENCODER);
|
||||
|
||||
PasswordEncoderParser pep = new PasswordEncoderParser(passwordEncoderElt, pc);
|
||||
BeanMetadataElement passwordEncoder = pep.getPasswordEncoder();
|
||||
if (passwordEncoder != null) {
|
||||
authProvider.getPropertyValues()
|
||||
.addPropertyValue("passwordEncoder", passwordEncoder);
|
||||
if (passwordEncoderElt != null) {
|
||||
PasswordEncoderParser pep = new PasswordEncoderParser(passwordEncoderElt, pc);
|
||||
authProvider.getPropertyValues().addPropertyValue("passwordEncoder",
|
||||
pep.getPasswordEncoder());
|
||||
|
||||
if (pep.getSaltSource() != null) {
|
||||
authProvider.getPropertyValues().addPropertyValue("saltSource",
|
||||
pep.getSaltSource());
|
||||
}
|
||||
}
|
||||
|
||||
Element userServiceElt = DomUtils.getChildElementByTagName(element,
|
||||
|
||||
+59
-6
@@ -14,6 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.security.config.authentication;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -25,13 +26,23 @@ import org.springframework.beans.factory.config.RuntimeBeanReference;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.security.authentication.encoding.BaseDigestPasswordEncoder;
|
||||
import org.springframework.security.authentication.encoding.LdapShaPasswordEncoder;
|
||||
import org.springframework.security.authentication.encoding.Md4PasswordEncoder;
|
||||
import org.springframework.security.authentication.encoding.Md5PasswordEncoder;
|
||||
import org.springframework.security.authentication.encoding.PlaintextPasswordEncoder;
|
||||
import org.springframework.security.authentication.encoding.ShaPasswordEncoder;
|
||||
import org.springframework.security.config.Elements;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.util.xml.DomUtils;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* Stateful parser for the <password-encoder> element.
|
||||
*
|
||||
* Will produce a PasswordEncoder and (optionally) a SaltSource.
|
||||
*
|
||||
* @author Luke Taylor
|
||||
*/
|
||||
public class PasswordEncoderParser {
|
||||
@@ -39,29 +50,38 @@ public class PasswordEncoderParser {
|
||||
public static final String ATT_HASH = "hash";
|
||||
static final String ATT_BASE_64 = "base64";
|
||||
static final String OPT_HASH_BCRYPT = "bcrypt";
|
||||
static final String OPT_HASH_PLAINTEXT = "plaintext";
|
||||
static final String OPT_HASH_SHA = "sha";
|
||||
static final String OPT_HASH_SHA256 = "sha-256";
|
||||
static final String OPT_HASH_MD4 = "md4";
|
||||
static final String OPT_HASH_MD5 = "md5";
|
||||
static final String OPT_HASH_LDAP_SHA = "{sha}";
|
||||
static final String OPT_HASH_LDAP_SSHA = "{ssha}";
|
||||
|
||||
private static final Map<String, Class<?>> ENCODER_CLASSES;
|
||||
|
||||
static {
|
||||
ENCODER_CLASSES = new HashMap<String, Class<?>>();
|
||||
ENCODER_CLASSES.put(OPT_HASH_PLAINTEXT, PlaintextPasswordEncoder.class);
|
||||
ENCODER_CLASSES.put(OPT_HASH_BCRYPT, BCryptPasswordEncoder.class);
|
||||
ENCODER_CLASSES.put(OPT_HASH_SHA, ShaPasswordEncoder.class);
|
||||
ENCODER_CLASSES.put(OPT_HASH_SHA256, ShaPasswordEncoder.class);
|
||||
ENCODER_CLASSES.put(OPT_HASH_MD4, Md4PasswordEncoder.class);
|
||||
ENCODER_CLASSES.put(OPT_HASH_MD5, Md5PasswordEncoder.class);
|
||||
ENCODER_CLASSES.put(OPT_HASH_LDAP_SHA, LdapShaPasswordEncoder.class);
|
||||
ENCODER_CLASSES.put(OPT_HASH_LDAP_SSHA, LdapShaPasswordEncoder.class);
|
||||
}
|
||||
|
||||
private static final Log logger = LogFactory.getLog(PasswordEncoderParser.class);
|
||||
|
||||
private BeanMetadataElement passwordEncoder;
|
||||
private BeanMetadataElement saltSource;
|
||||
|
||||
public PasswordEncoderParser(Element element, ParserContext parserContext) {
|
||||
parse(element, parserContext);
|
||||
}
|
||||
|
||||
private void parse(Element element, ParserContext parserContext) {
|
||||
if (element == null) {
|
||||
if (parserContext.getRegistry().containsBeanDefinition("passwordEncoder")) {
|
||||
this.passwordEncoder = parserContext.getRegistry().getBeanDefinition("passwordEncoder");
|
||||
}
|
||||
return;
|
||||
}
|
||||
String hash = element.getAttribute(ATT_HASH);
|
||||
boolean useBase64 = false;
|
||||
|
||||
@@ -79,6 +99,21 @@ public class PasswordEncoderParser {
|
||||
((RootBeanDefinition) passwordEncoder).setSource(parserContext
|
||||
.extractSource(element));
|
||||
}
|
||||
|
||||
Element saltSourceElt = DomUtils.getChildElementByTagName(element,
|
||||
Elements.SALT_SOURCE);
|
||||
|
||||
if (saltSourceElt != null) {
|
||||
if (OPT_HASH_BCRYPT.equals(hash)) {
|
||||
parserContext.getReaderContext().error(
|
||||
Elements.SALT_SOURCE + " isn't compatible with bcrypt",
|
||||
parserContext.extractSource(saltSourceElt));
|
||||
}
|
||||
else {
|
||||
saltSource = new SaltSourceBeanDefinitionParser().parse(saltSourceElt,
|
||||
parserContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static BeanDefinition createPasswordEncoderBeanDefinition(String hash,
|
||||
@@ -86,10 +121,28 @@ public class PasswordEncoderParser {
|
||||
Class<?> beanClass = ENCODER_CLASSES.get(hash);
|
||||
BeanDefinitionBuilder beanBldr = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(beanClass);
|
||||
|
||||
if (OPT_HASH_SHA256.equals(hash)) {
|
||||
beanBldr.addConstructorArgValue(Integer.valueOf(256));
|
||||
}
|
||||
|
||||
if (useBase64) {
|
||||
if (BaseDigestPasswordEncoder.class.isAssignableFrom(beanClass)) {
|
||||
beanBldr.addPropertyValue("encodeHashAsBase64", "true");
|
||||
}
|
||||
else {
|
||||
logger.warn(ATT_BASE_64 + " isn't compatible with " + hash
|
||||
+ " and will be ignored");
|
||||
}
|
||||
}
|
||||
return beanBldr.getBeanDefinition();
|
||||
}
|
||||
|
||||
public BeanMetadataElement getPasswordEncoder() {
|
||||
return passwordEncoder;
|
||||
}
|
||||
|
||||
public BeanMetadataElement getSaltSource() {
|
||||
return saltSource;
|
||||
}
|
||||
}
|
||||
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.security.config.authentication;
|
||||
|
||||
import org.springframework.beans.BeanMetadataElement;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.security.authentication.dao.ReflectionSaltSource;
|
||||
import org.springframework.security.authentication.dao.SystemWideSaltSource;
|
||||
import org.springframework.security.config.Elements;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* @author Luke Taylor
|
||||
* @since 2.0
|
||||
*/
|
||||
class SaltSourceBeanDefinitionParser {
|
||||
private static final String ATT_USER_PROPERTY = "user-property";
|
||||
private static final String ATT_REF = "ref";
|
||||
private static final String ATT_SYSTEM_WIDE = "system-wide";
|
||||
|
||||
public BeanMetadataElement parse(Element element, ParserContext parserContext) {
|
||||
String ref = element.getAttribute(ATT_REF);
|
||||
|
||||
if (StringUtils.hasText(ref)) {
|
||||
return new RuntimeBeanReference(ref);
|
||||
}
|
||||
|
||||
String userProperty = element.getAttribute(ATT_USER_PROPERTY);
|
||||
RootBeanDefinition saltSource;
|
||||
|
||||
if (StringUtils.hasText(userProperty)) {
|
||||
saltSource = new RootBeanDefinition(ReflectionSaltSource.class);
|
||||
saltSource.getPropertyValues().addPropertyValue("userPropertyToUse",
|
||||
userProperty);
|
||||
saltSource.setSource(parserContext.extractSource(element));
|
||||
saltSource.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
|
||||
return saltSource;
|
||||
}
|
||||
|
||||
String systemWideSalt = element.getAttribute(ATT_SYSTEM_WIDE);
|
||||
|
||||
if (StringUtils.hasText(systemWideSalt)) {
|
||||
saltSource = new RootBeanDefinition(SystemWideSaltSource.class);
|
||||
saltSource.getPropertyValues().addPropertyValue("systemWideSalt",
|
||||
systemWideSalt);
|
||||
saltSource.setSource(parserContext.extractSource(element));
|
||||
saltSource.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
|
||||
return saltSource;
|
||||
}
|
||||
|
||||
parserContext.getReaderContext().error(
|
||||
Elements.SALT_SOURCE + " requires an attribute", element);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
-113
@@ -1,113 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.config.core.userdetails;
|
||||
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.context.ResourceLoaderAware;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.security.core.userdetails.MapReactiveUserDetailsService;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.util.InMemoryResource;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Constructs an {@link MapReactiveUserDetailsService} from a resource using {@link UserDetailsResourceFactoryBean}.
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @since 5.0
|
||||
* @see UserDetailsResourceFactoryBean
|
||||
*/
|
||||
public class ReactiveUserDetailsServiceResourceFactoryBean
|
||||
implements ResourceLoaderAware, FactoryBean<MapReactiveUserDetailsService> {
|
||||
private UserDetailsResourceFactoryBean userDetails = new UserDetailsResourceFactoryBean();
|
||||
|
||||
@Override
|
||||
public MapReactiveUserDetailsService getObject() throws Exception {
|
||||
Collection<UserDetails> users = userDetails.getObject();
|
||||
return new MapReactiveUserDetailsService(users);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getObjectType() {
|
||||
return MapReactiveUserDetailsService.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setResourceLoader(ResourceLoader resourceLoader) {
|
||||
userDetails.setResourceLoader(resourceLoader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the location of a Resource that is a Properties file in the format defined in {@link UserDetailsResourceFactoryBean}.
|
||||
*
|
||||
* @param resourceLocation the location of the properties file that contains the users (i.e. "classpath:users.properties")
|
||||
* @return the UserDetailsResourceFactoryBean
|
||||
*/
|
||||
public void setResourceLocation(String resourceLocation) {
|
||||
this.userDetails.setResourceLocation(resourceLocation);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a Resource that is a Properties file in the format defined in {@link UserDetailsResourceFactoryBean}.
|
||||
*
|
||||
* @param resource the Resource to use
|
||||
*/
|
||||
public void setResource(Resource resource) {
|
||||
this.userDetails.setResource(resource);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a ReactiveUserDetailsServiceResourceFactoryBean with the location of a Resource that is a Properties file in the
|
||||
* format defined in {@link UserDetailsResourceFactoryBean}.
|
||||
*
|
||||
* @param resourceLocation the location of the properties file that contains the users (i.e. "classpath:users.properties")
|
||||
* @return the ReactiveUserDetailsServiceResourceFactoryBean
|
||||
*/
|
||||
public static ReactiveUserDetailsServiceResourceFactoryBean fromResourceLocation(String resourceLocation) {
|
||||
ReactiveUserDetailsServiceResourceFactoryBean result = new ReactiveUserDetailsServiceResourceFactoryBean();
|
||||
result.setResourceLocation(resourceLocation);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a ReactiveUserDetailsServiceResourceFactoryBean with a Resource that is a Properties file in the
|
||||
* format defined in {@link UserDetailsResourceFactoryBean}.
|
||||
*
|
||||
* @param propertiesResource the Resource that is a properties file that contains the users
|
||||
* @return the ReactiveUserDetailsServiceResourceFactoryBean
|
||||
*/
|
||||
public static ReactiveUserDetailsServiceResourceFactoryBean fromResource(Resource propertiesResource) {
|
||||
ReactiveUserDetailsServiceResourceFactoryBean result = new ReactiveUserDetailsServiceResourceFactoryBean();
|
||||
result.setResource(propertiesResource);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a ReactiveUserDetailsServiceResourceFactoryBean with a String that is in the
|
||||
* format defined in {@link UserDetailsResourceFactoryBean}.
|
||||
*
|
||||
* @param users the users in the format defined in {@link UserDetailsResourceFactoryBean}
|
||||
* @return the ReactiveUserDetailsServiceResourceFactoryBean
|
||||
*/
|
||||
public static ReactiveUserDetailsServiceResourceFactoryBean fromString(String users) {
|
||||
ReactiveUserDetailsServiceResourceFactoryBean result = new ReactiveUserDetailsServiceResourceFactoryBean();
|
||||
result.setResource(new InMemoryResource(users));
|
||||
return result;
|
||||
}
|
||||
}
|
||||
-86
@@ -1,86 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.config.core.userdetails;
|
||||
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.security.core.userdetails.User;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.memory.UserAttribute;
|
||||
import org.springframework.security.core.userdetails.memory.UserAttributeEditor;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Creates a {@code Collection<UserDetails>} from a @{code Map} in the format of
|
||||
* <p>
|
||||
* <code>
|
||||
* username=password[,enabled|disabled],roles...
|
||||
* </code>
|
||||
* <p>
|
||||
* The enabled and disabled properties are optional with enabled being the default. For example:
|
||||
* <p>
|
||||
* <code>
|
||||
* user=password,ROLE_USER
|
||||
* admin=secret,ROLE_USER,ROLE_ADMIN
|
||||
* disabled_user=does_not_matter,disabled,ROLE_USER
|
||||
* </code>
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @since 5.0
|
||||
*/
|
||||
public class UserDetailsMapFactoryBean implements FactoryBean<Collection<UserDetails>> {
|
||||
private final Map<String, String> userProperties;
|
||||
|
||||
public UserDetailsMapFactoryBean(Map<String, String> userProperties) {
|
||||
Assert.notNull(userProperties, "userProperties cannot be null");
|
||||
this.userProperties = userProperties;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Collection<UserDetails> getObject() throws Exception {
|
||||
Collection<UserDetails> users = new ArrayList<>(this.userProperties.size());
|
||||
|
||||
UserAttributeEditor editor = new UserAttributeEditor();
|
||||
for (Map.Entry<String, String> entry : this.userProperties.entrySet()) {
|
||||
String name = entry.getKey();
|
||||
String property = entry.getValue();
|
||||
editor.setAsText(property);
|
||||
UserAttribute attr = (UserAttribute) editor.getValue();
|
||||
if (attr == null) {
|
||||
throw new IllegalStateException("The entry with username '" + name
|
||||
+ "' and value '" + property + "' could not be converted to a UserDetails.");
|
||||
}
|
||||
UserDetails user = User.withUsername(name)
|
||||
.password(attr.getPassword())
|
||||
.disabled(!attr.isEnabled())
|
||||
.authorities(attr.getAuthorities())
|
||||
.build();
|
||||
users.add(user);
|
||||
} return users;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Class<?> getObjectType() {
|
||||
return Collection.class;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user