1
0
mirror of synced 2026-07-13 14:45:10 +00:00

Compare commits

..

103 Commits

Author SHA1 Message Date
Spring Buildmaster 8e9f7e2f10 Release version 4.2.9.RELEASE 2018-10-16 03:23:29 +00:00
Spring Buildmaster bf5a3a1aee Fix to be latest SNAPSHOT 2018-10-15 21:52:13 -05:00
Rob Winch 201690ceba Update to Spring Session 1.3.3
Fixes: gh-5977
2018-10-15 20:43:20 -05:00
Rob Winch e1f33d577f Update to Spring Data Ingalls SR16
Fixes: gh-5976
2018-10-15 20:43:13 -05:00
Rob Winch 879adcae5f Update to Spring Boot 1.5.16.RELEASE
Fixes: gh-5975
2018-10-15 20:43:01 -05:00
Josh Cummings eed8538071 Password Modify Extended Operation Support
LdapUserDetailsManager can be configured to either use direct
attribute modification or the LDAP Password Modify Extended Operation
to change a user's password.

Fixes: gh-3392
2018-10-15 11:37:30 -06:00
Josh Cummings 3df9ad1e8f Introducing UnboundIdContainer
A container for running an embedded unboundid LDAP server.

Fixes: gh-5920
2018-10-15 11:37:23 -06:00
Johnny Lim dac46dc57c Add a missing space in Secured.value() signature 2018-10-03 14:50:26 -04:00
Rob Winch b5b2e2c50e Fix SwitchUserFilter matchers
Fixes: gh-4249
2018-09-14 09:51:53 -05:00
Rob Winch 72c99af0d4 AntPathRequestMatcher supports UrlPathHelper
Fixes: gh-5846
2018-09-14 09:51:53 -05:00
Joe Grandja 742e5fd7a9 Downgrade to spring-boot-gradle-plugin:1.5.2
Fixes gh-5829
2018-09-10 11:14:07 -04:00
Joe Grandja 795c073f48 Update to powermock:1.6.5
Fixes gh-5821
2018-09-10 09:06:41 -04:00
Joe Grandja 58c9cbb471 Update to Spring 4.3.19
Fixes gh-5826
2018-09-07 18:12:55 -04:00
Joe Grandja e40bc262bb Update to Spring Data Commons 1.13.14
Fixes gh-5825
2018-09-07 17:43:55 -04:00
Joe Grandja b0d865e28f Update tomcat:7.0.90
Fixes gh-5824
2018-09-07 17:43:55 -04:00
Joe Grandja 0f7f0042ac Update to Spring Boot 1.5.15
Fixes gh-5822
2018-09-07 17:43:55 -04:00
Joe Grandja e0f1121d5b Update to javax.servlet.jsp.jstl-api:1.2.2
Fixes gh-5820
2018-09-07 17:35:35 -04:00
Joe Grandja ea93ed4165 Update to jackson-databind:2.8.11.2
Fixes gh-5819
2018-09-07 17:35:35 -04:00
Joe Grandja 96acf33019 Update to httpcomponents:httpclient:4.2.5
Fixes gh-5818
2018-09-07 17:35:34 -04:00
Joe Grandja 35dbc0e6a8 Update to bcpkix-jdk15on:1.60
Fixes gh-5816
2018-09-07 17:35:34 -04:00
Joe Grandja 0526c5233c Update to aspectj:1.8.13
Fixes gh-5813
2018-09-07 15:56:38 -04:00
Joe Grandja 60c011a976 Update to org.jacoco.agent:0.7.9
Fixes gh-5812
2018-09-07 15:52:23 -04:00
Joe Grandja 916a19ccbd Update to logback-classic:1.1.11
Fixes gh-5811
2018-09-07 15:48:29 -04:00
Joe Grandja 8138fac3f9 Update to hsqldb:2.3.6
Fixes gh-5810
2018-09-07 15:42:45 -04:00
Joe Grandja 62fadfd28a Update to ehcache:2.10.5
Fixes gh-5809
2018-09-07 15:39:23 -04:00
Rob Winch 166f48e6ab Fix OptimizeAntPathRequestMatcher
Previously the logic for determining if the pathInfo should be appended
was inverted.

