1
0
mirror of synced 2026-09-06 01:09:48 +00:00

Compare commits

..

95 Commits

Author SHA1 Message Date
Spring Buildmaster 081f0c4d94 Release version 4.2.2.RELEASE 2017-03-02 07:29:42 +00:00
Rob Winch 247f54dc41 Fix SwitchUserFilter.setSwitchFailureUrl assertion
Fixes gh-4198
2017-03-02 00:47:09 -06:00
Rob Winch 017e9834bd Fix NPE in UrlUtils with null url
Fixes gh-4233
2017-03-02 00:46:01 -06:00
Rob Winch 49719480a8 Fix configuration-source-ref doc
Fixes gh-4200
2017-03-02 00:25:51 -06:00
Rob Winch f3edaa673a Fix SecurityNamespaceHandler Version Error Message
Fixes gh-4210
2017-03-02 00:25:51 -06:00
pkovacs f99fe36e02 Refer to SimpleGrantedAuthority instead of GrantedAuthorityImpl
GrantedAuthorityImpl has been replaced a couple of years ago with
SimpleGrantedAuthority and this commit fixes the documentation items
which weren’t updated to reflect this change.

Fixes gh-4163.
2017-03-02 00:09:14 -06:00
Joris Kuipers 546d44d6e7 Fix NPE in WebSocketMessageBrokerSecurityBeanDefinitionParser
Fixes gh-4112
Closes gh-4194
2017-03-01 23:58:02 -06:00
stonio 901a4e183a Update SecurityContextHolder.java
Use StringUtils.hasText
2017-03-01 23:54:04 -06:00
Artyom Kosykh 72d08a2a5f Fix index.adoc typo 2017-03-01 23:45:50 -06:00
Kazuki Miyahara 2ac51c9c7f Fix class name in comment 2017-03-01 23:31:32 -06:00
Rob Winch b64cdb5765 Fix RoleHiearchyUtilsTests on Windows
Fixes gh-4228
2017-03-01 23:27:11 -06:00
pkovacs aa31f1f695 Update required JDK version to JDK8
Fixes gh-4154.
2017-03-01 23:18:50 -06:00
Eddú Meléndez 8353984733 Fix warning from spring-boot plugin 2017-03-01 23:13:56 -06:00
SendilKumar N c31bdb6390 SCryptPasswordEncoder to take default keyLength value
Fixes gh-4225
Closes gh-4231
2017-03-01 23:11:52 -06:00
Rob Winch 168f4b8f70 Prevent Duplicate Cache Headers
Fixes gh-4199
2017-03-01 16:14:12 -06:00
Rob Winch 9c03571bbb Use message in all Assert
This ensures compatibility with Spring 5.

Fixes gh-4193
2017-01-30 19:58:24 -06:00
Rob Winch 4c79107e01 Force mockito-core version 2017-01-09 15:30:50 -06:00
Rob Winch 3f543d0fbd Use anyListOf
Fixes compatability with Spring IO Cairo
2017-01-09 13:08:45 -06:00
Rob Winch 08104eb06c Add eclipseConfiguration Gradle task 2017-01-05 11:43:33 -06:00
Rob Winch b54d350e54 AspectJ fixes for Spring IO 2017-01-05 11:43:33 -06:00
Rob Winch b5e0886bde update to spring-io-plugin:0.0.6
- Update spring-io-plugin
- Update Spring Boot because spring-io-plugin now requires
  non passive dependency management plugin
2017-01-05 11:42:48 -06:00
Kazuki Shimizu 38492a5794 Add since version in javadoc
Issue: gh-4130
2016-12-21 16:12:39 -06:00
Spring Buildmaster b7541d56d0 Next development version 2016-12-21 17:23:37 +00:00
Spring Buildmaster 7a7ce11ebb Release version 4.2.1.RELEASE 2016-12-21 17:23:28 +00:00
Eddú Meléndez 028854b936 Add HttpSessionRequestCache sessionAttrName property
This commit allows to customize the session attribute name. Default is
SPRING_SECURITY_SAVED_REQUEST.

Fixes gh-4130
2016-12-21 10:22:09 -06:00
stonio aa5df61eff Fix index.adoc typo 2016-12-21 10:19:51 -06:00
stonio 6df5b76f24 Fix test.adoc typo 2016-12-21 10:19:51 -06:00
stonio c8ed130008 Fix websocket.adoc typo 2016-12-21 10:19:51 -06:00
Rob Winch d39f3385b6 Polish DefaultHttpFirewallTests
Issue gh-4169
2016-12-21 09:29:23 -06:00
Rob Winch 6bec625e68 Update to Spring 4.3.5.RELEASE
Fixes gh-4167
2016-12-21 09:04:16 -06:00
Rob Winch 666e356ebc Block URL Encoded "/" in DefaultHttpFirewall
Fixes gh-4169
2016-12-21 09:04:00 -06:00
Rob Winch fc516b55a6 Fix Build Against Spring 5.0.0.BUILD-SNAPSHOT
Change Bean definition to static to avoid SPR-12646

Fixes gh-4150
2016-12-08 15:54:46 -06:00
Rob Winch bb834bccf6 Polish Exception Message
Polish Exception message for bad salt in BCrypt

Issue gh-4147
2016-12-06 08:45:08 -06:00
Jan Brennenstuhl 09436649cc handling null-values for salts properly now - fixes gh-4147 2016-12-06 08:43:19 -06:00
Johnny Lim f94399cff9 Polish 2016-11-17 09:49:41 -06:00
Dapeng 94fb1893de fix typo "RemoteIpValve" 2016-11-16 14:13:53 -06:00
Johnny Lim 3185876a7d Remove dead code in AclAuthorizationStrategyImplTests 2016-11-14 10:18:58 -06:00
Spring Buildmaster 2cb38ae115 Next development version 2016-11-09 23:42:16 +00:00
Spring Buildmaster 24fcb6c45a Release version 4.2.0.RELEASE 2016-11-09 23:42:11 +00:00
Rob Winch a9024de734 Polish Spring Version Update
Fix related tests.

Issue gh-4123
2016-11-09 17:05:25 -06:00
Rob Winch fd9f57eb5f Update What's New changelogs 2016-11-09 17:00:09 -06:00
Rob Winch 7259759f8d Update to Spring LDAP 2.2.0.RELEASE
Fixes gh-4124
2016-11-09 16:55:19 -06:00
Rob Winch 14e5e06ae0 Update to Spring 4.3.4.RELEASE
Fixes gh-4123
2016-11-09 16:55:19 -06:00
Rob Winch 697daeab7c Add Jackson2 Support for PreAuthenticatedAuthenticationToken
Fixes gh-4120
2016-11-09 16:55:10 -06:00
Rob Winch f97f38fd57 jacksonDatavindVersion->jacksonDatabindVersion
Issue gh-4122
2016-11-09 16:46:38 -06:00
Rob Winch a853d38076 Update to Jackson 2.8.4
Fixes gh-4122
2016-11-09 16:42:41 -06:00
Rob Winch f0a9421aa4 SecurityJacksonModules->SecurityJackson2Modules
Fixes gh-4121
2016-11-09 16:42:41 -06:00
Rob Winch 36f4f7d081 Add securityCheckWhenCustomAuthorityThenNameIsUsed
Add a test for AclAuthorizationStrategyImpl.securityCheck when a custom
authority is used.

Issue gh-4085
2016-11-09 15:27:41 -06:00
Shazin Sadakath 07d1c7c5eb AclAuthorizationStrategyImpl uses name
Fixes gh-4085
2016-11-09 14:53:46 -06:00
Kazuki Shimizu d2c28c58e2 Polishing the ReferrerPolicyHeaderWriter gh-4110 2016-11-09 13:16:41 -06:00
Rob Winch 14a656186d Polish Referrer Header Policy Docs
Previously, the Referrer Header Policy was accidentally placed within
the CSP section.

Move Referrer Header Polich outside of the CSP section.

Issue gh-4110
2016-11-09 13:15:06 -06:00
stonio 2a197c72eb Fix typos in the reference
Fix typos in the reference documentation

Fixes gh-4113
2016-11-09 10:05:27 -06:00
Rob Winch ab5af87953 Add Referrer Policy to What's New 2016-11-08 16:14:20 -06:00
Eddú Meléndez 23294c4c57 Add Referrer-Policy header support
Fixes gh-4110
2016-11-08 13:21:35 -06:00
Kazuki Shimizu eb2870bf82 Polishing doc in What's New in Spring Security 4.2 2016-11-08 11:19:51 -06:00
Rob Winch 9fa42117f7 Update GRADLE_OPTS to use " instead of ' 2016-11-01 20:11:05 -05:00
Rob Winch cf3d6e7167 Fix Small Typo
propoerty->property
2016-10-31 11:31:52 -05:00
Spring Buildmaster 08f0b57243 Next development version 2016-10-26 02:49:27 +00:00
Spring Buildmaster 97b4cb0b73 Release version 4.2.0.RC1 2016-10-26 02:49:23 +00:00
Rob Winch 8ca4b55d32 Update What's New Section of Reference
Fixes gh-4109
2016-10-25 15:03:59 -05:00
Rob Winch 8e546454a5 Polish ApacheDSContainer LDAPs support
Issue gh-4096
2016-10-25 10:17:08 -05:00
Gunnar Hillert 406bb1d4d5 Add LDAPs support to ApacheDSContainer
* Add the ability to enable LDAP over SSL (LDAPs)
* Add tests

Fixes gh-4096
2016-10-25 10:16:35 -05:00
Rob Winch 8437d0fea3 Remove Eclipse Project Name customization
Previously the build specified the major.minor.x as a suffix for the
project name. This is now removed since Buildship ignores it.
2016-10-24 18:39:49 -05:00
Rob Winch df3b8bc284 Add Spring MVC test for override cache control
Issue gh-3975
2016-10-24 15:57:32 -05:00
Rob Winch 57d7ad05f9 Revert "Cache Control only written if not set"
This reverts commit 242b831f20.
Spring MVC fixed the issue we were working around and the changes
in Spring Security were unreliable.

Fixes gh-3975
2016-10-24 15:57:26 -05:00
Rob Winch e62596f36d Polish PasswordEncoderUtils do not leak length
Fix possible / 0 if expected is empty String.

Issue gh-255
2016-10-24 12:50:46 -05:00
Rob Winch d3685d89c5 Polish PasswordEncoderUtils do not leak length
Issue gh-255
2016-10-24 11:26:43 -05:00
avri-schneider a98389fa98 PasswordEncoderUtils do not leak length
Enforce constant time even when expectedLength != actualLength.

Fixes gh-255
2016-10-24 11:26:34 -05:00
Rob Winch dc9f9b140f Polish PasswordEncoderUtilsTests
* Add more tests
* Smaller tests
* Follow new naming convention
2016-10-24 11:24:24 -05:00
Rob Winch f432c04111 Create UserBuilder
This commit creates a UserBuilder and updates samples to use it. We do not
leverate it for JdbcUserDetailsManager because it requires the schema to
be created which is difficult with a single bean definition and
unpredicatble ordering. For this, it is still advised to use
AuthenticationManagerBuilder

Fixes gh-4095
2016-10-21 16:42:03 -05:00
Johnny Lim 50b72dddbc Fix typo in Javadoc
This commit simply fixes typo in Javadoc.
2016-10-20 21:07:15 -05:00
Rob Winch 94e580fe64 Add Support for Custom Default Configuration in Web Security
Fixes gh-4102
2016-10-19 16:15:56 -05:00
Rob Winch af9139b613 Add intercept-url@request-matcher-ref
Fixes gh-4097
2016-10-18 22:27:31 -05:00
Rob Winch f019ea89e7 Remove unused lowercase-comparisons from XSD
Fixes gh-3932
2016-10-18 22:27:28 -05:00
Rob Winch 0d700628dc Add spring-security-4.2.xsd to spring.schemas
Fixes gh-4098
2016-10-18 22:27:22 -05:00
Rob Winch aaa9708b95 Add BeanResolver to AuthenticationPrincipalArgumentResolver
Previously @AuthenticationPrincipal's expression attribute didn't support
bean references because the BeanResolver was not set on the SpEL context.

This commit adds a BeanResolver and ensures that the configuration
sets a BeanResolver.

Fixes gh-3949
2016-10-18 19:45:54 -05:00
Joe df9e6c973c linked to java configuration sample applications
removed outdated description and linked directly to java configuration sample applications
2016-10-17 21:12:17 -05:00
Paul Samsotha 1da9c06f3b Fix Reference (test.adoc) Typo
@SpringExecutionListeners -> @SpringTestExecutionListeners
2016-10-17 21:11:19 -05:00
Rob Winch 0c35209d77 Document Proxy Server
Issue gh-4076
2016-10-17 21:07:57 -05:00
Rob Winch badb466cc5 AuthenticationConfiguration imports ObjectPostProcessor
Fixes gh-4086
2016-10-17 20:00:27 -05:00
Rob Winch 46bb855737 Remove chat sample
Removed in favor of
https://github.com/spring-projects/spring-session/tree/master/samples/websocket

Fixes gh-4094
2016-10-17 17:02:59 -05:00
Rob Winch 6a3a5f7beb Polish Deprecations
Issue gh-4080
2016-10-17 17:02:59 -05:00
Rob Winch 52c6e3cf89 Create RedirectMatcher
This commit creates RedirectMatcher for binary backward compatability with
Spring 4.3.x and Spring 5 to ensure that the Spring IO tests pass.

Issue gh-4080
2016-10-17 17:02:58 -05:00
Rob Winch 17cfd4707b Fix deprecations
Issue gh-4080
2016-10-17 17:00:18 -05:00
Rob Winch 2c99cd3bbf Remove MatcherAssertionErrors
Spring 5 removes MatcherAssertionErrors. We should not have been using
this class anyways.

This commit updates to using assertj in favor of MatcherAssertionErrors.

Issue gh-4080
2016-10-17 17:00:17 -05:00
Rob Winch 8a7ac398e6 Remove TheController from Bean
It is already picked up with classpath scanning

Issue gh-4080
2016-10-17 17:00:17 -05:00
Rob Winch 5e35e37a2b Update to Thymeleaf 3.0.2 and remove tiles
Spring 5 removed support for Tiles 2 and Thymeleaf does not support
Tiles 3 yet. This commit updates to Thymeleaf 3.0.2 and uses
Thymeleaf's build in layout support.

Issue gh-4080
2016-10-17 17:00:17 -05:00
Rob Winch c1e9140940 Update itest/web to use Servelt 3.1
Previously itest/web used Servlet 2.5 which Spring 5 is not
compatabile with. This commit removes unnecessary tests (ones that
were already covered) and converts the remaining tests to MockMvc
using the provided servlet version.

Issue gh-4080
2016-10-17 17:00:17 -05:00
Rob Winch 1222fc5f10 XML ref to bean
Spring 5 removes ref XML attribute in favor of bean XML attribute. This
commit updates all the samples and tests to use bean instead of ref.

Issue gh-4080
2016-10-17 17:00:17 -05:00
Rob Winch 08c1f500a7 Version bumps for Spring 5
Issue gh-4080
2016-10-17 17:00:17 -05:00
Rob Winch a18707c870 gradlew disables Gradle Daemon
Fixes gh-4093
2016-10-17 17:00:16 -05:00
Jitendra Singh 48ff518a41 Fix Jackson 2.7+
UnmodifiableSetDeserializer added which will ensure
Collection$UnmodifiableSet deserialize properly with jackson-databind 2.7+

