1
0
mirror of synced 2026-07-08 12:20:02 +00:00

Compare commits

...

48 Commits

Author SHA1 Message Date
Rob Winch b1a6a574ac Merge pull request #159 from ractive/3.1.x
SEC-2812: Fix german translations
2015-01-14 16:29:47 -06:00
james 979badd550 SEC-2812: Fix german translations 2015-01-12 13:51:33 +01:00
Spring Buildmaster 2263a545ea Next development version 2014-08-15 11:39:31 -07:00
Rob Winch 0d86164a49 SEC-2547: Update to cas-client-core-3.3.3 2014-08-15 12:49:13 -05:00
Rob Winch b78bd897cd SEC-2688: CAS Proxy Ticket Authentication uses Service for host & port 2014-07-24 16:56:58 -05:00
Rob Winch 055eb72d60 Remove explict LDAP dir for integration tests 2014-06-18 09:50:17 -05:00
Rob Winch f4914b2271 Remove ApacheDSContainer import 2014-06-18 09:43:35 -05:00
Rob Winch 541aee8e3e SEC-2449: <ldap-server> default port should fallback to dynamic value 2014-06-18 09:34:49 -05:00
Rob Winch a6cab1be74 SEC-2606: ApacheDSServerIntegrationTests scan for available port 2014-06-12 12:28:40 -05:00
Rob Winch bbfcab0c81 SEC-2607: CAS Server logouts out synchronously 2014-06-12 12:28:40 -05:00
Spring Buildmaster 6e431e7d16 Next development version 2014-03-10 14:26:38 -07:00
Rob Winch 2eec67fe73 SEC-2507: Fix test imports 2014-03-10 15:09:36 -05:00
Rob Winch 88559882e9 SEC-2500: Prevent anonymous bind for ActiveDirectoryLdapAuthenticator 2014-03-10 14:43:59 -05:00
Rob Winch 9270845a21 SEC-2507: WebExpressionVoter.supports support subclasses of FilterInvocation 2014-03-10 14:43:56 -05:00
Spring Buildmaster 1d53dc5e5c Next development version 2014-02-19 07:12:15 -08:00
Rob Winch ac6cf5396a SEC-2468: JdbcUserDetailsManager#createNewAuthentication uses null credentials 2014-02-14 17:00:07 -06:00
james 5a2e99c940 SEC-2467: Fix Small errors in itest-web's jsps 2014-01-28 16:09:09 -06:00
Rob Winch 6f3c6f9b5b SEC-2447: JdbcMutableAclServiceTests should invoke aclCache.clearCache() 2013-12-14 10:20:31 -06:00
Rob Winch 1feb38048b Update to Gradle 1.9
Necessary to work with the latest Bamboo and Artifactory Gradle updates
2013-12-05 09:08:26 -06:00
Rob Winch 905c59f599 SEC-2313: Gradle javadoc hotfix 2013-09-11 15:42:53 -07:00
Rob Winch 241e984ea4 SEC-2171: Include Information about pooling in Spring LDAP documentation 2013-08-25 11:31:05 -05:00
Rob Winch 8053cb0de7 SEC-2103: Fix tests to verify debug logging instead of info 2013-08-25 10:05:48 -05:00
Rob Winch 889bba1d67 SEC-2103: Change log of no results to debug 2013-08-24 23:40:48 -05:00
Rob Winch f9fd448d88 SEC-2139: named-security-filter are all defined and ordered correctly 2013-08-24 15:20:23 -05:00
Rob Winch 7bf6046408 SEC-2108: Fix typo in ldap section of manual 2013-08-24 15:20:23 -05:00
Guillaume Smet 5dfeea7631 SEC-2245: Cast to interface instead of implementation
Makes our life easier when we want to override the
MethodSecurityExpressionRoot.
2013-08-05 17:06:09 -05:00
Luke Taylor f42720b1b6 SEC-2175: Correct XSD docs on auto-config. 2013-06-09 14:46:56 +01:00
Rob Winch 113e28a148 Update to next dev version - 3.1.5.CI-SNAPSHOT 2013-04-29 08:47:30 -05:00
Spring Buildmaster de6bcb80b9 [artifactory-release] Next development version 2013-04-27 13:05:38 -07:00
Rob Winch 102da87080 Disable artifactoryPublish for projects without artifacts 2013-04-27 13:56:12 -05:00
Rob Winch f1ae9da55e Remove ApacheDSContainerTests successfulStartupAndShutdown since it was commented out 2013-04-25 11:17:21 -05:00
Rob Winch 94e2e0c65e SEC-2161: <ldap-server> creates unique dir for embedded LDAP 2013-04-25 11:17:21 -05:00
Rob Winch fa3a30cc20 SEC-2162: ApacheDSContainer throws RuntimeException on failure to start 2013-04-25 11:17:21 -05:00
Rob Winch ee6e6ceafb SEC-2133: Update doc from ChannelAuthenticationFilter to ChannelProcessingFilter 2013-04-25 08:51:51 -05:00
Rob Winch 095594daea SEC-2147: Deprecate .encoding.PasswordEncoding 2013-04-25 08:49:33 -05:00
Rob Winch e9215c4dc3 SEC-2087: GlobalMethodSecurityBeanDefinitionParser uses AuthenticationManager to create AuthenticationManagerDelegator 2013-04-24 17:30:51 -05:00
@fbiville 0d70c703df SEC-2138: Fix code snippet in Hierarchical Roles section
The bean definition of RoleHierarchyVoter was syntactically incorrect.
2013-02-26 09:47:02 -06:00
Rob Winch 73710bf7b8 Add CONTRIBUTING.md 2013-02-25 17:14:21 -06:00
Jean-Pierre Bergamin ca5501eb31 SEC-2118: Fixing spring and aspectj OSGi version ranges [3.2, 3.2) -> [3.2, 3.3) 2013-02-25 17:10:07 -06:00
Rob Winch c703806fa2 Revert "SEC-2078: AbstractPreAuthenticatedProcessingFilter requriesAuthentication support for non-String Principals"
This reverts commit 3fe7791266.
2012-12-06 16:16:50 -06:00
Rob Winch 67eb9821f3 Revert "SEC-2078: Updated Javadoc to reflect that updates to Principal will also trigger reauthentication"
This reverts commit ece4a0f067.
2012-12-06 16:16:33 -06:00
Rob Winch 7b93ffd5d4 SEC-2078: Updated Javadoc to reflect that updates to Principal will also trigger reauthentication 2012-12-06 09:05:21 -06:00
Rob Winch 5fa252b848 SEC-2078: AbstractPreAuthenticatedProcessingFilter requriesAuthentication support for non-String Principals
Previously, if the Principal returned by getPreAuthenticatedPrincipal was not a String,
it prevented requiresAuthentication from detecting when the Principal was the same.
This caused the need to authenticate the user for every request even when the Principal
did not change.

Now requiresAuthentication will check to see if the result of
getPreAuthenticatedPrincipal is equal to the current Authentication.getPrincipal().
2012-12-04 13:04:41 -06:00
Rob Winch 87c3c7edb9 Use AspectJMethodSecurityInterceptor in reference
Change reference to use AspectJMethodSecurityInterceptor instead of
undefined AspectJSecurityInterceptor.
2012-12-04 10:07:30 -06:00
Rob Winch 7f342f3321 SEC-2074: Update reference to use <method-security-metadata-source> 2012-12-04 10:07:30 -06:00
Rob Winch 2f6325f651 SEC-2084: AntPathRequestMatcher and RegexpRequestMatcher support request.getMethod()
Previously a NullPointerException would occur if an HttpServletRequest.getMethod()
returned null.