This correctly concatenates url + pathInfo if url is a non empty String.

Fixes: gh-5473
2018-08-21 11:53:22 -05:00
Christoph Dreis 0f97086c86 Optimize AntPathRequestMatcher.getRequestPath() 2018-08-21 11:53:22 -05:00
Johnny Lim fe5c6d6621 Fix typo
Closes #5579
2018-08-03 09:58:58 -05:00
Rob Winch c642de537a BasicAuthenticationFilter case insenstive
Fixes: gh-5617
2018-07-31 09:14:38 -05:00
Spring Buildmaster fd27c07b55 Next development version 2018-06-13 02:35:13 +00:00
Spring Buildmaster e0d95c7c8a Release version 4.2.7.RELEASES 2018-06-13 02:35:06 +00:00
Rob Winch 9d76c98791 Fix Checkstyle
Issue: gh-5323
2018-06-12 20:47:49 -05:00
Rob Winch e923371724 Update SpringSecurityCoreVersion 2018-06-12 17:24:16 -05:00
Rob Winch 216512bc54 Update to Spring Framework 4.3.18.RELEASE
Fixes: gh-5437
2018-06-12 17:21:46 -05:00
Rob Winch 8445e91b22 Add Assumptions.assumeMinimumJdk8
Certain cryptographic algorithms are only supported on JDK8+. This
causes failures in JDK 7. This commit adds a JUnit assumption on
tests that leverage JDK8 specific cryptographic algorithms.

Issue: gh-5323
2018-05-10 10:53:18 -05:00
Rob Winch 13ccb83d6f Remove java.util.Base64
java.util.Base64 was not added until JDK8, so we should use
Spring Security's Base64 in 4.x

Issue: gh-5323
2018-05-10 10:53:18 -05:00
Rob Winch 127d9eece9 Default Spring IO version Brussels-SR9
Fixes: gh-5326
2018-05-10 10:53:18 -05:00
Spring Buildmaster 7891787a53 Next development version 2018-05-08 17:14:38 +00:00
Spring Buildmaster 2d8b6650db Release version 4.2.6.RELEASE 2018-05-08 17:14:29 +00:00
Rob Winch 78995ff0a9 Use Spring Boot 1.5.2 to prevent deploy error 2018-05-08 11:35:18 -05:00
Rob Winch 7974f3161d spring-boot-gradle-plugin:1.5.0.RELEASE 2018-05-08 11:27:32 -05:00
Rob Winch c35c1c0643 Update Dependencies 2018-05-08 10:53:35 -05:00
Trygve Aasjord 2162221589 Pass username as second parameter for search filter.
Allows the username only (without domain) to be used in custom search filter like "sAMAccountName={1}",
in eg. situations where the userPrincipalName has a different suffix than domain.

Thanks to contributors in issue.

fixes gh-2448