Fixes gh-4073
2016-10-13 07:42:07 -05:00
Rob Winch 0b1e3b4e4a Fix Reference Typo
unlimitted->unlimited
2016-09-23 16:45:08 -05:00
Rob Winch 6b4a52715b Fix Typo in Reference 2016-09-23 14:57:52 -05:00
Spring Buildmaster 7fb052e7ae Next development version 2016-09-23 19:39:35 +00:00
312 changed files with 3280 additions and 28211 deletions
+2 -2
View File
@@ -29,9 +29,9 @@ In the instructions below, http://vimeo.com/34436402[`./gradlew`] is invoked fro
a cross-platform, self-contained bootstrap mechanism for the build.
=== Prerequisites
http://help.github.com/set-up-git-redirect[Git] and the http://www.oracle.com/technetwork/java/javase/downloads[JDK7 build].
http://help.github.com/set-up-git-redirect[Git] and the http://www.oracle.com/technetwork/java/javase/downloads[JDK8 build].
Be sure that your `JAVA_HOME` environment variable points to the `jdk1.7.0` folder extracted from the JDK download.
Be sure that your `JAVA_HOME` environment variable points to the `jdk1.8.0` folder extracted from the JDK download.
=== Check out sources
[indent=0]
+3 -9
View File
@@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-acl</artifactId>
<version>4.2.0.M1</version>
<version>4.2.2.RELEASE</version>
<name>spring-security-acl</name>
<description>spring-security-acl</description>
<url>http://spring.io/spring-security</url>
@@ -35,7 +35,7 @@
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-framework-bom</artifactId>
<version>4.3.2.RELEASE</version>
<version>4.3.5.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
@@ -51,7 +51,7 @@
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>4.2.0.M1</version>
<version>4.2.2.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
@@ -151,12 +151,6 @@
<scope>test</scope>
</dependency>
</dependencies>
<repositories>
<repository>
<id>spring-milestone</id>
<url>https://repo.spring.io/milestone</url>
</repository>
</repositories>
<build>
<plugins>
<plugin>
@@ -16,18 +16,20 @@
package org.springframework.security.acls.domain;
import java.util.Arrays;
import java.util.List;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.acls.model.Acl;
import org.springframework.security.acls.model.Sid;
import org.springframework.security.acls.model.SidRetrievalStrategy;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.util.Assert;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
/**
* Default implementation of {@link AclAuthorizationStrategy}.
* <p>
@@ -118,7 +120,8 @@ public class AclAuthorizationStrategyImpl implements AclAuthorizationStrategy {
}
// Iterate this principal's authorities to determine right
if (authentication.getAuthorities().contains(requiredAuthority)) {
Set<String> authorities = AuthorityUtils.authorityListToSet(authentication.getAuthorities());
if (authorities.contains(requiredAuthority.getAuthority())) {
return;
}
@@ -26,6 +26,8 @@ import org.springframework.security.acls.model.Acl;
import org.springframework.security.acls.model.AclService;
import org.springframework.security.acls.model.ObjectIdentity;
import org.springframework.security.acls.model.ObjectIdentityRetrievalStrategy;
import org.springframework.security.acls.model.Permission;
import org.springframework.security.acls.model.Sid;
import org.springframework.security.acls.model.SidRetrievalStrategy;
import org.springframework.security.core.Authentication;
@@ -37,7 +39,6 @@ import org.springframework.security.core.Authentication;
public class AclPermissionEvaluatorTests {
@Test
@SuppressWarnings("unchecked")
public void hasPermissionReturnsTrueIfAclGrantsPermission() throws Exception {
AclService service = mock(AclService.class);
AclPermissionEvaluator pe = new AclPermissionEvaluator(service);
@@ -48,8 +49,8 @@ public class AclPermissionEvaluatorTests {
pe.setSidRetrievalStrategy(mock(SidRetrievalStrategy.class));
Acl acl = mock(Acl.class);
when(service.readAclById(any(ObjectIdentity.class), anyList())).thenReturn(acl);
when(acl.isGranted(anyList(), anyList(), eq(false))).thenReturn(true);
when(service.readAclById(any(ObjectIdentity.class), anyListOf(Sid.class))).thenReturn(acl);
when(acl.isGranted(anyListOf(Permission.class), anyListOf(Sid.class), eq(false))).thenReturn(true);
assertThat(pe.hasPermission(mock(Authentication.class), new Object(), "READ")).isTrue();
}
@@ -68,8 +69,8 @@ public class AclPermissionEvaluatorTests {
pe.setSidRetrievalStrategy(mock(SidRetrievalStrategy.class));
Acl acl = mock(Acl.class);
when(service.readAclById(any(ObjectIdentity.class), anyList())).thenReturn(acl);
when(acl.isGranted(anyList(), anyList(), eq(false))).thenReturn(true);
when(service.readAclById(any(ObjectIdentity.class), anyListOf(Sid.class))).thenReturn(acl);
when(acl.isGranted(anyListOf(Permission.class), anyListOf(Sid.class), eq(false))).thenReturn(true);
assertThat(pe.hasPermission(mock(Authentication.class), new Object(), "write")).isTrue();
@@ -0,0 +1,72 @@
/*
* 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.acls.domain;
import java.util.Arrays;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.security.acls.model.Acl;
import org.springframework.security.authentication.TestingAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
/**
*
* @author Rob Winch
*
*/
@RunWith(MockitoJUnitRunner.class)
public class AclAuthorizationStrategyImplTests {
@Mock
Acl acl;
GrantedAuthority authority;
AclAuthorizationStrategyImpl strategy;
@Before
public void setup() {
authority = new SimpleGrantedAuthority("ROLE_AUTH");
TestingAuthenticationToken authentication = new TestingAuthenticationToken("foo", "bar", Arrays.asList(authority));
authentication.setAuthenticated(true);
SecurityContextHolder.getContext().setAuthentication(authentication);
}
@After
public void cleanup() {
SecurityContextHolder.clearContext();
}
// gh-4085
@Test
public void securityCheckWhenCustomAuthorityThenNameIsUsed() {
strategy = new AclAuthorizationStrategyImpl(new CustomAuthority());
strategy.securityCheck(acl, AclAuthorizationStrategy.CHANGE_GENERAL);
}
@SuppressWarnings("serial")
class CustomAuthority implements GrantedAuthority {
@Override
public String getAuthority() {
return authority.getAuthority();
}
}
}
+3 -9
View File
@@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-aspects</artifactId>
<version>4.2.0.M1</version>
<version>4.2.2.RELEASE</version>
<name>spring-security-aspects</name>
<description>spring-security-aspects</description>
<url>http://spring.io/spring-security</url>
@@ -35,7 +35,7 @@
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-framework-bom</artifactId>
<version>4.3.2.RELEASE</version>
<version>4.3.5.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
@@ -45,7 +45,7 @@
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>4.2.0.M1</version>
<version>4.2.2.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
@@ -130,12 +130,6 @@
<scope>test</scope>
</dependency>
</dependencies>
<repositories>
<repository>
<id>spring-milestone</id>
<url>https://repo.spring.io/milestone</url>
</repository>
</repositories>
<build>
<plugins>
<plugin>
+10 -6
View File
@@ -1,15 +1,16 @@
buildscript {
repositories {
maven { url "https://repo.spring.io/plugins-release" }
maven { url "https://repo.spring.io/plugins-snapshot" }
}
dependencies {
classpath("org.springframework.build.gradle:propdeps-plugin:0.0.7")
classpath("io.spring.gradle:spring-io-plugin:0.0.5.RELEASE")
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.4.0.RELEASE")
classpath("org.springframework.boot:spring-boot-gradle-plugin:1.5.0.BUILD-SNAPSHOT")
}
}
@@ -27,8 +28,8 @@ allprojects {
ext.releaseBuild = version.endsWith('RELEASE')
ext.snapshotBuild = version.endsWith('SNAPSHOT')
ext.springVersion = '4.3.2.RELEASE'
ext.springLdapVersion = '2.0.2.RELEASE'
ext.springVersion = '4.3.5.RELEASE'
ext.springLdapVersion = '2.2.0.RELEASE'
group = 'org.springframework.security'
@@ -39,7 +40,6 @@ allprojects {
maven { url "http://repo.terracotta.org/maven2/" }
}
eclipse.project.name = "${project.name}-4.1.x"
}
sonarqube {
@@ -115,7 +115,11 @@ configure(coreModuleProjects) {
dependencyManagement {
springIoTestRuntime {
imports {
mavenBom "io.spring.platform:platform-bom:${springIoVersion}"
mavenBom("io.spring.platform:platform-bom:${springIoVersion}") {
bomProperties([
'mockito.version': '1.10.19'
])
}
}
}
}
@@ -4,12 +4,13 @@ import org.gradle.api.Project
import org.gradle.api.Plugin
import org.gradle.api.tasks.TaskAction
import org.gradle.api.logging.LogLevel
import org.gradle.api.file.FileCollection
import org.gradle.api.file.*
import org.gradle.api.tasks.SourceSet
import org.gradle.api.DefaultTask
import org.gradle.api.GradleException
import org.gradle.api.plugins.JavaPlugin
import org.gradle.api.tasks.compile.JavaCompile
import org.gradle.plugins.ide.eclipse.GenerateEclipseProject
import org.gradle.plugins.ide.eclipse.GenerateEclipseClasspath
import org.gradle.plugins.ide.eclipse.EclipsePlugin
@@ -41,28 +42,25 @@ class AspectJPlugin implements Plugin<Project> {
project.configurations.create('aspectpath')
}
project.tasks.create(name: 'compileAspect', overwrite: true, description: 'Compiles AspectJ Source', type: Ajc) {
dependsOn project.configurations*.getTaskDependencyFromProjectDependency(true, "compileJava")
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) {
inputs.files(javaCompileTask.inputs.files)
inputs.properties(javaCompileTask.inputs.properties)
sourceRoots.addAll(project.sourceSets.main.java.srcDirs)
if(javaCompileTaskName.contains("Test")) {
sourceRoots.addAll(project.sourceSets.test.java.srcDirs)
}
compileClasspath = javaCompileTask.classpath
destinationDir = javaCompileTask.destinationDir
aspectPath = project.configurations.aspectpath
}
javaCompileTask.deleteAllActions()
javaCompileTask.dependsOn ajCompileTask
dependsOn project.processResources
sourceSet = project.sourceSets.main
inputs.files(sourceSet.allSource)
outputs.dir(sourceSet.output.classesDir)
aspectPath = project.configurations.aspectpath
}
project.tasks.compileJava.deleteAllActions()
project.tasks.compileJava.dependsOn project.tasks.compileAspect
project.tasks.create(name: 'compileTestAspect', overwrite: true, description: 'Compiles AspectJ Test Source', type: Ajc) {
dependsOn project.processTestResources, project.compileJava, project.jar
sourceSet = project.sourceSets.test
inputs.files(sourceSet.allSource)
outputs.dir(sourceSet.output.classesDir)
aspectPath = project.files(project.configurations.aspectpath, project.jar.archivePath)
}
project.tasks.compileTestJava.deleteAllActions()
project.tasks.compileTestJava.dependsOn project.tasks.compileTestAspect
project.tasks.withType(GenerateEclipseProject) {
project.eclipse.project.file.whenMerged { p ->
@@ -91,7 +89,9 @@ class AspectJPlugin implements Plugin<Project> {
}
class Ajc extends DefaultTask {
SourceSet sourceSet
Set<File> sourceRoots = []
FileCollection compileClasspath
File destinationDir
FileCollection aspectPath
Ajc() {
@@ -103,15 +103,18 @@ class Ajc extends DefaultTask {
logger.info("="*30)
logger.info("="*30)
logger.info("Running ajc ...")
logger.info("classpath: ${sourceSet.compileClasspath.asPath}")
logger.info("srcDirs $sourceSet.java.srcDirs")
logger.info("classpath: ${compileClasspath?.files}")
logger.info("srcDirs ${sourceRoots}")
ant.taskdef(resource: "org/aspectj/tools/ant/taskdefs/aspectjTaskdefs.properties", classpath: project.configurations.ajtools.asPath)
ant.iajc(classpath: sourceSet.compileClasspath.asPath, fork: 'true', destDir: sourceSet.output.classesDir.absolutePath,
if(sourceRoots.empty) {
return
}
ant.iajc(classpath: compileClasspath.asPath, fork: 'true', destDir: destinationDir.absolutePath,
source: project.convention.plugins.java.sourceCompatibility,
target: project.convention.plugins.java.targetCompatibility,
aspectPath: aspectPath.asPath, sourceRootCopyFilter: '**/*.java', showWeaveInfo: 'true') {
sourceroots {
sourceSet.java.srcDirs.each {
sourceRoots.each {
logger.info(" sourceRoot $it")
pathelement(location: it.absolutePath)
}
+1 -1
View File
@@ -9,7 +9,7 @@ dependencies {
"org.jasig.cas.client:cas-client-core:$casClientVersion"
optional "net.sf.ehcache:ehcache:$ehcacheVersion",
"com.fasterxml.jackson.core:jackson-databind:$jacksonDatavindVersion"
"com.fasterxml.jackson.core:jackson-databind:$jacksonDatabindVersion"
testCompile "org.skyscreamer:jsonassert:$jsonassertVersion"
+6 -12
View File
@@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-cas</artifactId>
<version>4.2.0.M1</version>
<version>4.2.2.RELEASE</version>
<name>spring-security-cas</name>
<description>spring-security-cas</description>
<url>http://spring.io/spring-security</url>
@@ -35,7 +35,7 @@
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-framework-bom</artifactId>
<version>4.3.2.RELEASE</version>
<version>4.3.5.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
@@ -51,13 +51,13 @@
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>4.2.0.M1</version>
<version>4.2.2.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>4.2.0.M1</version>
<version>4.2.2.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
@@ -89,7 +89,7 @@
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.4.4</version>
<version>2.8.4</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
@@ -110,7 +110,7 @@
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
@@ -155,12 +155,6 @@
<scope>test</scope>
</dependency>
</dependencies>
<repositories>
<repository>
<id>spring-milestone</id>
<url>https://repo.spring.io/milestone</url>
</repository>
</repositories>
<build>
<plugins>
<plugin>
@@ -36,7 +36,7 @@ import java.util.Map;
*
* @author Jitendra Singh
* @see CasJackson2Module
* @see org.springframework.security.jackson2.SecurityJacksonModules
* @see org.springframework.security.jackson2.SecurityJackson2Modules
* @since 4.2
*/
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY)
@@ -33,7 +33,7 @@ import java.util.Map;
*
* @author Jitendra Singh
* @see CasJackson2Module
* @see org.springframework.security.jackson2.SecurityJacksonModules
* @see org.springframework.security.jackson2.SecurityJackson2Modules
* @since 4.2
*/
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY)
@@ -42,7 +42,7 @@ import java.util.Collection;
*
* @author Jitendra Singh
* @see CasJackson2Module
* @see org.springframework.security.jackson2.SecurityJacksonModules
* @see org.springframework.security.jackson2.SecurityJackson2Modules
* @since 4.2
*/
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY)
@@ -22,7 +22,7 @@ import com.fasterxml.jackson.databind.module.SimpleModule;
import org.jasig.cas.client.authentication.AttributePrincipalImpl;
import org.jasig.cas.client.validation.AssertionImpl;
import org.springframework.security.cas.authentication.CasAuthenticationToken;
import org.springframework.security.jackson2.SecurityJacksonModules;
import org.springframework.security.jackson2.SecurityJackson2Modules;
/**
* Jackson module for spring-security-cas. This module register {@link AssertionImplMixin},
@@ -34,10 +34,10 @@ import org.springframework.security.jackson2.SecurityJacksonModules;
* ObjectMapper mapper = new ObjectMapper();
* mapper.registerModule(new CasJackson2Module());
* </pre>
* <b>Note: use {@link SecurityJacksonModules#getModules(ClassLoader)} to get list of all security modules on the classpath.</b>
* <b>Note: use {@link SecurityJackson2Modules#getModules(ClassLoader)} to get list of all security modules on the classpath.</b>
*
* @author Jitendra Singh.
* @see org.springframework.security.jackson2.SecurityJacksonModules
* @see org.springframework.security.jackson2.SecurityJackson2Modules
* @since 4.2
*/
public class CasJackson2Module extends SimpleModule {
@@ -48,7 +48,7 @@ public class CasJackson2Module extends SimpleModule {
@Override
public void setupModule(SetupContext context) {
SecurityJacksonModules.enableDefaultTyping((ObjectMapper) context.getOwner());
SecurityJackson2Modules.enableDefaultTyping((ObjectMapper) context.getOwner());
context.setMixInAnnotations(AssertionImpl.class, AssertionImplMixin.class);
context.setMixInAnnotations(AttributePrincipalImpl.class, AttributePrincipalImplMixin.class);
context.setMixInAnnotations(CasAuthenticationToken.class, CasAuthenticationTokenMixin.class);
@@ -132,7 +132,7 @@ final class DefaultServiceAuthenticationDetails extends WebAuthenticationDetails
* @return
*/
static Pattern createArtifactPattern(String artifactParameterName) {
Assert.hasLength(artifactParameterName);
Assert.hasLength(artifactParameterName, "artifactParameterName is expected to have a length");
return Pattern.compile("&?" + Pattern.quote(artifactParameterName) + "=[^&]*");
}
@@ -36,7 +36,7 @@ import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.jackson2.SecurityJacksonModules;
import org.springframework.security.jackson2.SecurityJackson2Modules;
import static org.assertj.core.api.Assertions.assertThat;
@@ -103,7 +103,7 @@ public class CasAuthenticationTokenMixinTests {
public void setup() {
mapper = new ObjectMapper();
ClassLoader loader = getClass().getClassLoader();
mapper.registerModules(SecurityJacksonModules.getModules(loader));
mapper.registerModules(SecurityJackson2Modules.getModules(loader));
}
@Test
+2 -3
View File
@@ -39,8 +39,8 @@ dependencies {
"org.springframework:spring-orm:$springVersion",
"org.springframework:spring-tx:$springVersion",
"org.slf4j:jcl-over-slf4j:$slf4jVersion",
"org.eclipse.persistence:javax.persistence:2.0.5",
"org.hibernate:hibernate-entitymanager:4.1.0.Final",
"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",
@@ -50,7 +50,6 @@ dependencies {
'org.apache.directory.shared:shared-ldap:0.9.15',
'ldapsdk:ldapsdk:4.1',
powerMockDependencies,
"org.hibernate:hibernate-entitymanager:3.6.10.Final",
"org.hsqldb:hsqldb:$hsqlVersion",
spockDependencies
+13 -19
View File
@@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>4.2.0.M1</version>
<version>4.2.2.RELEASE</version>
<name>spring-security-config</name>
<description>spring-security-config</description>
<url>http://spring.io/spring-security</url>
@@ -35,7 +35,7 @@
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-framework-bom</artifactId>
<version>4.3.2.RELEASE</version>
<version>4.3.5.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
@@ -51,7 +51,7 @@
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>4.2.0.M1</version>
<version>4.2.2.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
@@ -97,28 +97,28 @@
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-ldap</artifactId>
<version>4.2.0.M1</version>
<version>4.2.2.RELEASE</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-messaging</artifactId>
<version>4.2.0.M1</version>
<version>4.2.2.RELEASE</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-openid</artifactId>
<version>4.2.0.M1</version>
<version>4.2.2.RELEASE</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>4.2.0.M1</version>
<version>4.2.2.RELEASE</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
@@ -155,7 +155,7 @@
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
@@ -239,13 +239,13 @@
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>javax.persistence</artifactId>
<version>2.0.5</version>
<version>2.1.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>4.1.0.Final</version>
<version>5.0.11.Final</version>
<scope>test</scope>
</dependency>
<dependency>
@@ -359,19 +359,19 @@
<dependency>
<groupId>org.springframework.ldap</groupId>
<artifactId>spring-ldap-core</artifactId>
<version>2.0.2.RELEASE</version>
<version>2.2.0.RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-aspects</artifactId>
<version>4.2.0.M1</version>
<version>4.2.2.RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-cas</artifactId>
<version>4.2.0.M1</version>
<version>4.2.2.RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
@@ -390,12 +390,6 @@
<scope>test</scope>
</dependency>
</dependencies>
<repositories>
<repository>
<id>spring-milestone</id>
<url>https://repo.spring.io/milestone</url>
</repository>
</repositories>
<build>
<plugins>
<plugin>
@@ -86,7 +86,7 @@ public final class SecurityNamespaceHandler implements NamespaceHandler {
if (!namespaceMatchesVersion(element)) {
pc.getReaderContext()
.fatal("You cannot use a spring-security-2.0.xsd or spring-security-3.0.xsd or spring-security-3.1.xsd schema or spring-security-3.2.xsd schema or spring-security-4.0.xsd schema "
+ "with Spring Security 4.1. Please update your schema declarations to the 4.1 schema.",
+ "with Spring Security 4.2. Please update your schema declarations to the 4.2 schema.",
element);
}
String name = pc.getDelegate().getLocalName(element);
@@ -221,7 +221,7 @@ public final class SecurityNamespaceHandler implements NamespaceHandler {
private boolean matchesVersionInternal(Element element) {
String schemaLocation = element.getAttributeNS(
"http://www.w3.org/2001/XMLSchema-instance", "schemaLocation");
return schemaLocation.matches("(?m).*spring-security-4\\.1.*.xsd.*")
return schemaLocation.matches("(?m).*spring-security-4\\.2.*.xsd.*")
|| schemaLocation.matches("(?m).*spring-security.xsd.*")
|| !schemaLocation.matches("(?m).*spring-security.*");
}
@@ -31,11 +31,13 @@ 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.context.annotation.Import;
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.GlobalAuthenticationConfigurerAdapter;
import org.springframework.security.config.annotation.configuration.ObjectPostProcessorConfiguration;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.util.Assert;
@@ -48,6 +50,7 @@ import org.springframework.util.Assert;
*
*/
@Configuration
@Import(ObjectPostProcessorConfiguration.class)
public class AuthenticationConfiguration {
private AtomicBoolean buildingAuthenticationManager = new AtomicBoolean();
@@ -16,19 +16,16 @@
package org.springframework.security.config.annotation.authentication.configurers.provisioning;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.springframework.security.config.annotation.SecurityBuilder;
import org.springframework.security.config.annotation.authentication.ProviderManagerBuilder;
import org.springframework.security.config.annotation.authentication.configurers.userdetails.UserDetailsServiceConfigurer;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.User.UserBuilder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.provisioning.UserDetailsManager;
import org.springframework.util.Assert;
/**
* Base class for populating an
@@ -82,13 +79,7 @@ public class UserDetailsManagerConfigurer<B extends ProviderManagerBuilder<B>, C
* should provided. The remaining attributes have reasonable defaults.
*/
public class UserDetailsBuilder {
private String username;
private String password;
private List<GrantedAuthority> authorities;
private boolean accountExpired;
private boolean accountLocked;
private boolean credentialsExpired;
private boolean disabled;
private UserBuilder user;
private final C builder;
/**
@@ -117,8 +108,7 @@ public class UserDetailsManagerConfigurer<B extends ProviderManagerBuilder<B>, C
* additional attributes for this user)
*/
private UserDetailsBuilder username(String username) {
Assert.notNull(username, "username cannot be null");
this.username = username;
this.user = User.withUsername(username);
return this;
}
@@ -130,8 +120,7 @@ public class UserDetailsManagerConfigurer<B extends ProviderManagerBuilder<B>, C
* additional attributes for this user)
*/
public UserDetailsBuilder password(String password) {
Assert.notNull(password, "password cannot be null");
this.password = password;
this.user.password(password);
return this;
}
@@ -161,14 +150,8 @@ public class UserDetailsManagerConfigurer<B extends ProviderManagerBuilder<B>, C
* additional attributes for this user)
*/
public UserDetailsBuilder roles(String... roles) {
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>(
roles.length);
for (String role : roles) {
Assert.isTrue(!role.startsWith("ROLE_"), role
+ " cannot start with ROLE_ (it is automatically added)");
authorities.add(new SimpleGrantedAuthority("ROLE_" + role));
}
return authorities(authorities);
this.user.roles(roles);
return this;
}
/**
@@ -181,7 +164,8 @@ public class UserDetailsManagerConfigurer<B extends ProviderManagerBuilder<B>, C
* @see #roles(String...)
*/
public UserDetailsBuilder authorities(GrantedAuthority... authorities) {
return authorities(Arrays.asList(authorities));
this.user.authorities(authorities);
return this;
}
/**
@@ -194,7 +178,7 @@ public class UserDetailsManagerConfigurer<B extends ProviderManagerBuilder<B>, C
* @see #roles(String...)
*/
public UserDetailsBuilder authorities(List<? extends GrantedAuthority> authorities) {
this.authorities = new ArrayList<GrantedAuthority>(authorities);
this.user.authorities(authorities);
return this;
}
@@ -208,7 +192,8 @@ public class UserDetailsManagerConfigurer<B extends ProviderManagerBuilder<B>, C
* @see #roles(String...)
*/
public UserDetailsBuilder authorities(String... authorities) {
return authorities(AuthorityUtils.createAuthorityList(authorities));
this.user.authorities(authorities);
return this;
}
/**
@@ -219,7 +204,7 @@ public class UserDetailsManagerConfigurer<B extends ProviderManagerBuilder<B>, C
* additional attributes for this user)
*/
public UserDetailsBuilder accountExpired(boolean accountExpired) {
this.accountExpired = accountExpired;
this.user.accountExpired(accountExpired);
return this;
}
@@ -231,7 +216,7 @@ public class UserDetailsManagerConfigurer<B extends ProviderManagerBuilder<B>, C
* additional attributes for this user)
*/
public UserDetailsBuilder accountLocked(boolean accountLocked) {
this.accountLocked = accountLocked;
this.user.accountLocked(accountLocked);
return this;
}
@@ -243,7 +228,7 @@ public class UserDetailsManagerConfigurer<B extends ProviderManagerBuilder<B>, C
* additional attributes for this user)
*/
public UserDetailsBuilder credentialsExpired(boolean credentialsExpired) {
this.credentialsExpired = credentialsExpired;
this.user.credentialsExpired(credentialsExpired);
return this;
}
@@ -255,13 +240,12 @@ public class UserDetailsManagerConfigurer<B extends ProviderManagerBuilder<B>, C
* additional attributes for this user)
*/
public UserDetailsBuilder disabled(boolean disabled) {
this.disabled = disabled;
this.user.disabled(disabled);
return this;
}
private UserDetails build() {
return new User(username, password, !disabled, !accountExpired,
!credentialsExpired, !accountLocked, authorities);
return this.user.build();
}
}
}
@@ -25,7 +25,6 @@ import org.springframework.context.annotation.Import;
import org.springframework.core.Ordered;
import org.springframework.security.access.annotation.Secured;
import org.springframework.security.config.annotation.authentication.configuration.EnableGlobalAuthentication;
import org.springframework.security.config.annotation.configuration.ObjectPostProcessorConfiguration;
/**
* <p>
@@ -45,7 +44,7 @@ import org.springframework.security.config.annotation.configuration.ObjectPostPr
@Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME)
@Target(value = { java.lang.annotation.ElementType.TYPE })
@Documented
@Import({ GlobalMethodSecuritySelector.class, ObjectPostProcessorConfiguration.class })
@Import({ GlobalMethodSecuritySelector.class })
@EnableGlobalAuthentication
@Configuration
public @interface EnableGlobalMethodSecurity {
@@ -49,7 +49,6 @@ import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
import org.springframework.security.access.intercept.AfterInvocationManager;
import org.springframework.security.access.intercept.AfterInvocationProviderManager;
import org.springframework.security.access.intercept.RunAsManager;
import org.springframework.security.access.intercept.RunAsManagerImpl;
import org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor;
import org.springframework.security.access.intercept.aspectj.AspectJMethodSecurityInterceptor;
import org.springframework.security.access.method.DelegatingMethodSecurityMetadataSource;
@@ -22,7 +22,6 @@ import java.lang.annotation.Target;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.security.config.annotation.authentication.configuration.EnableGlobalAuthentication;
import org.springframework.security.config.annotation.configuration.ObjectPostProcessorConfiguration;
import org.springframework.security.config.annotation.web.WebSecurityConfigurer;
/**
@@ -73,7 +72,7 @@ import org.springframework.security.config.annotation.web.WebSecurityConfigurer;
@Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME)
@Target(value = { java.lang.annotation.ElementType.TYPE })
@Documented
@Import({ WebSecurityConfiguration.class, ObjectPostProcessorConfiguration.class,
@Import({ WebSecurityConfiguration.class,
SpringWebMvcImportSelector.class })
@EnableGlobalAuthentication
@Configuration
@@ -15,7 +15,14 @@
*/
package org.springframework.security.config.annotation.web.configuration;
import java.util.List;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.expression.BeanFactoryResolver;
import org.springframework.expression.BeanResolver;
import org.springframework.security.web.method.annotation.AuthenticationPrincipalArgumentResolver;
import org.springframework.security.web.method.annotation.CsrfTokenArgumentResolver;
import org.springframework.security.web.servlet.support.csrf.CsrfRequestDataValueProcessor;
@@ -24,8 +31,6 @@ import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.support.RequestDataValueProcessor;
import java.util.List;
/**
* Used to add a {@link RequestDataValueProcessor} for Spring MVC and Spring Security CSRF
* integration. This configuration is added whenever {@link EnableWebMvc} is added by
@@ -36,12 +41,15 @@ import java.util.List;
* @author Rob Winch
* @since 3.2
*/
class WebMvcSecurityConfiguration extends WebMvcConfigurerAdapter {
class WebMvcSecurityConfiguration extends WebMvcConfigurerAdapter implements ApplicationContextAware {
private BeanResolver beanResolver;
@Override
@SuppressWarnings("deprecation")
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
argumentResolvers.add(new AuthenticationPrincipalArgumentResolver());
AuthenticationPrincipalArgumentResolver authenticationPrincipalResolver = new AuthenticationPrincipalArgumentResolver();
authenticationPrincipalResolver.setBeanResolver(beanResolver);
argumentResolvers.add(authenticationPrincipalResolver);
argumentResolvers
.add(new org.springframework.security.web.bind.support.AuthenticationPrincipalArgumentResolver());
argumentResolvers.add(new CsrfTokenArgumentResolver());
@@ -51,4 +59,9 @@ class WebMvcSecurityConfiguration extends WebMvcConfigurerAdapter {
public RequestDataValueProcessor requestDataValueProcessor() {
return new CsrfRequestDataValueProcessor();
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.beanResolver = new BeanFactoryResolver(applicationContext.getAutowireCapableBeanFactory());
}
}
@@ -34,6 +34,7 @@ import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.core.annotation.Order;
import org.springframework.core.io.support.SpringFactoriesLoader;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationTrustResolver;
import org.springframework.security.authentication.AuthenticationTrustResolverImpl;
@@ -44,6 +45,7 @@ import org.springframework.security.config.annotation.authentication.configurati
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;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.annotation.web.configurers.DefaultLoginPageConfigurer;
import org.springframework.security.config.annotation.web.configurers.SecurityContextConfigurer;
import org.springframework.security.core.Authentication;
@@ -59,8 +61,23 @@ import org.springframework.web.accept.ContentNegotiationStrategy;
import org.springframework.web.accept.HeaderContentNegotiationStrategy;
/**
* Provides a convenient base class for creating a {@link WebSecurityConfigurer} instance.
* The implementation allows customization by overriding methods.
* Provides a convenient base class for creating a {@link WebSecurityConfigurer}
* instance. The implementation allows customization by overriding methods.
*
* <p>
* Will automatically apply the result of looking up
* {@link AbstractHttpConfigurer} from {@link SpringFactoriesLoader} to allow
* developers to extend the defaults.
* To do this, you must create a class that extends AbstractHttpConfigurer and then create a file in the classpath at "META-INF/spring.factories" that looks something like:
* </p>
* <pre>
* org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer = sample.MyClassThatExtendsAbstractHttpConfigurer
* </pre>
* If you have multiple classes that should be added you can use "," to separate the values. For example:
*
* <pre>
* org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer = sample.MyClassThatExtendsAbstractHttpConfigurer, sample.OtherThatExtendsAbstractHttpConfigurer
* </pre>
*
* @see EnableWebSecurity
*
@@ -165,6 +182,7 @@ public abstract class WebSecurityConfigurerAdapter implements
* ] * @return the {@link HttpSecurity}
* @throws Exception
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
protected final HttpSecurity getHttp() throws Exception {
if (http != null) {
return http;
@@ -195,6 +213,13 @@ public abstract class WebSecurityConfigurerAdapter implements
.apply(new DefaultLoginPageConfigurer<HttpSecurity>()).and()
.logout();
// @formatter:on
ClassLoader classLoader = this.context.getClassLoader();
List<AbstractHttpConfigurer> defaultHttpConfigurers =
SpringFactoriesLoader.loadFactories(AbstractHttpConfigurer.class, classLoader);
for(AbstractHttpConfigurer configurer : defaultHttpConfigurers) {
http.apply(configurer);
}
}
configure(http);
return http;
@@ -29,7 +29,7 @@ import org.springframework.security.web.DefaultSecurityFilterChain;
* @author Rob Winch
*
*/
abstract class AbstractHttpConfigurer<T extends AbstractHttpConfigurer<T, B>, B extends HttpSecurityBuilder<B>>
public abstract class AbstractHttpConfigurer<T extends AbstractHttpConfigurer<T, B>, B extends HttpSecurityBuilder<B>>
extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, B> {
/**
@@ -28,6 +28,7 @@ import org.springframework.security.config.annotation.web.configuration.WebSecur
import org.springframework.security.web.header.HeaderWriter;
import org.springframework.security.web.header.HeaderWriterFilter;
import org.springframework.security.web.header.writers.*;
import org.springframework.security.web.header.writers.ReferrerPolicyHeaderWriter.ReferrerPolicy;
import org.springframework.security.web.header.writers.frameoptions.XFrameOptionsHeaderWriter;
import org.springframework.security.web.header.writers.frameoptions.XFrameOptionsHeaderWriter.XFrameOptionsMode;
import org.springframework.security.web.util.matcher.RequestMatcher;
@@ -56,6 +57,7 @@ import org.springframework.util.Assert;
* @author Rob Winch
* @author Tim Ysewyn
* @author Joe Grandja
* @author Eddú Meléndez
* @since 3.2
*/
public class HeadersConfigurer<H extends HttpSecurityBuilder<H>> extends
@@ -78,6 +80,8 @@ public class HeadersConfigurer<H extends HttpSecurityBuilder<H>> extends
private final ContentSecurityPolicyConfig contentSecurityPolicy = new ContentSecurityPolicyConfig();
private final ReferrerPolicyConfig referrerPolicy = new ReferrerPolicyConfig();
/**
* Creates a new instance
*
@@ -770,6 +774,7 @@ public class HeadersConfigurer<H extends HttpSecurityBuilder<H>> extends
addIfNotNull(writers, frameOptions.writer);
addIfNotNull(writers, hpkp.writer);
addIfNotNull(writers, contentSecurityPolicy.writer);
addIfNotNull(writers, referrerPolicy.writer);
writers.addAll(headerWriters);
return writers;
}
@@ -779,4 +784,68 @@ public class HeadersConfigurer<H extends HttpSecurityBuilder<H>> extends
values.add(value);
}
}
/**
* <p>
* Allows configuration for <a href="https://www.w3.org/TR/referrer-policy/">Referrer Policy</a>.
* </p>
*
* <p>
* Configuration is provided to the {@link ReferrerPolicyHeaderWriter} which support the writing
* of the header as detailed in the W3C Technical Report:
* </p>
* <ul>
* <li>Referrer-Policy</li>
* </ul>
*
* <p>Default value is:</p>
*
* <pre>
* Referrer-Policy: no-referrer
* </pre>
*
* @see ReferrerPolicyHeaderWriter
* @since 4.2
* @return the ReferrerPolicyConfig for additional configuration
*/
public ReferrerPolicyConfig referrerPolicy() {
this.referrerPolicy.writer = new ReferrerPolicyHeaderWriter();
return this.referrerPolicy;
}
/**
* <p>
* Allows configuration for <a href="https://www.w3.org/TR/referrer-policy/">Referrer Policy</a>.
* </p>
*
* <p>
* Configuration is provided to the {@link ReferrerPolicyHeaderWriter} which support the writing
* of the header as detailed in the W3C Technical Report:
* </p>
* <ul>
* <li>Referrer-Policy</li>
* </ul>
*
* @see ReferrerPolicyHeaderWriter
* @since 4.2
* @return the ReferrerPolicyConfig for additional configuration
* @throws IllegalArgumentException if policy is null or empty
*/
public ReferrerPolicyConfig referrerPolicy(ReferrerPolicy policy) {
this.referrerPolicy.writer = new ReferrerPolicyHeaderWriter(policy);
return this.referrerPolicy;
}
public final class ReferrerPolicyConfig {
private ReferrerPolicyHeaderWriter writer;
private ReferrerPolicyConfig() {
}
public HeadersConfigurer<H> and() {
return HeadersConfigurer.this;
}
}
}
@@ -481,7 +481,7 @@ final class AuthenticationConfigBuilder {
SimpleAttributes2GrantedAuthoritiesMapper.class));
String roles = jeeElt.getAttribute(ATT_MAPPABLE_ROLES);
Assert.state(StringUtils.hasText(roles));
Assert.hasLength(roles, "roles is expected to have length");
BeanDefinitionBuilder rolesBuilder = BeanDefinitionBuilder
.rootBeanDefinition(StringUtils.class);
rolesBuilder.addConstructorArgValue(roles);
@@ -15,13 +15,16 @@
*/
package org.springframework.security.config.http;
import static org.springframework.security.config.http.HttpSecurityBeanDefinitionParser.ATT_REQUEST_MATCHER_REF;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.w3c.dom.Element;
import org.springframework.beans.BeanMetadataElement;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.ManagedMap;
@@ -99,7 +102,7 @@ public class FilterInvocationSecurityMetadataSourceParser implements BeanDefinit
MatcherType matcherType = MatcherType.fromElement(httpElt);
boolean useExpressions = isUseExpressions(httpElt);
ManagedMap<BeanDefinition, BeanDefinition> requestToAttributesMap = parseInterceptUrlsForFilterInvocationRequestMap(
ManagedMap<BeanMetadataElement, BeanDefinition> requestToAttributesMap = parseInterceptUrlsForFilterInvocationRequestMap(
matcherType, interceptUrls, useExpressions, addAllAuth, pc);
BeanDefinitionBuilder fidsBuilder;
@@ -148,11 +151,11 @@ public class FilterInvocationSecurityMetadataSourceParser implements BeanDefinit
return !StringUtils.hasText(useExpressions) || "true".equals(useExpressions);
}
private static ManagedMap<BeanDefinition, BeanDefinition> parseInterceptUrlsForFilterInvocationRequestMap(
private static ManagedMap<BeanMetadataElement, BeanDefinition> parseInterceptUrlsForFilterInvocationRequestMap(
MatcherType matcherType, List<Element> urlElts, boolean useExpressions,
boolean addAuthenticatedAll, ParserContext parserContext) {
ManagedMap<BeanDefinition, BeanDefinition> filterInvocationDefinitionMap = new ManagedMap<BeanDefinition, BeanDefinition>();
ManagedMap<BeanMetadataElement, BeanDefinition> filterInvocationDefinitionMap = new ManagedMap<BeanMetadataElement, BeanDefinition>();
for (Element urlElt : urlElts) {
String access = urlElt.getAttribute(ATT_ACCESS);
@@ -161,8 +164,10 @@ public class FilterInvocationSecurityMetadataSourceParser implements BeanDefinit
}
String path = urlElt.getAttribute(ATT_PATTERN);
String matcherRef = urlElt.getAttribute(ATT_REQUEST_MATCHER_REF);
boolean hasMatcherRef = StringUtils.hasText(matcherRef);
if (!StringUtils.hasText(path)) {
if (!hasMatcherRef && !StringUtils.hasText(path)) {
parserContext.getReaderContext().error(
"path attribute cannot be empty or null", urlElt);
}
@@ -180,7 +185,7 @@ public class FilterInvocationSecurityMetadataSourceParser implements BeanDefinit
ATT_SERVLET_PATH + " is not applicable for request-matcher: '" + matcherType.name() + "'", urlElt);
}
BeanDefinition matcher = matcherType.createMatcher(parserContext, path,
BeanMetadataElement matcher = hasMatcherRef ? new RuntimeBeanReference(matcherRef) : matcherType.createMatcher(parserContext, path,
method, servletPath);
BeanDefinitionBuilder attributeBuilder = BeanDefinitionBuilder
.rootBeanDefinition(SecurityConfig.class);
@@ -189,7 +194,7 @@ public class FilterInvocationSecurityMetadataSourceParser implements BeanDefinit
logger.info("Creating access control expression attribute '" + access
+ "' for " + path);
// The single expression will be parsed later by the
// ExpressionFilterInvocationSecurityMetadataSource
// ExpressionBasedFilterInvocationSecurityMetadataSource
attributeBuilder.addConstructorArgValue(new String[] { access });
attributeBuilder.setFactoryMethod("createList");
@@ -31,6 +31,7 @@ import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.security.web.header.HeaderWriterFilter;
import org.springframework.security.web.header.writers.*;
import org.springframework.security.web.header.writers.ReferrerPolicyHeaderWriter.ReferrerPolicy;
import org.springframework.security.web.header.writers.frameoptions.RegExpAllowFromStrategy;
import org.springframework.security.web.header.writers.frameoptions.StaticAllowFromStrategy;
import org.springframework.security.web.header.writers.frameoptions.WhiteListedAllowFromStrategy;
@@ -45,6 +46,7 @@ import org.w3c.dom.Node;
*
* @author Marten Deinum
* @author Tim Ysewyn
* @author Eddú Meléndez
* @since 3.2
*/
public class HeadersBeanDefinitionParser implements BeanDefinitionParser {
@@ -82,6 +84,7 @@ public class HeadersBeanDefinitionParser implements BeanDefinitionParser {
private static final String GENERIC_HEADER_ELEMENT = "header";
private static final String CONTENT_SECURITY_POLICY_ELEMENT = "content-security-policy";
private static final String REFERRER_POLICY_ELEMENT = "referrer-policy";
private static final String ALLOW_FROM = "ALLOW-FROM";
@@ -109,6 +112,8 @@ public class HeadersBeanDefinitionParser implements BeanDefinitionParser {
parseContentSecurityPolicyElement(disabled, element, parserContext);
parseReferrerPolicyElement(element, parserContext);
parseHeaderElements(element);
boolean noWriters = headerWriters.isEmpty();
@@ -291,6 +296,23 @@ public class HeadersBeanDefinitionParser implements BeanDefinitionParser {
headerWriters.add(headersWriter.getBeanDefinition());
}
private void parseReferrerPolicyElement(Element element, ParserContext context) {
Element referrerPolicyElement = (element == null) ? null : DomUtils.getChildElementByTagName(element, REFERRER_POLICY_ELEMENT);
if (referrerPolicyElement != null) {
addReferrerPolicy(referrerPolicyElement, context);
}
}
private void addReferrerPolicy(Element referrerPolicyElement, ParserContext context) {
BeanDefinitionBuilder headersWriter = BeanDefinitionBuilder.genericBeanDefinition(ReferrerPolicyHeaderWriter.class);
String policy = referrerPolicyElement.getAttribute(ATT_POLICY);
if (StringUtils.hasLength(policy)) {
headersWriter.addConstructorArgValue(ReferrerPolicy.get(policy));
}
headerWriters.add(headersWriter.getBeanDefinition());
}
private void attrNotAllowed(ParserContext context, String attrName,
String otherAttrName, Element element) {
context.getReaderContext().error(
@@ -80,6 +80,7 @@ import org.springframework.util.xml.DomUtils;
import static org.springframework.security.config.http.HttpSecurityBeanDefinitionParser.ATT_FILTERS;
import static org.springframework.security.config.http.HttpSecurityBeanDefinitionParser.ATT_HTTP_METHOD;
import static org.springframework.security.config.http.HttpSecurityBeanDefinitionParser.ATT_PATH_PATTERN;
import static org.springframework.security.config.http.HttpSecurityBeanDefinitionParser.ATT_REQUEST_MATCHER_REF;
import static org.springframework.security.config.http.HttpSecurityBeanDefinitionParser.ATT_REQUIRES_CHANNEL;
import static org.springframework.security.config.http.SecurityFilters.CHANNEL_FILTER;
import static org.springframework.security.config.http.SecurityFilters.CONCURRENT_SESSION_FILTER;
@@ -582,7 +583,7 @@ class HttpConfigurationBuilder {
}
private void createChannelProcessingFilter() {
ManagedMap<BeanDefinition, BeanDefinition> channelRequestMap = parseInterceptUrlsForChannelSecurity();
ManagedMap<BeanMetadataElement, BeanDefinition> channelRequestMap = parseInterceptUrlsForChannelSecurity();
if (channelRequestMap.isEmpty()) {
return;
@@ -636,15 +637,17 @@ class HttpConfigurationBuilder {
* will be empty unless the <tt>requires-channel</tt> attribute has been used on a URL
* path.
*/
private ManagedMap<BeanDefinition, BeanDefinition> parseInterceptUrlsForChannelSecurity() {
private ManagedMap<BeanMetadataElement, BeanDefinition> parseInterceptUrlsForChannelSecurity() {
ManagedMap<BeanDefinition, BeanDefinition> channelRequestMap = new ManagedMap<BeanDefinition, BeanDefinition>();
ManagedMap<BeanMetadataElement, BeanDefinition> channelRequestMap = new ManagedMap<BeanMetadataElement, BeanDefinition>();
for (Element urlElt : interceptUrls) {
String path = urlElt.getAttribute(ATT_PATH_PATTERN);
String method = urlElt.getAttribute(ATT_HTTP_METHOD);
String matcherRef = urlElt.getAttribute(ATT_REQUEST_MATCHER_REF);
boolean hasMatcherRef = StringUtils.hasText(matcherRef);
if (!StringUtils.hasText(path)) {
if (!hasMatcherRef && !StringUtils.hasText(path)) {
pc.getReaderContext().error("pattern attribute cannot be empty or null",
urlElt);
}
@@ -652,7 +655,7 @@ class HttpConfigurationBuilder {
String requiredChannel = urlElt.getAttribute(ATT_REQUIRES_CHANNEL);
if (StringUtils.hasText(requiredChannel)) {
BeanDefinition matcher = matcherType.createMatcher(pc, path, method);
BeanMetadataElement matcher = hasMatcherRef ? new RuntimeBeanReference(matcherRef) : matcherType.createMatcher(pc, path, method);
RootBeanDefinition channelAttributes = new RootBeanDefinition(
ChannelAttributeFactory.class);
@@ -60,7 +60,7 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
.getLog(HttpSecurityBeanDefinitionParser.class);
private static final String ATT_AUTHENTICATION_MANAGER_REF = "authentication-manager-ref";
private static final String ATT_REQUEST_MATCHER_REF = "request-matcher-ref";
static final String ATT_REQUEST_MATCHER_REF = "request-matcher-ref";
static final String ATT_PATH_PATTERN = "pattern";
static final String ATT_HTTP_METHOD = "method";
@@ -163,7 +163,7 @@ final class ProtectPointcutPostProcessor implements BeanPostProcessor {
}
public void setPointcutMap(Map<String, List<ConfigAttribute>> map) {
Assert.notEmpty(map);
Assert.notEmpty(map, "configAttributes cannot be empty");
for (String expression : map.keySet()) {
List<ConfigAttribute> value = map.get(expression);
addPointcut(expression, value);
@@ -255,8 +255,8 @@ public final class WebSocketMessageBrokerSecurityBeanDefinitionParser implements
for (String beanName : beanNames) {
BeanDefinition bd = registry.getBeanDefinition(beanName);
String beanClassName = bd.getBeanClassName();
if (beanClassName.equals(SimpAnnotationMethodMessageHandler.class
.getName()) || beanClassName.equals(WEB_SOCKET_AMMH_CLASS_NAME)) {
if (SimpAnnotationMethodMessageHandler.class.getName().equals(beanClassName) ||
WEB_SOCKET_AMMH_CLASS_NAME.equals(beanClassName)) {
PropertyValue current = bd.getPropertyValues().getPropertyValue(
CUSTOM_ARG_RESOLVERS_PROP);
ManagedList<Object> argResolvers = new ManagedList<Object>();
@@ -275,16 +275,16 @@ public final class WebSocketMessageBrokerSecurityBeanDefinitionParser implements
}
}
}
else if (beanClassName
.equals("org.springframework.web.socket.server.support.WebSocketHttpRequestHandler")) {
else if ("org.springframework.web.socket.server.support.WebSocketHttpRequestHandler"
.equals(beanClassName)) {
addCsrfTokenHandshakeInterceptor(bd);
}
else if (beanClassName
.equals("org.springframework.web.socket.sockjs.transport.TransportHandlingSockJsService")) {
else if ("org.springframework.web.socket.sockjs.transport.TransportHandlingSockJsService"
.equals(beanClassName)) {
addCsrfTokenHandshakeInterceptor(bd);
}
else if (beanClassName
.equals("org.springframework.web.socket.sockjs.transport.handler.DefaultSockJsService")) {
else if ("org.springframework.web.socket.sockjs.transport.handler.DefaultSockJsService"
.equals(beanClassName)) {
addCsrfTokenHandshakeInterceptor(bd);
}
}
@@ -1,4 +1,5 @@
http\://www.springframework.org/schema/security/spring-security.xsd=org/springframework/security/config/spring-security-4.1.xsd
http\://www.springframework.org/schema/security/spring-security.xsd=org/springframework/security/config/spring-security-4.2.xsd
http\://www.springframework.org/schema/security/spring-security-4.2.xsd=org/springframework/security/config/spring-security-4.2.xsd
http\://www.springframework.org/schema/security/spring-security-4.1.xsd=org/springframework/security/config/spring-security-4.1.xsd
http\://www.springframework.org/schema/security/spring-security-4.0.xsd=org/springframework/security/config/spring-security-4.0.xsd
http\://www.springframework.org/schema/security/spring-security-3.2.xsd=org/springframework/security/config/spring-security-3.2.xsd
@@ -366,8 +366,7 @@ intercept-url =
## Specifies the access attributes and/or filter list for a particular set of URLs.
element intercept-url {intercept-url.attlist, empty}
intercept-url.attlist &=
## The pattern which defines the URL path. The content will depend on the type set in the containing http element, so will default to ant path syntax.
attribute pattern {xsd:token}
(pattern | request-matcher-ref)
intercept-url.attlist &=
## The access configuration attributes that apply for the configured path.
attribute access {xsd:token}?
@@ -508,9 +507,6 @@ fsmds.attlist &=
use-expressions?
fsmds.attlist &=
id?
fsmds.attlist &=
## Compare after forcing to lowercase
attribute lowercase-comparisons {xsd:boolean}?
fsmds.attlist &=
request-matcher?
@@ -551,7 +547,7 @@ concurrency-control =
element concurrency-control {concurrency-control.attlist, empty}
concurrency-control.attlist &=
## The maximum number of sessions a single authenticated user can have open at the same time. Defaults to "1". A negative value denotes unlimitted sessions.
## The maximum number of sessions a single authenticated user can have open at the same time. Defaults to "1". A negative value denotes unlimited sessions.
attribute max-sessions {xsd:integer}?
concurrency-control.attlist &=
## The URL a user will be redirected to if they attempt to use a session which has been "expired" because they have logged in again.
@@ -757,7 +753,7 @@ csrf-options.attlist &=
headers =
## Element for configuration of the HeaderWritersFilter. Enables easy setting for the X-Frame-Options, X-XSS-Protection and X-Content-Type-Options headers.
element headers { headers-options.attlist, (cache-control? & xss-protection? & hsts? & frame-options? & content-type-options? & hpkp? & content-security-policy? & header*)}
element headers { headers-options.attlist, (cache-control? & xss-protection? & hsts? & frame-options? & content-type-options? & hpkp? & content-security-policy? & referrer-policy? & header*)}
headers-options.attlist &=
## Specifies if the default headers should be disabled. Default false.
attribute defaults-disabled {xsd:boolean}?
@@ -828,6 +824,13 @@ csp-options.attlist &=
## Set to true, to enable the Content-Security-Policy-Report-Only header for reporting policy violations only. Defaults to false.
attribute report-only {xsd:boolean}?
referrer-policy =
## Adds support for Referrer Policy
element referrer-policy {referrer-options.attlist}
referrer-options.attlist &=
## The policies for the Referrer-Policy header.
attribute policy {"no-referrer","no-referrer-when-downgrade","same-origin","origin","strict-origin","origin-when-cross-origin","strict-origin-when-cross-origin","unsafe-url"}?
cache-control =
## Adds Cache-Control no-cache, no-store, must-revalidate, Pragma no-cache, and Expires 0 for every request
element cache-control {cache-control.attlist}
@@ -1292,10 +1292,15 @@
</xs:attributeGroup>
<xs:attributeGroup name="intercept-url.attlist">
<xs:attribute name="pattern" use="required" type="xs:token">
<xs:attribute name="pattern" type="xs:token">
<xs:annotation>
<xs:documentation>The pattern which defines the URL path. The content will depend on the type set in the
containing http element, so will default to ant path syntax.
<xs:documentation>The request URL pattern which will be mapped to the FilterChain.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="request-matcher-ref" type="xs:token">
<xs:annotation>
<xs:documentation>Allows a RequestMatcher instance to be used, as an alternative to pattern-matching.
</xs:documentation>
</xs:annotation>
</xs:attribute>
@@ -1673,12 +1678,6 @@
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="lowercase-comparisons" type="xs:boolean">
<xs:annotation>
<xs:documentation>Compare after forcing to lowercase
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="request-matcher">
<xs:annotation>
<xs:documentation>Defines the strategy use for matching incoming requests. Currently the options are 'mvc'
@@ -1773,7 +1772,7 @@
<xs:attribute name="max-sessions" type="xs:integer">
<xs:annotation>
<xs:documentation>The maximum number of sessions a single authenticated user can have open at the same time.
Defaults to "1". A negative value denotes unlimitted sessions.
Defaults to "1". A negative value denotes unlimited sessions.
</xs:documentation>
</xs:annotation>
</xs:attribute>
@@ -2358,6 +2357,7 @@
<xs:element ref="security:content-type-options"/>
<xs:element ref="security:hpkp"/>
<xs:element ref="security:content-security-policy"/>
<xs:element ref="security:referrer-policy"/>
<xs:element ref="security:header"/>
</xs:choice>
<xs:attributeGroup ref="security:headers-options.attlist"/>
@@ -2540,6 +2540,35 @@
</xs:annotation>
</xs:attribute>
</xs:attributeGroup>
<xs:element name="referrer-policy">
<xs:annotation>
<xs:documentation>Adds support for Referrer Policy
</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:attributeGroup ref="security:referrer-options.attlist"/>
</xs:complexType>
</xs:element>
<xs:attributeGroup name="referrer-options.attlist">
<xs:attribute name="policy">
<xs:annotation>
<xs:documentation>The policies for the Referrer-Policy header.
</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:token">
<xs:enumeration value="no-referrer"/>
<xs:enumeration value="no-referrer-when-downgrade"/>
<xs:enumeration value="same-origin"/>
<xs:enumeration value="origin"/>
<xs:enumeration value="strict-origin"/>
<xs:enumeration value="origin-when-cross-origin"/>
<xs:enumeration value="strict-origin-when-cross-origin"/>
<xs:enumeration value="unsafe-url"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:attributeGroup>
<xs:element name="cache-control">
<xs:annotation>
<xs:documentation>Adds Cache-Control no-cache, no-store, must-revalidate, Pragma no-cache, and Expires 0 for
@@ -20,12 +20,14 @@ import org.springframework.security.config.annotation.BaseSpringSpec
import org.springframework.security.config.annotation.web.builders.HttpSecurity
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter
import static org.springframework.security.web.header.writers.ReferrerPolicyHeaderWriter.ReferrerPolicy
/**
*
* @author Rob Winch
* @author Tim Ysewyn
* @author Joe Grandja
* @author Eddú Meléndez
*/
class HeadersConfigurerTests extends BaseSpringSpec {
@@ -453,4 +455,46 @@ class HeadersConfigurerTests extends BaseSpringSpec {
}
}
def "headers.referrerPolicy default"() {
setup:
loadConfig(ReferrerPolicyDefaultConfig)
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
responseHeaders == ['Referrer-Policy': 'no-referrer']
}
@EnableWebSecurity
static class ReferrerPolicyDefaultConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.headers()
.defaultsDisabled()
.referrerPolicy();
}
}
def "headers.referrerPolicy custom"() {
setup:
loadConfig(ReferrerPolicyCustomConfig)
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
responseHeaders == ['Referrer-Policy': 'same-origin']
}
@EnableWebSecurity
static class ReferrerPolicyCustomConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.headers()
.defaultsDisabled()
.referrerPolicy(ReferrerPolicy.SAME_ORIGIN);
}
}
}
@@ -920,6 +920,38 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
assertHeaders(response, expectedHeaders)
}
def 'http headers defaults : referrer-policy'() {
setup:
httpAutoConfig {
'headers'('defaults-disabled':true) {
'referrer-policy'()
}
}
createAppContext()
when:
def hf = getFilter(HeaderWriterFilter)
MockHttpServletResponse response = new MockHttpServletResponse()
hf.doFilter(new MockHttpServletRequest(), response, new MockFilterChain())
then:
assertHeaders(response, ['Referrer-Policy': 'no-referrer'])
}
def 'http headers defaults : referrer-policy same-origin'() {
setup:
httpAutoConfig {
'headers'('defaults-disabled':true) {
'referrer-policy'('policy': 'same-origin')
}
}
createAppContext()
when:
def hf = getFilter(HeaderWriterFilter)
MockHttpServletResponse response = new MockHttpServletResponse()
hf.doFilter(new MockHttpServletRequest(), response, new MockFilterChain())
then:
assertHeaders(response, ['Referrer-Policy': 'same-origin'])
}
def assertHeaders(MockHttpServletResponse response, Map<String,String> expected) {
assert response.headerNames == expected.keySet()
expected.each { headerName, value ->
@@ -0,0 +1,53 @@
/*
* 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.annotation.authentication.configuration;
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
*
* @author Rob Winch
*
*/
@RunWith(SpringJUnit4ClassRunner.class)
public class EnableGlobalAuthenticationTests {
@Autowired
AuthenticationConfiguration auth;
// gh-4086
@Test
public void authenticationConfigurationWhenGetAuthenticationManagerThenNotNull() throws Exception {
assertThat(auth.getAuthenticationManager()).isNotNull();
}
@Configuration
@EnableGlobalAuthentication
static class Config {
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("user").password("password").roles("USER");
}
}
}
@@ -0,0 +1,101 @@
/*
* 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.annotation.web;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import javax.servlet.Filter;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
/**
*
* @author Rob Winch
*
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
@WebAppConfiguration
public class HttpSecurityHeadersTests {
@Autowired
WebApplicationContext wac;
@Autowired
Filter springSecurityFilterChain;
MockMvc mockMvc;
@Before
public void setup() throws Exception {
mockMvc = MockMvcBuilders
.webAppContextSetup(wac)
.addFilters(springSecurityFilterChain)
.build();
}
// gh-2953
// gh-3975
@Test
public void headerWhenSpringMvcResourceThenCacheRelatedHeadersReset() throws Exception {
mockMvc.perform(get("/resources/file.js"))
.andExpect(status().isOk())
.andExpect(header().string(HttpHeaders.CACHE_CONTROL,"max-age=12345"))
.andExpect(header().string(HttpHeaders.PRAGMA, ""))
.andExpect(header().string(HttpHeaders.EXPIRES, ""));
}
@Test
public void headerWhenNotSpringResourceThenCacheRelatedHeadersSet() throws Exception {
mockMvc.perform(get("/notresource"))
.andExpect(header().string(HttpHeaders.CACHE_CONTROL,"no-cache, no-store, max-age=0, must-revalidate"))
.andExpect(header().string(HttpHeaders.PRAGMA, "no-cache"))
.andExpect(header().string(HttpHeaders.EXPIRES, "0"));
}
@EnableWebSecurity
static class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
}
}
@EnableWebMvc
@Configuration
static class WebMvcConfig extends WebMvcConfigurerAdapter {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("classpath:/resources/").setCachePeriod(12345);
}
}
}
@@ -0,0 +1,96 @@
/*
* 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.annotation.web;
import static org.assertj.core.api.Assertions.assertThat;
import static org.powermock.api.mockito.PowerMockito.*;
import java.util.Arrays;
import org.junit.After;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.springframework.core.io.support.SpringFactoriesLoader;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.web.context.ConfigurableWebApplicationContext;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
/**
*
* @author Rob Winch
*
*/
@RunWith(PowerMockRunner.class)
@PrepareForTest({ SpringFactoriesLoader.class })
public class WebSecurityConfigurerAdapterPowermockTests {
ConfigurableWebApplicationContext context;
@After
public void close() {
if(context != null) {
context.close();
}
}
@Test
public void loadConfigWhenDefaultConfigurerAsSpringFactoryhenDefaultConfigurerApplied() {
spy(SpringFactoriesLoader.class);
DefaultConfigurer configurer = new DefaultConfigurer();
when(SpringFactoriesLoader
.loadFactories(AbstractHttpConfigurer.class, getClass().getClassLoader()))
.thenReturn(Arrays.<AbstractHttpConfigurer>asList(configurer));
loadConfig(Config.class);
assertThat(configurer.init).isTrue();
assertThat(configurer.configure).isTrue();
}
private void loadConfig(Class<?>... classes) {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.setClassLoader(getClass().getClassLoader());
context.register(classes);
context.refresh();
this.context = context;
}
@EnableWebSecurity
static class Config extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
}
}
static class DefaultConfigurer extends AbstractHttpConfigurer<DefaultConfigurer,HttpSecurity> {
boolean init;
boolean configure;
@Override
public void init(HttpSecurity builder) throws Exception {
this.init = true;
}
@Override
public void configure(HttpSecurity builder) throws Exception {
this.configure = true;
}
}
}
@@ -0,0 +1,105 @@
/*
* 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.annotation.web.configuration;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import org.junit.After;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
/**
*
* @author Rob Winch
*
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
@WebAppConfiguration
public class AuthenticationPrincipalArgumentResolverTests {
@Autowired
WebApplicationContext wac;
@After
public void cleanup() {
SecurityContextHolder.clearContext();
}
@Test
public void authenticationPrincipalExpressionWhenBeanExpressionSuppliedThenBeanUsed() throws Exception {
User user = new User("user", "password", AuthorityUtils.createAuthorityList("ROLE_USER"));
SecurityContext context = SecurityContextHolder.createEmptyContext();
context.setAuthentication(new UsernamePasswordAuthenticationToken(user, user.getPassword(), user.getAuthorities()));
SecurityContextHolder.setContext(context);
MockMvc mockMvc = MockMvcBuilders
.webAppContextSetup(wac)
.build();
mockMvc.perform(get("/users/self"))
.andExpect(status().isOk())
.andExpect(content().string("extracted-user"));
}
@EnableWebSecurity
@EnableWebMvc
static class Config {
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication();
}
@Bean
public UsernameExtractor usernameExtractor() {
return new UsernameExtractor();
}
@RestController
static class UserController {
@GetMapping("/users/self")
public String usersSelf(@AuthenticationPrincipal(expression = "@usernameExtractor.extract(#this)") String userName) {
return userName;
}
}
}
static class UsernameExtractor {
public String extract(User u) {
return "extracted-" + u.getUsername();
}
}
}
@@ -444,7 +444,7 @@ public class AbstractSecurityWebSocketMessageBrokerConfigurerTests {
// @formatter:on
@Bean
public SecurityExpressionHandler<Message<Object>> messageSecurityExpressionHandler() {
public static SecurityExpressionHandler<Message<Object>> messageSecurityExpressionHandler() {
return new DefaultMessageSecurityExpressionHandler<Object>() {
@Override
protected SecurityExpressionOperations createSecurityExpressionRoot(
@@ -0,0 +1,85 @@
/*
* 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.http;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import javax.servlet.Filter;
import org.junit.After;
import org.junit.Test;
import org.springframework.mock.web.MockServletContext;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.ConfigurableWebApplicationContext;
import org.springframework.web.context.support.XmlWebApplicationContext;
public class HttpInterceptUrlTests {
ConfigurableWebApplicationContext context;
MockMvc mockMvc;
@After
public void close() {
if(context != null) {
context.close();
}
}
@Test
public void interceptUrlWhenRequestMatcherRefThenWorks() throws Exception {
loadConfig("interceptUrlWhenRequestMatcherRefThenWorks.xml");
mockMvc.perform(get("/foo"))
.andExpect(status().isUnauthorized());
mockMvc.perform(get("/FOO"))
.andExpect(status().isUnauthorized());
mockMvc.perform(get("/other"))
.andExpect(status().isOk());
}
private void loadConfig(String... configLocations) {
for(int i=0;i<configLocations.length;i++) {
configLocations[i] = getClass().getName().replaceAll("\\.", "/") + "-" + configLocations[i];
}
XmlWebApplicationContext context = new XmlWebApplicationContext();
context.setConfigLocations(configLocations);
context.setServletContext(new MockServletContext());
context.refresh();
this.context = context;
context.getAutowireCapableBeanFactory().autowireBean(this);
Filter springSecurityFilterChain = context.getBean("springSecurityFilterChain", Filter.class);
mockMvc = MockMvcBuilders
.standaloneSetup(new FooController())
.addFilters(springSecurityFilterChain)
.build();
}
@RestController
static class FooController {
@GetMapping("/*")
String foo() {
return "foo";
}
}
}
@@ -40,7 +40,7 @@ public class InMemoryXmlApplicationContext extends AbstractXmlApplicationContext
+ "http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-";
static final String BEANS_CLOSE = "</b:beans>\n";
static final String SPRING_SECURITY_VERSION = "4.1";
static final String SPRING_SECURITY_VERSION = "4.2";
Resource inMemoryXml;
@@ -0,0 +1,34 @@
/*
* 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.
* 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.websocket;
import org.junit.Test;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.beans.factory.support.SimpleBeanDefinitionRegistry;
public class MessageSecurityPostProcessorTest {
private WebSocketMessageBrokerSecurityBeanDefinitionParser.MessageSecurityPostProcessor postProcessor =
new WebSocketMessageBrokerSecurityBeanDefinitionParser.MessageSecurityPostProcessor("id", false);
@Test
public void handlesBeansWithoutClass() {
BeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();
registry.registerBeanDefinition("beanWithoutClass", new GenericBeanDefinition());
postProcessor.postProcessBeanDefinitionRegistry(registry);
}
}
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<b:beans xmlns:b="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/security"
xmlns:c="http://www.springframework.org/schema/c"
xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<http>
<http-basic/>
<intercept-url request-matcher-ref="matcherRef" access="denyAll"/>
</http>
<user-service>
<user name="user" password="password" authorities="ROLE_USER"/>
</user-service>
<b:bean id="matcherRef" class="org.springframework.security.web.util.matcher.AntPathRequestMatcher"
c:pattern="/foo"
c:httpMethod="GET"
c:caseSensitive="false"/>
</b:beans>
@@ -131,7 +131,7 @@
<constructor-arg ref="fooMatcher"/>
<constructor-arg>
<list>
<ref local="mockFilter"/>
<ref bean="mockFilter"/>
</list>
</constructor-arg>
</bean>
@@ -143,9 +143,9 @@
</constructor-arg>
<constructor-arg>
<list>
<ref local="sif"/>
<ref local="mockFilter"/>
<ref local="mockFilter2"/>
<ref bean="sif"/>
<ref bean="mockFilter"/>
<ref bean="mockFilter2"/>
</list>
</constructor-arg>
</bean>
@@ -167,9 +167,9 @@
</constructor-arg>
<constructor-arg>
<list>
<ref local="sif"/>
<ref local="apf"/>
<ref local="mockFilter"/>
<ref bean="sif"/>
<ref bean="apf"/>
<ref bean="mockFilter"/>
</list>
</constructor-arg>
</bean>
@@ -0,0 +1 @@
var f = 1;
+1 -1
View File
@@ -25,7 +25,7 @@ dependencies {
"org.aspectj:aspectjrt:$aspectjVersion",
"org.springframework:spring-jdbc:$springVersion",
"org.springframework:spring-tx:$springVersion",
"com.fasterxml.jackson.core:jackson-databind:$jacksonDatavindVersion"
"com.fasterxml.jackson.core:jackson-databind:$jacksonDatabindVersion"
included cryptoProject
+3 -9
View File
@@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>4.2.0.M1</version>
<version>4.2.2.RELEASE</version>
<name>spring-security-core</name>
<description>spring-security-core</description>
<url>http://spring.io/spring-security</url>
@@ -35,7 +35,7 @@
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-framework-bom</artifactId>
<version>4.3.2.RELEASE</version>
<version>4.3.5.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
@@ -82,7 +82,7 @@
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.4.4</version>
<version>2.8.4</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
@@ -294,12 +294,6 @@
</exclusions>
</dependency>
</dependencies>
<repositories>
<repository>
<id>spring-milestone</id>
<url>https://repo.spring.io/milestone</url>
</repository>
</repositories>
<build>
<plugins>
<plugin>
@@ -49,7 +49,7 @@ public class SecuredAnnotationSecurityMetadataSource extends
public SecuredAnnotationSecurityMetadataSource(
AnnotationMetadataExtractor annotationMetadataExtractor) {
Assert.notNull(annotationMetadataExtractor);
Assert.notNull(annotationMetadataExtractor, "annotationMetadataExtractor cannot be null");
annotationExtractor = annotationMetadataExtractor;
annotationType = (Class<? extends Annotation>) GenericTypeResolver
.resolveTypeArgument(annotationExtractor.getClass(),
@@ -41,7 +41,7 @@ public class RememberMeAuthenticationProvider implements AuthenticationProvider,
private String key;
public RememberMeAuthenticationProvider(String key) {
Assert.hasLength(key);
Assert.hasLength(key, "key must have a length");
this.key = key;
}
@@ -35,13 +35,12 @@ class PasswordEncoderUtils {
byte[] actualBytes = bytesUtf8(actual);
int expectedLength = expectedBytes == null ? -1 : expectedBytes.length;
int actualLength = actualBytes == null ? -1 : actualBytes.length;
if (expectedLength != actualLength) {
return false;
}
int result = 0;
for (int i = 0; i < expectedLength; i++) {
result |= expectedBytes[i] ^ actualBytes[i];
int result = expectedLength == actualLength ? 0 : 1;
for (int i = 0; i < actualLength; i++) {
byte expectedByte = expectedLength <= 0 ? 0 : expectedBytes[i % expectedLength];
byte actualByte = actualBytes[i % actualLength];
result |= expectedByte ^ actualByte;
}
return result == 0;
}
@@ -51,7 +50,7 @@ class PasswordEncoderUtils {
return null;
}
return Utf8.encode(s);
return Utf8.encode(s); // need to check if Utf8.encode() runs in constant time (probably not). This may leak length of string.
}
private PasswordEncoderUtils() {
@@ -45,7 +45,7 @@ public class InteractiveAuthenticationSuccessEvent extends AbstractAuthenticatio
public InteractiveAuthenticationSuccessEvent(Authentication authentication,
Class<?> generatedBy) {
super(authentication);
Assert.notNull(generatedBy);
Assert.notNull(generatedBy, "generatedBy cannot be null");
this.generatedBy = generatedBy;
}
@@ -40,7 +40,7 @@ public class SpringSecurityCoreVersion {
*/
public static final long SERIAL_VERSION_UID = 420L;
static final String MIN_SPRING_VERSION = "4.3.2.RELEASE";
static final String MIN_SPRING_VERSION = "4.3.5.RELEASE";
static {
performVersionChecks();
@@ -17,6 +17,7 @@
package org.springframework.security.core.context;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.StringUtils;
import java.lang.reflect.Constructor;
@@ -93,7 +94,7 @@ public class SecurityContextHolder {
}
private static void initialize() {
if ((strategyName == null) || "".equals(strategyName)) {
if (!StringUtils.hasText(strategyName)) {
// Set default
strategyName = MODE_THREADLOCAL;
}
@@ -17,9 +17,12 @@
package org.springframework.security.core.userdetails;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
@@ -27,6 +30,8 @@ import java.util.TreeSet;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.CredentialsContainer;
import org.springframework.security.core.SpringSecurityCoreVersion;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.util.Assert;
/**
@@ -238,4 +243,183 @@ public class User implements UserDetails, CredentialsContainer {
return sb.toString();
}
public static UserBuilder withUsername(String username) {
return new UserBuilder().username(username);
}
/**
* Builds the user to be added. At minimum the username, password, and authorities
* should provided. The remaining attributes have reasonable defaults.
*/
public static class UserBuilder {
private String username;
private String password;
private List<GrantedAuthority> authorities;
private boolean accountExpired;
private boolean accountLocked;
private boolean credentialsExpired;
private boolean disabled;
/**
* Creates a new instance
*/
private UserBuilder() {
}
/**
* Populates the username. This attribute is required.
*
* @param username the username. Cannot be null.
* @return the {@link UserBuilder} for method chaining (i.e. to populate
* additional attributes for this user)
*/
private UserBuilder username(String username) {
Assert.notNull(username, "username cannot be null");
this.username = username;
return this;
}
/**
* Populates the password. This attribute is required.
*
* @param password the password. Cannot be null.
* @return the {@link UserBuilder} for method chaining (i.e. to populate
* additional attributes for this user)
*/
public UserBuilder password(String password) {
Assert.notNull(password, "password cannot be null");
this.password = password;
return this;
}
/**
* Populates the roles. This method is a shortcut for calling
* {@link #authorities(String...)}, but automatically prefixes each entry with
* "ROLE_". This means the following:
*
* <code>
* builder.roles("USER","ADMIN");
* </code>
*
* is equivalent to
*
* <code>
* builder.authorities("ROLE_USER","ROLE_ADMIN");
* </code>
*
* <p>
* This attribute is required, but can also be populated with
* {@link #authorities(String...)}.
* </p>
*
* @param roles the roles for this user (i.e. USER, ADMIN, etc). Cannot be null,
* contain null values or start with "ROLE_"
* @return the {@link UserBuilder} for method chaining (i.e. to populate
* additional attributes for this user)
*/
public UserBuilder roles(String... roles) {
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>(
roles.length);
for (String role : roles) {
Assert.isTrue(!role.startsWith("ROLE_"), role
+ " cannot start with ROLE_ (it is automatically added)");
authorities.add(new SimpleGrantedAuthority("ROLE_" + role));
}
return authorities(authorities);
}
/**
* Populates the authorities. This attribute is required.
*
* @param authorities the authorities for this user. Cannot be null, or contain
* null values
* @return the {@link UserBuilder} for method chaining (i.e. to populate
* additional attributes for this user)
* @see #roles(String...)
*/
public UserBuilder authorities(GrantedAuthority... authorities) {
return authorities(Arrays.asList(authorities));
}
/**
* Populates the authorities. This attribute is required.
*
* @param authorities the authorities for this user. Cannot be null, or contain
* null values
* @return the {@link UserBuilder} for method chaining (i.e. to populate
* additional attributes for this user)
* @see #roles(String...)
*/
public UserBuilder authorities(List<? extends GrantedAuthority> authorities) {
this.authorities = new ArrayList<GrantedAuthority>(authorities);
return this;
}
/**
* Populates the authorities. This attribute is required.
*
* @param authorities the authorities for this user (i.e. ROLE_USER, ROLE_ADMIN,
* etc). Cannot be null, or contain null values
* @return the {@link UserBuilder} for method chaining (i.e. to populate
* additional attributes for this user)
* @see #roles(String...)
*/
public UserBuilder authorities(String... authorities) {
return authorities(AuthorityUtils.createAuthorityList(authorities));
}
/**
* Defines if the account is expired or not. Default is false.
*
* @param accountExpired true if the account is expired, false otherwise
* @return the {@link UserBuilder} for method chaining (i.e. to populate
* additional attributes for this user)
*/
public UserBuilder accountExpired(boolean accountExpired) {
this.accountExpired = accountExpired;
return this;
}
/**
* Defines if the account is locked or not. Default is false.
*
* @param accountLocked true if the account is locked, false otherwise
* @return the {@link UserBuilder} for method chaining (i.e. to populate
* additional attributes for this user)
*/
public UserBuilder accountLocked(boolean accountLocked) {
this.accountLocked = accountLocked;
return this;
}
/**
* Defines if the credentials are expired or not. Default is false.
*
* @param credentialsExpired true if the credentials are expired, false otherwise
* @return the {@link UserBuilder} for method chaining (i.e. to populate
* additional attributes for this user)
*/
public UserBuilder credentialsExpired(boolean credentialsExpired) {
this.credentialsExpired = credentialsExpired;
return this;
}
/**
* Defines if the account is disabled or not. Default is false.
*
* @param disabled true if the account is disabled, false otherwise
* @return the {@link UserBuilder} for method chaining (i.e. to populate
* additional attributes for this user)
*/
public UserBuilder disabled(boolean disabled) {
this.disabled = disabled;
return this;
}
public UserDetails build() {
return new User(username, password, !disabled, !accountExpired,
!credentialsExpired, !accountLocked, authorities);
}
}
}
@@ -35,7 +35,7 @@ import java.util.Collection;
*
* @author Jitendra Singh
* @see CoreJackson2Module
* @see SecurityJacksonModules
* @see SecurityJackson2Modules
* @since 4.2
*/
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY)
@@ -38,12 +38,13 @@ import java.util.Collections;
* ObjectMapper mapper = new ObjectMapper();
* mapper.registerModule(new CoreJackson2Module());
* </pre>
* <b>Note: use {@link SecurityJacksonModules#getModules(ClassLoader)} to get list of all security modules.</b>
* <b>Note: use {@link SecurityJackson2Modules#getModules(ClassLoader)} to get list of all security modules.</b>
*
* @author Jitendra Singh.
* @see SecurityJacksonModules
* @see SecurityJackson2Modules
* @since 4.2
*/
@SuppressWarnings("serial")
public class CoreJackson2Module extends SimpleModule {
public CoreJackson2Module() {
@@ -52,7 +53,7 @@ public class CoreJackson2Module extends SimpleModule {
@Override
public void setupModule(SetupContext context) {
SecurityJacksonModules.enableDefaultTyping((ObjectMapper) context.getOwner());
SecurityJackson2Modules.enableDefaultTyping((ObjectMapper) context.getOwner());
context.setMixInAnnotations(AnonymousAuthenticationToken.class, AnonymousAuthenticationTokenMixin.class);
context.setMixInAnnotations(RememberMeAuthenticationToken.class, RememberMeAuthenticationTokenMixin.class);
context.setMixInAnnotations(SimpleGrantedAuthority.class, SimpleGrantedAuthorityMixin.class);
@@ -41,7 +41,7 @@ import java.util.Collection;
*
* @author Jitendra Singh
* @see CoreJackson2Module
* @see SecurityJacksonModules
* @see SecurityJackson2Modules
* @since 4.2
*/
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY)
@@ -34,7 +34,7 @@ import java.util.List;
* <p>
* <pre>
* ObjectMapper mapper = new ObjectMapper();
* mapper.registerModules(SecurityJacksonModules.getModules());
* mapper.registerModules(SecurityJackson2Modules.getModules());
* </pre>
* Above code is equivalent to
* <p>
@@ -49,16 +49,16 @@ import java.util.List;
* @author Jitendra Singh.
* @since 4.2
*/
public final class SecurityJacksonModules {
public final class SecurityJackson2Modules {
private static final Log logger = LogFactory.getLog(SecurityJacksonModules.class);
private static final Log logger = LogFactory.getLog(SecurityJackson2Modules.class);
private static final List<String> securityJackson2ModuleClasses = Arrays.asList(
"org.springframework.security.jackson2.CoreJackson2Module",
"org.springframework.security.cas.jackson2.CasJackson2Module",
"org.springframework.security.web.jackson2.WebJackson2Module"
);
private SecurityJacksonModules() {
private SecurityJackson2Modules() {
}
public static void enableDefaultTyping(ObjectMapper mapper) {
@@ -28,7 +28,7 @@ import com.fasterxml.jackson.annotation.*;
* </pre>
* @author Jitendra Singh
* @see CoreJackson2Module
* @see SecurityJacksonModules
* @see SecurityJackson2Modules
* @since 4.2
*/
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY)
@@ -0,0 +1,61 @@
/*
* Copyright 2015-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.jackson2;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import java.io.IOException;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
/**
* Custom deserializer for {@link UnmodifiableSetMixin}.
*
* @author Jitendra Singh
* @see UnmodifiableSetMixin
* @since 4.2
*/
class UnmodifiableSetDeserializer extends JsonDeserializer<Set> {
@Override
public Set deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
ObjectMapper mapper = (ObjectMapper) jp.getCodec();
JsonNode node = mapper.readTree(jp);
Set<Object> resultSet = new HashSet<Object>();
if (node != null) {
if (node instanceof ArrayNode) {
ArrayNode arrayNode = (ArrayNode) node;
Iterator<JsonNode> nodeIterator = arrayNode.iterator();
while (nodeIterator.hasNext()) {
JsonNode elementNode = nodeIterator.next();
resultSet.add(mapper.readValue(elementNode.toString(), Object.class));
}
} else {
resultSet.add(mapper.readValue(node.toString(), Object.class));
}
}
return Collections.unmodifiableSet(resultSet);
}
}
@@ -18,6 +18,7 @@ package org.springframework.security.jackson2;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import java.util.Set;
@@ -31,11 +32,13 @@ import java.util.Set;
* </pre>
*
* @author Jitendra Singh
* @see UnmodifiableSetDeserializer
* @see CoreJackson2Module
* @see SecurityJacksonModules
* @see SecurityJackson2Modules
* @since 4.2
*/
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY)
@JsonDeserialize(using = UnmodifiableSetDeserializer.class)
class UnmodifiableSetMixin {
/**
@@ -37,7 +37,7 @@ import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
* @author Jitendra Singh
* @see UserDeserializer
* @see CoreJackson2Module
* @see SecurityJacksonModules
* @see SecurityJackson2Modules
* @since 4.2
*/
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY)
@@ -37,7 +37,7 @@ import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
* </pre>
* @author Jitendra Singh
* @see CoreJackson2Module
* @see SecurityJacksonModules
* @see SecurityJackson2Modules
* @since 4.2
*/
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class")
@@ -52,6 +52,9 @@ public class InMemoryUserDetailsManager implements UserDetailsManager {
private AuthenticationManager authenticationManager;
public InMemoryUserDetailsManager() {
}
public InMemoryUserDetailsManager(Collection<UserDetails> users) {
for (UserDetails user : users) {
createUser(user);
@@ -73,7 +76,7 @@ public class InMemoryUserDetailsManager implements UserDetailsManager {
}
public void createUser(UserDetails user) {
Assert.isTrue(!userExists(user.getUsername()));
Assert.isTrue(!userExists(user.getUsername()), "user should not exist");
users.put(user.getUsername().toLowerCase(), new MutableUser(user));
}
@@ -83,7 +86,7 @@ public class InMemoryUserDetailsManager implements UserDetailsManager {
}
public void updateUser(UserDetails user) {
Assert.isTrue(userExists(user.getUsername()));
Assert.isTrue(userExists(user.getUsername()), "user should exist");
users.put(user.getUsername().toLowerCase(), new MutableUser(user));
}
@@ -258,15 +258,15 @@ public class JdbcUserDetailsManager extends JdbcDaoImpl implements UserDetailsMa
}
public List<String> findUsersInGroup(String groupName) {
Assert.hasText(groupName);
Assert.hasText(groupName, "groupName should have text");
return getJdbcTemplate().queryForList(findUsersInGroupSql,
new String[] { groupName }, String.class);
}
public void createGroup(final String groupName,
final List<GrantedAuthority> authorities) {
Assert.hasText(groupName);
Assert.notNull(authorities);
Assert.hasText(groupName, "groupName should have text");
Assert.notNull(authorities, "authorities cannot be null");
logger.debug("Creating new group '" + groupName + "' with authorities "
+ AuthorityUtils.authorityListToSet(authorities));
@@ -289,7 +289,7 @@ public class JdbcUserDetailsManager extends JdbcDaoImpl implements UserDetailsMa
public void deleteGroup(String groupName) {
logger.debug("Deleting group '" + groupName + "'");
Assert.hasText(groupName);
Assert.hasText(groupName, "groupName should have text");
final int id = findGroupId(groupName);
PreparedStatementSetter groupIdPSS = new PreparedStatementSetter() {
@@ -304,16 +304,16 @@ public class JdbcUserDetailsManager extends JdbcDaoImpl implements UserDetailsMa
public void renameGroup(String oldName, String newName) {
logger.debug("Changing group name from '" + oldName + "' to '" + newName + "'");
Assert.hasText(oldName);
Assert.hasText(newName);
Assert.hasText(oldName,"oldName should have text");;
Assert.hasText(newName,"newName should have text");;
getJdbcTemplate().update(renameGroupSql, newName, oldName);
}
public void addUserToGroup(final String username, final String groupName) {
logger.debug("Adding user '" + username + "' to group '" + groupName + "'");
Assert.hasText(username);
Assert.hasText(groupName);
Assert.hasText(username,"username should have text");;
Assert.hasText(groupName,"groupName should have text");;
final int id = findGroupId(groupName);
getJdbcTemplate().update(insertGroupMemberSql, new PreparedStatementSetter() {
@@ -328,8 +328,8 @@ public class JdbcUserDetailsManager extends JdbcDaoImpl implements UserDetailsMa
public void removeUserFromGroup(final String username, final String groupName) {
logger.debug("Removing user '" + username + "' to group '" + groupName + "'");
Assert.hasText(username);
Assert.hasText(groupName);
Assert.hasText(username,"username should have text");;
Assert.hasText(groupName,"groupName should have text");;
final int id = findGroupId(groupName);
@@ -345,7 +345,7 @@ public class JdbcUserDetailsManager extends JdbcDaoImpl implements UserDetailsMa
public List<GrantedAuthority> findGroupAuthorities(String groupName) {
logger.debug("Loading authorities for group '" + groupName + "'");
Assert.hasText(groupName);
Assert.hasText(groupName,"groupName should have text");;
return getJdbcTemplate().query(groupAuthoritiesSql, new String[] { groupName },
new RowMapper<GrantedAuthority>() {
@@ -361,8 +361,8 @@ public class JdbcUserDetailsManager extends JdbcDaoImpl implements UserDetailsMa
public void removeGroupAuthority(String groupName, final GrantedAuthority authority) {
logger.debug("Removing authority '" + authority + "' from group '" + groupName
+ "'");
Assert.hasText(groupName);
Assert.notNull(authority);
Assert.hasText(groupName,"groupName should have text");
Assert.notNull(authority, "authority cannot be null");
final int id = findGroupId(groupName);
@@ -377,8 +377,8 @@ public class JdbcUserDetailsManager extends JdbcDaoImpl implements UserDetailsMa
public void addGroupAuthority(final String groupName, final GrantedAuthority authority) {
logger.debug("Adding authority '" + authority + "' to group '" + groupName + "'");
Assert.hasText(groupName);
Assert.notNull(authority);
Assert.hasText(groupName,"groupName should have text");;
Assert.notNull(authority, "authority cannot be null");
final int id = findGroupId(groupName);
getJdbcTemplate().update(insertGroupAuthoritySql, new PreparedStatementSetter() {
@@ -398,102 +398,102 @@ public class JdbcUserDetailsManager extends JdbcDaoImpl implements UserDetailsMa
}
public void setCreateUserSql(String createUserSql) {
Assert.hasText(createUserSql);
Assert.hasText(createUserSql,"createUserSql should have text");;
this.createUserSql = createUserSql;
}
public void setDeleteUserSql(String deleteUserSql) {
Assert.hasText(deleteUserSql);
Assert.hasText(deleteUserSql,"deleteUserSql should have text");;
this.deleteUserSql = deleteUserSql;
}
public void setUpdateUserSql(String updateUserSql) {
Assert.hasText(updateUserSql);
Assert.hasText(updateUserSql,"updateUserSql should have text");;
this.updateUserSql = updateUserSql;
}
public void setCreateAuthoritySql(String createAuthoritySql) {
Assert.hasText(createAuthoritySql);
Assert.hasText(createAuthoritySql,"createAuthoritySql should have text");;
this.createAuthoritySql = createAuthoritySql;
}
public void setDeleteUserAuthoritiesSql(String deleteUserAuthoritiesSql) {
Assert.hasText(deleteUserAuthoritiesSql);
Assert.hasText(deleteUserAuthoritiesSql,"deleteUserAuthoritiesSql should have text");;
this.deleteUserAuthoritiesSql = deleteUserAuthoritiesSql;
}
public void setUserExistsSql(String userExistsSql) {
Assert.hasText(userExistsSql);
Assert.hasText(userExistsSql,"userExistsSql should have text");;
this.userExistsSql = userExistsSql;
}
public void setChangePasswordSql(String changePasswordSql) {
Assert.hasText(changePasswordSql);
Assert.hasText(changePasswordSql,"changePasswordSql should have text");;
this.changePasswordSql = changePasswordSql;
}
public void setFindAllGroupsSql(String findAllGroupsSql) {
Assert.hasText(findAllGroupsSql);
Assert.hasText(findAllGroupsSql,"findAllGroupsSql should have text");;
this.findAllGroupsSql = findAllGroupsSql;
}
public void setFindUsersInGroupSql(String findUsersInGroupSql) {
Assert.hasText(findUsersInGroupSql);
Assert.hasText(findUsersInGroupSql,"findUsersInGroupSql should have text");;
this.findUsersInGroupSql = findUsersInGroupSql;
}
public void setInsertGroupSql(String insertGroupSql) {
Assert.hasText(insertGroupSql);
Assert.hasText(insertGroupSql,"insertGroupSql should have text");;
this.insertGroupSql = insertGroupSql;
}
public void setFindGroupIdSql(String findGroupIdSql) {
Assert.hasText(findGroupIdSql);
Assert.hasText(findGroupIdSql,"findGroupIdSql should have text");;
this.findGroupIdSql = findGroupIdSql;
}
public void setInsertGroupAuthoritySql(String insertGroupAuthoritySql) {
Assert.hasText(insertGroupAuthoritySql);
Assert.hasText(insertGroupAuthoritySql,"insertGroupAuthoritySql should have text");;
this.insertGroupAuthoritySql = insertGroupAuthoritySql;
}
public void setDeleteGroupSql(String deleteGroupSql) {
Assert.hasText(deleteGroupSql);
Assert.hasText(deleteGroupSql,"deleteGroupSql should have text");;
this.deleteGroupSql = deleteGroupSql;
}
public void setDeleteGroupAuthoritiesSql(String deleteGroupAuthoritiesSql) {
Assert.hasText(deleteGroupAuthoritiesSql);
Assert.hasText(deleteGroupAuthoritiesSql,"deleteGroupAuthoritiesSql should have text");;
this.deleteGroupAuthoritiesSql = deleteGroupAuthoritiesSql;
}
public void setDeleteGroupMembersSql(String deleteGroupMembersSql) {
Assert.hasText(deleteGroupMembersSql);
Assert.hasText(deleteGroupMembersSql,"deleteGroupMembersSql should have text");;
this.deleteGroupMembersSql = deleteGroupMembersSql;
}
public void setRenameGroupSql(String renameGroupSql) {
Assert.hasText(renameGroupSql);
Assert.hasText(renameGroupSql,"renameGroupSql should have text");;
this.renameGroupSql = renameGroupSql;
}
public void setInsertGroupMemberSql(String insertGroupMemberSql) {
Assert.hasText(insertGroupMemberSql);
Assert.hasText(insertGroupMemberSql,"insertGroupMemberSql should have text");;
this.insertGroupMemberSql = insertGroupMemberSql;
}
public void setDeleteGroupMemberSql(String deleteGroupMemberSql) {
Assert.hasText(deleteGroupMemberSql);
Assert.hasText(deleteGroupMemberSql,"deleteGroupMemberSql should have text");;
this.deleteGroupMemberSql = deleteGroupMemberSql;
}
public void setGroupAuthoritiesSql(String groupAuthoritiesSql) {
Assert.hasText(groupAuthoritiesSql);
Assert.hasText(groupAuthoritiesSql,"groupAuthoritiesSql should have text");;
this.groupAuthoritiesSql = groupAuthoritiesSql;
}
public void setDeleteGroupAuthoritySql(String deleteGroupAuthoritySql) {
Assert.hasText(deleteGroupAuthoritySql);
Assert.hasText(deleteGroupAuthoritySql,"deleteGroupAuthoritySql should have text");;
this.deleteGroupAuthoritySql = deleteGroupAuthoritySql;
}
@@ -52,7 +52,7 @@ public class InMemoryResource extends AbstractResource {
}
public InMemoryResource(byte[] source, String description) {
Assert.notNull(source);
Assert.notNull(source, "source cannot be null");
this.source = source;
this.description = description;
}
@@ -74,7 +74,7 @@ public abstract class HierarchicalRolesTestHelper {
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>(roles.length);
for (final String role : roles) {
// Use non GrantedAuthorityImpl (SEC-863)
// Use non SimpleGrantedAuthority (SEC-863)
authorities.add(new GrantedAuthority() {
public String getAuthority() {
return role;
@@ -28,10 +28,16 @@ import static org.assertj.core.api.Assertions.assertThat;
* @author Joe Grandja
*/
public class RoleHierarchyUtilsTests {
private static final String EOL = System.lineSeparator();
@Test
public void roleHierarchyFromMapWhenMapValidThenConvertsCorrectly() throws Exception {
String expectedRoleHierarchy = "ROLE_A > ROLE_B\nROLE_A > ROLE_C\nROLE_B > ROLE_D\nROLE_C > ROLE_D\n";
// @formatter:off
String expectedRoleHierarchy = "ROLE_A > ROLE_B" + EOL +
"ROLE_A > ROLE_C" + EOL +
"ROLE_B > ROLE_D" + EOL +
"ROLE_C > ROLE_D" + EOL;
// @formatter:on
Map<String, List<String>> roleHierarchyMap = new TreeMap<String, List<String>>();
roleHierarchyMap.put("ROLE_A", asList("ROLE_B", "ROLE_C"));
@@ -25,25 +25,46 @@ import org.junit.Test;
public class PasswordEncoderUtilsTests {
@Test
public void differentLength() {
public void equalsWhenDifferentLengthThenFalse() {
assertThat(PasswordEncoderUtils.equals("abc", "a")).isFalse();
assertThat(PasswordEncoderUtils.equals("a", "abc")).isFalse();
}
@Test
public void equalsNull() {
public void equalsWhenNullAndNotEmtpyThenFalse() {
assertThat(PasswordEncoderUtils.equals(null, "a")).isFalse();
assertThat(PasswordEncoderUtils.equals("a", null)).isFalse();
}
@Test
public void equalsWhenNullAndNullThenTrue() {
assertThat(PasswordEncoderUtils.equals(null, null)).isTrue();
}
@Test
public void equalsCaseSensitive() {
public void equalsWhenNullAndEmptyThenFalse() {
assertThat(PasswordEncoderUtils.equals(null, "")).isFalse();
assertThat(PasswordEncoderUtils.equals("", null)).isFalse();
}
@Test
public void equalsWhenNotEmptyAndEmptyThenFalse() {
assertThat(PasswordEncoderUtils.equals("abc", "")).isFalse();
assertThat(PasswordEncoderUtils.equals("", "abc")).isFalse();
}
@Test
public void equalsWhenEmtpyAndEmptyThenTrue() {
assertThat(PasswordEncoderUtils.equals("", "")).isTrue();
}
@Test
public void equalsWhenDifferentCaseThenFalse() {
assertThat(PasswordEncoderUtils.equals("aBc", "abc")).isFalse();
}
@Test
public void equalsSuccess() {
public void equalsWhenSameThenTrue() {
assertThat(PasswordEncoderUtils.equals("abcdef", "abcdef")).isTrue();
}
}
@@ -33,7 +33,7 @@ public abstract class AbstractMixinTests {
public void setup() {
mapper = new ObjectMapper();
ClassLoader loader = getClass().getClassLoader();
mapper.registerModules(SecurityJacksonModules.getModules(loader));
mapper.registerModules(SecurityJackson2Modules.getModules(loader));
}
User createDefaultUser() {
+2 -8
View File
@@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-crypto</artifactId>
<version>4.2.0.M1</version>
<version>4.2.2.RELEASE</version>
<name>spring-security-crypto</name>
<description>spring-security-crypto</description>
<url>http://spring.io/spring-security</url>
@@ -35,7 +35,7 @@
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-framework-bom</artifactId>
<version>4.3.2.RELEASE</version>
<version>4.3.5.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
@@ -92,12 +92,6 @@
<scope>test</scope>
</dependency>
</dependencies>
<repositories>
<repository>
<id>spring-milestone</id>
<url>https://repo.spring.io/milestone</url>
</repository>
</repositories>
<build>
<plugins>
<plugin>
@@ -532,8 +532,9 @@ public class BCrypt {
* @param password the password to hash
* @param salt the salt to hash with (perhaps generated using BCrypt.gensalt)
* @return the hashed password
* @throws IllegalArgumentException if invalid salt is passed
*/
public static String hashpw(String password, String salt) {
public static String hashpw(String password, String salt) throws IllegalArgumentException {
BCrypt B;
String real_salt;
byte passwordb[], saltb[], hashed[];
@@ -541,6 +542,10 @@ public class BCrypt {
int rounds, off = 0;
StringBuilder rs = new StringBuilder();
if (salt == null) {
throw new IllegalArgumentException("salt cannot be null");
}
int saltLength = salt.length();
if (saltLength < 28) {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* 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.
@@ -163,7 +163,7 @@ public class SCryptPasswordEncoder implements PasswordEncoder {
}
private String digest(CharSequence rawPassword, byte[] salt) {
byte[] derived = SCrypt.generate(Utf8.encode(rawPassword), salt, cpuCost, memoryCost, parallelization, 32);
byte[] derived = SCrypt.generate(Utf8.encode(rawPassword), salt, cpuCost, memoryCost, parallelization, keyLength);
String params = Long
.toString(((int) (Math.log(cpuCost) / Math.log(2)) << 16L) | memoryCost << 8 | parallelization, 16);
@@ -14,10 +14,11 @@
package org.springframework.security.crypto.bcrypt;
import org.junit.Test;
import java.util.Arrays;
import org.junit.Test;
import static org.assertj.core.api.Assertions.*;
import static org.assertj.core.api.Assertions.assertThat;
/**
* JUnit unit tests for BCrypt routines
@@ -271,6 +272,11 @@ public class BCryptTests {
assertThat(BCrypt.gensalt(31).startsWith("$2a$31$")).isTrue();
}
@Test(expected = IllegalArgumentException.class)
public void hashpwFailsWhenSaltIsNull() {
BCrypt.hashpw("password", null);
}
@Test(expected = IllegalArgumentException.class)
public void hashpwFailsWhenSaltSpecifiesTooFewRounds() {
BCrypt.hashpw("password", "$2a$03$......................");
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* 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.
@@ -65,7 +65,7 @@ public class SCryptPasswordEncoderTests {
@Test
public void samePasswordWithDifferentParams() {
SCryptPasswordEncoder oldEncoder = new SCryptPasswordEncoder(512, 8, 4, 64, 16);
SCryptPasswordEncoder oldEncoder = new SCryptPasswordEncoder(16384, 8, 1, 32,64);
SCryptPasswordEncoder newEncoder = new SCryptPasswordEncoder();
String password = "secret";
+3 -9
View File
@@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-data</artifactId>
<version>4.2.0.M1</version>
<version>4.2.2.RELEASE</version>
<name>spring-security-data</name>
<description>spring-security-data</description>
<url>http://spring.io/spring-security</url>
@@ -35,7 +35,7 @@
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-framework-bom</artifactId>
<version>4.3.2.RELEASE</version>
<version>4.3.5.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
@@ -51,7 +51,7 @@
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>4.2.0.M1</version>
<version>4.2.2.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
@@ -108,12 +108,6 @@
<scope>test</scope>
</dependency>
</dependencies>
<repositories>
<repository>
<id>spring-milestone</id>
<url>https://repo.spring.io/milestone</url>
</repository>
</repositories>
<build>
<plugins>
<plugin>
@@ -162,12 +162,12 @@ Our existing configuration means that all we need to do is create a *login.html*
.src/main/resources/views/login.html
[source,xml]
----
<html xmlns:th="http://www.thymeleaf.org" xmlns:tiles="http://www.thymeleaf.org">
<head>
<title tiles:fragment="title">Messages : Create</title>
<html xmlns:th="http://www.thymeleaf.org">
<head th:include="layout :: head(title=~{::title},links=~{})">
<title>Please Login</title>
</head>
<body>
<div tiles:fragment="content">
<body th:include="layout :: body" th:with="content=~{::content}">
<div th:fragment="content">
<form name="f" th:action="@{/login}" method="post"> <1>
<fieldset>
<legend>Please Login</legend>
@@ -431,7 +431,7 @@ To use JDBC instead, you can implement the interface yourself, using whatever SQ
* prefix "ROLE_" to mark attributes which are supported by Spring Security's RoleVoter.
*/
public GrantedAuthority mapRow(ResultSet rs, int rowNum) throws SQLException {
return new GrantedAuthorityImpl("ROLE_" + rs.getString(1);
return new SimpleGrantedAuthority("ROLE_" + rs.getString(1);
}
}
}
@@ -10,7 +10,7 @@ To use it, register the `JacksonJacksonModules.getModules(ClassLoader)` as http:
----
ObjectMapper mapper = new ObjectMapper();
ClassLoader loader = getClass().getClassLoader();
List<Module> modules = SecurityJacksonModules.getModules(loader);
List<Module> modules = SecurityJackson2Modules.getModules(loader);
mapper.registerModules(modules);
// ... use ObjectMapper as normally ...
@@ -0,0 +1,11 @@
[[appendix-proxy-server]]
== Proxy Server Configuration
When using a proxy server it is important to ensure that you have configured your application properly.
For example, many applications will have a load balancer that responds to request for https://example.com/ by forwarding the request to an application server at http://192.168.1:8080
Without proper configuration, the application server will not know that the load balancer exists and treat the request as though http://192.168.1:8080 was requested by the client.
To fix this you can use https://tools.ietf.org/html/rfc7239[RFC 7239] to specify that a load balancer is being used.
To make the application aware of this, you need to either configure your application server aware of the X-Forwarded headers.
For example Tomcat uses the https://tomcat.apache.org/tomcat-8.0-doc/api/org/apache/catalina/valves/RemoteIpValve.html[RemoteIpValve] and Jetty uses http://download.eclipse.org/jetty/stable-9/apidocs/org/eclipse/jetty/server/ForwardedRequestCustomizer.html[ForwardedRequestCustomizer].
Alternatively, Spring 4.3+ users can leverage https://github.com/spring-projects/spring-framework/blob/v4.3.3.RELEASE/spring-web/src/main/java/org/springframework/web/filter/ForwardedHeaderFilter.java[ForwardedHeaderFilter].
@@ -11,7 +11,7 @@ To use the Spring Security test support, you must include `spring-security-test-
[[test-method]]
== Testing Method Security
This section demonstrates how to use Spring Security's Test support to test method based security.
This section demonstrates how to use Spring Security's Test support to test method based security.
We first introduce a `MessageService` that requires the user to be authenticated in order to access it.
[source,java]
@@ -49,13 +49,13 @@ public class WithMockUserTests {
This is a basic example of how to setup Spring Security Test. The highlights are:
<1> `@RunWith` instructs the spring-test module that it should create an ApplicationContext This is no different than using the existing Spring Test support. For additional information, refer to the http://docs.spring.io/spring-framework/docs/4.0.x/spring-framework-reference/htmlsingle/#integration-testing-annotations-standard[Spring Reference]
<1> `@RunWith` instructs the spring-test module that it should create an `ApplicationContext`. This is no different than using the existing Spring Test support. For additional information, refer to the http://docs.spring.io/spring-framework/docs/4.0.x/spring-framework-reference/htmlsingle/#integration-testing-annotations-standard[Spring Reference]
<2> `@ContextConfiguration` instructs the spring-test the configuration to use to create the `ApplicationContext`. Since no configuration is specified, the default configuration locations will be tried. This is no different than using the existing Spring Test support. For additional information, refer to the http://docs.spring.io/spring-framework/docs/4.0.x/spring-framework-reference/htmlsingle/#testcontext-ctx-management[Spring Reference]
NOTE: Spring Security hooks into Spring Test support using the `WithSecurityContextTestExecutionListener` which will ensure our tests are ran with the correct user.
NOTE: Spring Security hooks into Spring Test support using the `WithSecurityContextTestExecutionListener` which will ensure our tests are ran with the correct user.
It does this by populating the `SecurityContextHolder` prior to running our tests.
After the test is done, it will clear out the `SecurityContextHolder`.
If you only need Spring Security related support, you can replace `@ContextConfiguration` with `@SecurityExecutionListeners`.
If you only need Spring Security related support, you can replace `@ContextConfiguration` with `@SecurityTestExecutionListeners`.
Remember we added the `@PreAuthorize` annotation to our `HelloMessageService` and so it requires an authenticated user to invoke it.
If we ran the following test, we would expect the following test will pass:
@@ -73,7 +73,7 @@ public void getMessageUnauthenticated() {
The question is "How could we most easily run the test as a specific user?"
The answer is to use `@WithMockUser`.
The following test will be ran as a user with the username "user", the password "password", and the roles "ROLE_USER".
The following test will be run as a user with the username "user", the password "password", and the roles "ROLE_USER".
[source,java]
----
@@ -291,7 +291,7 @@ final class WithUserDetailsSecurityContextFactory
public SecurityContext createSecurityContext(WithUserDetails withUser) {
String username = withUser.value();
Assert.hasLength(username, "value() must be non empty String");
Assert.hasLength(username, "value() must be non-empty String");
UserDetails principal = userDetailsService.loadUserByUsername(username);
Authentication authentication = new UsernamePasswordAuthenticationToken(principal, principal.getPassword(), principal.getAuthorities());
SecurityContext context = SecurityContextHolder.createEmptyContext();
@@ -386,7 +386,7 @@ import static org.springframework.security.test.web.servlet.request.SecurityMock
[[test-mockmvc-csrf]]
==== Testing with CSRF Protection
When testing any non safe HTTP methods and using Spring Security's CSRF protection, you must be sure to include a valid CSRF Token in the request.
When testing any non-safe HTTP methods and using Spring Security's CSRF protection, you must be sure to include a valid CSRF Token in the request.
To specify a valid CSRF token as a request parameter using the following:
[source,java]
@@ -93,7 +93,7 @@ public class WebSocketSecurityConfig extends AbstractSecurityWebSocketMessageBro
This will ensure that:
<1> Any message without a destination (i.e. anything other that Message type of MESSAGE or SUBSCRIBE) will require the user to be authenticated
<1> Any message without a destination (i.e. anything other than Message type of MESSAGE or SUBSCRIBE) will require the user to be authenticated
<2> Anyone can subscribe to /user/queue/errors
<3> Any message that has a destination starting with "/app/" will be require the user to have the role ROLE_USER
<4> Any message that starts with "/user/" or "/topic/friends/" that is of type SUBSCRIBE will require ROLE_USER
@@ -162,7 +162,7 @@ It is also is important to understand how destinations are transformed.
Consider a chat application.
* User's can send messages to a specific user by sending a message to the destination of "/app/chat".
* Users can send messages to a specific user by sending a message to the destination of "/app/chat".
* The application sees the message, ensures that the "from" attribute is specified as the current user (we cannot trust the client).
* The application then sends the message to the recipient using `SimpMessageSendingOperations.convertAndSendToUser("toUser", "/queue/messages", message)`.
* The message gets turned into the destination of "/queue/user/messages-<sessionid>"
@@ -200,7 +200,7 @@ The Same Origin Policy ensures that evil.com cannot read or write data to bank.c
With WebSockets the Same Origin Policy does not apply.
In fact, unless bank.com explicitly forbids it, evil.com can read and write data on behalf of the user.
This means that anything the user can do over the websocket (i.e. transfer money), evil.com can do on that users behalf.
This means that anything the user can do over the webSocket (i.e. transfer money), evil.com can do on that users behalf.
Since SockJS tries to emulate WebSockets it also bypasses the Same Origin Policy.
This means developers need to explicitly protect their applications from external domains when using SockJS.
@@ -246,7 +246,7 @@ public class CsrfController {
}
----
The javascript can make a REST call to the endpoint and use the response to populate the headerName and the token.
The JavaScript can make a REST call to the endpoint and use the response to populate the headerName and the token.
We can now include the token in our Stomp client.
For example:
@@ -397,4 +397,4 @@ For example:
</b:bean>
</b:constructor-arg>
</b:bean>
----
----
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -1 +1 @@
version=4.2.0.M1
version=4.2.2.RELEASE
+1 -1
View File
@@ -1,4 +1,4 @@
apply plugin: 'spring-boot'
apply plugin: 'org.springframework.boot'
sonarqube {
skipProject = true
+2
View File
@@ -50,6 +50,8 @@ tasks["eclipseJdt"].dependsOn(eclipseJdtPrepare)
tasks["cleanEclipse"].dependsOn(cleanEclipseJdtUi)
tasks["eclipse"].dependsOn(eclipseCheckstyle, eclipseSettings, eclipseWstComponent)
task eclipseConfiguration(dependsOn: [eclipseCheckstyle, eclipseSettings, eclipseWstComponent]) {
}
eclipse {
classpath {
+8 -4
View File
@@ -19,23 +19,27 @@ ext.ehcacheVersion = '2.9.0'
ext.gebVersion = '0.10.0'
ext.groovyVersion = '2.4.4'
ext.hsqlVersion = '2.3.2'
ext.jacksonDatavindVersion = '2.4.4'
ext.hibernateVersion = '5.0.11.Final'
ext.hibernateValidatorVersion = '5.2.4.Final'
ext.jacksonDatabindVersion = '2.8.4'
ext.javaPersistenceVersion = '2.1.1'
ext.jettyVersion = '6.1.26'
ext.jstlVersion = '1.2.1'
ext.junitVersion = '4.12'
ext.logbackVersion = '1.1.2'
ext.powerMockVersion = '1.6.2'
ext.seleniumVersion = '2.44.0'
ext.servletApiVersion = '3.0.1'
ext.servletApiVersion = '3.1.0'
ext.slf4jVersion = '1.7.7'
ext.spockVersion = '0.7-groovy-2.0'
ext.springDataCommonsVersion = '1.12.2.RELEASE'
ext.springDataJpaVersion = '1.10.2.RELEASE'
ext.springDataRedisVersion = '1.7.2.RELEASE'
ext.springSessionVersion = '1.2.1.RELEASE'
ext.springBootVersion = '1.4.0.RELEASE'
ext.thymeleafVersion = '2.1.5.RELEASE'
ext.springBootVersion = '1.5.0.BUILD-SNAPSHOT'
ext.thymeleafVersion = '3.0.2.RELEASE'
ext.jsonassertVersion = '1.3.0'
ext.validationApiVersion = '1.1.0.Final'
ext.spockDependencies = [
dependencies.create("org.spockframework:spock-spring:$spockVersion") {
Vendored
+2 -1
View File
@@ -7,7 +7,8 @@
##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS="-Xmx1024M -XX:MaxPermSize=512M"
DEFAULT_JVM_OPTS="-Xmx2048M -XX:MaxPermSize=512M"
export GRADLE_OPTS='-Dorg.gradle.daemon=false'
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
Vendored
+1
View File
@@ -10,6 +10,7 @@ if "%OS%"=="Windows_NT" setlocal
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=-Xmx1024M
set GRADLE_OPTS="-Dorg.gradle.daemon=false"
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
+6 -12
View File
@@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.security</groupId>
<artifactId>itest-context</artifactId>
<version>4.2.0.M1</version>
<version>4.2.2.RELEASE</version>
<name>itest-context</name>
<description>itest-context</description>
<url>http://spring.io/spring-security</url>
@@ -35,7 +35,7 @@
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-framework-bom</artifactId>
<version>4.3.2.RELEASE</version>
<version>4.3.5.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
@@ -57,7 +57,7 @@
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>4.2.0.M1</version>
<version>4.2.2.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
@@ -96,7 +96,7 @@
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
<version>3.1.0</version>
<scope>test</scope>
</dependency>
<dependency>
@@ -132,13 +132,13 @@
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>4.2.0.M1</version>
<version>4.2.2.RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>4.2.0.M1</version>
<version>4.2.2.RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
@@ -152,12 +152,6 @@
<scope>test</scope>
</dependency>
</dependencies>
<repositories>
<repository>
<id>spring-milestone</id>
<url>https://repo.spring.io/milestone</url>
</repository>
</repositories>
<build>
<plugins>
<plugin>
+3 -17
View File
@@ -7,32 +7,18 @@ dependencies {
testCompile project(':spring-security-core'),
project(':spring-security-web'),
project(':spring-security-taglibs'),
project(':spring-security-test'),
"org.springframework:spring-beans:$springVersion",
"org.springframework:spring-webmvc:$springVersion",
"org.mortbay.jetty:jetty-util:$jettyVersion",
"org.testng:testng:6.8.21"
testCompile ("org.mortbay.jetty:jetty:$jettyVersion") {
exclude group: 'org.mortbay.jetty', module: 'servlet-api'
}
testCompile ('net.sourceforge.jwebunit:jwebunit-core:2.2') {
exclude group: 'javax.servlet', module: 'servlet-api'
exclude group: 'regexp', module: 'regexp'
}
"org.springframework:spring-test:$springVersion"
testRuntime project(':spring-security-config'),
project(':spring-security-ldap'),
"org.mortbay.jetty:jsp-2.1-jetty:$jettyVersion",
testRuntime ('net.sourceforge.jwebunit:jwebunit-htmlunit-plugin:2.2') {
exclude group: 'javax.servlet', module: 'servlet-api'
}
project(':spring-security-ldap')
}
integrationTest {
useTestNG();
options {
jvmArgs = ["-ea", '-Xms128m', '-Xmx500m']
systemProperties = ['webapp.dir': "$projectDir/src/main/webapp"]
}
maxParallelForks = 1
}
+9 -73
View File
@@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.security</groupId>
<artifactId>itest-web</artifactId>
<version>4.2.0.M1</version>
<version>4.2.2.RELEASE</version>
<name>itest-web</name>
<description>itest-web</description>
<url>http://spring.io/spring-security</url>
@@ -35,7 +35,7 @@
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-framework-bom</artifactId>
<version>4.3.2.RELEASE</version>
<version>4.3.5.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
@@ -62,7 +62,7 @@
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
@@ -77,34 +77,6 @@
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>net.sourceforge.jwebunit</groupId>
<artifactId>jwebunit-core</artifactId>
<version>2.2</version>
<scope>test</scope>
<exclusions>
<exclusion>
<artifactId>regexp</artifactId>
<groupId>regexp</groupId>
</exclusion>
<exclusion>
<artifactId>servlet-api</artifactId>
<groupId>javax.servlet</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>net.sourceforge.jwebunit</groupId>
<artifactId>jwebunit-htmlunit-plugin</artifactId>
<version>2.2</version>
<scope>test</scope>
<exclusions>
<exclusion>
<artifactId>servlet-api</artifactId>
<groupId>javax.servlet</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
@@ -117,30 +89,6 @@
<version>1.10.19</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty</artifactId>
<version>6.1.26</version>
<scope>test</scope>
<exclusions>
<exclusion>
<artifactId>servlet-api</artifactId>
<groupId>org.mortbay.jetty</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty-util</artifactId>
<version>6.1.26</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jsp-2.1-jetty</artifactId>
<version>6.1.26</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
@@ -150,31 +98,31 @@
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>4.2.0.M1</version>
<version>4.2.2.RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>4.2.0.M1</version>
<version>4.2.2.RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-ldap</artifactId>
<version>4.2.0.M1</version>
<version>4.2.2.RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-taglibs</artifactId>
<version>4.2.0.M1</version>
<artifactId>spring-security-test</artifactId>
<version>4.2.2.RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>4.2.0.M1</version>
<version>4.2.2.RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
@@ -192,19 +140,7 @@
<artifactId>spring-webmvc</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>6.8.21</version>
<scope>test</scope>
</dependency>
</dependencies>
<repositories>
<repository>
<id>spring-milestone</id>
<url>https://repo.spring.io/milestone</url>
</repository>
</repositories>
<build>
<plugins>
<plugin>
@@ -15,26 +15,14 @@
*/
package org.springframework.security.integration;
import java.util.List;
import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity;
import javax.servlet.ServletContext;
import javax.servlet.http.Cookie;
import net.sourceforge.jwebunit.junit.WebTester;
import org.mortbay.jetty.Server;
import org.mortbay.jetty.servlet.ServletHolder;
import org.mortbay.jetty.webapp.WebAppContext;
import org.springframework.security.web.session.HttpSessionEventPublisher;
import org.springframework.util.StringUtils;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.springframework.web.servlet.DispatcherServlet;
import org.testng.annotations.AfterClass;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeMethod;
import org.junit.After;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.mock.web.MockServletContext;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.support.XmlWebApplicationContext;
/**
* Base class which allows the application to be started with a particular Spring
@@ -45,131 +33,29 @@ import org.testng.annotations.BeforeMethod;
* @author Luke Taylor
*/
public abstract class AbstractWebServerIntegrationTests {
private Server server;
private final Object SERVER_LOCK = new Object();
protected final WebTester tester = new WebTester();
protected ConfigurableApplicationContext context;
/**
* Override to set the application context files that should be loaded or return null
* to use web.xml.
*/
protected abstract String getContextConfigLocations();
protected String getContextPath() {
return "/testapp";
}
@BeforeClass
public void startServer() throws Exception {
synchronized (SERVER_LOCK) {
if (server == null) {
// System.setProperty("DEBUG", "true");
// System.setProperty("VERBOSE", "true");
// System.setProperty("IGNORED", "true");
server = new Server(0);
server.addHandler(createWebContext());
server.start();
}
@After
public void close() {
if(context != null) {
context.close();
}
}
@SuppressWarnings("unchecked")
private WebAppContext createWebContext() {
String webappDir = System.getProperty("webapp.dir");
WebAppContext webCtx = new WebAppContext(webappDir == null ? "src/main/webapp"
: webappDir, getContextPath());
if (StringUtils.hasText(getContextConfigLocations())) {
webCtx.addEventListener(new ContextLoaderListener());
webCtx.addEventListener(new HttpSessionEventPublisher());
webCtx.getInitParams().put("contextConfigLocation",
getContextConfigLocations());
protected final MockMvc createMockMvc(String... configLocations) throws Exception {
if(this.context != null) {
throw new IllegalStateException("context is already loaded");
}
ServletHolder servlet = new ServletHolder();
servlet.setName("testapp");
servlet.setClassName(DispatcherServlet.class.getName());
webCtx.addServlet(servlet, "*.htm");
XmlWebApplicationContext context = new XmlWebApplicationContext();
context.setConfigLocations(configLocations);
context.setServletContext(new MockServletContext());
context.refresh();
this.context = context;
return webCtx;
}
@AfterClass
public void stopServer() throws Exception {
synchronized (SERVER_LOCK) {
if (server != null) {
server.stop();
}
server = null;
}
}
@BeforeMethod
public void initializeTester() {
tester.getTestContext().setBaseUrl(getBaseUrl());
}
@AfterMethod
public void resetWebConversation() {
tester.closeBrowser();
tester.setTestContext(null);
}
protected final String getBaseUrl() {
int port = server.getConnectors()[0].getLocalPort();
return "http://localhost:" + port + getContextPath() + "/";
}
protected final Object getBean(String beanName) {
return getAppContext().getBean(beanName);
}
protected final WebApplicationContext getAppContext() {
ServletContext servletCtx = ((WebAppContext) server.getHandler())
.getServletContext();
WebApplicationContext appCtx = WebApplicationContextUtils
.getRequiredWebApplicationContext(servletCtx);
return appCtx;
}
@SuppressWarnings("unchecked")
protected Cookie getRememberMeCookie() {
List<Cookie> cookies = (List<Cookie>) tester.getTestingEngine().getCookies();
for (Cookie c : cookies) {
if (c.getName().equals("remember-me")) {
return c;
}
}
return null;
}
protected final void submit() {
tester.submit();
}
protected final void beginAt(String url) {
tester.beginAt(url);
}
protected final void setTextField(String name, String value) {
tester.setTextField(name, value);
}
protected final void assertFormPresent() {
tester.assertFormPresent();
}
protected final void assertTextPresent(String text) {
tester.assertTextPresent(text);
}
// Security-specific utility methods
protected void login(String username, String password) {
assertFormPresent();
setTextField("username", username);
setTextField("password", password);
submit();
return MockMvcBuilders
.webAppContextSetup(context)
.apply(springSecurity())
.build();
}
}
@@ -15,25 +15,29 @@
*/
package org.springframework.security.integration;
import org.testng.annotations.Test;
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.httpBasic;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import org.junit.Test;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
public class BasicAuthenticationTests extends AbstractWebServerIntegrationTests {
@Override
protected String getContextConfigLocations() {
return "/WEB-INF/http-security-basic.xml /WEB-INF/in-memory-provider.xml";
@Test
public void httpBasicWhenAuthenticationRequiredAndNotAuthenticatedThen401() throws Exception {
MockMvc mockMvc = createMockMvc("classpath:/spring/http-security-basic.xml", "classpath:/spring/in-memory-provider.xml", "classpath:/spring/testapp-servlet.xml");
mockMvc.perform(get("secure/index"))
.andExpect(status().isUnauthorized());
}
@Test
public void basicAuthenticationIsSuccessful() throws Exception {
tester.setIgnoreFailingStatusCodes(true);
beginAt("secure/index.html");
// Ignore the 401
tester.setIgnoreFailingStatusCodes(false);
tester.assertHeaderEquals("WWW-Authenticate",
"Basic realm=\"Spring Security Application\"");
tester.getTestContext().setAuthorization("johnc", "johncspassword");
beginAt("secure/index.html");
public void httpBasicWhenProvidedThen200() throws Exception {
MockMvc mockMvc = createMockMvc("classpath:/spring/http-security-basic.xml", "classpath:/spring/in-memory-provider.xml", "classpath:/spring/testapp-servlet.xml");
MockHttpServletRequestBuilder request = get("/secure/index")
.with(httpBasic("johnc", "johncspassword"));
mockMvc.perform(request)
.andExpect(status().isOk());
}
}

Some files were not shown because too many files have changed in this diff Show More