Compare commits
78 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6747e1330f | |||
| 932b084923 | |||
| 66ca1d93f2 | |||
| 8fb27d9329 | |||
| 14e3e0f0b7 | |||
| 76f33ae6e6 | |||
| b0651b97fd | |||
| 7cce996ebe | |||
| 2aa09d11e2 | |||
| 8ab8376b9c | |||
| 5699a36627 | |||
| 0f0e973c1e | |||
| 9c76f54958 | |||
| 14e4a812a1 | |||
| be0759302f | |||
| ff25799f36 | |||
| 54b28873ee | |||
| 692ac213f9 | |||
| e4e7363196 | |||
| 75e248344b | |||
| 3ae6cdf05f | |||
| a9c8b350b8 | |||
| da9eca223b | |||
| c7e18db138 | |||
| 9c181c58cb | |||
| 7b61962915 | |||
| a302106082 | |||
| fe737cc67d | |||
| d4508858f3 | |||
| 76432029c5 | |||
| 0d0afb992e | |||
| b35d7e229d | |||
| 3c81e122bd | |||
| 929a5de163 | |||
| ecac6cdfc1 | |||
| 2ad73af130 | |||
| 0aaefa2bb9 | |||
| 21c70155a3 | |||
| 7ca913dadf | |||
| 7eb87b19b3 | |||
| 1683d30c2e | |||
| adfb3ddf77 | |||
| 1ba1fb61a7 | |||
| e3a1fa2f86 | |||
| ac657a32a6 | |||
| 6c98a49010 | |||
| f2db4b6cdb | |||
| 9156d3bce3 | |||
| 327c52d650 | |||
| d98d23e5ef | |||
| f892746c00 | |||
| b95ccc211b | |||
| 820b2046fb | |||
| bde423524b | |||
| 78d8b9fa71 | |||
| 35bbccad3c | |||
| 04cc0d486b | |||
| e7b43f14c8 | |||
| 0629ecbb00 | |||
| 93557505c0 | |||
| 8facc74da2 | |||
| c0f16908a1 | |||
| 8be0691e8f | |||
| e794dcd203 | |||
| dbaeb2fdd9 | |||
| ae2809634f | |||
| 8fd5cca501 | |||
| a867f92416 | |||
| a1a61d3259 | |||
| fbf3c7d083 | |||
| 76a869995e | |||
| 702ec17a5f | |||
| ba4953b057 | |||
| b87ea1373d | |||
| 7754a11a4a | |||
| 409ef7d5e1 | |||
| d01b6fc6b1 | |||
| 0994a64830 |
@@ -0,0 +1,22 @@
|
|||||||
|
name: PR Build
|
||||||
|
|
||||||
|
on: pull_request
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
name: Build
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Set up JDK
|
||||||
|
uses: actions/setup-java@v1
|
||||||
|
with:
|
||||||
|
java-version: '8'
|
||||||
|
- name: Cache Gradle packages
|
||||||
|
uses: actions/cache@v2
|
||||||
|
with:
|
||||||
|
path: ~/.gradle/caches
|
||||||
|
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }}
|
||||||
|
- name: Build with Gradle
|
||||||
|
run: ./gradlew test --refresh-dependencies --no-daemon
|
||||||
-16
@@ -1,16 +0,0 @@
|
|||||||
language: java
|
|
||||||
|
|
||||||
jdk:
|
|
||||||
- oraclejdk8
|
|
||||||
|
|
||||||
os:
|
|
||||||
- linux
|
|
||||||
|
|
||||||
before_cache:
|
|
||||||
- rm -f $HOME/.gradle/caches/modules-2/modules-2.lock
|
|
||||||
cache:
|
|
||||||
directories:
|
|
||||||
- $HOME/.gradle/caches/
|
|
||||||
- $HOME/.gradle/wrapper/
|
|
||||||
|
|
||||||
script: ./gradlew build
|
|
||||||
Vendored
+109
@@ -0,0 +1,109 @@
|
|||||||
|
def projectProperties = [
|
||||||
|
[$class: 'BuildDiscarderProperty',
|
||||||
|
strategy: [$class: 'LogRotator', numToKeepStr: '5']],
|
||||||
|
pipelineTriggers([cron('@daily')])
|
||||||
|
]
|
||||||
|
properties(projectProperties)
|
||||||
|
|
||||||
|
def SUCCESS = hudson.model.Result.SUCCESS.toString()
|
||||||
|
currentBuild.result = SUCCESS
|
||||||
|
|
||||||
|
|
||||||
|
def ARTIFACTORY_CREDENTIALS = usernamePassword(credentialsId: '02bd1690-b54f-4c9f-819d-a77cb7a9822c', usernameVariable: 'ARTIFACTORY_USERNAME', passwordVariable: 'ARTIFACTORY_PASSWORD')
|
||||||
|
|
||||||
|
try {
|
||||||
|
parallel check: {
|
||||||
|
stage('Check') {
|
||||||
|
node {
|
||||||
|
checkout scm
|
||||||
|
sh "git clean -dfx"
|
||||||
|
try {
|
||||||
|
withCredentials([ARTIFACTORY_CREDENTIALS]) {
|
||||||
|
withEnv(["JAVA_HOME=${ tool 'jdk8' }"]) {
|
||||||
|
sh "./gradlew test -PartifactoryUsername=$ARTIFACTORY_USERNAME -PartifactoryPassword=$ARTIFACTORY_PASSWORD --refresh-dependencies --no-daemon --stacktrace"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch(Exception e) {
|
||||||
|
currentBuild.result = 'FAILED: check'
|
||||||
|
throw e
|
||||||
|
} finally {
|
||||||
|
junit '**/build/test-results/*/*.xml'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(currentBuild.result == 'SUCCESS') {
|
||||||
|
parallel artifacts: {
|
||||||
|
stage('Deploy Artifacts') {
|
||||||
|
node {
|
||||||
|
checkout scm
|
||||||
|
sh "git clean -dfx"
|
||||||
|
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([ARTIFACTORY_CREDENTIALS]) {
|
||||||
|
withEnv(["JAVA_HOME=${ tool 'jdk8' }"]) {
|
||||||
|
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
|
||||||
|
sh "git clean -dfx"
|
||||||
|
withCredentials([file(credentialsId: 'docs.spring.io-jenkins_private_ssh_key', variable: 'DEPLOY_SSH_KEY')]) {
|
||||||
|
withEnv(["JAVA_HOME=${ tool 'jdk8' }"]) {
|
||||||
|
sh "./gradlew deployDocs -PdeployDocsSshKeyPath=$DEPLOY_SSH_KEY -PdeployDocsSshUsername=$SPRING_DOCS_USERNAME --refresh-dependencies --no-daemon --stacktrace"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
schema: {
|
||||||
|
stage('Deploy Schema') {
|
||||||
|
node {
|
||||||
|
checkout scm
|
||||||
|
sh "git clean -dfx"
|
||||||
|
withCredentials([file(credentialsId: 'docs.spring.io-jenkins_private_ssh_key', variable: 'DEPLOY_SSH_KEY')]) {
|
||||||
|
withEnv(["JAVA_HOME=${ tool 'jdk8' }"]) {
|
||||||
|
sh "./gradlew deploySchema -PdeployDocsSshKeyPath=$DEPLOY_SSH_KEY -PdeployDocsSshUsername=$SPRING_DOCS_USERNAME --refresh-dependencies --no-daemon --stacktrace"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch(Exception e) {
|
||||||
|
currentBuild.result = 'FAILED: deploys'
|
||||||
|
throw e
|
||||||
|
} 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"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,5 @@
|
|||||||
image::https://badges.gitter.im/Join%20Chat.svg[Gitter,link=https://gitter.im/spring-projects/spring-security?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge]
|
image::https://badges.gitter.im/Join%20Chat.svg[Gitter,link=https://gitter.im/spring-projects/spring-security?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge]
|
||||||
|
|
||||||
image:https://travis-ci.org/spring-projects/spring-security.svg?branch=master["Build Status", link="https://travis-ci.org/spring-security/spring-security"]
|
|
||||||
|
|
||||||
= Spring Security
|
= Spring Security
|
||||||
|
|
||||||
Spring Security provides security services for the https://docs.spring.io[Spring IO Platform]. Spring Security 3.1 requires Spring 3.0.3 as
|
Spring Security provides security services for the https://docs.spring.io[Spring IO Platform]. Spring Security 3.1 requires Spring 3.0.3 as
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
apply plugin: 'maven-bom'
|
apply plugin: 'maven-bom'
|
||||||
apply from: "$rootDir/gradle/maven-deployment.gradle"
|
apply from: "$rootDir/gradle/maven-deployment.gradle"
|
||||||
|
apply from: "$rootDir/gradle/artifactory.gradle"
|
||||||
|
apply from: "$rootDir/gradle/ossrh.gradle"
|
||||||
|
apply from: "$rootDir/gradle/deploy-artifacts.gradle"
|
||||||
|
|
||||||
generatePom.enabled = false
|
generatePom.enabled = false
|
||||||
sonarqube.skipProject = true
|
sonarqube.skipProject = true
|
||||||
|
|||||||
+42
-9
@@ -1,17 +1,27 @@
|
|||||||
buildscript {
|
buildscript {
|
||||||
repositories {
|
repositories {
|
||||||
maven { url "https://repo.spring.io/plugins-release" }
|
maven {
|
||||||
maven { url "https://repo.spring.io/plugins-snapshot" }
|
url = 'https://repo.spring.io/plugins-snapshot'
|
||||||
|
if (project.hasProperty('artifactoryUsername')) {
|
||||||
|
credentials {
|
||||||
|
username "$artifactoryUsername"
|
||||||
|
password "$artifactoryPassword"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath "com.github.ben-manes:gradle-versions-plugin:0.17.0"
|
classpath "com.github.ben-manes:gradle-versions-plugin:0.17.0"
|
||||||
classpath("org.springframework.build.gradle:propdeps-plugin:0.0.7")
|
classpath("org.springframework.build.gradle:propdeps-plugin:0.0.7")
|
||||||
classpath("io.spring.gradle:spring-io-plugin:0.0.6.RELEASE")
|
classpath("io.spring.gradle:spring-io-plugin:0.0.8.RELEASE")
|
||||||
classpath("com.bmuschko:gradle-tomcat-plugin:2.2.4")
|
classpath("com.bmuschko:gradle-tomcat-plugin:2.2.4")
|
||||||
classpath('me.champeau.gradle:gradle-javadoc-hotfix-plugin:0.1')
|
classpath('me.champeau.gradle:gradle-javadoc-hotfix-plugin:0.1')
|
||||||
classpath('org.asciidoctor:asciidoctor-gradle-plugin:1.5.1')
|
classpath('org.asciidoctor:asciidoctor-gradle-plugin:1.5.7')
|
||||||
classpath("io.spring.gradle:docbook-reference-plugin:0.3.1")
|
classpath("io.spring.gradle:docbook-reference-plugin:0.3.1")
|
||||||
classpath("org.springframework.boot:spring-boot-gradle-plugin:1.5.19.RELEASE")
|
classpath("org.springframework.boot:spring-boot-gradle-plugin:1.5.22.RELEASE")
|
||||||
|
classpath "org.jfrog.buildinfo:build-info-extractor-gradle:4.12.0"
|
||||||
|
classpath 'org.hidetake:gradle-ssh-plugin:2.10.1'
|
||||||
|
classpath 'io.codearte.gradle.nexus:gradle-nexus-staging-plugin:0.10.0'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -20,6 +30,7 @@ plugins {
|
|||||||
}
|
}
|
||||||
|
|
||||||
apply plugin: 'base'
|
apply plugin: 'base'
|
||||||
|
apply from: "$rootDir/gradle/finalize-deploy.gradle"
|
||||||
|
|
||||||
description = 'Spring Security'
|
description = 'Spring Security'
|
||||||
|
|
||||||
@@ -30,8 +41,8 @@ allprojects {
|
|||||||
|
|
||||||
ext.releaseBuild = version.endsWith('RELEASE')
|
ext.releaseBuild = version.endsWith('RELEASE')
|
||||||
ext.snapshotBuild = version.endsWith('SNAPSHOT')
|
ext.snapshotBuild = version.endsWith('SNAPSHOT')
|
||||||
ext.springVersion = '4.3.23.RELEASE'
|
ext.springVersion = '4.3.30.RELEASE'
|
||||||
ext.springLdapVersion = '2.3.2.RELEASE'
|
ext.springLdapVersion = '2.3.3.RELEASE'
|
||||||
|
|
||||||
group = 'org.springframework.security'
|
group = 'org.springframework.security'
|
||||||
|
|
||||||
@@ -86,7 +97,6 @@ configure(allprojects - javaProjects) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
configure(subprojects - coreModuleProjects - project(':spring-security-samples-javaconfig-messages') - project(':spring-security-bom')) {
|
configure(subprojects - coreModuleProjects - project(':spring-security-samples-javaconfig-messages') - project(':spring-security-bom')) {
|
||||||
tasks.findByPath("artifactoryPublish")?.enabled = false
|
|
||||||
sonarqube {
|
sonarqube {
|
||||||
skipProject = true
|
skipProject = true
|
||||||
}
|
}
|
||||||
@@ -102,10 +112,13 @@ configure(javaProjects) {
|
|||||||
}
|
}
|
||||||
apply from: "$rootDir/gradle/ide.gradle"
|
apply from: "$rootDir/gradle/ide.gradle"
|
||||||
apply from: "$rootDir/gradle/release-checks.gradle"
|
apply from: "$rootDir/gradle/release-checks.gradle"
|
||||||
apply from: "$rootDir/gradle/maven-deployment.gradle"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
configure(coreModuleProjects) {
|
configure(coreModuleProjects) {
|
||||||
|
apply from: "$rootDir/gradle/maven-deployment.gradle"
|
||||||
|
apply from: "$rootDir/gradle/artifactory.gradle"
|
||||||
|
apply from: "$rootDir/gradle/ossrh.gradle"
|
||||||
|
apply from: "$rootDir/gradle/deploy-artifacts.gradle"
|
||||||
apply plugin: 'emma'
|
apply plugin: 'emma'
|
||||||
apply plugin: 'spring-io'
|
apply plugin: 'spring-io'
|
||||||
|
|
||||||
@@ -116,6 +129,9 @@ configure(coreModuleProjects) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencyManagement {
|
dependencyManagement {
|
||||||
|
imports {
|
||||||
|
mavenBom("org.springframework:spring-framework-bom:${springVersion}")
|
||||||
|
}
|
||||||
springIoTestRuntime {
|
springIoTestRuntime {
|
||||||
imports {
|
imports {
|
||||||
mavenBom("io.spring.platform:platform-bom:${springIoVersion}") {
|
mavenBom("io.spring.platform:platform-bom:${springIoVersion}") {
|
||||||
@@ -194,3 +210,20 @@ artifacts {
|
|||||||
archives project(':docs').docsZip
|
archives project(':docs').docsZip
|
||||||
archives project(':docs').schemaZip
|
archives project(':docs').schemaZip
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (project.hasProperty('artifactoryUsername')) {
|
||||||
|
allprojects { project ->
|
||||||
|
project.repositories { repos ->
|
||||||
|
all { repo ->
|
||||||
|
if (!repo.url.toString().startsWith("https://repo.spring.io/")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
repo.credentials {
|
||||||
|
username = artifactoryUsername
|
||||||
|
password = artifactoryPassword
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -15,5 +15,6 @@ public class MavenBomPlugin implements Plugin<Project> {
|
|||||||
project.plugins.apply(MavenPlugin)
|
project.plugins.apply(MavenPlugin)
|
||||||
project.task(MAVEN_BOM_TASK_NAME, type: MavenBomTask, group: 'Generate', description: 'Configures the pom as a Maven Build of Materials (BOM)')
|
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
|
project.install.dependsOn project.mavenBom
|
||||||
|
project.uploadArchives.dependsOn project.mavenBom
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -20,7 +20,7 @@ public class MavenBomTask extends DefaultTask {
|
|||||||
|
|
||||||
@TaskAction
|
@TaskAction
|
||||||
public void configureBom() {
|
public void configureBom() {
|
||||||
project.configurations.archives.artifacts.clear()
|
// project.configurations.archives.artifacts.clear()
|
||||||
|
|
||||||
bomFile.parentFile.mkdirs()
|
bomFile.parentFile.mkdirs()
|
||||||
bomFile.write("Maven Build of Materials (BOM). See https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html#Importing_Dependencies")
|
bomFile.write("Maven Build of Materials (BOM). See https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html#Importing_Dependencies")
|
||||||
@@ -30,20 +30,30 @@ public class MavenBomTask extends DefaultTask {
|
|||||||
}
|
}
|
||||||
project.install {
|
project.install {
|
||||||
repositories.mavenInstaller {
|
repositories.mavenInstaller {
|
||||||
pom.whenConfigured {
|
customizePom(pom)
|
||||||
packaging = "pom"
|
}
|
||||||
withXml {
|
}
|
||||||
asNode().children().last() + {
|
|
||||||
delegate.dependencyManagement {
|
|
||||||
delegate.dependencies {
|
|
||||||
projects.sort { dep -> "$dep.group:$dep.name" }.each { p ->
|
|
||||||
|
|
||||||
delegate.dependency {
|
project.uploadArchives {
|
||||||
delegate.groupId(p.group)
|
repositories.mavenDeployer {
|
||||||
delegate.artifactId(p.name)
|
customizePom(pom)
|
||||||
delegate.version(p.version)
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void customizePom(pom) {
|
||||||
|
pom.whenConfigured {
|
||||||
|
packaging = "pom"
|
||||||
|
withXml {
|
||||||
|
asNode().children().last() + {
|
||||||
|
delegate.dependencyManagement {
|
||||||
|
delegate.dependencies {
|
||||||
|
projects.sort { dep -> "$dep.group:$dep.name" }.each { p ->
|
||||||
|
|
||||||
|
delegate.dependency {
|
||||||
|
delegate.groupId(p.group)
|
||||||
|
delegate.artifactId(p.name)
|
||||||
|
delegate.version(p.version)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -52,4 +62,4 @@ public class MavenBomTask extends DefaultTask {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -47,7 +47,7 @@ public class ServiceAuthenticationDetailsSource implements
|
|||||||
// ===================================================================================================
|
// ===================================================================================================
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an implementation that uses the specified ServiceProperites and the default
|
* Creates an implementation that uses the specified ServiceProperties and the default
|
||||||
* CAS artifactParameterName.
|
* CAS artifactParameterName.
|
||||||
*
|
*
|
||||||
* @param serviceProperties The ServiceProperties to use to construct the serviceUrl.
|
* @param serviceProperties The ServiceProperties to use to construct the serviceUrl.
|
||||||
|
|||||||
+4
@@ -16,8 +16,10 @@
|
|||||||
package org.springframework.security.config.annotation.configuration;
|
package org.springframework.security.config.annotation.configuration;
|
||||||
|
|
||||||
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
|
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
|
||||||
|
import org.springframework.beans.factory.config.BeanDefinition;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.context.annotation.Role;
|
||||||
import org.springframework.security.config.annotation.ObjectPostProcessor;
|
import org.springframework.security.config.annotation.ObjectPostProcessor;
|
||||||
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
|
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
|
||||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||||
@@ -34,9 +36,11 @@ import org.springframework.security.config.annotation.web.configuration.EnableWe
|
|||||||
* @since 3.2
|
* @since 3.2
|
||||||
*/
|
*/
|
||||||
@Configuration
|
@Configuration
|
||||||
|
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||||
public class ObjectPostProcessorConfiguration {
|
public class ObjectPostProcessorConfiguration {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
|
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||||
public ObjectPostProcessor<Object> objectPostProcessor(
|
public ObjectPostProcessor<Object> objectPostProcessor(
|
||||||
AutowireCapableBeanFactory beanFactory) {
|
AutowireCapableBeanFactory beanFactory) {
|
||||||
return new AutowireBeanFactoryObjectPostProcessor(beanFactory);
|
return new AutowireBeanFactoryObjectPostProcessor(beanFactory);
|
||||||
|
|||||||
+3
@@ -28,8 +28,10 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
import org.springframework.context.annotation.AdviceMode;
|
import org.springframework.context.annotation.AdviceMode;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.beans.factory.config.BeanDefinition;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.context.annotation.ImportAware;
|
import org.springframework.context.annotation.ImportAware;
|
||||||
|
import org.springframework.context.annotation.Role;
|
||||||
import org.springframework.core.annotation.AnnotationAttributes;
|
import org.springframework.core.annotation.AnnotationAttributes;
|
||||||
import org.springframework.core.annotation.AnnotationUtils;
|
import org.springframework.core.annotation.AnnotationUtils;
|
||||||
import org.springframework.core.type.AnnotationMetadata;
|
import org.springframework.core.type.AnnotationMetadata;
|
||||||
@@ -80,6 +82,7 @@ import org.springframework.util.Assert;
|
|||||||
* @see EnableGlobalMethodSecurity
|
* @see EnableGlobalMethodSecurity
|
||||||
*/
|
*/
|
||||||
@Configuration
|
@Configuration
|
||||||
|
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||||
public class GlobalMethodSecurityConfiguration
|
public class GlobalMethodSecurityConfiguration
|
||||||
implements ImportAware, SmartInitializingSingleton {
|
implements ImportAware, SmartInitializingSingleton {
|
||||||
private static final Log logger = LogFactory
|
private static final Log logger = LogFactory
|
||||||
|
|||||||
+4
@@ -15,14 +15,18 @@
|
|||||||
*/
|
*/
|
||||||
package org.springframework.security.config.annotation.method.configuration;
|
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.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.context.annotation.Role;
|
||||||
import org.springframework.security.access.annotation.Jsr250MethodSecurityMetadataSource;
|
import org.springframework.security.access.annotation.Jsr250MethodSecurityMetadataSource;
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
|
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||||
class Jsr250MetadataSourceConfiguration {
|
class Jsr250MetadataSourceConfiguration {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
|
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||||
public Jsr250MethodSecurityMetadataSource jsr250MethodSecurityMetadataSource() {
|
public Jsr250MethodSecurityMetadataSource jsr250MethodSecurityMetadataSource() {
|
||||||
return new Jsr250MethodSecurityMetadataSource();
|
return new Jsr250MethodSecurityMetadataSource();
|
||||||
}
|
}
|
||||||
|
|||||||
+11
@@ -325,6 +325,13 @@ public abstract class WebSecurityConfigurerAdapter implements
|
|||||||
/**
|
/**
|
||||||
* Override this method to configure {@link WebSecurity}. For example, if you wish to
|
* Override this method to configure {@link WebSecurity}. For example, if you wish to
|
||||||
* ignore certain requests.
|
* ignore certain requests.
|
||||||
|
*
|
||||||
|
* Endpoints specified in this method will be ignored by Spring Security, meaning it
|
||||||
|
* will not protect them from CSRF, XSS, Clickjacking, and so on.
|
||||||
|
*
|
||||||
|
* Instead, if you want to protect endpoints against common vulnerabilities, then see
|
||||||
|
* {@link #configure(HttpSecurity)} and the {@link HttpSecurity#authorizeRequests}
|
||||||
|
* configuration method.
|
||||||
*/
|
*/
|
||||||
public void configure(WebSecurity web) throws Exception {
|
public void configure(WebSecurity web) throws Exception {
|
||||||
}
|
}
|
||||||
@@ -338,6 +345,10 @@ public abstract class WebSecurityConfigurerAdapter implements
|
|||||||
* http.authorizeRequests().anyRequest().authenticated().and().formLogin().and().httpBasic();
|
* http.authorizeRequests().anyRequest().authenticated().and().formLogin().and().httpBasic();
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
|
* Any endpoint that requires defense against common vulnerabilities can be specified here, including public ones.
|
||||||
|
* See {@link HttpSecurity#authorizeRequests} and the `permitAll()` authorization rule
|
||||||
|
* for more details on public endpoints.
|
||||||
|
*
|
||||||
* @param http the {@link HttpSecurity} to modify
|
* @param http the {@link HttpSecurity} to modify
|
||||||
* @throws Exception if an error occurs
|
* @throws Exception if an error occurs
|
||||||
*/
|
*/
|
||||||
|
|||||||
+1
-1
@@ -162,7 +162,7 @@ public abstract class AbstractAuthenticationFilterConfigurer<B extends HttpSecur
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Specifies the {@link AuthenticationSuccessHandler} to be used. The default is
|
* Specifies the {@link AuthenticationSuccessHandler} to be used. The default is
|
||||||
* {@link SavedRequestAwareAuthenticationSuccessHandler} with no additional properites
|
* {@link SavedRequestAwareAuthenticationSuccessHandler} with no additional properties
|
||||||
* set.
|
* set.
|
||||||
*
|
*
|
||||||
* @param successHandler the {@link AuthenticationSuccessHandler}.
|
* @param successHandler the {@link AuthenticationSuccessHandler}.
|
||||||
|
|||||||
+1
-1
@@ -160,7 +160,7 @@ public class HeadersConfigurer<H extends HttpSecurityBuilder<H>> extends
|
|||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* Allows customizing the {@link XXssProtectionHeaderWriter} which adds the <a href=
|
* Allows customizing the {@link XXssProtectionHeaderWriter} which adds the <a href=
|
||||||
* "https://blogs.msdn.com/b/ieinternals/archive/2011/01/31/controlling-the-internet-explorer-xss-filter-with-the-x-xss-protection-http-header.aspx"
|
* "https://web.archive.org/web/20160201174302/https://blogs.msdn.com/b/ieinternals/archive/2011/01/31/controlling-the-internet-explorer-xss-filter-with-the-x-xss-protection-http-header.aspx"
|
||||||
* >X-XSS-Protection header</a>
|
* >X-XSS-Protection header</a>
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
|
|||||||
+1
-1
@@ -129,7 +129,7 @@ import org.springframework.util.Assert;
|
|||||||
* </property>
|
* </property>
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* A configuration note: The JaasAuthenticationProvider uses the security properites
|
* A configuration note: The JaasAuthenticationProvider uses the security properties
|
||||||
* "login.config.url.X" to configure jaas. If you would like to customize the way Jaas
|
* "login.config.url.X" to configure jaas. If you would like to customize the way Jaas
|
||||||
* gets configured, create a subclass of this and override the
|
* gets configured, create a subclass of this and override the
|
||||||
* {@link #configureJaas(Resource)} method.
|
* {@link #configureJaas(Resource)} method.
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ public class SpringSecurityCoreVersion {
|
|||||||
*/
|
*/
|
||||||
public static final long SERIAL_VERSION_UID = 420L;
|
public static final long SERIAL_VERSION_UID = 420L;
|
||||||
|
|
||||||
static final String MIN_SPRING_VERSION = "4.3.23.RELEASE";
|
static final String MIN_SPRING_VERSION = "4.3.30.RELEASE";
|
||||||
|
|
||||||
static {
|
static {
|
||||||
performVersionChecks();
|
performVersionChecks();
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ DigestAuthenticationFilter.usernameNotFound=Username {0} not found
|
|||||||
JdbcDaoImpl.noAuthority=User {0} has no GrantedAuthority
|
JdbcDaoImpl.noAuthority=User {0} has no GrantedAuthority
|
||||||
JdbcDaoImpl.notFound=User {0} not found
|
JdbcDaoImpl.notFound=User {0} not found
|
||||||
LdapAuthenticationProvider.badCredentials=Bad credentials
|
LdapAuthenticationProvider.badCredentials=Bad credentials
|
||||||
|
LdapAuthenticationProvider.badLdapConnection=Connection to LDAP server failed
|
||||||
LdapAuthenticationProvider.credentialsExpired=User credentials have expired
|
LdapAuthenticationProvider.credentialsExpired=User credentials have expired
|
||||||
LdapAuthenticationProvider.disabled=User is disabled
|
LdapAuthenticationProvider.disabled=User is disabled
|
||||||
LdapAuthenticationProvider.expired=User account has expired
|
LdapAuthenticationProvider.expired=User account has expired
|
||||||
|
|||||||
+8
@@ -65,6 +65,10 @@ public class BCryptPasswordEncoder implements PasswordEncoder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String encode(CharSequence rawPassword) {
|
public String encode(CharSequence rawPassword) {
|
||||||
|
if (rawPassword == null) {
|
||||||
|
throw new IllegalArgumentException("rawPassword cannot be null");
|
||||||
|
}
|
||||||
|
|
||||||
String salt;
|
String salt;
|
||||||
if (strength > 0) {
|
if (strength > 0) {
|
||||||
if (random != null) {
|
if (random != null) {
|
||||||
@@ -81,6 +85,10 @@ public class BCryptPasswordEncoder implements PasswordEncoder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean matches(CharSequence rawPassword, String encodedPassword) {
|
public boolean matches(CharSequence rawPassword, String encodedPassword) {
|
||||||
|
if (rawPassword == null) {
|
||||||
|
throw new IllegalArgumentException("rawPassword cannot be null");
|
||||||
|
}
|
||||||
|
|
||||||
if (encodedPassword == null || encodedPassword.length() == 0) {
|
if (encodedPassword == null || encodedPassword.length() == 0) {
|
||||||
logger.warn("Empty encoded password");
|
logger.warn("Empty encoded password");
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2011-2016 the original author or authors.
|
* Copyright 2011-2020 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -32,16 +32,13 @@ public class Encryptors {
|
|||||||
* (Password-Based Key Derivation Function #2). Salts the password to prevent
|
* (Password-Based Key Derivation Function #2). Salts the password to prevent
|
||||||
* dictionary attacks against the key. The provided salt is expected to be
|
* dictionary attacks against the key. The provided salt is expected to be
|
||||||
* hex-encoded; it should be random and at least 8 bytes in length. Also applies a
|
* hex-encoded; it should be random and at least 8 bytes in length. Also applies a
|
||||||
* random 16 byte initialization vector to ensure each encrypted message will be
|
* random 16-byte initialization vector to ensure each encrypted message will be
|
||||||
* unique. Requires Java 6.
|
* unique. Requires Java 6.
|
||||||
*
|
*
|
||||||
* @param password the password used to generate the encryptor's secret key; should
|
* @param password the password used to generate the encryptor's secret key; should
|
||||||
* not be shared
|
* not be shared
|
||||||
* @param salt a hex-encoded, random, site-global salt value to use to generate the
|
* @param salt a hex-encoded, random, site-global salt value to use to generate the
|
||||||
* key
|
* key
|
||||||
*
|
|
||||||
* @see #standard(CharSequence, CharSequence) which uses the slightly weaker CBC mode
|
|
||||||
* (instead of GCM)
|
|
||||||
*/
|
*/
|
||||||
public static BytesEncryptor stronger(CharSequence password, CharSequence salt) {
|
public static BytesEncryptor stronger(CharSequence password, CharSequence salt) {
|
||||||
return new AesBytesEncryptor(password.toString(), salt,
|
return new AesBytesEncryptor(password.toString(), salt,
|
||||||
@@ -53,13 +50,21 @@ public class Encryptors {
|
|||||||
* Derives the secret key using PKCS #5's PBKDF2 (Password-Based Key Derivation
|
* Derives the secret key using PKCS #5's PBKDF2 (Password-Based Key Derivation
|
||||||
* Function #2). Salts the password to prevent dictionary attacks against the key. The
|
* Function #2). Salts the password to prevent dictionary attacks against the key. The
|
||||||
* provided salt is expected to be hex-encoded; it should be random and at least 8
|
* provided salt is expected to be hex-encoded; it should be random and at least 8
|
||||||
* bytes in length. Also applies a random 16 byte initialization vector to ensure each
|
* bytes in length. Also applies a random 16-byte initialization vector to ensure each
|
||||||
* encrypted message will be unique. Requires Java 6.
|
* encrypted message will be unique. Requires Java 6.
|
||||||
|
* NOTE: This mode is not
|
||||||
|
* <a href="https://en.wikipedia.org/wiki/Authenticated_encryption">authenticated</a>
|
||||||
|
* and does not provide any guarantees about the authenticity of the data.
|
||||||
|
* For a more secure alternative, users should prefer
|
||||||
|
* {@link #stronger(CharSequence, CharSequence)}.
|
||||||
*
|
*
|
||||||
* @param password the password used to generate the encryptor's secret key; should
|
* @param password the password used to generate the encryptor's secret key; should
|
||||||
* not be shared
|
* not be shared
|
||||||
* @param salt a hex-encoded, random, site-global salt value to use to generate the
|
* @param salt a hex-encoded, random, site-global salt value to use to generate the
|
||||||
* key
|
* key
|
||||||
|
*
|
||||||
|
* @see #stronger(CharSequence, CharSequence), which uses the significatly more secure
|
||||||
|
* GCM (instead of CBC)
|
||||||
*/
|
*/
|
||||||
public static BytesEncryptor standard(CharSequence password, CharSequence salt) {
|
public static BytesEncryptor standard(CharSequence password, CharSequence salt) {
|
||||||
return new AesBytesEncryptor(password.toString(), salt,
|
return new AesBytesEncryptor(password.toString(), salt,
|
||||||
@@ -100,7 +105,10 @@ public class Encryptors {
|
|||||||
* not be shared
|
* not be shared
|
||||||
* @param salt a hex-encoded, random, site-global salt value to use to generate the
|
* @param salt a hex-encoded, random, site-global salt value to use to generate the
|
||||||
* secret key
|
* secret key
|
||||||
|
* @deprecated This encryptor is not secure. Instead, look to your data store for a
|
||||||
|
* mechanism to query encrypted data.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public static TextEncryptor queryableText(CharSequence password, CharSequence salt) {
|
public static TextEncryptor queryableText(CharSequence password, CharSequence salt) {
|
||||||
return new HexEncodingTextEncryptor(new AesBytesEncryptor(password.toString(),
|
return new HexEncodingTextEncryptor(new AesBytesEncryptor(password.toString(),
|
||||||
salt));
|
salt));
|
||||||
|
|||||||
+2
-1
@@ -26,7 +26,8 @@ package org.springframework.security.crypto.password;
|
|||||||
* @deprecated This PasswordEncoder is not secure. Instead use an
|
* @deprecated This PasswordEncoder is not secure. Instead use an
|
||||||
* adaptive one way function like BCryptPasswordEncoder, Pbkdf2PasswordEncoder, or
|
* adaptive one way function like BCryptPasswordEncoder, Pbkdf2PasswordEncoder, or
|
||||||
* SCryptPasswordEncoder. Even better use {@link DelegatingPasswordEncoder} which supports
|
* SCryptPasswordEncoder. Even better use {@link DelegatingPasswordEncoder} which supports
|
||||||
* password upgrades.
|
* password upgrades. There are no plans to remove this support. It is deprecated to indicate that
|
||||||
|
* this is a legacy implementation and using it is considered insecure.
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public final class NoOpPasswordEncoder implements PasswordEncoder {
|
public final class NoOpPasswordEncoder implements PasswordEncoder {
|
||||||
|
|||||||
+11
@@ -92,4 +92,15 @@ public class BCryptPasswordEncoderTests {
|
|||||||
assertThat(encoder.matches("password", "012345678901234567890123456789")).isFalse();
|
assertThat(encoder.matches("password", "012345678901234567890123456789")).isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test(expected = IllegalArgumentException.class)
|
||||||
|
public void encodeNullRawPassword() {
|
||||||
|
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
|
||||||
|
encoder.encode(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IllegalArgumentException.class)
|
||||||
|
public void matchNullRawPassword() {
|
||||||
|
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
|
||||||
|
encoder.matches(null, "does-not-matter");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
// Docbook and Javadoc building and uploading tasks
|
// Docbook and Javadoc building and uploading tasks
|
||||||
apply plugin: 'base'
|
apply plugin: 'base'
|
||||||
|
apply from: "$rootDir/gradle/deploy-docs.gradle"
|
||||||
|
apply from: "$rootDir/gradle/deploy-schema.gradle"
|
||||||
|
|
||||||
task docs {
|
task docs {
|
||||||
dependsOn 'manual:reference', 'apidocs', 'guides:asciidoctor'
|
dependsOn 'manual:reference', 'apidocs', 'guides:asciidoctor'
|
||||||
@@ -152,6 +154,7 @@ task schemaZip(type: Zip) {
|
|||||||
}
|
}
|
||||||
assert xsdFile != null
|
assert xsdFile != null
|
||||||
into (shortName) {
|
into (shortName) {
|
||||||
|
duplicatesStrategy 'exclude'
|
||||||
from xsdFile.path
|
from xsdFile.path
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6671,14 +6671,17 @@ The Encryptors class provides factory methods for constructing symmetric encrypt
|
|||||||
|
|
||||||
[[spring-security-crypto-encryption-bytes]]
|
[[spring-security-crypto-encryption-bytes]]
|
||||||
==== BytesEncryptor
|
==== BytesEncryptor
|
||||||
Use the Encryptors.standard factory method to construct a "standard" BytesEncryptor:
|
Use the `Encryptors.stronger` factory method to construct a BytesEncryptor:
|
||||||
|
|
||||||
[source,java]
|
[source,java]
|
||||||
----
|
----
|
||||||
Encryptors.standard("password", "salt");
|
Encryptors.stronger("password", "salt");
|
||||||
----
|
----
|
||||||
|
|
||||||
The "standard" encryption method is 256-bit AES using PKCS #5's PBKDF2 (Password-Based Key Derivation Function #2). This method requires Java 6. The password used to generate the SecretKey should be kept in a secure place and not be shared. The salt is used to prevent dictionary attacks against the key in the event your encrypted data is compromised. A 16-byte random initialization vector is also applied so each encrypted message is unique.
|
The "stronger" encryption method creates an encryptor using 256 bit AES encryption with
|
||||||
|
Galois Counter Mode (GCM).
|
||||||
|
It derives the secret key using PKCS #5's PBKDF2 (Password-Based Key Derivation Function #2).
|
||||||
|
This method requires Java 6. The password used to generate the SecretKey should be kept in a secure place and not be shared. The salt is used to prevent dictionary attacks against the key in the event your encrypted data is compromised. A 16-byte random initialization vector is also applied so each encrypted message is unique.
|
||||||
|
|
||||||
The provided salt should be in hex-encoded String form, be random, and be at least 8 bytes in length. Such a salt may be generated using a KeyGenerator:
|
The provided salt should be in hex-encoded String form, be random, and be at least 8 bytes in length. Such a salt may be generated using a KeyGenerator:
|
||||||
|
|
||||||
@@ -6687,6 +6690,11 @@ The provided salt should be in hex-encoded String form, be random, and be at lea
|
|||||||
String salt = KeyGenerators.string().generateKey(); // generates a random 8-byte salt that is then hex-encoded
|
String salt = KeyGenerators.string().generateKey(); // generates a random 8-byte salt that is then hex-encoded
|
||||||
----
|
----
|
||||||
|
|
||||||
|
Users may also use the `standard` encryption method, which is 256-bit AES in Cipher Block Chaining (CBC) Mode.
|
||||||
|
This mode is not https://en.wikipedia.org/wiki/Authenticated_encryption[authenticated] and does not provide any
|
||||||
|
guarantees about the authenticity of the data.
|
||||||
|
For a more secure alternative, users should prefer `Encryptors.stronger`.
|
||||||
|
|
||||||
[[spring-security-crypto-encryption-text]]
|
[[spring-security-crypto-encryption-text]]
|
||||||
==== TextEncryptor
|
==== TextEncryptor
|
||||||
Use the Encryptors.text factory method to construct a standard TextEncryptor:
|
Use the Encryptors.text factory method to construct a standard TextEncryptor:
|
||||||
|
|||||||
+3
-1
@@ -1 +1,3 @@
|
|||||||
version=4.2.13.RELEASE
|
version=4.2.20.RELEASE
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
apply plugin: "com.jfrog.artifactory"
|
||||||
|
|
||||||
|
def isSnapshot = version?.matches(/^.*[.-]BUILD-SNAPSHOT$/)
|
||||||
|
|
||||||
|
artifactory {
|
||||||
|
contextUrl = 'https://repo.spring.io'
|
||||||
|
publish {
|
||||||
|
repository {
|
||||||
|
repoKey = isSnapshot ? 'libs-snapshot-local' : 'libs-release-local'
|
||||||
|
if(project.hasProperty('artifactoryUsername')) {
|
||||||
|
username = artifactoryUsername
|
||||||
|
password = artifactoryPassword
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
artifactoryPublish {
|
||||||
|
publishConfigs 'archives'
|
||||||
|
publishIvy false
|
||||||
|
properties = [
|
||||||
|
'bintray.package': "${project.group}:spring-security",
|
||||||
|
'bintray.version': "${project.version}"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
artifactory {
|
||||||
|
publish {
|
||||||
|
defaults {
|
||||||
|
publishConfigs('archives')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
def isSnapshot = version?.matches(/^.*[.-]BUILD-SNAPSHOT$/)
|
||||||
|
|
||||||
|
task deployArtifacts {
|
||||||
|
group = 'Deploy tasks'
|
||||||
|
description = "Deploys the artifacts to either Artifactory or Maven Central"
|
||||||
|
if(isSnapshot) {
|
||||||
|
dependsOn "artifactoryPublish"
|
||||||
|
} else {
|
||||||
|
dependsOn "uploadArchives"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
apply plugin: 'org.hidetake.ssh'
|
||||||
|
|
||||||
|
project.ssh.settings {
|
||||||
|
knownHosts = allowAnyHosts
|
||||||
|
}
|
||||||
|
|
||||||
|
project.remotes {
|
||||||
|
docs {
|
||||||
|
role 'docs'
|
||||||
|
host = 'docs.af.pivotal.io'
|
||||||
|
user = project.findProperty('deployDocsSshUsername')
|
||||||
|
if(project.hasProperty('deployDocsSshKeyPath')) {
|
||||||
|
identity = project.file(project.findProperty('deployDocsSshKeyPath'))
|
||||||
|
}
|
||||||
|
if(project.hasProperty('deployDocsSshPassphrase')) {
|
||||||
|
passphrase = project.findProperty('deployDocsSshPassphrase')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
project.task('deployDocs') {
|
||||||
|
dependsOn 'docsZip'
|
||||||
|
doFirst {
|
||||||
|
project.ssh.run {
|
||||||
|
session(project.remotes.docs) {
|
||||||
|
def now = System.currentTimeMillis()
|
||||||
|
def name = project.rootProject.name
|
||||||
|
def version = project.rootProject.version
|
||||||
|
def tempPath = "/tmp/${name}-${now}-docs".replaceAll(' ', '_')
|
||||||
|
execute "mkdir -p $tempPath"
|
||||||
|
|
||||||
|
project.tasks.docsZip.outputs.each { o ->
|
||||||
|
put from: o.files, into: tempPath
|
||||||
|
}
|
||||||
|
|
||||||
|
execute "unzip $tempPath/*.zip -d $tempPath"
|
||||||
|
|
||||||
|
def extractPath = "/var/www/domains/springsource.org/www/htdocs/autorepo/docs/${name}/${version}/"
|
||||||
|
|
||||||
|
execute "rm -rf $extractPath"
|
||||||
|
execute "mkdir -p $extractPath"
|
||||||
|
execute "mv $tempPath/* $extractPath"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
apply plugin: 'org.hidetake.ssh'
|
||||||
|
|
||||||
|
project.ssh.settings {
|
||||||
|
knownHosts = allowAnyHosts
|
||||||
|
}
|
||||||
|
|
||||||
|
project.remotes {
|
||||||
|
docs {
|
||||||
|
role 'docs'
|
||||||
|
host = 'docs.af.pivotal.io'
|
||||||
|
user = project.findProperty('deployDocsSshUsername')
|
||||||
|
if(project.hasProperty('deployDocsSshKeyPath')) {
|
||||||
|
identity = project.file(project.findProperty('deployDocsSshKeyPath'))
|
||||||
|
}
|
||||||
|
if(project.hasProperty('deployDocsSshPassphrase')) {
|
||||||
|
passphrase = project.findProperty('deployDocsSshPassphrase')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
project.task('deploySchema') {
|
||||||
|
dependsOn 'schemaZip'
|
||||||
|
doFirst {
|
||||||
|
project.ssh.run {
|
||||||
|
session(project.remotes.docs) {
|
||||||
|
def now = System.currentTimeMillis()
|
||||||
|
def name = project.rootProject.name
|
||||||
|
def version = project.rootProject.version
|
||||||
|
def tempPath = "/tmp/${name}-${now}-schema".replaceAll(' ', '_')
|
||||||
|
|
||||||
|
execute "mkdir -p $tempPath"
|
||||||
|
|
||||||
|
project.tasks.schemaZip.outputs.each { o ->
|
||||||
|
println "Putting $o.files"
|
||||||
|
put from: o.files, into: tempPath
|
||||||
|
}
|
||||||
|
|
||||||
|
execute "unzip $tempPath/*.zip -d $tempPath"
|
||||||
|
|
||||||
|
def extractPath = "/var/www/domains/springsource.org/www/htdocs/autorepo/schema/${name}/${version}/"
|
||||||
|
|
||||||
|
execute "rm -rf $extractPath"
|
||||||
|
execute "mkdir -p $extractPath"
|
||||||
|
execute "rm -f $tempPath*.zip"
|
||||||
|
execute "rm -rf $extractPath*"
|
||||||
|
execute "mv $tempPath/* $extractPath"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
def isSnapshot = version?.matches(/^.*[.-]BUILD-SNAPSHOT$/)
|
||||||
|
def isRelease = !isSnapshot
|
||||||
|
|
||||||
|
task finalizeDeployArtifacts {
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isRelease && project.hasProperty("ossrhUsername")) {
|
||||||
|
project.ext.nexusUsername = project.ossrhUsername
|
||||||
|
project.ext.nexusPassword = project.ossrhPassword
|
||||||
|
project.getPluginManager().apply("io.codearte.nexus-staging")
|
||||||
|
finalizeDeployArtifacts.dependsOn project.tasks.closeAndReleaseRepository
|
||||||
|
project.nexusStaging.packageGroup = 'org.springframework'
|
||||||
|
}
|
||||||
+10
-10
@@ -11,17 +11,17 @@ targetCompatibility = 1.6
|
|||||||
ext.apacheDsVersion = '1.5.5'
|
ext.apacheDsVersion = '1.5.5'
|
||||||
ext.aspectjVersion = '1.8.14'
|
ext.aspectjVersion = '1.8.14'
|
||||||
ext.casClientVersion = '3.4.1'
|
ext.casClientVersion = '3.4.1'
|
||||||
ext.cglibVersion = '3.2.10'
|
ext.cglibVersion = '3.2.12'
|
||||||
ext.commonsCodecVersion = '1.12'
|
ext.commonsCodecVersion = '1.12'
|
||||||
ext.commonsCollectionsVersion = '3.2.2'
|
ext.commonsCollectionsVersion = '3.2.2'
|
||||||
ext.commonsLoggingVersion = '1.2'
|
ext.commonsLoggingVersion = '1.2'
|
||||||
ext.ehcacheVersion = '2.10.6'
|
ext.ehcacheVersion = '2.10.6'
|
||||||
ext.gebVersion = '0.10.0'
|
ext.gebVersion = '0.10.0'
|
||||||
ext.groovyVersion = '2.4.4'
|
ext.groovyVersion = '2.4.19'
|
||||||
ext.hsqlVersion = '2.3.6'
|
ext.hsqlVersion = '2.3.6'
|
||||||
ext.hibernateVersion = '5.0.12.Final'
|
ext.hibernateVersion = '5.0.12.Final'
|
||||||
ext.hibernateValidatorVersion = '5.3.6.Final'
|
ext.hibernateValidatorVersion = '5.3.6.Final'
|
||||||
ext.jacksonDatabindVersion = '2.8.11.3'
|
ext.jacksonDatabindVersion = '2.8.11.6'
|
||||||
ext.javaPersistenceVersion = '2.1.1'
|
ext.javaPersistenceVersion = '2.1.1'
|
||||||
ext.jettyVersion = '6.1.26'
|
ext.jettyVersion = '6.1.26'
|
||||||
ext.jstlVersion = '1.2.2'
|
ext.jstlVersion = '1.2.2'
|
||||||
@@ -32,12 +32,12 @@ ext.seleniumVersion = '2.44.0'
|
|||||||
ext.servletApiVersion = '3.1.0'
|
ext.servletApiVersion = '3.1.0'
|
||||||
ext.slf4jVersion = '1.7.25'
|
ext.slf4jVersion = '1.7.25'
|
||||||
ext.spockVersion = '0.7-groovy-2.0'
|
ext.spockVersion = '0.7-groovy-2.0'
|
||||||
ext.springDataCommonsVersion = '1.13.20.RELEASE'
|
ext.springDataCommonsVersion = '1.13.23.RELEASE'
|
||||||
ext.springDataJpaVersion = '1.11.20.RELEASE'
|
ext.springDataJpaVersion = '1.11.23.RELEASE'
|
||||||
ext.springDataRedisVersion = '1.8.20.RELEASE'
|
ext.springDataRedisVersion = '1.8.23.RELEASE'
|
||||||
ext.springSessionVersion = '1.3.4.RELEASE'
|
ext.springSessionVersion = '1.3.5.RELEASE'
|
||||||
ext.springBootVersion = '1.5.16.RELEASE'
|
ext.springBootVersion = '1.5.22.RELEASE'
|
||||||
ext.thymeleafVersion = '3.0.9.RELEASE'
|
ext.thymeleafVersion = '3.0.11.RELEASE'
|
||||||
ext.jsonassertVersion = '1.4.0'
|
ext.jsonassertVersion = '1.4.0'
|
||||||
ext.validationApiVersion = '1.1.0.Final'
|
ext.validationApiVersion = '1.1.0.Final'
|
||||||
|
|
||||||
@@ -77,7 +77,7 @@ ext.springCoreDependency = [
|
|||||||
|
|
||||||
ext.jstlDependencies = [
|
ext.jstlDependencies = [
|
||||||
"javax.servlet.jsp.jstl:javax.servlet.jsp.jstl-api:$jstlVersion",
|
"javax.servlet.jsp.jstl:javax.servlet.jsp.jstl-api:$jstlVersion",
|
||||||
"org.apache.taglibs:taglibs-standard-jstlel:1.2.1"
|
"org.apache.taglibs:taglibs-standard-jstlel:1.2.5"
|
||||||
]
|
]
|
||||||
|
|
||||||
ext.apachedsDependencies = [
|
ext.apachedsDependencies = [
|
||||||
|
|||||||
@@ -25,6 +25,12 @@ install {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uploadArchives {
|
||||||
|
repositories.mavenDeployer {
|
||||||
|
customizePom(pom, project)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
def customizePom(pom, gradleProject) {
|
def customizePom(pom, gradleProject) {
|
||||||
pom.whenConfigured { p ->
|
pom.whenConfigured { p ->
|
||||||
p.dependencies.findAll{ it.scope == "optional" }.each {
|
p.dependencies.findAll{ it.scope == "optional" }.each {
|
||||||
@@ -71,19 +77,6 @@ def customizePom(pom, gradleProject) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Exclude spring-framework-bom for sample Boot projects since spring-boot-starter-parent imports spring-framework-bom
|
// Exclude spring-framework-bom for sample Boot projects since spring-boot-starter-parent imports spring-framework-bom
|
||||||
if(!gradleProject.name.endsWith('-bom') && !sampleBootProjects.contains(gradleProject)) {
|
|
||||||
dependencyManagement {
|
|
||||||
dependencies {
|
|
||||||
dependency {
|
|
||||||
groupId 'org.springframework'
|
|
||||||
artifactId 'spring-framework-bom'
|
|
||||||
version project.springVersion
|
|
||||||
type 'pom'
|
|
||||||
scope 'import'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(isWar) {
|
if(isWar) {
|
||||||
properties {
|
properties {
|
||||||
'm2eclipse.wtp.contextRoot' '/' + project.war.baseName
|
'm2eclipse.wtp.contextRoot' '/' + project.war.baseName
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
def isSnapshot = version?.matches(/^.*[.-]BUILD-SNAPSHOT$/)
|
||||||
|
def isRelease = !isSnapshot
|
||||||
|
|
||||||
|
if(project.hasProperty("signing.keyId") && isRelease) {
|
||||||
|
apply plugin: "signing"
|
||||||
|
sign(project)
|
||||||
|
}
|
||||||
|
|
||||||
|
if(project.hasProperty('ossrhUsername')) {
|
||||||
|
uploadArchives {
|
||||||
|
repositories {
|
||||||
|
mavenDeployer {
|
||||||
|
repository(url: "https://oss.sonatype.org/service/local/staging/deploy/maven2/") {
|
||||||
|
authentication(userName: project.ossrhUsername, password: project.ossrhPassword)
|
||||||
|
}
|
||||||
|
|
||||||
|
snapshotRepository(url: "https://oss.sonatype.org/content/repositories/snapshots/") {
|
||||||
|
authentication(userName: project.ossrhUsername, password: project.ossrhPassword)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def sign(Project project) {
|
||||||
|
project.install {
|
||||||
|
repositories {
|
||||||
|
mavenDeployer {
|
||||||
|
beforeDeployment { MavenDeployment deployment -> project.signing.signPom(deployment) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
project.uploadArchives {
|
||||||
|
repositories {
|
||||||
|
mavenDeployer {
|
||||||
|
beforeDeployment { MavenDeployment deployment -> project.signing.signPom(deployment) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
project.signing {
|
||||||
|
required { project.gradle.taskGraph.hasTask("uploadArchives") }
|
||||||
|
sign project.configurations.archives
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,7 +10,7 @@ buildscript {
|
|||||||
apply plugin: 'com.bmuschko.tomcat'
|
apply plugin: 'com.bmuschko.tomcat'
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
def tomcatVersion = '7.0.90'
|
def tomcatVersion = '7.0.103'
|
||||||
tomcat "org.apache.tomcat.embed:tomcat-embed-core:${tomcatVersion}",
|
tomcat "org.apache.tomcat.embed:tomcat-embed-core:${tomcatVersion}",
|
||||||
"org.apache.tomcat.embed:tomcat-embed-logging-juli:${tomcatVersion}",
|
"org.apache.tomcat.embed:tomcat-embed-logging-juli:${tomcatVersion}",
|
||||||
"org.apache.tomcat.embed:tomcat-embed-websocket:${tomcatVersion}",
|
"org.apache.tomcat.embed:tomcat-embed-websocket:${tomcatVersion}",
|
||||||
|
|||||||
+17
-4
@@ -16,6 +16,7 @@
|
|||||||
package org.springframework.security.ldap.authentication.ad;
|
package org.springframework.security.ldap.authentication.ad;
|
||||||
|
|
||||||
import org.springframework.dao.IncorrectResultSizeDataAccessException;
|
import org.springframework.dao.IncorrectResultSizeDataAccessException;
|
||||||
|
import org.springframework.ldap.CommunicationException;
|
||||||
import org.springframework.ldap.core.DirContextOperations;
|
import org.springframework.ldap.core.DirContextOperations;
|
||||||
import org.springframework.ldap.core.DistinguishedName;
|
import org.springframework.ldap.core.DistinguishedName;
|
||||||
import org.springframework.ldap.core.support.DefaultDirObjectFactory;
|
import org.springframework.ldap.core.support.DefaultDirObjectFactory;
|
||||||
@@ -24,6 +25,7 @@ import org.springframework.security.authentication.AccountExpiredException;
|
|||||||
import org.springframework.security.authentication.BadCredentialsException;
|
import org.springframework.security.authentication.BadCredentialsException;
|
||||||
import org.springframework.security.authentication.CredentialsExpiredException;
|
import org.springframework.security.authentication.CredentialsExpiredException;
|
||||||
import org.springframework.security.authentication.DisabledException;
|
import org.springframework.security.authentication.DisabledException;
|
||||||
|
import org.springframework.security.authentication.InternalAuthenticationServiceException;
|
||||||
import org.springframework.security.authentication.LockedException;
|
import org.springframework.security.authentication.LockedException;
|
||||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||||
import org.springframework.security.core.GrantedAuthority;
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
@@ -140,12 +142,15 @@ public final class ActiveDirectoryLdapAuthenticationProvider extends
|
|||||||
UsernamePasswordAuthenticationToken auth) {
|
UsernamePasswordAuthenticationToken auth) {
|
||||||
String username = auth.getName();
|
String username = auth.getName();
|
||||||
String password = (String) auth.getCredentials();
|
String password = (String) auth.getCredentials();
|
||||||
|
DirContext ctx = null;
|
||||||
DirContext ctx = bindAsUser(username, password);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
ctx = bindAsUser(username, password);
|
||||||
return searchForUser(ctx, username);
|
return searchForUser(ctx, username);
|
||||||
}
|
}
|
||||||
|
catch (CommunicationException e) {
|
||||||
|
throw badLdapConnection(e);
|
||||||
|
}
|
||||||
catch (NamingException e) {
|
catch (NamingException e) {
|
||||||
logger.error("Failed to locate directory entry for authenticated user: "
|
logger.error("Failed to locate directory entry for authenticated user: "
|
||||||
+ username, e);
|
+ username, e);
|
||||||
@@ -207,8 +212,7 @@ public final class ActiveDirectoryLdapAuthenticationProvider extends
|
|||||||
|| (e instanceof OperationNotSupportedException)) {
|
|| (e instanceof OperationNotSupportedException)) {
|
||||||
handleBindException(bindPrincipal, e);
|
handleBindException(bindPrincipal, e);
|
||||||
throw badCredentials(e);
|
throw badCredentials(e);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
throw LdapUtils.convertLdapException(e);
|
throw LdapUtils.convertLdapException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -300,6 +304,12 @@ public final class ActiveDirectoryLdapAuthenticationProvider extends
|
|||||||
return (BadCredentialsException) badCredentials().initCause(cause);
|
return (BadCredentialsException) badCredentials().initCause(cause);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private InternalAuthenticationServiceException badLdapConnection(Throwable cause) {
|
||||||
|
return new InternalAuthenticationServiceException(messages.getMessage(
|
||||||
|
"LdapAuthenticationProvider.badLdapConnection",
|
||||||
|
"Connection to LDAP server failed."), cause);
|
||||||
|
}
|
||||||
|
|
||||||
private DirContextOperations searchForUser(DirContext context, String username)
|
private DirContextOperations searchForUser(DirContext context, String username)
|
||||||
throws NamingException {
|
throws NamingException {
|
||||||
SearchControls searchControls = new SearchControls();
|
SearchControls searchControls = new SearchControls();
|
||||||
@@ -314,6 +324,9 @@ public final class ActiveDirectoryLdapAuthenticationProvider extends
|
|||||||
searchControls, searchRoot, searchFilter,
|
searchControls, searchRoot, searchFilter,
|
||||||
new Object[] { bindPrincipal, username });
|
new Object[] { bindPrincipal, username });
|
||||||
}
|
}
|
||||||
|
catch (CommunicationException ldapCommunicationException) {
|
||||||
|
throw badLdapConnection(ldapCommunicationException);
|
||||||
|
}
|
||||||
catch (IncorrectResultSizeDataAccessException incorrectResults) {
|
catch (IncorrectResultSizeDataAccessException incorrectResults) {
|
||||||
// Search should never return multiple results if properly configured - just
|
// Search should never return multiple results if properly configured - just
|
||||||
// rethrow
|
// rethrow
|
||||||
|
|||||||
+22
-6
@@ -32,6 +32,7 @@ import org.springframework.security.authentication.AccountExpiredException;
|
|||||||
import org.springframework.security.authentication.BadCredentialsException;
|
import org.springframework.security.authentication.BadCredentialsException;
|
||||||
import org.springframework.security.authentication.CredentialsExpiredException;
|
import org.springframework.security.authentication.CredentialsExpiredException;
|
||||||
import org.springframework.security.authentication.DisabledException;
|
import org.springframework.security.authentication.DisabledException;
|
||||||
|
import org.springframework.security.authentication.InternalAuthenticationServiceException;
|
||||||
import org.springframework.security.authentication.LockedException;
|
import org.springframework.security.authentication.LockedException;
|
||||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
@@ -58,6 +59,9 @@ import static org.springframework.security.ldap.authentication.ad.ActiveDirector
|
|||||||
* @author Rob Winch
|
* @author Rob Winch
|
||||||
*/
|
*/
|
||||||
public class ActiveDirectoryLdapAuthenticationProviderTests {
|
public class ActiveDirectoryLdapAuthenticationProviderTests {
|
||||||
|
public static final String EXISTING_LDAP_PROVIDER = "ldap://192.168.1.200/";
|
||||||
|
public static final String NON_EXISTING_LDAP_PROVIDER = "ldap://192.168.1.201/";
|
||||||
|
|
||||||
@Rule
|
@Rule
|
||||||
public ExpectedException thrown = ExpectedException.none();
|
public ExpectedException thrown = ExpectedException.none();
|
||||||
|
|
||||||
@@ -378,17 +382,29 @@ public class ActiveDirectoryLdapAuthenticationProviderTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = org.springframework.ldap.CommunicationException.class)
|
@Test(expected = org.springframework.ldap.CommunicationException.class)
|
||||||
public void nonAuthenticationExceptionIsConvertedToSpringLdapException()
|
public void nonAuthenticationExceptionIsConvertedToSpringLdapException() throws Throwable {
|
||||||
throws Exception {
|
try {
|
||||||
provider.contextFactory = createContextFactoryThrowing(new CommunicationException(
|
provider.contextFactory = createContextFactoryThrowing(new CommunicationException(
|
||||||
msg));
|
msg));
|
||||||
provider.authenticate(joe);
|
provider.authenticate(joe);
|
||||||
|
} catch (InternalAuthenticationServiceException e) {
|
||||||
|
// Since GH-8418 ldap communication exception is wrapped into InternalAuthenticationServiceException.
|
||||||
|
// This test is about the wrapped exception, so we throw it.
|
||||||
|
throw e.getCause();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = org.springframework.security.authentication.InternalAuthenticationServiceException.class )
|
||||||
|
public void connectionExceptionIsWrappedInInternalException() throws Exception {
|
||||||
|
ActiveDirectoryLdapAuthenticationProvider noneReachableProvider = new ActiveDirectoryLdapAuthenticationProvider(
|
||||||
|
"mydomain.eu", NON_EXISTING_LDAP_PROVIDER, "dc=ad,dc=eu,dc=mydomain");
|
||||||
|
noneReachableProvider.doAuthentication(joe);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void rootDnProvidedSeparatelyFromDomainAlsoWorks() throws Exception {
|
public void rootDnProvidedSeparatelyFromDomainAlsoWorks() throws Exception {
|
||||||
ActiveDirectoryLdapAuthenticationProvider provider = new ActiveDirectoryLdapAuthenticationProvider(
|
ActiveDirectoryLdapAuthenticationProvider provider = new ActiveDirectoryLdapAuthenticationProvider(
|
||||||
"mydomain.eu", "ldap://192.168.1.200/", "dc=ad,dc=eu,dc=mydomain");
|
"mydomain.eu", EXISTING_LDAP_PROVIDER, "dc=ad,dc=eu,dc=mydomain");
|
||||||
checkAuthentication("dc=ad,dc=eu,dc=mydomain", provider);
|
checkAuthentication("dc=ad,dc=eu,dc=mydomain", provider);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,6 @@ dependencies {
|
|||||||
|
|
||||||
provided "javax.servlet:javax.servlet-api:$servletApiVersion"
|
provided "javax.servlet:javax.servlet-api:$servletApiVersion"
|
||||||
|
|
||||||
runtime 'org.apache.httpcomponents:httpclient:4.2.5',
|
runtime 'org.apache.httpcomponents:httpclient:4.2.6',
|
||||||
'net.sourceforge.nekohtml:nekohtml:1.9.20'
|
'net.sourceforge.nekohtml:nekohtml:1.9.22'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ dependencies {
|
|||||||
"org.springframework:spring-core:$springVersion",
|
"org.springframework:spring-core:$springVersion",
|
||||||
"org.springframework:spring-aspects:$springVersion",
|
"org.springframework:spring-aspects:$springVersion",
|
||||||
"org.thymeleaf:thymeleaf-spring4:$thymeleafVersion",
|
"org.thymeleaf:thymeleaf-spring4:$thymeleafVersion",
|
||||||
"nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect:2.0.4",
|
"nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect:2.0.5",
|
||||||
"org.eclipse.persistence:javax.persistence:$javaPersistenceVersion"
|
"org.eclipse.persistence:javax.persistence:$javaPersistenceVersion"
|
||||||
compile("org.hibernate:hibernate-entitymanager:$hibernateVersion") {
|
compile("org.hibernate:hibernate-entitymanager:$hibernateVersion") {
|
||||||
exclude group:'javassist', module: 'javassist'
|
exclude group:'javassist', module: 'javassist'
|
||||||
|
|||||||
@@ -23,5 +23,5 @@ dependencies {
|
|||||||
runtime "opensymphony:sitemesh:2.4.2",
|
runtime "opensymphony:sitemesh:2.4.2",
|
||||||
"cglib:cglib-nodep:$cglibVersion",
|
"cglib:cglib-nodep:$cglibVersion",
|
||||||
'ch.qos.logback:logback-classic:0.9.30',
|
'ch.qos.logback:logback-classic:0.9.30',
|
||||||
"net.sourceforge.nekohtml:nekohtml:1.9.10"
|
"net.sourceforge.nekohtml:nekohtml:1.9.22"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ apply plugin: 'jetty'
|
|||||||
apply plugin: 'groovy'
|
apply plugin: 'groovy'
|
||||||
|
|
||||||
def excludeModules = ['spring-security-acl', 'jsr250-api', 'spring-jdbc', 'spring-tx']
|
def excludeModules = ['spring-security-acl', 'jsr250-api', 'spring-jdbc', 'spring-tx']
|
||||||
def jettyVersion = '8.1.9.v20130131'
|
def jettyVersion = '8.1.22.v20160922'
|
||||||
def keystore = "$rootDir/samples/certificates/server.jks"
|
def keystore = "$rootDir/samples/certificates/server.jks"
|
||||||
def password = 'password'
|
def password = 'password'
|
||||||
|
|
||||||
|
|||||||
@@ -2,14 +2,14 @@ apply plugin: 'war'
|
|||||||
apply plugin: 'jetty'
|
apply plugin: 'jetty'
|
||||||
apply plugin: 'appengine'
|
apply plugin: 'appengine'
|
||||||
|
|
||||||
def gaeVersion="1.9.23"
|
def gaeVersion="1.9.83"
|
||||||
|
|
||||||
buildscript {
|
buildscript {
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.google.appengine:gradle-appengine-plugin:1.9.23'
|
classpath 'com.google.appengine:gradle-appengine-plugin:1.9.59'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,4 +49,4 @@ dependencies {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
appengineRun.onlyIf { !gradle.taskGraph.hasTask(appengineFunctionalTest) }
|
appengineRun.onlyIf { !gradle.taskGraph.hasTask(appengineFunctionalTest) }
|
||||||
|
|||||||
+6
@@ -0,0 +1,6 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
BUILD_NUMBER=$1
|
||||||
|
ENCRYPTED_ARTIFACTORY_PWD=$2
|
||||||
|
export ARTIFACTORY_BUILD_API_URL=https://repo.spring.io/api/build/distribute/Spring%20Security%20-%204.2.x%20-%20Default%20Job/$BUILD_NUMBER
|
||||||
|
curl -i -u buildmaster:$ENCRYPTED_ARTIFACTORY_PWD -XPOST $ARTIFACTORY_BUILD_API_URL -H "Content-Type: application/json" -d '{"sourceRepos": ["libs-release-local"], "targetRepo": "spring-distributions"}'
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
releasenotes:
|
||||||
|
sections:
|
||||||
|
- title: "New Features"
|
||||||
|
emoji: ":star:"
|
||||||
|
labels: ["enhancement"]
|
||||||
|
- title: "Bug Fixes"
|
||||||
|
emoji: ":beetle:"
|
||||||
|
labels: ["bug", "regression"]
|
||||||
|
- title: "Dependency Upgrades"
|
||||||
|
emoji: ":hammer:"
|
||||||
|
labels: ["dependency-upgrade"]
|
||||||
|
- title: "Non-passive"
|
||||||
|
emoji: ":rewind:"
|
||||||
|
labels: ["breaks-passivity"]
|
||||||
Executable
+7
@@ -0,0 +1,7 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
RELEASE_VERSION=$1
|
||||||
|
BINTRAY_API_KEY=$2
|
||||||
|
SONATYPE_USER_TOKEN=$3
|
||||||
|
SONATYPE_USER_TOKEN_PWD=$4
|
||||||
|
curl -i -u spring-operator:$BINTRAY_API_KEY -XPOST "https://api.bintray.com/maven_central_sync/spring/jars/org.springframework.security/versions/$RELEASE_VERSION" -H "Content-Type: application/json" -d "{\"username\": \"$SONATYPE_USER_TOKEN\", \"password\": \"$SONATYPE_USER_TOKEN_PWD\"}"
|
||||||
Executable
+4
@@ -0,0 +1,4 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
VERSION=$1
|
||||||
|
until http -h --check-status --ignore-stdin https://repo1.maven.org/maven2/org/springframework/security/spring-security-core/$VERSION/; do sleep 10; clear; done; spd-say "It is now uploaded"
|
||||||
+1
-1
@@ -43,7 +43,7 @@ final class WithMockUserSecurityContextFactory implements
|
|||||||
.username() : withUser.value();
|
.username() : withUser.value();
|
||||||
if (username == null) {
|
if (username == null) {
|
||||||
throw new IllegalArgumentException(withUser
|
throw new IllegalArgumentException(withUser
|
||||||
+ " cannot have null username on both username and value properites");
|
+ " cannot have null username on both username and value properties");
|
||||||
}
|
}
|
||||||
|
|
||||||
List<GrantedAuthority> grantedAuthorities = new ArrayList<GrantedAuthority>();
|
List<GrantedAuthority> grantedAuthorities = new ArrayList<GrantedAuthority>();
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ import java.util.*;
|
|||||||
* requests which match the pattern. An example configuration might look like this:
|
* requests which match the pattern. An example configuration might look like this:
|
||||||
*
|
*
|
||||||
* <pre>
|
* <pre>
|
||||||
* <bean id="myfilterChainProxy" class="org.springframework.security.util.FilterChainProxy">
|
* <bean id="myfilterChainProxy" class="org.springframework.security.web.FilterChainProxy">
|
||||||
* <constructor-arg>
|
* <constructor-arg>
|
||||||
* <util:list>
|
* <util:list>
|
||||||
* <security:filter-chain pattern="/do/not/filter*" filters="none"/>
|
* <security:filter-chain pattern="/do/not/filter*" filters="none"/>
|
||||||
|
|||||||
@@ -228,10 +228,15 @@ class DummyRequest extends HttpServletRequestWrapper {
|
|||||||
public void setQueryString(String queryString) {
|
public void setQueryString(String queryString) {
|
||||||
this.queryString = queryString;
|
this.queryString = queryString;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getServerName() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final class UnsupportedOperationExceptionInvocationHandler implements InvocationHandler {
|
final class UnsupportedOperationExceptionInvocationHandler implements InvocationHandler {
|
||||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||||
throw new UnsupportedOperationException(method + " is not supported");
|
throw new UnsupportedOperationException(method + " is not supported");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -563,6 +563,6 @@ public class SwitchUserFilter extends GenericFilterBean
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static RequestMatcher createMatcher(String pattern) {
|
private static RequestMatcher createMatcher(String pattern) {
|
||||||
return new AntPathRequestMatcher(pattern, null, true, new UrlPathHelper());
|
return new AntPathRequestMatcher(pattern, "POST", true, new UrlPathHelper());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+39
-3
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2017 the original author or authors.
|
* Copyright 2012-2020 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -16,14 +16,14 @@
|
|||||||
|
|
||||||
package org.springframework.security.web.firewall;
|
package org.springframework.security.web.firewall;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
@@ -59,10 +59,15 @@ import java.util.Set;
|
|||||||
* Rejects URLs that contain a URL encoded percent. See
|
* Rejects URLs that contain a URL encoded percent. See
|
||||||
* {@link #setAllowUrlEncodedPercent(boolean)}
|
* {@link #setAllowUrlEncodedPercent(boolean)}
|
||||||
* </li>
|
* </li>
|
||||||
|
* <li>
|
||||||
|
* Rejects hosts that are not allowed. See
|
||||||
|
* {@link #setAllowedHostnames(Collection)}
|
||||||
|
* </li>
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
* @see DefaultHttpFirewall
|
* @see DefaultHttpFirewall
|
||||||
* @author Rob Winch
|
* @author Rob Winch
|
||||||
|
* @author Eddú Meléndez
|
||||||
* @since 4.2.4
|
* @since 4.2.4
|
||||||
*/
|
*/
|
||||||
public class StrictHttpFirewall implements HttpFirewall {
|
public class StrictHttpFirewall implements HttpFirewall {
|
||||||
@@ -82,6 +87,8 @@ public class StrictHttpFirewall implements HttpFirewall {
|
|||||||
|
|
||||||
private Set<String> decodedUrlBlacklist = new HashSet<String>();
|
private Set<String> decodedUrlBlacklist = new HashSet<String>();
|
||||||
|
|
||||||
|
private Collection<String> allowedHostnames;
|
||||||
|
|
||||||
public StrictHttpFirewall() {
|
public StrictHttpFirewall() {
|
||||||
urlBlacklistsAddAll(FORBIDDEN_SEMICOLON);
|
urlBlacklistsAddAll(FORBIDDEN_SEMICOLON);
|
||||||
urlBlacklistsAddAll(FORBIDDEN_FORWARDSLASH);
|
urlBlacklistsAddAll(FORBIDDEN_FORWARDSLASH);
|
||||||
@@ -230,6 +237,21 @@ public class StrictHttpFirewall implements HttpFirewall {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* Determines which hostnames should be allowed. The default is to allow any hostname.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param allowedHostnames the set of allowed hostnames
|
||||||
|
* @since 4.2.17
|
||||||
|
*/
|
||||||
|
public void setAllowedHostnames(Collection<String> allowedHostnames) {
|
||||||
|
if (allowedHostnames == null) {
|
||||||
|
throw new IllegalArgumentException("allowedHostnames cannot be null");
|
||||||
|
}
|
||||||
|
this.allowedHostnames = allowedHostnames;
|
||||||
|
}
|
||||||
|
|
||||||
private void urlBlacklistsAddAll(Collection<String> values) {
|
private void urlBlacklistsAddAll(Collection<String> values) {
|
||||||
this.encodedUrlBlacklist.addAll(values);
|
this.encodedUrlBlacklist.addAll(values);
|
||||||
this.decodedUrlBlacklist.addAll(values);
|
this.decodedUrlBlacklist.addAll(values);
|
||||||
@@ -243,6 +265,7 @@ public class StrictHttpFirewall implements HttpFirewall {
|
|||||||
@Override
|
@Override
|
||||||
public FirewalledRequest getFirewalledRequest(HttpServletRequest request) throws RequestRejectedException {
|
public FirewalledRequest getFirewalledRequest(HttpServletRequest request) throws RequestRejectedException {
|
||||||
rejectedBlacklistedUrls(request);
|
rejectedBlacklistedUrls(request);
|
||||||
|
rejectedUntrustedHosts(request);
|
||||||
|
|
||||||
if (!isNormalized(request)) {
|
if (!isNormalized(request)) {
|
||||||
throw new RequestRejectedException("The request was rejected because the URL was not normalized.");
|
throw new RequestRejectedException("The request was rejected because the URL was not normalized.");
|
||||||
@@ -272,6 +295,19 @@ public class StrictHttpFirewall implements HttpFirewall {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void rejectedUntrustedHosts(HttpServletRequest request) {
|
||||||
|
String serverName = request.getServerName();
|
||||||
|
if (serverName == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (this.allowedHostnames == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!this.allowedHostnames.contains(serverName)) {
|
||||||
|
throw new RequestRejectedException("The request was rejected because the domain " + serverName + " is untrusted.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HttpServletResponse getFirewalledResponse(HttpServletResponse response) {
|
public HttpServletResponse getFirewalledResponse(HttpServletResponse response) {
|
||||||
return new FirewalledResponse(response);
|
return new FirewalledResponse(response);
|
||||||
|
|||||||
+7
-6
@@ -42,7 +42,6 @@ import org.springframework.security.core.AuthenticationException;
|
|||||||
import org.springframework.security.core.context.SecurityContext;
|
import org.springframework.security.core.context.SecurityContext;
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
import org.springframework.security.web.AuthenticationEntryPoint;
|
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||||
import org.springframework.security.web.authentication.logout.CompositeLogoutHandler;
|
|
||||||
import org.springframework.security.web.authentication.logout.LogoutHandler;
|
import org.springframework.security.web.authentication.logout.LogoutHandler;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
@@ -82,7 +81,7 @@ final class HttpServlet3RequestFactory implements HttpServletRequestFactory {
|
|||||||
private AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl();
|
private AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl();
|
||||||
private AuthenticationEntryPoint authenticationEntryPoint;
|
private AuthenticationEntryPoint authenticationEntryPoint;
|
||||||
private AuthenticationManager authenticationManager;
|
private AuthenticationManager authenticationManager;
|
||||||
private LogoutHandler logoutHandler;
|
private List<LogoutHandler> logoutHandlers;
|
||||||
|
|
||||||
HttpServlet3RequestFactory(String rolePrefix) {
|
HttpServlet3RequestFactory(String rolePrefix) {
|
||||||
this.rolePrefix = rolePrefix;
|
this.rolePrefix = rolePrefix;
|
||||||
@@ -146,7 +145,7 @@ final class HttpServlet3RequestFactory implements HttpServletRequestFactory {
|
|||||||
* {@link HttpServletRequest#logout()}.
|
* {@link HttpServletRequest#logout()}.
|
||||||
*/
|
*/
|
||||||
public void setLogoutHandlers(List<LogoutHandler> logoutHandlers) {
|
public void setLogoutHandlers(List<LogoutHandler> logoutHandlers) {
|
||||||
this.logoutHandler = CollectionUtils.isEmpty(logoutHandlers) ? null : new CompositeLogoutHandler(logoutHandlers);
|
this.logoutHandlers = logoutHandlers;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -246,8 +245,8 @@ final class HttpServlet3RequestFactory implements HttpServletRequestFactory {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void logout() throws ServletException {
|
public void logout() throws ServletException {
|
||||||
LogoutHandler handler = HttpServlet3RequestFactory.this.logoutHandler;
|
List<LogoutHandler> handlers = HttpServlet3RequestFactory.this.logoutHandlers;
|
||||||
if (handler == null) {
|
if (CollectionUtils.isEmpty(handlers)) {
|
||||||
HttpServlet3RequestFactory.this.logger.debug(
|
HttpServlet3RequestFactory.this.logger.debug(
|
||||||
"logoutHandlers is null, so allowing original HttpServletRequest to handle logout");
|
"logoutHandlers is null, so allowing original HttpServletRequest to handle logout");
|
||||||
super.logout();
|
super.logout();
|
||||||
@@ -255,7 +254,9 @@ final class HttpServlet3RequestFactory implements HttpServletRequestFactory {
|
|||||||
}
|
}
|
||||||
Authentication authentication = SecurityContextHolder.getContext()
|
Authentication authentication = SecurityContextHolder.getContext()
|
||||||
.getAuthentication();
|
.getAuthentication();
|
||||||
handler.logout(this, this.response, authentication);
|
for (LogoutHandler handler : handlers) {
|
||||||
|
handler.logout(this, this.response, authentication);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isAuthenticated() {
|
private boolean isAuthenticated() {
|
||||||
|
|||||||
+2
-2
@@ -67,7 +67,7 @@ public final class AntPathRequestMatcher
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a matcher with the specific pattern which will match all HTTP methods in a
|
* Creates a matcher with the specific pattern which will match all HTTP methods in a
|
||||||
* case insensitive manner.
|
* case sensitive manner.
|
||||||
*
|
*
|
||||||
* @param pattern the ant pattern to use for matching
|
* @param pattern the ant pattern to use for matching
|
||||||
*/
|
*/
|
||||||
@@ -76,7 +76,7 @@ public final class AntPathRequestMatcher
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a matcher with the supplied pattern and HTTP method in a case insensitive
|
* Creates a matcher with the supplied pattern and HTTP method in a case sensitive
|
||||||
* manner.
|
* manner.
|
||||||
*
|
*
|
||||||
* @param pattern the ant pattern to use for matching
|
* @param pattern the ant pattern to use for matching
|
||||||
|
|||||||
+42
-5
@@ -16,11 +16,17 @@
|
|||||||
|
|
||||||
package org.springframework.security.web.authentication.switchuser;
|
package org.springframework.security.web.authentication.switchuser;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.*;
|
import java.util.ArrayList;
|
||||||
import static org.mockito.Mockito.*;
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.servlet.FilterChain;
|
||||||
|
|
||||||
import org.junit.*;
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Rule;
|
||||||
|
import org.junit.Test;
|
||||||
import org.junit.rules.ExpectedException;
|
import org.junit.rules.ExpectedException;
|
||||||
|
|
||||||
import org.springframework.mock.web.MockHttpServletRequest;
|
import org.springframework.mock.web.MockHttpServletRequest;
|
||||||
import org.springframework.mock.web.MockHttpServletResponse;
|
import org.springframework.mock.web.MockHttpServletResponse;
|
||||||
import org.springframework.security.authentication.AccountExpiredException;
|
import org.springframework.security.authentication.AccountExpiredException;
|
||||||
@@ -42,8 +48,10 @@ import org.springframework.security.web.DefaultRedirectStrategy;
|
|||||||
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
|
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
|
||||||
import org.springframework.security.web.util.matcher.AnyRequestMatcher;
|
import org.springframework.security.web.util.matcher.AnyRequestMatcher;
|
||||||
|
|
||||||
import javax.servlet.FilterChain;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import java.util.*;
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.never;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests
|
* Tests
|
||||||
@@ -75,6 +83,7 @@ public class SwitchUserFilterTests {
|
|||||||
request.setScheme("http");
|
request.setScheme("http");
|
||||||
request.setServerName("localhost");
|
request.setServerName("localhost");
|
||||||
request.setRequestURI("/login/impersonate");
|
request.setRequestURI("/login/impersonate");
|
||||||
|
request.setMethod("POST");
|
||||||
|
|
||||||
return request;
|
return request;
|
||||||
}
|
}
|
||||||
@@ -125,6 +134,20 @@ public class SwitchUserFilterTests {
|
|||||||
assertThat(filter.requiresExitUser(request)).isFalse();
|
assertThat(filter.requiresExitUser(request)).isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
// gh-4183
|
||||||
|
public void requiresExitUserWhenGetThenDoesNotMatch() {
|
||||||
|
SwitchUserFilter filter = new SwitchUserFilter();
|
||||||
|
|
||||||
|
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||||
|
request.setScheme("http");
|
||||||
|
request.setServerName("localhost");
|
||||||
|
request.setRequestURI("/login/impersonate");
|
||||||
|
request.setMethod("GET");
|
||||||
|
|
||||||
|
assertThat(filter.requiresExitUser(request)).isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void requiresExitUserWhenMatcherThenWorks() {
|
public void requiresExitUserWhenMatcherThenWorks() {
|
||||||
SwitchUserFilter filter = new SwitchUserFilter();
|
SwitchUserFilter filter = new SwitchUserFilter();
|
||||||
@@ -159,6 +182,20 @@ public class SwitchUserFilterTests {
|
|||||||
assertThat(filter.requiresSwitchUser(request)).isFalse();
|
assertThat(filter.requiresSwitchUser(request)).isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
// gh-4183
|
||||||
|
public void requiresSwitchUserWhenGetThenDoesNotMatch() {
|
||||||
|
SwitchUserFilter filter = new SwitchUserFilter();
|
||||||
|
|
||||||
|
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||||
|
request.setScheme("http");
|
||||||
|
request.setServerName("localhost");
|
||||||
|
request.setRequestURI("/login/impersonate");
|
||||||
|
request.setMethod("GET");
|
||||||
|
|
||||||
|
assertThat(filter.requiresSwitchUser(request)).isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void requiresSwitchUserWhenMatcherThenWorks() {
|
public void requiresSwitchUserWhenMatcherThenWorks() {
|
||||||
SwitchUserFilter filter = new SwitchUserFilter();
|
SwitchUserFilter filter = new SwitchUserFilter();
|
||||||
|
|||||||
+42
-1
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2017 the original author or authors.
|
* Copyright 2012-2020 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -16,6 +16,8 @@
|
|||||||
|
|
||||||
package org.springframework.security.web.firewall;
|
package org.springframework.security.web.firewall;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.springframework.mock.web.MockHttpServletRequest;
|
import org.springframework.mock.web.MockHttpServletRequest;
|
||||||
|
|
||||||
@@ -23,6 +25,7 @@ import static org.assertj.core.api.Assertions.fail;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Rob Winch
|
* @author Rob Winch
|
||||||
|
* @author Eddú Meléndez
|
||||||
*/
|
*/
|
||||||
public class StrictHttpFirewallTests {
|
public class StrictHttpFirewallTests {
|
||||||
public String[] unnormalizedPaths = { "/..", "/./path/", "/path/path/.", "/path/path//.", "./path/../path//.",
|
public String[] unnormalizedPaths = { "/..", "/./path/", "/path/path/.", "/path/path//.", "./path/../path//.",
|
||||||
@@ -373,4 +376,42 @@ public class StrictHttpFirewallTests {
|
|||||||
|
|
||||||
this.firewall.getFirewalledRequest(request);
|
this.firewall.getFirewalledRequest(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getFirewalledRequestWhenTrustedDomainThenNoException() {
|
||||||
|
String host = "example.org";
|
||||||
|
this.request.addHeader("Host", host);
|
||||||
|
this.firewall.setAllowedHostnames(Arrays.asList(host));
|
||||||
|
|
||||||
|
try {
|
||||||
|
this.firewall.getFirewalledRequest(this.request);
|
||||||
|
} catch (RequestRejectedException fail) {
|
||||||
|
fail("Host " + host + " was rejected");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getFirewalledRequestWhenUntrustedDomainThenException() {
|
||||||
|
String host = "example.org";
|
||||||
|
this.request.addHeader("Host", host);
|
||||||
|
this.firewall.setAllowedHostnames(Arrays.asList("myexample.org"));
|
||||||
|
|
||||||
|
try {
|
||||||
|
this.firewall.getFirewalledRequest(this.request);
|
||||||
|
fail("Host " + host + " was accepted");
|
||||||
|
} catch (RequestRejectedException expected) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getFirewalledRequestWhenDefaultsThenNoException() {
|
||||||
|
String host = "example.org";
|
||||||
|
this.request.addHeader("Host", host);
|
||||||
|
|
||||||
|
try {
|
||||||
|
this.firewall.getFirewalledRequest(this.request);
|
||||||
|
} catch (RequestRejectedException fail) {
|
||||||
|
fail("Host " + host + " was rejected");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user