(cherry picked from commit 8d717c62af)
2018-05-04 10:51:14 -05:00
Kazuki Shimizu 040fb6aa3c Fix incorrect explanation for customizing query on JdbcDaoImpl 2018-05-04 10:45:09 -05:00
Rob Winch b152218ee0 Add InMemoryUserDetailsManager(UserDetails...)
Fixes: gh-5304
2018-05-04 10:33:40 -05:00
Rob Winch 544e421157 Add UserBuilder Methods
Fixes: gh-5303
2018-05-04 10:33:25 -05:00
Rob Winch 0f612bf637 Add crypto PasswordEncoder from 5.0.x
Fixes: gh-5302
2018-05-04 10:32:53 -05:00
Rob Winch c683bc10bf Fixes: gh-5190 2018-04-16 17:51:51 -05:00
Spring Buildmaster 11ab23f4f4 Next development version 2018-03-30 16:34:47 +00:00
Spring Buildmaster 0065b55a75 Release version 4.2.5.RELEASE 2018-03-30 16:34:39 +00:00
Rob Winch d6f9d2e34a CookieClearingLogoutHandler adds uses contextPath + "/"
Fixes: gh-5141
2018-03-19 16:52:14 -05:00
Rob Winch 5dedbb6283 Update to jackson-databind-2.8.11.1
Fixes: gh-5101
2018-03-09 13:55:49 -06:00
Rob Winch 4cad151b57 Fix TestingAuthenticationTokenTests JDK 1.6 compile
Issue: gh-5097
2018-03-09 13:46:10 -06:00
Josh Cummings 72080bb5fe Authorities authenticate TestingAuthenticationToken
In other extensions of `AbstractAuthenticationToken`, the constructors
that include `authorities` call `setAuthenticated(true)`. This includes
`PreAuthenticated`-, `UsernamePassword`-, and
`RememberMeAuthenticationToken`.

This change brings `TestingAuthenticationToken` in line with that
convention.

Note that this was done once already to one of the constructors
(ee13be4) in `TestingAuthenticationToken` that takes an arity of
`authorities`. It was not propagated to the constructor that takes a
collection, which is what this commit remedies.

Fixes: gh-5097
2018-03-09 13:27:27 -06:00
Rob Winch 5854f00977 Fix StrictHttpFirewall rules
Fixes: gh-5093
2018-03-08 21:31:37 -06:00
Rob Winch 93118f4e91 Use HttpFirewall Bean
Fixes: gh-5025
2018-02-16 15:45:20 -06:00
Rob Winch 8796850816 Format HttpFirewall Reference
Put each sentence on a newline.

Issue: gh-5025
2018-02-16 15:41:18 -06:00
Rob Winch cee2ea9c60 Polish StrictHttpFirewall Javadoc
Also cleanup DefaultHttpFirewall Javadoc

Issue: gh-5009
2018-02-15 17:32:37 -06:00
Rob Winch 1159c9f302 Fix since on StrictHttpFirewall
Fixes: gh-5006
2018-02-08 14:14:52 -06:00
Rob Winch 6c5ce1237d Polish StrictHttpFirewall Javadoc
Fixes: gh-5009
2018-02-08 14:12:35 -06:00
Rob Winch f81b58112b Cache headers only if no cache headers set
Fixes: gh-5005
2018-02-07 14:57:20 -06:00
Spring Buildmaster 0e02b489c8 Next development version 2018-01-24 23:19:49 +00:00
Spring Buildmaster d1669b909f Release 4.2.4.RELEASE 2018-01-24 23:19:40 +00:00
Rob Winch cb8041ba67 Add StrictHttpFirewall 2018-01-24 16:31:40 -06:00
Rob Winch 6f74162a1f Test Jackson HashMap in Whitelist
Issue: gh-4889
2018-01-03 16:08:57 -06:00
Chris Burrell 99a0baadfa Add HashMap to Jackson whitelist
Issue: gh-4889
2018-01-03 16:08:28 -06:00
Rob Winch 1f9a0e579f Update Spring Data Ingalls SR8
Fixes gh-4785
2017-11-02 16:34:40 -05:00
Rob Winch 9e7d08c9e7 Update to Boot 1.5.8.RELEASE
Fixes gh-4784
2017-11-02 16:20:43 -05:00
Rob Winch 82168faf9d Update to jsonassert 1.4.0
Fixes gh-4783
2017-11-02 16:19:58 -05:00
Rob Winch 9d0f8977a9 Update to slfj4 1.7.25
Fixes gh-4782
2017-11-02 16:19:16 -05:00
Rob Winch 5ae615f3b4 Update Jackson to 2.8.10
Fixes gh-4781
2017-11-02 16:18:31 -05:00
Rob Winch d2b0077392 Update Hibernate Versions
- Hibernate to 5.0.12.Final
- Hibernate validator to 5.3.6.Final