Now AntPathRequestMatcher and RegexpRequestMatcher will handle if the
HttpServletRequest.getMethod() returns null. While under normal circumstances,
it is unlikely for the method to be null this can occur when using
DefaultWebInvocationPrivilegeEvaluator.isAllowed(String, Authentication).
2012-12-03 15:08:37 -06:00
Rob Winch e3f53908af SEC-2072: <security:anonymous> granted-authority supports multiple authorities again 2012-11-02 16:23:37 -05:00
Rob Winch 4d1127106b Add 3.1.x suffix to eclipse projects 2012-11-02 10:00:45 -05:00
74 changed files with 1057 additions and 157 deletions
+186
View File
@@ -0,0 +1,186 @@
_Have something you'd like to contribute to the framework? We welcome pull requests, but ask that you carefully read this document first to understand how best to submit them; what kind of changes are likely to be accepted; and what to expect from the Spring Security team when evaluating your submission._
_Please refer back to this document as a checklist before issuing any pull request; this will save time for everyone!_
# Similar but different
Each Spring module is slightly different than another in terms of team size, number of issues, etc. Therefore each project is managed slightly different. You will notice that this document is very similar to the [Spring Framework Contributor guidelines](https://github.com/SpringSource/spring-framework/wiki/Contributor-guidelines). However, there are some subtle differences between the two documents, so please be sure to read this document thoroughly.
# Understand the basics
Not sure what a pull request is, or how to submit one? Take a look at GitHub's excellent [help documentation first](http://help.github.com/send-pull-requests).
# Search JIRA first; create an issue if necessary
Is there already an issue that addresses your concern? Do a bit of searching in our [JIRA issue tracker](https://jira.springsource.org/browse/SEC) to see if you can find something similar. If not, please create a new issue before submitting a pull request unless the change is not a user facing issue.
# Discuss non-trivial contribution ideas with committers
If you're considering anything more than correcting a typo or fixing a minor bug , please discuss it on the [Spring Security forums](http://forum.springsource.org/forumdisplay.php?33-Security) before submitting a pull request. We're happy to provide guidance but please spend an hour or two researching the subject on your own including searching the forums for prior discussions.
# Sign the Contributor License Agreement
If you have not previously done so, please fill out and submit the SpringSource CLA form. You'll receive a token when this process is complete. Keep track of this, you may be asked for it later!
* For **Project** select _Spring Security_
* For **Project Lead** enter _Rob Winch_
* Note that emailing/postal mailing a signed copy is not necessary. Submission of the web form is all that is required.
When you've completed the web form, simply add the following in a comment on your pull request:
> I have signed and agree to the terms of the SpringSource Individual Contributor License Agreement.
You do not need to include your token/id. Please add the statement above to all future pull requests as well, simply so the Spring Security team knows immediately that this process is complete.
# Create your branch from master
Create your topic branch to be submitted as a pull request from master. The Spring team will consider your pull request for backporting on a case-by-case basis; you don't need to worry about submitting anything for backporting.
# Use short branch names
Branches used when submitting pull requests should preferably be named according to JIRA issues, e.g. 'SEC-1234'. Otherwise, use succinct, lower-case, dash (-) delimited names, such as 'fix-warnings', 'fix-typo', etc. This is important, because branch names show up in the merge commits that result from accepting pull requests, and should be as expressive and concise as possible.
#Keep commits focused
Remember each JIRA should be focused on a single item of interest since the JIRA tickets are used to produce the changelog. Since each commit should be tied to a JIRA, ensure that your commits are focused. For example, do not include an update to a transitive library in your commit unless the JIRA is to update the library. Reviewing your commits is essential before sending a pull request.
# Mind the whitespace
Please carefully follow the whitespace and formatting conventions already present in the framework.
1. Spaces, not tabs
1. Unix (LF), not dos (CRLF) line endings
1. Eliminate all trailing whitespace
1. Aim to wrap code at 120 characters, but favor readability over wrapping
1. Preserve existing formatting; i.e. do not reformat code for its own sake
1. Search the codebase using git grep and other tools to discover common naming conventions, etc.
1. Latin-1 (ISO-8859-1) encoding for Java sources; use native2ascii to convert if necessary
Whitespace management tips
1. You can use the [AnyEdit Eclipse plugin](http://marketplace.eclipse.org/content/anyedit-tools) to ensure spaces are used and to clean up trailing whitespaces.
1. Use git's pre-commit.sample hook to prevent invalid whitespace from being pushed out. You can enable it by moving ~/spring-security/.git/hooks/pre-commit.sample to ~/spring-security/.git/hooks/pre-commit and ensuring it is executable. For more information on hooks refer to [Pro Git's Pre-Commit Hook's section](http://git-scm.com/book/cs/ch7-3.html)
# Add Apache license header to all new classes
<pre>
/*
* Copyright 2002-2012 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 ...;
</pre>
# Update Apache license header to modified files as necessary
Always check the date range in the license header. For example, if you've modified a file in 2012 whose header still reads
<pre>
* Copyright 2002-2011 the original author or authors.
</pre>
then be sure to update it to 2012 appropriately
<pre>
* Copyright 2002-2012 the original author or authors.
</pre>
# Use @since tags for newly-added public API types and methods
e.g.
<pre>
/**
* ...
*
* @author First Last
* @since 3.2
* @see ...
*/
</pre>
#Submit JUnit test cases for all behavior changes
Search the codebase to find related unit tests and add additional `@Test` methods within.
1. Any new tests should end in the name Tests (note this is plural). For example, a valid name would be `FilterChainProxyTests`. An invalid name would be `FilterChainProxyTest`.
2. New test methods should not start with test. This is an old JUnit3 convention and is not necessary since the method is annotated with @Test.
# Squash commits
Use git rebase --interactive, git add --patch and other tools to "squash" multiple commits into atomic changes. In addition to the man pages for git, there are many resources online to help you understand how these tools work. Here is one: http://book.git-scm.com/4_interactive_rebasing.html.
# Use real name in git commits
Please configure git to use your real first and last name for any commits you intend to submit as pull requests. For example, this is not acceptable:
<pre>
Author: Nickname &lt;user@mail.com&gt;
</pre>
Rather, please include your first and last name, properly capitalized, as submitted against the SpringSource contributor license agreement:
<pre>
Author: First Last &lt;user@mail.com&gt;
</pre>
This helps ensure traceability against the CLA, and also goes a long way to ensuring useful output from tools like git shortlog and others.
You can configure this globally via the account admin area GitHub (useful for fork-and-edit cases); globally with
<pre>
git config --global user.name "First Last"
git config --global user.email user@mail.com
</pre>
or locally for the spring-security repository only by omitting the '--global' flag:
<pre>
cd spring-security
git config user.name "First Last"
git config user.email user@mail.com
</pre>
# Format commit messages
<pre>
SEC-1234: Short (50 chars or less) summary of changes
More detailed explanatory text, if necessary. Wrap it to about 72
characters or so. In some contexts, the first line is treated as the
subject of an email and the rest of the text as the body. The blank
line separating the summary from the body is critical (unless you omit
the body entirely); tools like rebase can get confused if you run the
two together.
Further paragraphs come after blank lines.
- Bullet points are okay, too
- Typically a hyphen or asterisk is used for the bullet, preceded by a
single space, with blank lines in between, but conventions vary here
</pre>
1. The commit subject should start with the associated jira issue followed by a : as shown in the example above
2. Keep the subject line to 50 characters or less if possible
3. Do not end the subject line with a period
4. In the body of the commit message, explain how things worked before this commit, what has changed, and how things work now
# Run all tests prior to submission
<pre>
cd spring-security
./gradlew clean build integrationTest
</pre>
# Submit your pull request
Subject line:
Follow the same conventions for pull request subject lines as mentioned above for commit message subject lines.
In the body:
1. Explain your use case. What led you to submit this change? Why were existing mechanisms in the framework insufficient? Make a case that this is a general-purpose problem and that yours is a general-purpose solution, etc
2. Add any additional information and ask questions; start a conversation, or continue one from JIRA
3. Mention the JIRA issue ID
4. Also mention that you have submitted the CLA as described above
Note that for pull requests containing a single commit, GitHub will default the subject line and body of the pull request to match the subject line and body of the commit message. This is fine, but please also include the items above in the body of the request.
# Mention your pull request on the associated JIRA issue
Add a comment to the associated JIRA issue(s) linking to your new pull request.
# Expect discussion and rework
The Spring team takes a very conservative approach to accepting contributions to the framework. This is to keep code quality and stability as high as possible, and to keep complexity at a minimum. Your changes, if accepted, may be heavily modified prior to merging. You will retain "Author:" attribution for your Git commits granted that the bulk of your changes remain intact. You may be asked to rework the submission for style (as explained above) and/or substance. Again, we strongly recommend discussing any serious submissions with the Spring Framework team prior to engaging in serious development work.
Note that you can always force push (git push -f) reworked / rebased commits against the branch used to submit your pull request. i.e. you do not need to issue a new pull request when asked to make changes.
@@ -105,6 +105,7 @@ public class JdbcMutableAclServiceTests extends AbstractTransactionalJUnit4Sprin
jdbcTemplate.execute("drop table acl_object_identity");
jdbcTemplate.execute("drop table acl_class");
jdbcTemplate.execute("drop table acl_sid");
aclCache.clearCache();
}
@Test
+14 -1
View File
@@ -1,3 +1,12 @@
buildscript {
repositories {
maven { url "http://repo.springsource.org/plugins-release" }
}
dependencies {
classpath('me.champeau.gradle:gradle-javadoc-hotfix-plugin:0.1')
}
}
apply plugin: 'base'
description = 'Spring Security'
@@ -20,6 +29,10 @@ ext.itestProjects = subprojects.findAll { project -> project.name.startsWith('it
ext.coreModuleProjects = javaProjects - sampleProjects - itestProjects
ext.aspectjProjects = [project(':spring-security-aspects'), project(':spring-security-samples-aspectj')]
configure(subprojects - coreModuleProjects) {
tasks.findByPath("artifactoryPublish")?.enabled = false
}
configure(javaProjects) {
apply from: "$rootDir/gradle/javaprojects.gradle"
}
@@ -75,5 +88,5 @@ artifacts {
apply from: "$rootDir/gradle/ide-integration.gradle"
task wrapper(type: Wrapper) {
gradleVersion = '1.2'
gradleVersion = '1.9'
}
@@ -11,6 +11,7 @@ import org.gradle.api.GradleException
import org.gradle.plugins.ide.eclipse.GenerateEclipseProject
import org.gradle.plugins.ide.eclipse.GenerateEclipseClasspath
import org.gradle.plugins.ide.eclipse.EclipsePlugin
import org.gradle.plugins.ide.eclipse.model.BuildCommand
import org.gradle.plugins.ide.eclipse.model.ProjectDependency
@@ -37,21 +38,26 @@ class AspectJPlugin implements Plugin<Project> {
project.configurations.add('aspectpath')
}
project.tasks.add(name: 'compileJava', overwrite: true, description: 'Compiles AspectJ Source', type: Ajc) {
project.tasks.add(name: 'compileAspect', overwrite: true, description: 'Compiles AspectJ Source', type: Ajc) {
dependsOn project.configurations*.getTaskDependencyFromProjectDependency(true, "compileJava")
dependsOn project.processResources
sourceSet = project.sourceSets.main
inputs.files(sourceSet.java.srcDirs)
outputs.dir(sourceSet.output.classesDir)
aspectPath = project.configurations.aspectpath
}
project.tasks.compileJava.deleteAllActions()
project.tasks.compileJava.dependsOn project.tasks.compileAspect
project.tasks.add(name: 'compileTestJava', overwrite: true, description: 'Compiles AspectJ Test Source', type: Ajc) {
project.tasks.add(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.java.srcDirs)
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 ->
@@ -63,8 +69,13 @@ class AspectJPlugin implements Plugin<Project> {
project.tasks.withType(GenerateEclipseClasspath) {
project.eclipse.classpath.file.whenMerged { classpath ->
def entries = classpath.entries.findAll { it instanceof ProjectDependency}.findAll { entry ->
def projectPath = entry.path.replaceAll('/',':')
project.rootProject.findProject(projectPath).plugins.findPlugin(AspectJPlugin)
def projectPath = entry.path.replaceAll('/','')
project.rootProject.allprojects.find{ p->
if(p.plugins.findPlugin(EclipsePlugin)) {
return p.eclipse.project.name == projectPath && p.plugins.findPlugin(AspectJPlugin)
}
false
}
}
entries.each { entry->
entry.entryAttributes.put('org.eclipse.ajdt.aspectpath','org.eclipse.ajdt.aspectpath')
+2 -2
View File
@@ -5,8 +5,8 @@ dependencies {
"org.springframework:spring-context:$springVersion",
"org.springframework:spring-beans:$springVersion",
"org.springframework:spring-web:$springVersion",
"org.jasig.cas.client:cas-client-core:3.1.12",
"org.jasig.cas.client:cas-client-core:3.3.3",
"net.sf.ehcache:ehcache:$ehcacheVersion"
provided 'javax.servlet:servlet-api:2.5'
}
}
@@ -49,9 +49,7 @@ public class ServiceProperties implements InitializingBean {
//~ Methods ========================================================================================================
public void afterPropertiesSet() throws Exception {
if(!authenticateAllArtifacts) {
Assert.hasLength(this.service, "service must be specified unless authenticateAllArtifacts is true.");
}
Assert.hasLength(this.service, "service cannot be empty.");
Assert.hasLength(this.artifactParameter, "artifactParameter cannot be empty.");
Assert.hasLength(this.serviceParameter, "serviceParameter cannot be empty.");
}
@@ -15,6 +15,8 @@
*/
package org.springframework.security.cas.web.authentication;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.regex.Pattern;
import javax.servlet.http.HttpServletRequest;
@@ -50,11 +52,13 @@ final class DefaultServiceAuthenticationDetails extends WebAuthenticationDetails
* string from containing the artifact name and value. This can
* be created using {@link #createArtifactPattern(String)}.
*/
DefaultServiceAuthenticationDetails(HttpServletRequest request, Pattern artifactPattern) {
DefaultServiceAuthenticationDetails(String casService, HttpServletRequest request, Pattern artifactPattern) throws MalformedURLException {
super(request);
URL casServiceUrl = new URL(casService);
int port = getServicePort(casServiceUrl);
final String query = getQueryString(request,artifactPattern);
this.serviceUrl = UrlUtils.buildFullRequestUrl(request.getScheme(),
request.getServerName(), request.getServerPort(),
this.serviceUrl = UrlUtils.buildFullRequestUrl(casServiceUrl.getProtocol(),
casServiceUrl.getHost(), port,
request.getRequestURI(), query);
}
@@ -128,4 +132,17 @@ final class DefaultServiceAuthenticationDetails extends WebAuthenticationDetails
Assert.hasLength(artifactParameterName);
return Pattern.compile("&?"+Pattern.quote(artifactParameterName)+"=[^&]*");
}
/**
* Gets the port from the casServiceURL ensuring to return the proper value if the default port is being used.
* @param casServiceUrl the casServerUrl to be used (i.e. "https://example.com/context/j_spring_security_cas_check")
* @return the port that is configured for the casServerUrl
*/
private static int getServicePort(URL casServiceUrl) {
int port = casServiceUrl.getPort();
if(port == -1) {
port = casServiceUrl.getDefaultPort();
}
return port;
}
}
@@ -15,12 +15,18 @@
*/
package org.springframework.security.cas.web.authentication;
import java.net.MalformedURLException;
import java.util.regex.Pattern;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.security.authentication.AuthenticationDetailsSource;
import org.springframework.security.cas.ServiceProperties;
import org.springframework.util.Assert;
/**
* The {@code AuthenticationDetailsSource} that is set on the
@@ -33,20 +39,33 @@ import org.springframework.security.cas.ServiceProperties;
* @author Rob Winch
*/
public class ServiceAuthenticationDetailsSource implements AuthenticationDetailsSource<HttpServletRequest,
ServiceAuthenticationDetails> {
ServiceAuthenticationDetails>, ApplicationContextAware {
//~ Instance fields ================================================================================================
private final Pattern artifactPattern;
private ServiceProperties serviceProperties;
//~ Constructors ===================================================================================================
/**
* Creates an implementation that uses the default CAS artifactParameterName.
* @deprecated Use ServiceAuthenticationDetailsSource(ServiceProperties)
*/
@Deprecated
public ServiceAuthenticationDetailsSource() {
this(ServiceProperties.DEFAULT_CAS_ARTIFACT_PARAMETER);
}
/**
* Creates an implementation that uses the specified ServiceProperites and the default CAS artifactParameterName.
*
* @param serviceProperties The ServiceProperties to use to construct the serviceUrl.
*/
public ServiceAuthenticationDetailsSource(ServiceProperties serviceProperties) {
this(serviceProperties,ServiceProperties.DEFAULT_CAS_ARTIFACT_PARAMETER);
}
/**
* Creates an implementation that uses the specified artifactParameterName
*
@@ -54,11 +73,27 @@ public class ServiceAuthenticationDetailsSource implements AuthenticationDetails
* the artifactParameterName that is removed from the current
* URL. The result becomes the service url. Cannot be null and
* cannot be an empty String.
* @deprecated Use ServiceAuthenticationDetailsSource(ServiceProperties,String)
*/
public ServiceAuthenticationDetailsSource(final String artifactParameterName) {
this.artifactPattern = DefaultServiceAuthenticationDetails.createArtifactPattern(artifactParameterName);
}
/**
* Creates an implementation that uses the specified artifactParameterName
*
* @param serviceProperties The ServiceProperties to use to construct the serviceUrl.
* @param artifactParameterName
* the artifactParameterName that is removed from the current
* URL. The result becomes the service url. Cannot be null and
* cannot be an empty String.
*/
public ServiceAuthenticationDetailsSource(ServiceProperties serviceProperties, String artifactParameterName) {
Assert.notNull(serviceProperties, "serviceProperties cannot be null");
this.serviceProperties = serviceProperties;
this.artifactPattern = DefaultServiceAuthenticationDetails.createArtifactPattern(artifactParameterName);
}
//~ Methods ========================================================================================================
/**
@@ -66,6 +101,17 @@ public class ServiceAuthenticationDetailsSource implements AuthenticationDetails
* @return the {@code ServiceAuthenticationDetails} containing information about the current request
*/
public ServiceAuthenticationDetails buildDetails(HttpServletRequest context) {
return new DefaultServiceAuthenticationDetails(context,artifactPattern);
try {
return new DefaultServiceAuthenticationDetails(serviceProperties.getService(),context,artifactPattern);
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
if(serviceProperties == null) {
serviceProperties = applicationContext.getBean(ServiceProperties.class);
}
}
}
@@ -36,10 +36,13 @@ public class ServicePropertiesTests {
}
@Test
public void allowNullServiceWhenAuthenticateAllTokens() throws Exception {
public void nullServiceWhenAuthenticateAllTokens() throws Exception {
ServiceProperties sp = new ServiceProperties();
sp.setAuthenticateAllArtifacts(true);
sp.afterPropertiesSet();
try {
sp.afterPropertiesSet();
fail("Expected Exception");
}catch(IllegalArgumentException success) {}
sp.setAuthenticateAllArtifacts(false);
try {
sp.afterPropertiesSet();
@@ -18,11 +18,21 @@ import static org.junit.Assert.assertEquals;
import java.util.regex.Pattern;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.context.support.GenericXmlApplicationContext;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.security.cas.ServiceProperties;
import org.springframework.security.web.util.UrlUtils;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
*
@@ -32,9 +42,13 @@ public class DefaultServiceAuthenticationDetailsTests {
private DefaultServiceAuthenticationDetails details;
private MockHttpServletRequest request;
private Pattern artifactPattern;
private String casServiceUrl;
private ConfigurableApplicationContext context;
@Before
public void setUp() {
casServiceUrl = "https://localhost:8443/j_spring_security_cas";
request = new MockHttpServletRequest();
request.setScheme("https");
request.setServerName("localhost");
@@ -44,45 +58,82 @@ public class DefaultServiceAuthenticationDetailsTests {
}
@Test
public void getServiceUrlNullQuery() throws Exception {
details = new DefaultServiceAuthenticationDetails(request,artifactPattern);
assertEquals(UrlUtils.buildFullRequestUrl(request),details.getServiceUrl());
@After
public void cleanup() {
if(context != null) {
context.close();
}
}
@Test
public void getServiceUrlTicketOnlyParam() {
public void getServiceUrlNullQuery() throws Exception {
details = new DefaultServiceAuthenticationDetails(casServiceUrl, request,artifactPattern);
assertEquals(UrlUtils.buildFullRequestUrl(request), details.getServiceUrl());
}
@Test
public void getServiceUrlTicketOnlyParam() throws Exception {
request.setQueryString("ticket=123");
details = new DefaultServiceAuthenticationDetails(request,artifactPattern);
details = new DefaultServiceAuthenticationDetails(casServiceUrl,request,artifactPattern);
String serviceUrl = details.getServiceUrl();
request.setQueryString(null);
assertEquals(UrlUtils.buildFullRequestUrl(request),serviceUrl);
}
@Test
public void getServiceUrlTicketFirstMultiParam() {
public void getServiceUrlTicketFirstMultiParam() throws Exception {
request.setQueryString("ticket=123&other=value");
details = new DefaultServiceAuthenticationDetails(request,artifactPattern);
details = new DefaultServiceAuthenticationDetails(casServiceUrl, request,artifactPattern);
String serviceUrl = details.getServiceUrl();
request.setQueryString("other=value");
assertEquals(UrlUtils.buildFullRequestUrl(request),serviceUrl);
}
@Test
public void getServiceUrlTicketLastMultiParam() {
public void getServiceUrlTicketLastMultiParam() throws Exception {
request.setQueryString("other=value&ticket=123");
details = new DefaultServiceAuthenticationDetails(request,artifactPattern);
details = new DefaultServiceAuthenticationDetails(casServiceUrl,request,artifactPattern);
String serviceUrl = details.getServiceUrl();
request.setQueryString("other=value");
assertEquals(UrlUtils.buildFullRequestUrl(request),serviceUrl);
}
@Test
public void getServiceUrlTicketMiddleMultiParam() {
public void getServiceUrlTicketMiddleMultiParam() throws Exception {
request.setQueryString("other=value&ticket=123&last=this");
details = new DefaultServiceAuthenticationDetails(request,artifactPattern);
details = new DefaultServiceAuthenticationDetails(casServiceUrl,request,artifactPattern);
String serviceUrl = details.getServiceUrl();
request.setQueryString("other=value&last=this");
assertEquals(UrlUtils.buildFullRequestUrl(request),serviceUrl);
}
@Test
public void getServiceUrlDoesNotUseHostHeader() throws Exception {
casServiceUrl = "https://example.com/j_spring_security_cas";
request.setServerName("evil.com");
details = new DefaultServiceAuthenticationDetails(casServiceUrl, request,artifactPattern);
assertEquals("https://example.com/cas-sample/secure/",details.getServiceUrl());
}
@Test
public void getServiceUrlDoesNotUseHostHeaderPassivity() {
casServiceUrl = "https://example.com/j_spring_security_cas";
request.setServerName("evil.com");
ServiceAuthenticationDetails details = loadServiceAuthenticationDetails("defaultserviceauthenticationdetails-passivity.xml");
assertEquals("https://example.com/cas-sample/secure/", details.getServiceUrl());
}
@Test
public void getServiceUrlDoesNotUseHostHeaderExplicit() {
casServiceUrl = "https://example.com/j_spring_security_cas";
request.setServerName("evil.com");
ServiceAuthenticationDetails details = loadServiceAuthenticationDetails("defaultserviceauthenticationdetails-explicit.xml");
assertEquals("https://example.com/cas-sample/secure/", details.getServiceUrl());
}
private ServiceAuthenticationDetails loadServiceAuthenticationDetails(String resourceName) {
context = new GenericXmlApplicationContext(getClass(), resourceName);
ServiceAuthenticationDetailsSource source = context.getBean(ServiceAuthenticationDetailsSource.class);
return source.buildDetails(request);
}
}
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<bean id="serviceProperties"
class="org.springframework.security.cas.ServiceProperties">
<property name="service"
value="https://example.com/j_spring_security_cas"/>
<property name="sendRenew" value="false"/>
</bean>
<bean id="serviceProperties2"
class="org.springframework.security.cas.ServiceProperties">
<property name="service"
value="https://example2.com/j_spring_security_cas"/>
<property name="sendRenew" value="false"/>
</bean>
<bean class="org.springframework.security.cas.web.authentication.ServiceAuthenticationDetailsSource">
<constructor-arg ref="serviceProperties"/>
</bean>
</beans>
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<bean id="serviceProperties"
class="org.springframework.security.cas.ServiceProperties">
<property name="service"
value="https://example.com/j_spring_security_cas"/>
<property name="sendRenew" value="false"/>
</bean>
<bean class="org.springframework.security.cas.web.authentication.ServiceAuthenticationDetailsSource"/>
</beans>
+1 -1
View File
@@ -14,7 +14,7 @@ Import-Template:
org.springframework.security.core.*;version="${secRange}",
org.springframework.security.authentication.*;version="${secRange}",
org.springframework.security.web.*;version="${secRange}",
org.springframework.beans.factory;version="${springRange}",
org.springframework.beans.*;version="${springRange}",
org.springframework.context.*;version="${springRange}",
org.springframework.dao;version="${springRange}",
org.springframework.util;version="${springRange}",
+1 -5
View File
@@ -52,8 +52,4 @@ dependencies {
test {
inputs.file file("$rootDir/docs/manual/src/docbook/appendix-namespace.xml")
}
integrationTest {
systemProperties['apacheDSWorkDir'] = "${buildDir}/apacheDSWork"
}
}
@@ -12,7 +12,10 @@
*/
package org.springframework.security.config.ldap;
import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;
import java.io.IOException;
import java.net.ServerSocket;
import org.junit.After;
import org.junit.Test;
@@ -50,10 +53,11 @@ public class LdapServerBeanDefinitionParserTests {
}
@Test
public void useOfUrlAttributeCreatesCorrectContextSource() {
public void useOfUrlAttributeCreatesCorrectContextSource() throws Exception {
int port = getDefaultPort();
// Create second "server" with a url pointing at embedded one
appCtx = new InMemoryXmlApplicationContext("<ldap-server ldif='classpath:test-server.ldif' port='33388'/>" +
"<ldap-server ldif='classpath:test-server.ldif' id='blah' url='ldap://127.0.0.1:33388/dc=springframework,dc=org' />");
appCtx = new InMemoryXmlApplicationContext("<ldap-server ldif='classpath:test-server.ldif' port='" + port + "'/>" +
"<ldap-server ldif='classpath:test-server.ldif' id='blah' url='ldap://127.0.0.1:" + port + "/dc=springframework,dc=org' />");
// Check the default context source is still there.
appCtx.getBean(BeanIds.CONTEXT_SOURCE);
@@ -83,4 +87,16 @@ public class LdapServerBeanDefinitionParserTests {
assertEquals("classpath*:*.ldif", ReflectionTestUtils.getField(dsContainer, "ldifResources"));
}
private int getDefaultPort() throws IOException {
ServerSocket server = null;
try {
server = new ServerSocket(0);
return server.getLocalPort();
} finally {
try {
server.close();
} catch(IOException e) {}
}
}
}
@@ -534,7 +534,7 @@ final class AuthenticationConfigBuilder {
anonymousFilter = new RootBeanDefinition(AnonymousAuthenticationFilter.class);
anonymousFilter.getConstructorArgumentValues().addIndexedArgumentValue(0, key);
anonymousFilter.getConstructorArgumentValues().addIndexedArgumentValue(1, username);
anonymousFilter.getConstructorArgumentValues().addIndexedArgumentValue(2, AuthorityUtils.createAuthorityList(grantedAuthority));
anonymousFilter.getConstructorArgumentValues().addIndexedArgumentValue(2, AuthorityUtils.commaSeparatedStringToAuthorityList(grantedAuthority));
anonymousFilter.setSource(source);
RootBeanDefinition anonymousProviderBean = new RootBeanDefinition(AnonymousAuthenticationProvider.class);
@@ -1,5 +1,8 @@
package org.springframework.security.config.ldap;
import java.io.IOException;
import java.net.ServerSocket;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.config.BeanDefinition;
@@ -40,7 +43,8 @@ public class LdapServerBeanDefinitionParser implements BeanDefinitionParser {
/** Defines the port the LDAP_PROVIDER server should run on */
public static final String ATT_PORT = "port";
public static final String OPT_DEFAULT_PORT = "33389";
private static final int DEFAULT_PORT = 33389;
public static final String OPT_DEFAULT_PORT = String.valueOf(DEFAULT_PORT);
public BeanDefinition parse(Element elt, ParserContext parserContext) {
@@ -101,7 +105,10 @@ public class LdapServerBeanDefinitionParser implements BeanDefinitionParser {
String port = element.getAttribute(ATT_PORT);
if (!StringUtils.hasText(port)) {
port = OPT_DEFAULT_PORT;
port = getDefaultPort();
if(logger.isDebugEnabled()) {
logger.debug("Using default port of " + port);
}
}
String url = "ldap://127.0.0.1:" + port + "/" + suffix;
@@ -134,4 +141,26 @@ public class LdapServerBeanDefinitionParser implements BeanDefinitionParser {
return (RootBeanDefinition) contextSource.getBeanDefinition();
}
private String getDefaultPort() {
ServerSocket serverSocket = null;
try {
try {
serverSocket = new ServerSocket(DEFAULT_PORT);
} catch (IOException e) {
try {
serverSocket = new ServerSocket(0);
} catch(IOException e2) {
return String.valueOf(DEFAULT_PORT);
}
}
return String.valueOf(serverSocket.getLocalPort());
} finally {
if(serverSocket != null) {
try {
serverSocket.close();
} catch (IOException e) {}
}
}
}
}
@@ -1,3 +1,18 @@
/*
* Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* 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.method;
import static org.springframework.security.config.Elements.*;
@@ -47,7 +62,6 @@ import org.springframework.security.access.vote.AffirmativeBased;
import org.springframework.security.access.vote.AuthenticatedVoter;
import org.springframework.security.access.vote.RoleVoter;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.config.BeanIds;
import org.springframework.security.config.Elements;
import org.springframework.security.config.authentication.AuthenticationManagerFactoryBean;
@@ -63,6 +77,7 @@ import org.w3c.dom.Element;
*
* @author Ben Alex
* @author Luke Taylor
* @author Rob Winch
* @since 2.0
*/
public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionParser {
@@ -234,7 +249,7 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP
* expression voter if expression-based access control is enabled.
* @return
*/
@SuppressWarnings("unchecked")
@SuppressWarnings({ "unchecked", "rawtypes" })
private String registerAccessManager(ParserContext pc, boolean jsr250Enabled, BeanDefinition expressionVoter) {
BeanDefinitionBuilder accessMgrBuilder = BeanDefinitionBuilder.rootBeanDefinition(AffirmativeBased.class);
@@ -259,7 +274,7 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP
return id;
}
@SuppressWarnings("unchecked")
@SuppressWarnings("rawtypes")
private BeanReference registerDelegatingMethodSecurityMetadataSource(ParserContext pc, ManagedList delegates, Object source) {
RootBeanDefinition delegatingMethodSecurityMetadataSource = new RootBeanDefinition(DelegatingMethodSecurityMetadataSource.class);
delegatingMethodSecurityMetadataSource.setSource(source);
@@ -383,7 +398,7 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP
if (delegate == null) {
Assert.state(beanFactory != null, "BeanFactory must be set to resolve " + authMgrBean);
try {
delegate = beanFactory.getBean(authMgrBean, ProviderManager.class);
delegate = beanFactory.getBean(authMgrBean, AuthenticationManager.class);
} catch (NoSuchBeanDefinitionException e) {
if (BeanIds.AUTHENTICATION_MANAGER.equals(e.getBeanName())) {
throw new NoSuchBeanDefinitionException(BeanIds.AUTHENTICATION_MANAGER,
@@ -292,7 +292,7 @@ http.attlist &=
## Allows a RequestMatcher instance to be used, as an alternative to pattern-matching.
attribute request-matcher-ref { xsd:token }?
http.attlist &=
## Automatically registers a login form, BASIC authentication, anonymous authentication, logout services, remember-me and servlet-api-integration. If set to "true", all of these capabilities are added (although you can still customize the configuration of each by providing the respective element). If unspecified, defaults to "false".
## A legacy attribute which automatically registers a login form, BASIC authentication and a logout URL and logout services. If unspecified, defaults to "false". We'd recommend you avoid using this and instead explicitly configure the services you require.
attribute auto-config {xsd:boolean}?
http.attlist &=
use-expressions?
@@ -739,4 +739,4 @@ position =
## The explicit position at which the custom-filter should be placed in the chain. Use if you are replacing a standard filter.
attribute position {named-security-filter}
named-security-filter = "FIRST" | "CHANNEL_FILTER" | "CONCURRENT_SESSION_FILTER" | "SECURITY_CONTEXT_FILTER" | "LOGOUT_FILTER" | "X509_FILTER" | "PRE_AUTH_FILTER" | "CAS_FILTER" | "FORM_LOGIN_FILTER" | "OPENID_FILTER" |"BASIC_AUTH_FILTER" | "SERVLET_API_SUPPORT_FILTER" | "REMEMBER_ME_FILTER" | "ANONYMOUS_FILTER" | "EXCEPTION_TRANSLATION_FILTER" | "SESSION_MANAGEMENT_FILTER" | "FILTER_SECURITY_INTERCEPTOR" | "SWITCH_USER_FILTER" | "LAST"
named-security-filter = "FIRST" | "CHANNEL_FILTER" | "SECURITY_CONTEXT_FILTER" | "CONCURRENT_SESSION_FILTER" | "LOGOUT_FILTER" | "X509_FILTER" | "PRE_AUTH_FILTER" | "CAS_FILTER" | "FORM_LOGIN_FILTER" | "OPENID_FILTER" | "LOGIN_PAGE_FILTER" | "DIGEST_AUTH_FILTER" |"BASIC_AUTH_FILTER" | "REQUEST_CACHE_FILTER" | "SERVLET_API_SUPPORT_FILTER" | "JAAS_API_SUPPORT_FILTER" | "REMEMBER_ME_FILTER" | "ANONYMOUS_FILTER" | "SESSION_MANAGEMENT_FILTER" | "EXCEPTION_TRANSLATION_FILTER" | "FILTER_SECURITY_INTERCEPTOR" | "SWITCH_USER_FILTER" | "LAST"
@@ -746,7 +746,7 @@
</xs:attribute>
<xs:attribute name="auto-config" type="xs:boolean">
<xs:annotation>
<xs:documentation>Automatically registers a login form, BASIC authentication, anonymous authentication, logout services, remember-me and servlet-api-integration. If set to "true", all of these capabilities are added (although you can still customize the configuration of each by providing the respective element). If unspecified, defaults to "false".</xs:documentation>
<xs:documentation>A legacy attribute which automatically registers a login form, BASIC authentication and a logout URL and logout services. If unspecified, defaults to "false". We'd recommend you avoid using this and instead explicitly configure the services you require.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="use-expressions" type="xs:boolean">
@@ -1632,20 +1632,24 @@
<xs:restriction base="xs:token">
<xs:enumeration value="FIRST"/>
<xs:enumeration value="CHANNEL_FILTER"/>
<xs:enumeration value="CONCURRENT_SESSION_FILTER"/>
<xs:enumeration value="SECURITY_CONTEXT_FILTER"/>
<xs:enumeration value="CONCURRENT_SESSION_FILTER"/>
<xs:enumeration value="LOGOUT_FILTER"/>
<xs:enumeration value="X509_FILTER"/>
<xs:enumeration value="PRE_AUTH_FILTER"/>
<xs:enumeration value="CAS_FILTER"/>
<xs:enumeration value="FORM_LOGIN_FILTER"/>
<xs:enumeration value="OPENID_FILTER"/>
<xs:enumeration value="LOGIN_PAGE_FILTER"/>
<xs:enumeration value="DIGEST_AUTH_FILTER"/>
<xs:enumeration value="BASIC_AUTH_FILTER"/>
<xs:enumeration value="REQUEST_CACHE_FILTER"/>
<xs:enumeration value="SERVLET_API_SUPPORT_FILTER"/>
<xs:enumeration value="JAAS_API_SUPPORT_FILTER"/>
<xs:enumeration value="REMEMBER_ME_FILTER"/>
<xs:enumeration value="ANONYMOUS_FILTER"/>
<xs:enumeration value="EXCEPTION_TRANSLATION_FILTER"/>
<xs:enumeration value="SESSION_MANAGEMENT_FILTER"/>
<xs:enumeration value="EXCEPTION_TRANSLATION_FILTER"/>
<xs:enumeration value="FILTER_SECURITY_INTERCEPTOR"/>
<xs:enumeration value="SWITCH_USER_FILTER"/>
<xs:enumeration value="LAST"/>
@@ -15,7 +15,10 @@
*/
package org.springframework.security.config.doc
import groovy.util.slurpersupport.NodeChild;
import groovy.util.slurpersupport.NodeChild
import org.springframework.security.config.http.SecurityFilters
import spock.lang.*
/**
@@ -31,10 +34,11 @@ class XsdDocumentedTests extends Specification {
@Shared File schemaDocument = new File('src/main/resources/org/springframework/security/config/spring-security-3.1.xsd')
@Shared Map<String,Element> elementNameToElement
@Shared schemaRootElement
def setupSpec() {
def rootElement = new XmlSlurper().parse(schemaDocument)
elementNameToElement = new SpringSecurityXsdParser(rootElement: rootElement).parse()
schemaRootElement = new XmlSlurper().parse(schemaDocument)
elementNameToElement = new SpringSecurityXsdParser(rootElement: schemaRootElement).parse()
appendixRoot.getMetaClass().sections = {
delegate.breadthFirst().inject([]) {result, c->
if(c.name() == 'section' && c.@id) {
@@ -55,6 +59,18 @@ class XsdDocumentedTests extends Specification {
}
}
def 'SEC-2139: named-security-filter are all defined and ordered properly'() {
setup:
def expectedFilters = (EnumSet.allOf(SecurityFilters) as List).sort { it.order }
when:
def nsf = schemaRootElement.simpleType.find { it.@name == 'named-security-filter' }
def nsfValues = nsf.children().children().collect { c ->
Enum.valueOf(SecurityFilters, c.@value.toString())
}
then:
expectedFilters == nsfValues
}
/**
* This will check to ensure that the expected number of xsd documents are found to ensure that we are validating
* against the current xsd document. If this test fails, all that is needed is to update the schemaDocument
@@ -212,6 +212,23 @@ class MiscHttpConfigTests extends AbstractHttpConfigTests {
'anonymity' == filter.authorities[0].authority
}
def anonymousSupportsMultipleGrantedAuthorities() {
xml.http {
'form-login'()
'anonymous'(username: 'joe', 'granted-authority':'ROLE_INVITADO,ROLE_PROFILE_INVITADO,ROLE_GRUPO_PUBLICO', key: 'customKey')
}
createAppContext()
AnonymousAuthenticationFilter filter = getFilter(AnonymousAuthenticationFilter);
def providers = appContext.getBeansOfType(AuthenticationManager).values()*.providers.flatten()
expect:
'customKey' == providers.find { it instanceof AnonymousAuthenticationProvider }.key
'customKey' == filter.key
'joe' == filter.principal
['ROLE_INVITADO','ROLE_PROFILE_INVITADO','ROLE_GRUPO_PUBLICO'] == filter.authorities*.authority
}
def httpMethodMatchIsSupported() {
httpAutoConfig {
interceptUrl '/secure*', 'DELETE', 'ROLE_SUPERVISOR'
@@ -10,9 +10,11 @@ import org.junit.After;
import org.junit.Test;
import org.springframework.aop.Advisor;
import org.springframework.aop.framework.Advised;
import org.springframework.beans.BeansException;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.parsing.BeanDefinitionParsingException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.support.AbstractXmlApplicationContext;
import org.springframework.context.support.StaticApplicationContext;
import org.springframework.security.access.AccessDeniedException;
@@ -29,11 +31,13 @@ import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.access.prepost.PreInvocationAuthorizationAdviceVoter;
import org.springframework.security.access.vote.AffirmativeBased;
import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.TestingAuthenticationToken;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.config.ConfigTestUtils;
import org.springframework.security.config.PostProcessedMockUserDetailsService;
import org.springframework.security.config.util.InMemoryXmlApplicationContext;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.context.SecurityContextHolder;
@@ -368,6 +372,52 @@ public class GlobalMethodSecurityBeanDefinitionParserTests {
foo.foo(new SecurityConfig("A"));
}
@Test
public void supportsCustomAuthenticationManager() throws Exception {
setContext(
"<b:bean id='target' class='" + ConcreteFoo.class.getName() + "'/>" +
"<method-security-metadata-source id='mds'>" +
" <protect method='"+ Foo.class.getName() + ".foo' access='ROLE_ADMIN'/>" +
"</method-security-metadata-source>" +
"<global-method-security pre-post-annotations='enabled' metadata-source-ref='mds' authentication-manager-ref='customAuthMgr'/>" +
"<b:bean id='customAuthMgr' class='org.springframework.security.config.method.GlobalMethodSecurityBeanDefinitionParserTests$CustomAuthManager'>" +
" <b:constructor-arg value='authManager'/>" +
"</b:bean>" +
AUTH_PROVIDER_XML
);
SecurityContextHolder.getContext().setAuthentication(bob);
Foo foo = (Foo) appContext.getBean("target");
try {
foo.foo(new SecurityConfig("A"));
fail("Bob can't invoke admin methods");
} catch (AccessDeniedException expected) {
}
SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken("admin", "password"));
foo.foo(new SecurityConfig("A"));
}
static class CustomAuthManager implements AuthenticationManager, ApplicationContextAware {
private String beanName;
private AuthenticationManager authenticationManager;
CustomAuthManager(String beanName) {
this.beanName = beanName;
}
public Authentication authenticate(Authentication authentication)
throws AuthenticationException {
return authenticationManager.authenticate(authentication);
}
/* (non-Javadoc)
* @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
*/
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
this.authenticationManager = applicationContext.getBean(beanName,AuthenticationManager.class);
}
}
private void setContext(String context) {
appContext = new InMemoryXmlApplicationContext(context);
}
@@ -17,7 +17,6 @@ import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.security.access.PermissionCacheOptimizer;
import org.springframework.security.access.expression.AbstractSecurityExpressionHandler;
import org.springframework.security.access.expression.ExpressionUtils;
import org.springframework.security.access.expression.SecurityExpressionOperations;
import org.springframework.security.authentication.AuthenticationTrustResolver;
import org.springframework.security.authentication.AuthenticationTrustResolverImpl;
import org.springframework.security.core.Authentication;
@@ -153,6 +152,6 @@ public class DefaultMethodSecurityExpressionHandler extends AbstractSecurityExpr
}
public void setReturnObject(Object returnObject, EvaluationContext ctx) {
((MethodSecurityExpressionRoot)ctx.getRootObject().getValue()).setReturnObject(returnObject);
((MethodSecurityExpressionOperations)ctx.getRootObject().getValue()).setReturnObject(returnObject);
}
}
@@ -20,7 +20,12 @@ package org.springframework.security.authentication.encoding;
* Interface for performing authentication operations on a password.
*
* @author colin sampaleanu
* @deprecated It is recommended to use
* {@link org.springframework.security.crypto.password.PasswordEncoder}
* instead which better accommodates best practice of randomly
* generated salt that is included with the password.
*/
@Deprecated
public interface PasswordEncoder {
//~ Methods ========================================================================================================
@@ -221,7 +221,7 @@ public class JdbcUserDetailsManager extends JdbcDaoImpl implements UserDetailsMa
UserDetails user = loadUserByUsername(currentAuth.getName());
UsernamePasswordAuthenticationToken newAuthentication =
new UsernamePasswordAuthenticationToken(user, user.getPassword(), user.getAuthorities());
new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities());
newAuthentication.setDetails(currentAuth.getDetails());
return newAuthentication;
@@ -1,4 +1,5 @@
AbstractAccessDecisionManager.accessDenied=Access is denied
AbstractLdapAuthenticationProvider.emptyPassword=Empty Password
AbstractSecurityInterceptor.authenticationNotFound=An Authentication object was not found in the SecurityContext
AbstractUserDetailsAuthenticationProvider.badCredentials=Bad credentials
AbstractUserDetailsAuthenticationProvider.credentialsExpired=User credentials have expired
@@ -1,4 +1,5 @@
AbstractAccessDecisionManager.accessDenied=P\u0159\u00EDstup odep\u0159en
AbstractLdapAuthenticationProvider.emptyPassword=\u0160patn\u00E9 p\u0159ihla\u0161ovac\u00ED \u00FAdaje
AbstractSecurityInterceptor.authenticationNotFound=Nebyl nalezen \u017E\u00E1dn\u00FD Authentication objekt v SecurityContext
AbstractUserDetailsAuthenticationProvider.badCredentials=\u0160patn\u00E9 p\u0159ihla\u0161ovac\u00ED \u00FAdaje
AbstractUserDetailsAuthenticationProvider.credentialsExpired=Platnost u\u017Eivatelsk\u00E9ho hesla vypr\u0161ela
@@ -1,19 +1,20 @@
AbstractAccessDecisionManager.accessDenied=Zugriff verweigert
AbstractLdapAuthenticationProvider.emptyPassword=Ung\u00FCltige Anmeldedaten
AbstractSecurityInterceptor.authenticationNotFound=Im SecurityContext wurde keine Authentifikation gefunden
AbstractUserDetailsAuthenticationProvider.badCredentials=Ung\u00FCltige Benutzerberechtigungen
AbstractUserDetailsAuthenticationProvider.credentialsExpired=Die G\u00FCltigkeit der Benutzerberechtigungen ist abgelaufen
AbstractUserDetailsAuthenticationProvider.badCredentials=Ung\u00FCltige Anmeldedaten
AbstractUserDetailsAuthenticationProvider.credentialsExpired=Die G\u00FCltigkeit der Anmeldedaten ist abgelaufen
AbstractUserDetailsAuthenticationProvider.disabled=Der Benutzer ist deaktiviert
AbstractUserDetailsAuthenticationProvider.expired=Die G\u00FCltigkeit des Benutzerkontos ist abgelaufen
AbstractUserDetailsAuthenticationProvider.locked=Das Benutzerkonto ist gesperrt
AbstractUserDetailsAuthenticationProvider.onlySupports=Nur UsernamePasswordAuthenticationToken wird unterst\u00FCtzt
AccountStatusUserDetailsChecker.credentialsExpired=Die G\u00FCltigkeit der Benutzerberechtigungen ist abgelaufen
AccountStatusUserDetailsChecker.credentialsExpired=Die G\u00FCltigkeit der Anmeldedaten ist abgelaufen
AccountStatusUserDetailsChecker.disabled=Der Benutzer ist deaktiviert
AccountStatusUserDetailsChecker.expired=Die G\u00FCltigkeit des Benutzerkontos ist abgelaufen
AccountStatusUserDetailsChecker.locked=Das Benutzerkonto ist gesperrt
AclEntryAfterInvocationProvider.noPermission=Authentifikation {0} hat KEINE Berechtigungen bez\u00FCglich des Dom\u00E4nen-Objekts {1}
AnonymousAuthenticationProvider.incorrectKey=Das angegebene AnonymousAuthenticationToken enth\u00E4lt nicht den erwarteten Schl\u00FCssel
BindAuthenticator.badCredentials=Ung\u00FCltige Benutzerberechtigungen
BindAuthenticator.emptyPassword=Ung\u00FCltige Benutzerberechtigungen
BindAuthenticator.badCredentials=Ung\u00FCltige Anmeldedaten
BindAuthenticator.emptyPassword=Ung\u00FCltige Anmeldedaten
CasAuthenticationProvider.incorrectKey=Das angegebene CasAuthenticationToken enth\u00E4lt nicht den erwarteten Schl\u00FCssel
CasAuthenticationProvider.noServiceTicket=Es konnte kein CAS Service-Ticket zur Pr\u00FCfung geliefert werden
ConcurrentSessionControlStrategy.exceededAllowed=Die maximale Sitzungs-Anzahl von {0} f\u00FCr diesen Nutzer wurde \u00FCberschritten
@@ -29,14 +30,14 @@ DigestAuthenticationFilter.nonceNotTwoTokens=Nonce sollte zwei Elemente beinhalt
DigestAuthenticationFilter.usernameNotFound=Benutzername {0} wurde nicht gefunden
#JdbcDaoImpl.noAuthority=User {0} has no GrantedAuthority
#JdbcDaoImpl.notFound=User {0} not found
LdapAuthenticationProvider.badCredentials=Ung\u00FCltige Benutzerberechtigungen
LdapAuthenticationProvider.credentialsExpired=Die G\u00FCltigkeit der Benutzerberechtigungen ist abgelaufen
LdapAuthenticationProvider.badCredentials=Ung\u00FCltige Anmeldedaten
LdapAuthenticationProvider.credentialsExpired=Die G\u00FCltigkeit der Anmeldedaten ist abgelaufen
LdapAuthenticationProvider.disabled=Der Benutzer ist deaktiviert
LdapAuthenticationProvider.expired=Die G\u00FCltigkeit des Benutzerkontos ist abgelaufen
LdapAuthenticationProvider.locked=Das Benutzerkonto ist gesperrt
LdapAuthenticationProvider.emptyUsername=Ein leerer Benutzername ist nicht erlaubt
LdapAuthenticationProvider.onlySupports=Nur UsernamePasswordAuthenticationToken wird unterst\u00FCtzt
PasswordComparisonAuthenticator.badCredentials=Ung\u00FCltige Benutzerberechtigungen
PasswordComparisonAuthenticator.badCredentials=Ung\u00FCltige Anmeldedaten
#PersistentTokenBasedRememberMeServices.cookieStolen=Invalid remember-me token (Series/token) mismatch. Implies previous cookie theft attack.
ProviderManager.providerNotFound=F\u00FCr {0} wurde kein AuthenticationProvider gefunden
RememberMeAuthenticationProvider.incorrectKey=Das angegebene RememberMeAuthenticationToken enth\u00E4lt nicht den erwarteten Schl\u00FCssel
@@ -1,4 +1,5 @@
AbstractAccessDecisionManager.accessDenied=Acceso denegado
AbstractLdapAuthenticationProvider.emptyPassword=Credenciales err\u00F3neas
AbstractSecurityInterceptor.authenticationNotFound=El objeto Authentication no ha sido encontrado en el SecurityContext
AbstractUserDetailsAuthenticationProvider.badCredentials=Credenciales err\u00F3neas
AbstractUserDetailsAuthenticationProvider.credentialsExpired=Las credenciales del usuario han expirado
@@ -3,6 +3,7 @@
# Translation by Laurent Pireyn (laurent.pireyn@pisolutions.eu)
# Translation by Valentin Crettaz (valentin.crettaz@consulthys.com)
AbstractAccessDecisionManager.accessDenied=Acc\u00E8s refus\u00E9
AbstractLdapAuthenticationProvider.emptyPassword=Le mot de passe est obligatoire
AbstractSecurityInterceptor.authenticationNotFound=Aucun objet Authentication n'a \u00E9t\u00E9 trouv\u00E9 dans le SecurityContext
AbstractUserDetailsAuthenticationProvider.badCredentials=Les cr\u00E9ances sont erron\u00E9es
AbstractUserDetailsAuthenticationProvider.credentialsExpired=Les cr\u00E9ances de l'utilisateur ont expir\u00E9
@@ -1,4 +1,5 @@
AbstractAccessDecisionManager.accessDenied=Accesso negato
AbstractLdapAuthenticationProvider.badCredentials=Credenziali non valide
AbstractSecurityInterceptor.authenticationNotFound=Nessuna autenticazione trovata dentro il Security Context
AbstractUserDetailsAuthenticationProvider.badCredentials=Credenziali non valide
AbstractUserDetailsAuthenticationProvider.credentialsExpired=Credenziali dell'utente scadute
@@ -1,4 +1,5 @@
AbstractAccessDecisionManager.accessDenied=\uC811\uADFC\uC774 \uAC70\uBD80\uB418\uC5C8\uC2B5\uB2C8\uB2E4.
AbstractLdapAuthenticationProvider.badCredentials=\uBE44\uBC00\uBC88\uD638\uAC00 \uB9DE\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.
AbstractSecurityInterceptor.authenticationNotFound=SecurityContext\uC5D0\uC11C Authentication \uAC1D\uCCB4\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.
AbstractUserDetailsAuthenticationProvider.badCredentials=\uBE44\uBC00\uBC88\uD638(credential)\uAC00 \uB9DE\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.
AbstractUserDetailsAuthenticationProvider.credentialsExpired=\uBE44\uBC00\uBC88\uD638(credential)\uC758 \uC720\uD6A8 \uAE30\uAC04\uC774 \uB9CC\uB8CC\uB418\uC5C8\uC2B5\uB2C8\uB2E4.
@@ -1,4 +1,5 @@
AbstractAccessDecisionManager.accessDenied=Pri\u0117jimas neleid\u017eiamas
AbstractLdapAuthenticationProvider.emptyPassword=Tu\u0161\u010dias slapta\u017eodis
AbstractSecurityInterceptor.authenticationNotFound=Authentication objektas nerastas SecurityContext kontekste
AbstractUserDetailsAuthenticationProvider.badCredentials=Blogi kredencialai
AbstractUserDetailsAuthenticationProvider.credentialsExpired=Pasibaig\u0117 vartotojo kredencial\u0173 galiojimas
@@ -1,4 +1,5 @@
AbstractAccessDecisionManager.accessDenied=Dost\u0119p zabroniony
AbstractLdapAuthenticationProvider.emptyPassword=Niepoprawne dane uwierzytelniaj\u0105ce
AbstractSecurityInterceptor.authenticationNotFound=Obiekt Authentication nie zosta\u0142 odnaleziony w SecurityContext
AbstractUserDetailsAuthenticationProvider.badCredentials=Niepoprawne dane uwierzytelniaj\u0105ce
AbstractUserDetailsAuthenticationProvider.credentialsExpired=Wa\u017Cno\u015B\u0107 danych uwierzytelniaj\u0105cych wygas\u0142a
@@ -2,6 +2,7 @@
# Messages in Brazilian Portuguese
# Translation by Leonardo Pinto (leoviveiros@gmail.com)
AbstractAccessDecisionManager.accessDenied=Acesso negado
AbstractLdapAuthenticationProvider.emptyPassword=Usu\u00E1rio inexistente ou senha inv\u00E1lida
AbstractSecurityInterceptor.authenticationNotFound=Um objeto de autentica\u00E7\u00E3o n\u00E3o foi encontrado no SecurityContext
AbstractUserDetailsAuthenticationProvider.badCredentials=Usu\u00E1rio inexistente ou senha inv\u00E1lida
AbstractUserDetailsAuthenticationProvider.credentialsExpired=Credenciais expiradas
@@ -1,6 +1,7 @@
# Spring Security Portuguese Resource Bundle
# Author: José Santos
AbstractAccessDecisionManager.accessDenied=Acesso negado
AbstractLdapAuthenticationProvider.emptyPassword=Credenciais inv\u00E1lidas
AbstractSecurityInterceptor.authenticationNotFound=Objecto Authentication n\u00E3o encontrado em SecurityContext
AbstractUserDetailsAuthenticationProvider.badCredentials=Credenciais inv\u00E1lidas
AbstractUserDetailsAuthenticationProvider.credentialsExpired=As credenciais do utilizador expiraram
@@ -1,4 +1,5 @@
AbstractAccessDecisionManager.accessDenied=\u0414\u043E\u0441\u0442\u0443\u043F \u0437\u0430\u0431\u043E\u0440\u043E\u043D\u0435\u043D\u0438\u0439
AbstractLdapAuthenticationProvider.emptyPassword=\u0414\u0430\u043D\u0456 \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 \u043D\u0435\u043A\u043E\u0440\u0435\u043A\u0442\u043D\u0456
AbstractSecurityInterceptor.authenticationNotFound=\u041E\u0431'\u0454\u043A\u0442 Authentication \u043D\u0435 \u0437\u043D\u0430\u0439\u0434\u0435\u043D\u0438\u0439 \u0432 SecurityContext
AbstractUserDetailsAuthenticationProvider.badCredentials=\u0414\u0430\u043D\u0456 \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 \u043D\u0435\u043A\u043E\u0440\u0435\u043A\u0442\u043D\u0456
AbstractUserDetailsAuthenticationProvider.credentialsExpired=\u041F\u043E\u0432\u043D\u043E\u0432\u0430\u0436\u0435\u043D\u043D\u044F \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 \u0432\u0438\u0447\u0435\u0440\u043F\u0430\u043B\u0438 \u0442\u0435\u0440\u043C\u0456\u043D \u0434\u0456\u0457
@@ -1,4 +1,5 @@
AbstractAccessDecisionManager.accessDenied=\u4E0D\u5141\u8BB8\u8BBF\u95EE
AbstractLdapAuthenticationProvider.emptyPassword=\u574F\u7684\u51ED\u8BC1
AbstractSecurityInterceptor.authenticationNotFound=\u672A\u5728SecurityContext\u4E2D\u67E5\u627E\u5230\u8BA4\u8BC1\u5BF9\u8C61
AbstractUserDetailsAuthenticationProvider.badCredentials=\u574F\u7684\u51ED\u8BC1
AbstractUserDetailsAuthenticationProvider.credentialsExpired=\u7528\u6237\u51ED\u8BC1\u5DF2\u8FC7\u671F
@@ -168,7 +168,7 @@ public class JdbcUserDetailsManagerTests {
Authentication newAuth = SecurityContextHolder.getContext().getAuthentication();
assertEquals("joe", newAuth.getName());
assertEquals(currentAuth.getDetails(), newAuth.getDetails());
assertEquals("newPassword", newAuth.getCredentials());
assertNull(newAuth.getCredentials());
assertFalse(cache.getUserMap().containsKey("joe"));
}
@@ -302,6 +302,15 @@ public class JdbcUserDetailsManagerTests {
assertEquals(0, template.queryForList(SELECT_JOE_AUTHORITIES_SQL).size());
}
// SEC-2166
@Test
public void createNewAuthenticationUsesNullPasswordToKeepPassordsSave() {
insertJoe();
UsernamePasswordAuthenticationToken currentAuth = new UsernamePasswordAuthenticationToken("joe",null, AuthorityUtils.createAuthorityList("ROLE_USER"));
Authentication updatedAuth = manager.createNewAuthentication(currentAuth, "new");
assertNull(updatedAuth.getCredentials());
}
private Authentication authenticateJoe() {
UsernamePasswordAuthenticationToken auth =
new UsernamePasswordAuthenticationToken("joe","password", joe.getAuthorities());
@@ -494,7 +494,7 @@
interested in and to configure how they should be handled. It is used to construct
the <interfacename>FilterInvocationSecurityMetadataSource</interfacename> used by
the <classname>FilterSecurityInterceptor</classname>. It is also responsible for
configuring a <classname>ChannelAuthenticationFilter</classname> if particular URLs
configuring a <classname>ChannelProcessingFilter</classname> if particular URLs
need to be accessed by HTTPS, for example. When matching the specified patterns
against an incoming request, the matching is done in the order in which the elements
are declared. So the most specific matches patterns should come first and the most
@@ -544,7 +544,7 @@
Alternatively the value <quote>any</quote> can be used when there is no
preference. If this attribute is present on any
<literal>&lt;intercept-url&gt;</literal> element, then a
<classname>ChannelAuthenticationFilter</classname> will be added to the filter
<classname>ChannelProcessingFilter</classname> will be added to the filter
stack and its additional dependencies added to the application
context.<!--See the chapter on <link
xlink:href="#channel-security-config">channel security</link> for an example
@@ -314,7 +314,7 @@ boolean supports(Class clazz);
<programlisting language="xml"><![CDATA[
<bean id="roleVoter" class="org.springframework.security.access.vote.RoleHierarchyVoter">
<constructor-arg ref="roleHierarchy" />
</class>
</bean>
<bean id="roleHierarchy"
class="org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl">
<property name="hierarchy">
@@ -526,7 +526,9 @@
<property name="serviceProperties" ref="serviceProperties"/>
<property name="authenticationDetailsSource">
<bean class=
"org.springframework.security.cas.web.authentication.ServiceAuthenticationDetailsSource"/>
"org.springframework.security.cas.web.authentication.ServiceAuthenticationDetailsSource">
<constructor-arg ref="serviceProperties"/>
</bean>
</property>
</bean>
]]></programlisting></para>
@@ -22,6 +22,11 @@
don't use any third-party LDAP libraries (Mozilla, JLDAP etc.) in the LDAP provider, but
extensive use is made of Spring LDAP, so some familiarity with that project may be
useful if you plan on adding your own customizations.</para>
<para>When using LDAP authentication, it is important to ensure that you configure LDAP connection
pooling properly. If you are unfamiliar with how to do this, you can refer to the
<uri xmlns:xlink="http://www.w3.org/1999/xlink"
xlink:href="http://docs.oracle.com/javase/jndi/tutorial/ldap/connect/config.html">Java LDAP
documentation</uri>.</para>
</section>
<section>
<info>
@@ -410,7 +415,7 @@ public interface UserDetailsContextMapper {
<para>By default, the user authorities are obtained from the <literal>memberOf</literal>
attribute values of the user entry. The authorities allocated to the user can again
be customized using a <interfacename>UserDetailsContextMapper</interfacename>. You
can also inject a <interfacename>GrantedAuthoritiesMaper</interfacename> into the
can also inject a <interfacename>GrantedAuthoritiesMapper</interfacename> into the
provider instance to control the authorities which end up in the
<interfacename>Authentication</interfacename> object.</para>
<section>
+9 -9
View File
@@ -35,10 +35,10 @@
<property name="accessDecisionManager" ref="accessDecisionManager"/>
<property name="afterInvocationManager" ref="afterInvocationManager"/>
<property name="securityMetadataSource">
<value>
com.mycompany.BankManager.delete*=ROLE_SUPERVISOR
com.mycompany.BankManager.getBalance=ROLE_TELLER,ROLE_SUPERVISOR
</value>
<sec:method-security-metadata-source>
<sec:protect method="com.mycompany.BankManager.delete*" access="ROLE_SUPERVISOR"/>
<sec:protect method="com.mycompany.BankManager.getBalance" access="ROLE_TELLER,ROLE_SUPERVISOR"/>
</sec:method-security-metadata-source>
</property>
</bean> ]]>
</programlisting></para>
@@ -64,15 +64,15 @@
configured in the Spring application context:</para>
<programlisting language="xml"><![CDATA[
<bean id="bankManagerSecurity" class=
"org.springframework.security.access.intercept.aspectj.AspectJSecurityInterceptor">
"org.springframework.security.access.intercept.aspectj.AspectJMethodSecurityInterceptor">
<property name="authenticationManager" ref="authenticationManager"/>
<property name="accessDecisionManager" ref="accessDecisionManager"/>
<property name="afterInvocationManager" ref="afterInvocationManager"/>
<property name="securityMetadataSource">
<value>
com.mycompany.BankManager.delete*=ROLE_SUPERVISOR
com.mycompany.BankManager.getBalance=ROLE_TELLER,ROLE_SUPERVISOR
</value>
<sec:method-security-metadata-source>
<sec:protect method="com.mycompany.BankManager.delete*" access="ROLE_SUPERVISOR"/>
<sec:protect method="com.mycompany.BankManager.getBalance" access="ROLE_TELLER,ROLE_SUPERVISOR"/>
</sec:method-security-metadata-source>
</property>
</bean>]]> </programlisting>
<para>As you can see, aside from the class name, the
+1 -1
View File
@@ -1 +1 @@
version=3.1.4.CI-SNAPSHOT
version=3.1.8.CI-SNAPSHOT
+7 -5
View File
@@ -1,10 +1,12 @@
apply plugin: 'idea'
configure(javaProjects) {
configure(allprojects) {
apply plugin: 'idea'
apply plugin: 'eclipse-wtp'
eclipse.classpath.downloadSources = true
eclipse.project.name = "${project.name}-3.1.x"
}
configure(javaProjects) {
eclipse.classpath.downloadSources = true
// GRADLE-1116
project.eclipse.classpath.file.whenMerged { classpath ->
@@ -49,7 +51,7 @@ project(':spring-security-samples-aspectj') {
doLast {
def classpath = new XmlParser().parse(srcFile)
classpath.classpathentry.findAll{ it.@path == '/spring-security-aspects' }.each { node ->
classpath.classpathentry.findAll{ it.@path.startsWith('/spring-security-aspects') }.each { node ->
if(node.children().size() == 0) {
def attrs = new Node(node,'attributes')
def adjtAttr = new Node(attrs,'attributes',[name: 'org.eclipse.ajdt.aspectpath', value: 'org.eclipse.ajdt.aspectpath'])
+7 -6
View File
@@ -1,4 +1,5 @@
apply plugin: 'java'
apply plugin: 'javadocHotfix'
apply plugin: 'eclipse'
sourceCompatibility = 1.5
@@ -15,13 +16,13 @@ ext.hsqlVersion = '1.8.0.10'
ext.slf4jVersion = '1.6.1'
ext.logbackVersion = '0.9.29'
ext.cglibVersion = '2.2'
ext.powerMockVersion = '1.4.12'
ext.powerMockVersion = '1.5.1'
ext.bundlorProperties = [
version: version,
secRange: "[$version, 3.2.0)",
springRange: "[$springVersion, 3.2.0)",
aspectjRange: '[1.6.0, 1.7.0)',
secRange: "[$version, 3.3.0)",
springRange: "[$springVersion, 3.3.0)",
aspectjRange: '[1.6.0, 1.8.0)',
casRange: '[3.1.1, 3.2.0)',
cloggingRange: '[1.0.4, 2.0.0)',
ehcacheRange: '[1.4.1, 2.5.0)',
@@ -78,8 +79,8 @@ dependencies {
exclude(group: 'commons-logging', module: 'commons-logging')
}
testCompile 'junit:junit:4.7',
'org.mockito:mockito-core:1.8.5',
testCompile 'junit:junit:4.10',
'org.mockito:mockito-core:1.9.5',
"org.springframework:spring-test:$springVersion"
// Use slf4j/logback for logging
Binary file not shown.
+2 -2
View File
@@ -1,6 +1,6 @@
#Fri Sep 21 14:16:44 CDT 2012
#Thu Dec 05 08:38:26 CST 2013
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=http\://services.gradle.org/distributions/gradle-1.2-bin.zip
distributionUrl=http\://services.gradle.org/distributions/gradle-1.9-bin.zip
Vendored
+2 -2
View File
@@ -1,4 +1,4 @@
#!/bin/bash
#!/usr/bin/env bash
##############################################################################
##
@@ -7,7 +7,7 @@
##############################################################################
# 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=256M"
DEFAULT_JVM_OPTS=""
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
Vendored
+1 -1
View File
@@ -9,7 +9,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 -XX:MaxPermSize=256M
set DEFAULT_JVM_OPTS=
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
@@ -3,15 +3,13 @@
<body>
<h1>Authentication Tag Test Page</h1>
<p>
<ul>
<li>This is the authentication name: <sec:authentication property="name"/></li>
<li>This is the principal.username: <sec:authentication property="principal.username"/></li>
<li>This is the unescaped authentication name: <sec:authentication property="name" htmlEscape="false"/></li>
<li>This is the unescaped principal.username: <sec:authentication property="principal.username" htmlEscape="false"/></li>
</ul
</p>
</ul>
</body>
</html>
+4 -1
View File
@@ -7,6 +7,9 @@
<title>A secure page</title>
</head>
<body>
<jsp:include page="secure1body.jsp?x=1&y=2"/>
<jsp:include page="secure1body.jsp">
<jsp:param name="x" value="1" />
<jsp:param name="y" value="2" />
</jsp:include>
</body>
</html>
-2
View File
@@ -33,13 +33,11 @@ integrationTest {
include('**/ApacheDSServerIntegrationTests.class')
// exclude('**/OpenLDAPIntegrationTestSuite.class')
maxParallelForks = 1
systemProperties['apacheDSWorkDir'] = "${buildDir}/apacheDSWork"
}
// Runs a server for running the integration tests against (from an IDE, for example)
task(ldapServer, dependsOn: 'integrationTestClasses', type: JavaExec) {
classpath = sourceSets.integrationTest.runtimeClasspath
main = 'org.springframework.security.ldap.ApacheDSServerIntegrationTests'
systemProperties['apacheDSWorkDir'] = "${buildDir}/apacheDSWork"
}
@@ -25,7 +25,8 @@ public abstract class AbstractLdapIntegrationTests {
@BeforeClass
public static void createContextSource() throws Exception {
contextSource = new DefaultSpringSecurityContextSource("ldap://127.0.0.1:53389/dc=springframework,dc=org");
int serverPort = ApacheDSServerIntegrationTests.getServerPort();
contextSource = new DefaultSpringSecurityContextSource("ldap://127.0.0.1:" + serverPort + "/dc=springframework,dc=org");
// OpenLDAP configuration
// contextSource = new DefaultSpringSecurityContextSource("ldap://127.0.0.1:22389/dc=springsource,dc=com");
// contextSource.setUserDn("cn=admin,dc=springsource,dc=com");
@@ -1,5 +1,8 @@
package org.springframework.security.ldap;
import java.io.IOException;
import java.net.ServerSocket;
import org.junit.*;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
@@ -26,6 +29,7 @@ import org.springframework.security.ldap.userdetails.LdapUserDetailsManagerTests
)
public final class ApacheDSServerIntegrationTests {
private static ApacheDSContainer server;
private static Integer serverPort;
@BeforeClass
public static void startServer() throws Exception {
@@ -34,12 +38,15 @@ public final class ApacheDSServerIntegrationTests {
// contextSource.setUserDn("cn=admin,dc=springsource,dc=com");
// contextSource.setPassword("password");
server = new ApacheDSContainer("dc=springframework,dc=org", "classpath:test-server.ldif");
server.setPort(53389);
int port = getAvailablePort();
server.setPort(port);
server.afterPropertiesSet();
serverPort = port;
}
@AfterClass
public static void stopServer() throws Exception {
serverPort = null;
if (server != null) {
server.stop();
}
@@ -53,6 +60,12 @@ public final class ApacheDSServerIntegrationTests {
server.afterPropertiesSet();
}
public static int getServerPort() {
if(serverPort == null) {
throw new IllegalStateException("The ApacheDSContainer is not currently running");
}
return serverPort;
}
/*
@After
public final void reloadServerDataIfDirty() throws Exception {
@@ -105,4 +118,18 @@ public final class ApacheDSServerIntegrationTests {
}
}
*/
private static int getAvailablePort() throws IOException {
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(0);
return serverSocket.getLocalPort();
} finally {
if(serverSocket != null) {
try {
serverSocket.close();
} catch (IOException e) {}
}
}
}
}
@@ -71,7 +71,7 @@ public class DefaultSpringSecurityContextSourceTests extends AbstractLdapIntegra
@Test
public void serverUrlWithSpacesIsSupported() throws Exception {
DefaultSpringSecurityContextSource
contextSource = new DefaultSpringSecurityContextSource("ldap://127.0.0.1:53389/ou=space%20cadets,dc=springframework,dc=org");
contextSource = new DefaultSpringSecurityContextSource("ldap://127.0.0.1:" + ApacheDSServerIntegrationTests.getServerPort() + "/ou=space%20cadets,dc=springframework,dc=org");
contextSource.afterPropertiesSet();
contextSource.getContext("uid=space cadet,ou=space cadets,dc=springframework,dc=org", "spacecadetspassword");
}
@@ -121,7 +121,7 @@ public class SpringSecurityLdapTemplateTests extends AbstractLdapIntegrationTest
public void nonSpringLdapSearchCodeTestMethod() throws Exception {
java.util.Hashtable<String, String> env = new java.util.Hashtable<String, String>();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldap://localhost:53389");
env.put(Context.PROVIDER_URL, "ldap://localhost:" + ApacheDSServerIntegrationTests.getServerPort());
env.put(Context.SECURITY_PRINCIPAL, "");
env.put(Context.SECURITY_CREDENTIALS, "");
@@ -1,26 +1,69 @@
/*
* Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* 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.ldap.server;
import org.apache.directory.shared.ldap.name.LdapDN;
import static junit.framework.Assert.fail;
import org.junit.Test;
/**
* Useful for debugging the container by itself.
*
* @author Luke Taylor
* @author Rob Winch
* @since 3.0
*/
public class ApacheDSContainerTests {
// SEC-2162
@Test
public void successfulStartupAndShutdown() throws Exception {
LdapDN people = new LdapDN("ou=people,dc=springframework,dc=org");
people.toString();
public void failsToStartThrowsException() throws Exception {
ApacheDSContainer server1 = new ApacheDSContainer("dc=springframework,dc=org", "classpath:test-server.ldif");
ApacheDSContainer server2 = new ApacheDSContainer("dc=springframework,dc=org", "classpath:test-server.ldif");
try {
server1.afterPropertiesSet();
try {
server2.afterPropertiesSet();
fail("Expected Exception");
} catch(RuntimeException success) {}
} finally {
try {
server1.destroy();
}catch(Throwable t) {}
try {
server2.destroy();
}catch(Throwable t) {}
}
}
// ApacheDSContainer server = new ApacheDSContainer("dc=springframework,dc=org", "classpath:test-server.ldif");
// server.afterPropertiesSet();
//
// server.getService().getAdminSession().lookup(people);
//
// server.stop();
// SEC-2161
@Test
public void multipleInstancesSimultanciously() throws Exception {
ApacheDSContainer server1 = new ApacheDSContainer("dc=springframework,dc=org", "classpath:test-server.ldif");
ApacheDSContainer server2 = new ApacheDSContainer("dc=springframework,dc=org", "classpath:test-server.ldif");
try {
server1.afterPropertiesSet();
server2.afterPropertiesSet();
} finally {
try {
server1.destroy();
}catch(Throwable t) {}
try {
server2.destroy();
}catch(Throwable t) {}
}
}
}
@@ -1,4 +1,18 @@
package org.springframework.security.ldap.authentication;
/*
* Copyright 2002-2014 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.ldap.authentication;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -56,6 +70,11 @@ public abstract class AbstractLdapAuthenticationProvider implements Authenticati
"Empty Username"));
}
if (!StringUtils.hasLength(password)) {
throw new BadCredentialsException(messages.getMessage("AbstractLdapAuthenticationProvider.emptyPassword",
"Empty Password"));
}
Assert.notNull(password, "Null password was supplied in authentication token");
DirContextOperations userData = doAuthentication(userToken);
@@ -1,8 +1,22 @@
/*
* Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* 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.ldap.server;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
@@ -50,6 +64,7 @@ import org.springframework.util.Assert;
* framework public API.
*
* @author Luke Taylor
* @author Rob Winch
*/
public class ApacheDSContainer implements InitializingBean, DisposableBean, Lifecycle, ApplicationContextAware {
private final Log logger = LogFactory.getLog(getClass());
@@ -103,7 +118,7 @@ public class ApacheDSContainer implements InitializingBean, DisposableBean, Life
String apacheWorkDir = System.getProperty("apacheDSWorkDir");
if (apacheWorkDir == null) {
apacheWorkDir = System.getProperty("java.io.tmpdir") + File.separator + "apacheds-spring-security";
apacheWorkDir = createTempDirectory("apacheds-spring-security-");
}
setWorkingDirectory(new File(apacheWorkDir));
@@ -162,8 +177,7 @@ public class ApacheDSContainer implements InitializingBean, DisposableBean, Life
service.startup();
server.start();
} catch (Exception e) {
logger.error("Server startup failed ", e);
return;
throw new RuntimeException("Server startup failed", e);
}
try {
@@ -252,6 +266,22 @@ public class ApacheDSContainer implements InitializingBean, DisposableBean, Life
}
}
private String createTempDirectory(String prefix) throws IOException {
String parentTempDir = System.getProperty("java.io.tmpdir");
String fileNamePrefix = prefix + System.nanoTime();
String fileName = fileNamePrefix;
for(int i=0;i<1000;i++) {
File tempDir = new File(parentTempDir, fileName);
if(!tempDir.exists()) {
return tempDir.getAbsolutePath();
}
fileName = fileNamePrefix + "~" + i;
}
throw new IOException("Failed to create a temporary directory for file at " + new File(parentTempDir, fileNamePrefix));
}
private boolean deleteDir(File dir) {
if (dir.isDirectory()) {
String[] children = dir.list();
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2014 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
@@ -141,6 +141,12 @@ public class ActiveDirectoryLdapAuthenticationProviderTests {
provider.authenticate(joe);
}
// SEC-2500
@Test(expected = BadCredentialsException.class)
public void sec2500PreventAnonymousBind() {
provider.authenticate(new UsernamePasswordAuthenticationToken("rwinch", ""));
}
@SuppressWarnings("unchecked")
@Test(expected = IncorrectResultSizeDataAccessException.class)
public void duplicateUserSearchCausesError() throws Exception {
+2 -2
View File
@@ -34,7 +34,7 @@ dependencies {
compile project(':spring-security-core'),
project(':spring-security-cas'),
"org.jasig.cas.client:cas-client-core:3.1.12"
"org.jasig.cas.client:cas-client-core:3.3.3"
runtime project(':spring-security-web'),
project(':spring-security-config'),
@@ -126,4 +126,4 @@ gradle.taskGraph.whenReady {graph ->
def casServer() {
tasks.getByPath(':spring-security-samples-casserver:casServer')
}
}
@@ -0,0 +1,96 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<description>
This is the main Spring configuration file with some of the main "core" classes defined. You shouldn't really
modify this unless you
know what you're doing!
</description>
<!--
Including this aspectj-autoproxy element will cause spring to automatically
create proxies around any beans defined in this file that match the pointcuts
of any aspects defined in this file.
-->
<aop:aspectj-autoproxy/>
<!--
Declare the TimingAspect that we want to weave into the other beans
defined in this config file.
-->
<bean id="timingAspect" class="org.perf4j.log4j.aop.TimingAspect"/>
<!-- Message source for this context, loaded from localized "messages_xx" files -->
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource"
p:basename="messages"/>
<bean
id="servicesManager"
class="org.jasig.cas.services.DefaultServicesManagerImpl">
<constructor-arg index="0" ref="serviceRegistryDao"/>
</bean>
<!--
Job to periodically reload services from service registry.
This job is needed for a clustered CAS environment since service changes
in one CAS node are not known to the other until a reload.
-->
<bean id="serviceRegistryReloaderJobDetail"
class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"
p:targetObject-ref="servicesManager"
p:targetMethod="reload"/>
<bean id="periodicServiceRegistryReloaderTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean"
p:jobDetail-ref="serviceRegistryReloaderJobDetail"
p:startDelay="120000"
p:repeatInterval="120000"/>
<bean id="persistentIdGenerator"
class="org.jasig.cas.authentication.principal.ShibbolethCompatiblePersistentIdGenerator"
p:salt="casrocks"/>
<!-- CentralAuthenticationService -->
<bean id="centralAuthenticationService" class="org.jasig.cas.CentralAuthenticationServiceImpl"
p:ticketGrantingTicketExpirationPolicy-ref="grantingTicketExpirationPolicy"
p:serviceTicketExpirationPolicy-ref="serviceTicketExpirationPolicy"
p:authenticationManager-ref="authenticationManager"
p:ticketGrantingTicketUniqueTicketIdGenerator-ref="ticketGrantingTicketUniqueIdGenerator"
p:ticketRegistry-ref="ticketRegistry"
p:servicesManager-ref="servicesManager"
p:persistentIdGenerator-ref="persistentIdGenerator"
p:uniqueTicketIdGeneratorsForService-ref="uniqueIdGeneratorsMap"/>
<bean id="proxy10Handler" class="org.jasig.cas.ticket.proxy.support.Cas10ProxyHandler"/>
<bean id="proxy20Handler" class="org.jasig.cas.ticket.proxy.support.Cas20ProxyHandler"
p:httpClient-ref="httpClient"
p:uniqueTicketIdGenerator-ref="proxy20TicketUniqueIdGenerator"/>
<!-- ADVISORS -->
<bean id="advisorAutoProxyCreator"
class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>
<bean id="validationAnnotationBeanPostProcessor" class="org.jasig.cas.util.CustomBeanValidationPostProcessor" />
<!-- The scheduler bean wires up any triggers that define scheduled tasks -->
<bean id="scheduler" class="org.jasig.cas.util.AutowiringSchedulerFactoryBean"/>
<!-- Customizations -->
<!-- Make requests synchronous. This ensures that Single Logout has completed before the Logout page renders. -->
<bean id="httpClient" class="org.jasig.cas.util.HttpClient"
p:readTimeout="5000"
p:connectionTimeout="5000">
<property name="executorService">
<bean class="org.springframework.core.task.support.ExecutorServiceAdapter">
<constructor-arg>
<bean class="org.springframework.core.task.SyncTaskExecutor"/>
</constructor-arg>
</bean>
</property>
</bean>
</beans>
@@ -1,22 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<description>
Customizations to the CAS Server. The name starts with zzz to ensure it is the last file loaded to override other bean definitions.
</description>
<!-- Make requests synchronous. This ensures that Single Logout has completed before the Logout page renders. -->
<bean id="httpClient" class="org.jasig.cas.util.HttpClient"
p:readTimeout="5000"
p:connectionTimeout="5000">
<property name="executorService">
<bean class="org.springframework.core.task.support.ExecutorServiceAdapter">
<constructor-arg>
<bean class="org.springframework.core.task.SyncTaskExecutor"/>
</constructor-arg>
</bean>
</property>
</bean>
</beans>
@@ -49,7 +49,7 @@ public class WebExpressionVoter implements AccessDecisionVoter<FilterInvocation>
}
public boolean supports(Class<?> clazz) {
return clazz.isAssignableFrom(FilterInvocation.class);
return FilterInvocation.class.isAssignableFrom(clazz);
}
public void setExpressionHandler(SecurityExpressionHandler<FilterInvocation> expressionHandler) {
@@ -91,8 +91,8 @@ public class JdbcTokenRepositoryImpl extends JdbcDaoSupport implements Persisten
}
}, seriesId);
} catch(EmptyResultDataAccessException zeroResults) {
if(logger.isInfoEnabled()) {
logger.info("Querying token for series '" + seriesId + "' returned no results.", zeroResults);
if(logger.isDebugEnabled()) {
logger.debug("Querying token for series '" + seriesId + "' returned no results.", zeroResults);
}
}catch(IncorrectResultSizeDataAccessException moreThanOne) {
logger.error("Querying token for series '" + seriesId + "' returned more than one value. Series" +
@@ -1,3 +1,15 @@
/*
* Copyright 2002-2012 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.web.util;
import javax.servlet.http.HttpServletRequest;
@@ -23,6 +35,7 @@ import org.springframework.util.StringUtils;
* for this class for comprehensive information on the syntax used.
*
* @author Luke Taylor
* @author Rob Winch
* @since 3.1
*
* @see org.springframework.util.AntPathMatcher
@@ -80,7 +93,7 @@ public final class AntPathRequestMatcher implements RequestMatcher {
* {@code servletPath} + {@code pathInfo} of the request.
*/
public boolean matches(HttpServletRequest request) {
if (httpMethod != null && httpMethod != HttpMethod.valueOf(request.getMethod())) {
if (httpMethod != null && request.getMethod() != null && httpMethod != HttpMethod.valueOf(request.getMethod())) {
if (logger.isDebugEnabled()) {
logger.debug("Request '" + request.getMethod() + " " + getRequestPath(request) + "'"
+ " doesn't match '" + httpMethod + " " + pattern);
@@ -1,3 +1,15 @@
/*
* Copyright 2002-2012 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.web.util;
import java.util.regex.Pattern;
@@ -19,6 +31,7 @@ import org.springframework.util.StringUtils;
* argument.
*
* @author Luke Taylor
* @author Rob Winch
* @since 3.1
*/
public final class RegexRequestMatcher implements RequestMatcher {
@@ -61,7 +74,7 @@ public final class RegexRequestMatcher implements RequestMatcher {
* @return true if the pattern matches the URL, false otherwise.
*/
public boolean matches(HttpServletRequest request) {
if (httpMethod != null && httpMethod != HttpMethod.valueOf(request.getMethod())) {
if (httpMethod != null && request.getMethod() != null && httpMethod != HttpMethod.valueOf(request.getMethod())) {
return false;
}
@@ -19,6 +19,10 @@ import org.springframework.security.web.FilterInvocation;
import java.util.ArrayList;
import javax.servlet.FilterChain;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
/**
* @author Luke Taylor
*/
@@ -63,4 +67,29 @@ public class WebExpressionVoterTests {
assertEquals(AccessDecisionVoter.ACCESS_DENIED, voter.vote(user, fi, attributes));
}
// SEC-2507
@Test
public void supportFilterInvocationSubClass() {
WebExpressionVoter voter = new WebExpressionVoter();
assertTrue(voter.supports(FilterInvocationChild.class));
}
private static class FilterInvocationChild extends FilterInvocation {
public FilterInvocationChild(ServletRequest request,
ServletResponse response, FilterChain chain) {
super(request, response, chain);
}
}
@Test
public void supportFilterInvocation() {
WebExpressionVoter voter = new WebExpressionVoter();
assertTrue(voter.supports(FilterInvocation.class));
}
@Test
public void supportsObjectIsFalse() {
WebExpressionVoter voter = new WebExpressionVoter();
assertFalse(voter.supports(Object.class));
}
}
@@ -123,12 +123,12 @@ public class JdbcTokenRepositoryImplTests {
// SEC-1964
@Test
public void retrievingTokenWithNoSeriesReturnsNull() {
when(logger.isInfoEnabled()).thenReturn(true);
when(logger.isDebugEnabled()).thenReturn(true);
assertNull(repo.getTokenForSeries("missingSeries"));
verify(logger).isInfoEnabled();
verify(logger).info(eq("Querying token for series 'missingSeries' returned no results."),
verify(logger).isDebugEnabled();
verify(logger).debug(eq("Querying token for series 'missingSeries' returned no results."),
any(EmptyResultDataAccessException.class));
verifyNoMoreInteractions(logger);
}
@@ -1,12 +1,27 @@
/*
* Copyright 2002-2012 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.web.util;
import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import org.junit.*;
import org.junit.Test;
import org.springframework.mock.web.MockHttpServletRequest;
/**
* @author Luke Taylor
* @author Rob Winch
*/
public class AntPathRequestMatcherTests {
@@ -46,6 +61,39 @@ public class AntPathRequestMatcherTests {
assertTrue(matcher.matches(createRequest("/blah/aaa/blah/bbb")));
}
@Test
public void requestHasNullMethodMatches() {
AntPathRequestMatcher matcher = new AntPathRequestMatcher("/something/*", "GET");
MockHttpServletRequest request = createRequest("/something/here");
request.setMethod(null);
assertTrue(matcher.matches(request));
}
// SEC-2084
@Test
public void requestHasNullMethodNoMatch() {
AntPathRequestMatcher matcher = new AntPathRequestMatcher("/something/*", "GET");
MockHttpServletRequest request = createRequest("/nomatch");
request.setMethod(null);
assertFalse(matcher.matches(request));
}
@Test
public void requestHasNullMethodAndNullMatcherMatches() {
AntPathRequestMatcher matcher = new AntPathRequestMatcher("/something/*");
MockHttpServletRequest request = createRequest("/something/here");
request.setMethod(null);
assertTrue(matcher.matches(request));
}
@Test
public void requestHasNullMethodAndNullMatcherNoMatch() {
AntPathRequestMatcher matcher = new AntPathRequestMatcher("/something/*");
MockHttpServletRequest request = createRequest("/nomatch");
request.setMethod(null);
assertFalse(matcher.matches(request));
}
@Test
public void exactMatchOnlyMatchesIdenticalPath() throws Exception {
AntPathRequestMatcher matcher = new AntPathRequestMatcher("/login.html");
@@ -1,3 +1,15 @@
/*
* Copyright 2002-2012 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.web.util;
import static org.junit.Assert.*;
@@ -7,6 +19,7 @@ import org.springframework.mock.web.MockHttpServletRequest;
/**
* @author Luke Taylor
* @author Rob Winch
*/
public class RegexRequestMatcherTests {
@@ -40,4 +53,46 @@ public class RegexRequestMatcherTests {
assertTrue(matcher.matches(request));
}
@Test
public void requestHasNullMethodMatches() {
RegexRequestMatcher matcher = new RegexRequestMatcher("/something/.*", "GET");
MockHttpServletRequest request = createRequest("/something/here");
request.setMethod(null);
assertTrue(matcher.matches(request));
}
// SEC-2084
@Test
public void requestHasNullMethodNoMatch() {
RegexRequestMatcher matcher = new RegexRequestMatcher("/something/.*", "GET");
MockHttpServletRequest request = createRequest("/nomatch");
request.setMethod(null);
assertFalse(matcher.matches(request));
}
@Test
public void requestHasNullMethodAndNullMatcherMatches() {
RegexRequestMatcher matcher = new RegexRequestMatcher("/something/.*", null);
MockHttpServletRequest request = createRequest("/something/here");
request.setMethod(null);
assertTrue(matcher.matches(request));
}
@Test
public void requestHasNullMethodAndNullMatcherNoMatch() {
RegexRequestMatcher matcher = new RegexRequestMatcher("/something/.*", null);
MockHttpServletRequest request = createRequest("/nomatch");
request.setMethod(null);
assertFalse(matcher.matches(request));
}
private MockHttpServletRequest createRequest(String path) {
MockHttpServletRequest request = new MockHttpServletRequest();
request.setQueryString("doesntMatter");
request.setServletPath(path);
request.setMethod("POST");
return request;
}
}