Fixes gh-4780
2017-11-02 16:17:46 -05:00
Rob Winch 092c5aecf7 Update to Ehcache 2.10.4
Fixes gh-4779
2017-11-02 16:13:43 -05:00
Rob Winch a5d56d8724 Update to Aspectj 1.8.12
Fixes gh-4778
2017-11-02 16:12:39 -05:00
Rob Winch 7c0da854da Update to Spring LDAP 2.3.2
Fixes gh-4777
2017-11-02 16:11:03 -05:00
Rob Winch 0f546dcb07 Update to Spring 4.3.12
Fixes gh-4776
2017-11-02 16:08:50 -05:00
Rob Winch cb576d16e1 DelegatingApplicationListener uses CopyOnWriteArrayList
Fixes gh-4417
2017-11-02 14:41:20 -05:00
Greg Turnquist 3b4df40f47 Fix UsernamePasswordAuthenticationTokenMixin to handle null credentials/details
Fixes gh-4773
2017-11-02 14:41:20 -05:00
Gajendra kumar 6cbf71bd72 Allow inject Map into SessionRegistryImpl
As principals and sessionIds are set in class itself so one can't share
user session count across nodes(Cluster). Using constructor for setting
principals and sessionIds we can pass Cache map to constructor which can
enable common session count in cluster otherwise user would be allowed to
logged in with multiple sessions. There is no point keeping principals
and sessionIds completely internal.

Fixes gh-4772
2017-11-02 14:41:20 -05:00
Rob Winch cd63329b63 Polish XFrameOptionsHeaderWriter
Fixes: gh-4771
2017-11-02 14:41:20 -05:00
Nathan Wong cc7f504f96 Add check to see if return value is DENY
Originally, if the return from getAllowFromValue(request) is "DENY",
then the X-Frame-Options header's value will proceed to be written as
"ALLOW FROM DENY" - an invalid value.

This commit adds a condition in the if clause that checks whether
allowFromValue is "DENY". This way, the X-Frame-Options header will be
written as "ALLOW FROM origin" or "DENY".

Issue gh-4771
2017-11-02 14:41:20 -05:00
Antoine a094563052 Fix leading space characters reported by checkstyle 2017-11-02 14:41:20 -05:00
Rob Winch da19435f21 Fix assertj
Fix for 4.2.x
2017-11-02 14:41:02 -05:00
Antoine be50cd8ada Polish more AssertJ assertions
Issue gh-4770
2017-11-02 14:40:53 -05:00
Antoine 21efbb6ba7 Polish AssertJ assertions
Fixes gh-4770
2017-11-02 14:40:53 -05:00
Arend v. Reinersdorff c7cf6fdd73 Minor typos PreAuthenticatedAuthenticationProvider
Fixes gh-4769
2017-11-02 14:40:53 -05:00
Rob Winch 8129bf2ce0 Update .gitignore
- ignore classes/
- ignore s101plugin.state
2017-11-02 14:40:53 -05:00
Joris Portegies Zwart d48079eb19 JavaDoc for Pbkdf2PasswordEncoder refer to constants
Fix Javadoc so that it uses the actual values for default hash width and number of iterations

Fixes gh-4768
2017-11-02 14:40:53 -05:00
Kyle Anderson 45f1179b52 Fix Typo in Reference Docs
Fixes gh-4767
2017-11-02 14:40:52 -05:00
Rob Winch e11dfa7578 Lookup HandlerMappingIntrospector from Bean 2017-11-02 14:40:52 -05:00
Frank Pavageau 6cc0f6c054 Deserialize the principal in a neutral way
When the principal of the Authentication is an object, it is not necessarily
an User: it could be another implementation of UserDetails, or even a
completely unrelated type. Since the type of the object is serialized as a
property and used by the deserialization anyway, there's no point in
enforcing a stricter type.
2017-10-31 16:42:50 -05:00
Frank Pavageau 22ea835643 Map values directly from the JSON nodes
Not only is it more efficient without converting to an intermediate String,
using JsonNode.toString() may not even produce valid JSON according to its
Javadoc (ObjectMapper.writeValueAsString() should be used).
2017-10-31 16:42:50 -05:00
linzhaoming 9f51d68e92 Fix wrong doc of HttpServletRequest.authenticate()
Should be HttpServletRequest.authenticate(HttpServletResponse response), should not include argument HttpServletRequest
2017-10-30 01:01:44 -05:00
linzhaoming 32af1884f7 Fix wrong typo: DigestAuthenticatonEntryPoint to DigestAuthenticationEntryPoint
Fix wrong type
2017-10-30 01:01:44 -05:00
Chaouki Dhib a88035196a Fix typo in the doc in 5.7 Multiple HttpSecurity 2017-10-12 07:43:55 -05:00
Spring Buildmaster 0db94b1d36 Next development version 2017-06-08 04:34:44 +00:00
Spring Buildmaster 9e8994a2b7 Release version 4.2.3.RELEASE 2017-06-08 04:34:34 +00:00
Rob Winch 8b2faff7ad Update to Spring 4.3.9.RELEASE
Fixes gh-4375
2017-06-07 22:52:58 -05:00
Rob Winch 469bc20e6d UrlUtils reuses ABSOLUTE_URL
Fixes gh-4234
2017-06-07 22:52:58 -05:00
Rob Winch 947d11f433 Update SecurityJackson2Modules
Fixes gh-4370
2017-06-07 22:52:58 -05:00
Rob Winch b3a60a83f6 Force springIoTestRuntime assertj.version=2.2.0 2017-05-18 18:02:33 -05:00
Rob Winch 5bc7e4171c Fix DefaultSavedRequestMixinTests with Spring 5
Previously DefaultSavedRequestMixinTests
serializeDefaultRequestBuildWithConstructorTest broke in Spring 5
because Spring 5's MockHttpServletRequest.setCookie now automatically adds
the Cookie header.

This commit ensures that the Cookie header is not added by overriding the
class we are writing.

Fixes gh-4272
2017-05-18 17:57:18 -05:00
Rob Winch 80e96b0f7b Use Spring IO Brussels-SR1 2017-03-21 14:39:46 -05:00
1046 changed files with 21576 additions and 43457 deletions
+1 -1
View File
@@ -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
View File
@@ -13,4 +13,4 @@ cache:
- $HOME/.gradle/caches/
- $HOME/.gradle/wrapper/
script: ./gradlew build --refresh-dependencies --no-daemon
script: ./gradlew build
Vendored
-119
View File
@@ -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
View File
@@ -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].
+19
View File
@@ -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
View File
@@ -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>
-18
View File
@@ -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'
}
@@ -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;
}
}
@@ -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)
);
@@ -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));
}
@@ -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));
}
}
@@ -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();
}
@@ -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);
}
}
@@ -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");
}
}
@@ -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;
}
}
@@ -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));
}
}
@@ -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);
}
}
}
@@ -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;
}
}
@@ -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>
+6 -7
View File
@@ -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>
+10
View File
@@ -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
View File
@@ -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>
-11
View File
@@ -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>
+9
View File
@@ -0,0 +1,9 @@
apply plugin: 'maven-bom'
apply from: "$rootDir/gradle/maven-deployment.gradle"
generatePom.enabled = false
sonarqube.skipProject = true
mavenBom {
projects = coreModuleProjects
}
-10
View File
@@ -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
View File
@@ -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
}
}
}
+2 -2
View File
@@ -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) {
+17
View File
@@ -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
View File
@@ -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>
-18
View File
@@ -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'
}
@@ -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());
@@ -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
@@ -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");
}
}
@@ -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"));
-15
View File
@@ -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>
+77
View File
@@ -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
View File
@@ -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>
-81
View File
@@ -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
@@ -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)
@@ -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";
@@ -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();
}
}
}
}
@@ -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;
@@ -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);
}
@@ -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 {
}
}
}
@@ -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());
}
}
@@ -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,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);
@@ -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;
}
@@ -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());
}
}
}
@@ -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");
}
}
@@ -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()]);
}
}
@@ -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);
@@ -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
* &#064;Override
* protected void configure(AuthenticationManagerBuilder auth) throws Exception {
* auth.inMemoryAuthentication().withUser(&quot;user&quot;).password(&quot;password&quot;).roles(&quot;USER&quot;)
* .and().withUser(&quot;admin&quot;).password(&quot;password&quot;).roles(&quot;ADMIN&quot;, &quot;USER&quot;);
* .and().withUser(&quot;adminr&quot;).password(&quot;password&quot;).roles(&quot;ADMIN&quot;, &quot;USER&quot;);
* }
* }
* </pre>
@@ -627,7 +626,7 @@ public final class HttpSecurity extends
* &#064;Override
* protected void configure(AuthenticationManagerBuilder auth) throws Exception {
* auth.inMemoryAuthentication().withUser(&quot;user&quot;).password(&quot;password&quot;).roles(&quot;USER&quot;)
* .and().withUser(&quot;admin&quot;).password(&quot;password&quot;).roles(&quot;ADMIN&quot;, &quot;USER&quot;);
* .and().withUser(&quot;adminr&quot;).password(&quot;password&quot;).roles(&quot;ADMIN&quot;, &quot;USER&quot;);
* }
* }
* </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 &quot;authentication flow&quot; 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>&quot;/login&quot;</code> and
* redirects to <code>&quot;/login?error&quot;</code> when an authentication error occurs.
* The login page will display each of the clients with a link
* that is capable of initiating the &quot;authentication flow&quot;.
* <br>
* <br>
*
* <p>
* <h2>Example Configuration</h2>
*
* The following example shows the minimal configuration required, using Google as the Authentication Provider.
*
* <pre>
* &#064;Configuration
* public class OAuth2LoginConfig {
*
* &#064;EnableWebSecurity
* public static class OAuth2LoginSecurityConfig extends WebSecurityConfigurerAdapter {
* &#064;Override
* protected void configure(HttpSecurity http) throws Exception {
* http
* .authorizeRequests()
* .anyRequest().authenticated()
* .and()
* .oauth2Login();
* }
* }
*
* &#064;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>
@@ -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) {}
}
}
@@ -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());
}
}
}
@@ -160,7 +160,7 @@ public class WebSecurityConfiguration implements ImportAware, BeanClassLoaderAwa
}
@Bean
public static AutowiredWebSecurityConfigurersIgnoreParents autowiredWebSecurityConfigurersIgnoreParents(
public AutowiredWebSecurityConfigurersIgnoreParents autowiredWebSecurityConfigurersIgnoreParents(
ConfigurableListableBeanFactory beanFactory) {
return new AutowiredWebSecurityConfigurersIgnoreParents(beanFactory);
}
@@ -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();
}
}
}
@@ -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
*
@@ -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);
}
@@ -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);
@@ -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));
@@ -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
@@ -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);
}
}
}
@@ -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;
}
}
}
@@ -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;
}
}
}
@@ -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);
}
}
@@ -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);
}
}
}
@@ -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>
@@ -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">
* &#064;EnableWebFluxSecurity
* public class MyMinimalSecurityConfiguration {
*
* &#064;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">
* &#064;EnableWebFluxSecurity
* public class MyExplicitSecurityConfiguration {
* &#064;Bean
* SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
* http
* .authorizeExchange()
* .anyExchange().authenticated()
* .and()
* .httpBasic().and()
* .formLogin();
* return http.build();
* }
*
* &#064;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 {
}
@@ -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;
}
}
@@ -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();
}
}
@@ -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();
}
}
}
@@ -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;
}
}
}
@@ -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,
@@ -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 &lt;password-encoder&gt; 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;
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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