From ae6af5d73ce77f93926379f96371e84b1e9401f1 Mon Sep 17 00:00:00 2001 From: Rob Winch Date: Mon, 23 Mar 2015 11:21:19 -0500 Subject: [PATCH] SEC-2915: Updated Java Code Formatting --- .../security/acls/AclEntryVoter.java | 341 +-- .../acls/AclPermissionCacheOptimizer.java | 63 +- .../security/acls/AclPermissionEvaluator.java | 190 +- .../afterinvocation/AbstractAclProvider.java | 145 +- ...InvocationCollectionFilteringProvider.java | 145 +- .../AclEntryAfterInvocationProvider.java | 131 +- .../acls/afterinvocation/ArrayFilterer.java | 136 +- .../afterinvocation/CollectionFilterer.java | 103 +- .../acls/afterinvocation/Filterer.java | 40 +- .../acls/domain/AbstractPermission.java | 98 +- .../acls/domain/AccessControlEntryImpl.java | 246 +- .../acls/domain/AclAuthorizationStrategy.java | 15 +- .../domain/AclAuthorizationStrategyImpl.java | 181 +- .../acls/domain/AclFormattingUtils.java | 140 +- .../security/acls/domain/AclImpl.java | 520 ++-- .../security/acls/domain/AuditLogger.java | 6 +- .../security/acls/domain/BasePermission.java | 23 +- .../acls/domain/ConsoleAuditLogger.java | 27 +- .../acls/domain/CumulativePermission.java | 54 +- .../acls/domain/DefaultPermissionFactory.java | 200 +- .../DefaultPermissionGrantingStrategy.java | 187 +- .../acls/domain/EhCacheBasedAclCache.java | 183 +- .../acls/domain/GrantedAuthoritySid.java | 76 +- .../domain/IdentityUnavailableException.java | 39 +- .../acls/domain/ObjectIdentityImpl.java | 218 +- .../ObjectIdentityRetrievalStrategyImpl.java | 23 +- .../acls/domain/PermissionFactory.java | 27 +- .../security/acls/domain/PrincipalSid.java | 82 +- .../acls/domain/SidRetrievalStrategyImpl.java | 46 +- .../acls/domain/SpringCacheBasedAclCache.java | 156 +- .../acls/jdbc/BasicLookupStrategy.java | 1224 ++++----- .../security/acls/jdbc/JdbcAclService.java | 145 +- .../acls/jdbc/JdbcMutableAclService.java | 706 ++--- .../security/acls/jdbc/LookupStrategy.java | 31 +- .../acls/model/AccessControlEntry.java | 41 +- .../security/acls/model/Acl.java | 289 ++- .../security/acls/model/AclCache.java | 16 +- .../acls/model/AclDataAccessException.java | 38 +- .../security/acls/model/AclService.java | 154 +- .../acls/model/AlreadyExistsException.java | 40 +- .../model/AuditableAccessControlEntry.java | 8 +- .../security/acls/model/AuditableAcl.java | 6 +- .../acls/model/ChildrenExistException.java | 41 +- .../security/acls/model/MutableAcl.java | 66 +- .../acls/model/MutableAclService.java | 69 +- .../acls/model/NotFoundException.java | 40 +- .../security/acls/model/ObjectIdentity.java | 81 +- .../acls/model/ObjectIdentityGenerator.java | 24 +- .../ObjectIdentityRetrievalStrategy.java | 6 +- .../security/acls/model/OwnershipAcl.java | 11 +- .../security/acls/model/Permission.java | 61 +- .../model/PermissionGrantingStrategy.java | 15 +- .../security/acls/model/Sid.java | 42 +- .../acls/model/SidRetrievalStrategy.java | 10 +- .../acls/model/UnloadedSidException.java | 45 +- .../acls/AclFormattingUtilsTests.java | 211 +- .../AclPermissionCacheOptimizerTests.java | 57 +- .../acls/AclPermissionEvaluatorTests.java | 30 +- ...ationCollectionFilteringProviderTests.java | 75 +- .../AclEntryAfterInvocationProviderTests.java | 161 +- .../domain/AccessControlImplEntryTests.java | 142 +- .../security/acls/domain/AclImplTests.java | 1102 ++++---- .../AclImplementationSecurityCheckTests.java | 457 ++-- .../acls/domain/AuditLoggerTests.java | 98 +- .../acls/domain/ObjectIdentityImplTests.java | 290 ++- ...ectIdentityRetrievalStrategyImplTests.java | 42 +- .../security/acls/domain/PermissionTests.java | 134 +- .../acls/domain/SpecialPermission.java | 11 +- .../acls/jdbc/BasicLookupStrategyTests.java | 511 ++-- .../security/acls/jdbc/DatabaseSeeder.java | 18 +- .../acls/jdbc/EhCacheBasedAclCacheTests.java | 352 +-- .../acls/jdbc/JdbcAclServiceTests.java | 38 +- .../acls/jdbc/JdbcMutableAclServiceTests.java | 982 +++---- .../jdbc/SpringCacheBasedAclCacheTests.java | 194 +- .../security/acls/sid/CustomSid.java | 20 +- .../acls/sid/SidRetrievalStrategyTests.java | 63 +- .../security/acls/sid/SidTests.java | 317 +-- .../aspect/AnnotationSecurityAspectTests.java | 240 +- .../security/cas/SamlServiceProperties.java | 15 +- .../security/cas/ServiceProperties.java | 179 +- .../CasAssertionAuthenticationToken.java | 34 +- .../CasAuthenticationProvider.java | 356 +-- .../CasAuthenticationToken.java | 169 +- .../EhCacheBasedTicketCache.java | 82 +- .../NullStatelessTicketCache.java | 59 +- .../SpringCacheBasedTicketCache.java | 74 +- .../authentication/StatelessTicketCache.java | 138 +- ...bstractCasAssertionUserDetailsService.java | 33 +- ...AssertionAttributesUserDetailsService.java | 90 +- .../cas/web/CasAuthenticationEntryPoint.java | 204 +- .../cas/web/CasAuthenticationFilter.java | 504 ++-- .../DefaultServiceAuthenticationDetails.java | 213 +- .../ServiceAuthenticationDetails.java | 19 +- .../ServiceAuthenticationDetailsSource.java | 96 +- .../cas/web/authentication/package-info.java | 1 + .../AbstractStatelessTicketCacheTests.java | 18 +- .../CasAuthenticationProviderTests.java | 738 +++--- .../CasAuthenticationTokenTests.java | 260 +- .../EhCacheBasedTicketCacheTests.java | 85 +- .../NullStatelessTicketCacheTests.java | 25 +- .../SpringCacheBasedTicketCacheTests.java | 56 +- ...tionAttributesUserDetailsServiceTests.java | 51 +- .../web/CasAuthenticationEntryPointTests.java | 126 +- .../cas/web/CasAuthenticationFilterTests.java | 285 +- .../cas/web/ServicePropertiesTests.java | 79 +- ...aultServiceAuthenticationDetailsTests.java | 164 +- ...dapAuthenticationProviderTestsConfigs.java | 37 +- .../LdapServerBeanDefinitionParserTests.java | 121 +- ...pUserServiceBeanDefinitionParserTests.java | 216 +- .../security/config/BeanIds.java | 41 +- .../config/DebugBeanDefinitionParser.java | 11 +- .../security/config/Elements.java | 98 +- .../config/SecurityNamespaceHandler.java | 275 +- .../AbstractConfiguredSecurityBuilder.java | 739 +++--- .../annotation/AbstractSecurityBuilder.java | 70 +- .../annotation/AlreadyBuiltException.java | 8 +- .../annotation/ObjectPostProcessor.java | 22 +- .../config/annotation/SecurityBuilder.java | 14 +- .../config/annotation/SecurityConfigurer.java | 53 +- .../annotation/SecurityConfigurerAdapter.java | 190 +- .../ProviderManagerBuilder.java | 26 +- .../AuthenticationManagerBuilder.java | 469 ++-- .../AuthenticationConfiguration.java | 157 +- .../EnableGlobalAuthentication.java | 59 +- ...GlobalAuthenticationConfigurerAdapter.java | 17 +- .../LdapAuthenticationProviderConfigurer.java | 945 +++---- .../InMemoryUserDetailsManagerConfigurer.java | 22 +- .../JdbcUserDetailsManagerConfigurer.java | 283 +- .../UserDetailsManagerConfigurer.java | 414 +-- .../AbstractDaoAuthenticationConfigurer.java | 132 +- .../DaoAuthenticationConfigurer.java | 36 +- .../UserDetailsAwareConfigurer.java | 16 +- .../UserDetailsServiceConfigurer.java | 47 +- ...utowireBeanFactoryObjectPostProcessor.java | 101 +- .../ObjectPostProcessorConfiguration.java | 16 +- .../EnableGlobalMethodSecurity.java | 119 +- ...thodSecurityAspectJAutoProxyRegistrar.java | 35 +- .../GlobalMethodSecurityConfiguration.java | 635 ++--- .../GlobalMethodSecuritySelector.java | 54 +- .../Jsr250MetadataSourceConfiguration.java | 8 +- .../web/AbstractRequestMatcherRegistry.java | 300 ++- .../annotation/web/HttpSecurityBuilder.java | 218 +- .../annotation/web/WebSecurityConfigurer.java | 12 +- .../web/builders/FilterComparator.java | 243 +- .../annotation/web/builders/HttpSecurity.java | 2291 ++++++++--------- .../annotation/web/builders/WebSecurity.java | 489 ++-- ...edWebSecurityConfigurersIgnoreParents.java | 35 +- .../ConditionalOnMissingBean.java | 2 +- .../web/configuration/EnableWebSecurity.java | 80 +- .../web/configuration/OnBeanCondition.java | 19 +- .../SpringWebMvcImportSelector.java | 21 +- .../WebMvcSecurityConfiguration.java | 35 +- .../WebSecurityConfiguration.java | 299 ++- .../WebSecurityConfigurerAdapter.java | 746 +++--- ...bstractAuthenticationFilterConfigurer.java | 574 +++-- ...ConfigAttributeRequestMatcherRegistry.java | 190 +- .../configurers/AbstractHttpConfigurer.java | 39 +- .../AbstractInterceptUrlConfigurer.java | 248 +- .../web/configurers/AnonymousConfigurer.java | 235 +- .../ChannelSecurityConfigurer.java | 226 +- .../web/configurers/CsrfConfigurer.java | 369 +-- .../DefaultLoginPageConfigurer.java | 62 +- .../ExceptionHandlingConfigurer.java | 302 +-- .../ExpressionUrlAuthorizationConfigurer.java | 555 ++-- .../web/configurers/FormLoginConfigurer.java | 392 +-- .../web/configurers/HeadersConfigurer.java | 868 +++---- .../web/configurers/HttpBasicConfigurer.java | 189 +- .../web/configurers/JeeConfigurer.java | 356 +-- .../web/configurers/LogoutConfigurer.java | 446 ++-- .../web/configurers/PermitAllSupport.java | 101 +- .../web/configurers/PortMapperConfigurer.java | 149 +- .../web/configurers/RememberMeConfigurer.java | 557 ++-- .../configurers/RequestCacheConfigurer.java | 152 +- .../SecurityContextConfigurer.java | 78 +- .../web/configurers/ServletApiConfigurer.java | 71 +- .../SessionManagementConfigurer.java | 815 +++--- .../UrlAuthorizationConfigurer.java | 427 +-- .../web/configurers/X509Configurer.java | 240 +- .../openid/OpenIDLoginConfigurer.java | 715 ++--- ...MessageSecurityMetadataSourceRegistry.java | 691 ++--- .../configuration/EnableWebMvcSecurity.java | 8 +- .../WebMvcSecurityConfiguration.java | 31 +- ...urityWebSocketMessageBrokerConfigurer.java | 276 +- ...serDetailsServiceBeanDefinitionParser.java | 94 +- ...enticationManagerBeanDefinitionParser.java | 179 +- .../AuthenticationManagerFactoryBean.java | 74 +- ...nticationProviderBeanDefinitionParser.java | 103 +- .../CachingUserDetailsService.java | 43 +- .../JdbcUserServiceBeanDefinitionParser.java | 75 +- .../authentication/PasswordEncoderParser.java | 156 +- .../SaltSourceBeanDefinitionParser.java | 59 +- .../UserServiceBeanDefinitionParser.java | 138 +- ...SecurityDebugBeanFactoryPostProcessor.java | 52 +- .../http/AuthenticationConfigBuilder.java | 1476 ++++++----- .../config/http/ChannelAttributeFactory.java | 39 +- .../config/http/CsrfBeanDefinitionParser.java | 187 +- .../http/DefaultFilterChainValidator.java | 282 +- .../http/FilterChainBeanDefinitionParser.java | 56 +- ...FilterChainMapBeanDefinitionDecorator.java | 91 +- ...nvocationSecurityMetadataSourceParser.java | 233 +- .../http/FormLoginBeanDefinitionParser.java | 324 +-- .../http/HeadersBeanDefinitionParser.java | 501 ++-- .../config/http/HttpConfigurationBuilder.java | 1352 +++++----- .../HttpFirewallBeanDefinitionParser.java | 29 +- .../HttpSecurityBeanDefinitionParser.java | 609 +++-- .../http/LogoutBeanDefinitionParser.java | 167 +- .../security/config/http/MatcherType.java | 52 +- .../PortMappingsBeanDefinitionParser.java | 62 +- .../http/RememberMeBeanDefinitionParser.java | 247 +- .../security/config/http/SecurityFilters.java | 57 +- .../config/http/SessionCreationPolicy.java | 22 +- .../http/UserDetailsServiceFactoryBean.java | 178 +- .../security/config/http/WebConfigUtils.java | 45 +- .../ContextSourceSettingPostProcessor.java | 89 +- .../LdapProviderBeanDefinitionParser.java | 148 +- .../ldap/LdapServerBeanDefinitionParser.java | 241 +- .../LdapUserServiceBeanDefinitionParser.java | 274 +- ...balMethodSecurityBeanDefinitionParser.java | 835 +++--- ...terceptMethodsBeanDefinitionDecorator.java | 99 +- .../config/method/MethodConfigUtils.java | 38 +- ...ityMetadataSourceBeanDefinitionParser.java | 36 +- .../method/ProtectPointcutPostProcessor.java | 242 +- ...ageBrokerSecurityBeanDefinitionParser.java | 329 +-- .../ConcereteSecurityConfigurerAdapter.java | 21 +- .../annotation/ObjectPostProcessorTests.java | 23 +- .../PasswordEncoderConfigurerConfigs.java | 84 +- .../AroundMethodInterceptor.java | 6 +- .../configuration/MyAdvisedBean.java | 6 +- .../annotation/issue50/ApplicationConfig.java | 46 +- .../annotation/issue50/SecurityConfig.java | 87 +- .../annotation/issue50/domain/User.java | 46 +- .../issue50/repo/UserRepository.java | 4 +- ...SecurityConfigurerAdapterTestsConfigs.java | 74 +- .../builders/DisableUseExpressionsConfig.java | 19 +- ...orizedRequestsWithPostProcessorConfig.java | 42 +- ...sionUrlAuthorizationConfigurerConfigs.java | 196 +- .../FormLoginBeanDefinitionParserTests.groovy | 150 +- .../BeanNameCollectingPostProcessor.java | 30 +- .../security/CollectingAppListener.java | 60 +- .../security/config/ConfigTestUtils.java | 21 +- .../security/config/DataSourcePopulator.java | 72 +- .../config/FilterChainProxyConfigTests.java | 180 +- .../config/InvalidConfigurationTests.java | 82 +- .../config/MockAfterInvocationProvider.java | 21 +- .../config/MockTransactionManager.java | 15 +- .../MockUserServiceBeanPostProcessor.java | 24 +- .../PostProcessedMockUserDetailsService.java | 26 +- .../config/SecurityNamespaceHandlerTests.java | 193 +- .../security/config/TestBusinessBean.java | 10 +- .../security/config/TestBusinessBeanImpl.java | 37 +- .../config/TransactionalTestBusinessBean.java | 24 +- .../WebMvcSecurityConfigurationTests.java | 129 +- .../CsrfConfigurerNoWebMvcTests.java | 95 +- ...ionManagementConfigurerServlet31Tests.java | 152 +- ...geSecurityMetadataSourceRegistryTests.java | 438 ++-- ...SocketMessageBrokerConfigurerDocTests.java | 199 +- ...WebSocketMessageBrokerConfigurerTests.java | 760 +++--- ...cutorSubscribableChannelPostProcessor.java | 26 +- ...ationManagerBeanDefinitionParserTests.java | 98 +- ...tionProviderBeanDefinitionParserTests.java | 287 ++- ...cUserServiceBeanDefinitionParserTests.java | 207 +- .../UserServiceBeanDefinitionParserTests.java | 200 +- .../DefaultFilterChainValidatorTests.java | 85 +- ...tadataSourceBeanDefinitionParserTests.java | 148 +- ...SessionManagementConfigServlet31Tests.java | 163 +- .../config/http/WebConfigUtilsTest.java | 21 +- ...thodSecurityBeanDefinitionParserTests.java | 693 ++--- ...ptMethodsBeanDefinitionDecoratorTests.java | 110 +- ...tationDrivenBeanDefinitionParserTests.java | 100 +- .../security/config/method/Sec2196Tests.java | 76 +- ...tationDrivenBeanDefinitionParserTests.java | 131 +- .../method/TestPermissionEvaluator.java | 15 +- .../sec2136/JpaPermissionEvaluator.java | 26 +- .../config/method/sec2136/Sec2136Tests.java | 6 +- .../config/method/sec2499/Sec2499Tests.java | 39 +- .../util/InMemoryXmlApplicationContext.java | 78 +- ...SecurityInterceptorWithAopConfigTests.java | 165 +- .../access/AccessDecisionManager.java | 81 +- .../security/access/AccessDecisionVoter.java | 120 +- .../access/AccessDeniedException.java | 44 +- .../access/AfterInvocationProvider.java | 60 +- .../access/AuthorizationServiceException.java | 45 +- .../security/access/ConfigAttribute.java | 47 +- .../access/PermissionCacheOptimizer.java | 18 +- .../security/access/PermissionEvaluator.java | 51 +- .../security/access/SecurityConfig.java | 74 +- .../access/SecurityMetadataSource.java | 70 +- .../AnnotationMetadataExtractor.java | 6 +- .../Jsr250MethodSecurityMetadataSource.java | 130 +- .../annotation/Jsr250SecurityConfig.java | 12 +- .../access/annotation/Jsr250Voter.java | 103 +- .../security/access/annotation/Secured.java | 41 +- ...curedAnnotationSecurityMetadataSource.java | 87 +- .../access/annotation/package-info.java | 1 + .../event/AbstractAuthorizationEvent.java | 20 +- ...uthenticationCredentialsNotFoundEvent.java | 67 +- .../event/AuthorizationFailureEvent.java | 91 +- .../access/event/AuthorizedEvent.java | 66 +- .../security/access/event/LoggerListener.java | 85 +- .../access/event/PublicInvocationEvent.java | 32 +- .../security/access/event/package-info.java | 1 + .../AbstractSecurityExpressionHandler.java | 141 +- .../DenyAllPermissionEvaluator.java | 40 +- .../access/expression/ExpressionUtils.java | 16 +- .../expression/SecurityExpressionHandler.java | 21 +- .../SecurityExpressionOperations.java | 168 +- .../expression/SecurityExpressionRoot.java | 282 +- ...tExpressionBasedMethodConfigAttribute.java | 60 +- ...efaultMethodSecurityExpressionHandler.java | 283 +- ...essionBasedAnnotationAttributeFactory.java | 111 +- .../ExpressionBasedPostInvocationAdvice.java | 73 +- .../ExpressionBasedPreInvocationAdvice.java | 95 +- .../MethodSecurityEvaluationContext.java | 125 +- .../MethodSecurityExpressionHandler.java | 49 +- .../MethodSecurityExpressionOperations.java | 10 +- .../method/MethodSecurityExpressionRoot.java | 65 +- .../PostInvocationExpressionAttribute.java | 41 +- .../PreInvocationExpressionAttribute.java | 65 +- .../expression/method/package-info.java | 1 + .../access/expression/package-info.java | 1 + .../CycleInRoleHierarchyException.java | 8 +- .../hierarchicalroles/NullRoleHierarchy.java | 7 +- .../hierarchicalroles/RoleHierarchy.java | 32 +- .../RoleHierarchyAuthoritiesMapper.java | 15 +- .../hierarchicalroles/RoleHierarchyImpl.java | 309 +-- .../hierarchicalroles/package-info.java | 1 + .../AbstractSecurityInterceptor.java | 849 +++--- .../intercept/AfterInvocationManager.java | 117 +- .../AfterInvocationProviderManager.java | 153 +- .../intercept/InterceptorStatusToken.java | 57 +- .../MethodInvocationPrivilegeEvaluator.java | 105 +- .../access/intercept/NullRunAsManager.java | 26 +- .../RunAsImplAuthenticationProvider.java | 84 +- .../access/intercept/RunAsManager.java | 125 +- .../access/intercept/RunAsManagerImpl.java | 148 +- .../access/intercept/RunAsUserToken.java | 79 +- .../MethodSecurityInterceptor.java | 83 +- .../MethodSecurityMetadataSourceAdvisor.java | 150 +- .../intercept/aopalliance/package-info.java | 1 + .../intercept/aspectj/AspectJCallback.java | 12 +- .../AspectJMethodSecurityInterceptor.java | 70 +- .../aspectj/MethodInvocationAdapter.java | 101 +- .../intercept/aspectj/package-info.java | 1 + .../access/intercept/package-info.java | 1 + ...tFallbackMethodSecurityMetadataSource.java | 134 +- .../AbstractMethodSecurityMetadataSource.java | 58 +- ...elegatingMethodSecurityMetadataSource.java | 158 +- .../MapBasedMethodSecurityMetadataSource.java | 442 ++-- .../method/MethodSecurityMetadataSource.java | 7 +- .../security/access/method/P.java | 17 +- .../security/access/method/package-info.java | 1 + .../access/prepost/PostAuthorize.java | 14 +- .../security/access/prepost/PostFilter.java | 14 +- .../prepost/PostInvocationAdviceProvider.java | 63 +- .../prepost/PostInvocationAttribute.java | 3 +- .../PostInvocationAuthorizationAdvice.java | 5 +- .../security/access/prepost/PreAuthorize.java | 15 +- .../security/access/prepost/PreFilter.java | 44 +- .../prepost/PreInvocationAttribute.java | 5 +- .../PreInvocationAuthorizationAdvice.java | 23 +- ...PreInvocationAuthorizationAdviceVoter.java | 80 +- ...ePostAnnotationSecurityMetadataSource.java | 177 +- .../PrePostInvocationAttributeFactory.java | 6 +- .../security/access/prepost/package-info.java | 1 + .../vote/AbstractAccessDecisionManager.java | 129 +- .../access/vote/AbstractAclVoter.java | 77 +- .../access/vote/AffirmativeBased.java | 95 +- .../access/vote/AuthenticatedVoter.java | 155 +- .../security/access/vote/ConsensusBased.java | 151 +- .../access/vote/RoleHierarchyVoter.java | 30 +- .../security/access/vote/RoleVoter.java | 146 +- .../security/access/vote/UnanimousBased.java | 118 +- .../security/access/vote/package-info.java | 1 + .../AbstractAuthenticationToken.java | 289 ++- .../AccountExpiredException.java | 44 +- .../AccountStatusException.java | 16 +- .../AccountStatusUserDetailsChecker.java | 39 +- .../AnonymousAuthenticationProvider.java | 73 +- .../AnonymousAuthenticationToken.java | 114 +- ...nticationCredentialsNotFoundException.java | 46 +- .../AuthenticationDetailsSource.java | 25 +- .../AuthenticationEventPublisher.java | 5 +- .../authentication/AuthenticationManager.java | 56 +- .../AuthenticationProvider.java | 81 +- .../AuthenticationServiceException.java | 44 +- .../AuthenticationTrustResolver.java | 62 +- .../AuthenticationTrustResolverImpl.java | 66 +- .../BadCredentialsException.java | 44 +- .../CredentialsExpiredException.java | 44 +- .../DefaultAuthenticationEventPublisher.java | 203 +- .../authentication/DisabledException.java | 43 +- .../InsufficientAuthenticationException.java | 55 +- ...nternalAuthenticationServiceException.java | 32 +- .../authentication/LockedException.java | 44 +- .../authentication/ProviderManager.java | 385 +-- .../ProviderNotFoundException.java | 27 +- .../RememberMeAuthenticationProvider.java | 77 +- .../RememberMeAuthenticationToken.java | 113 +- .../TestingAuthenticationProvider.java | 30 +- .../TestingAuthenticationToken.java | 63 +- .../UsernamePasswordAuthenticationToken.java | 120 +- ...ractUserDetailsAuthenticationProvider.java | 533 ++-- .../dao/DaoAuthenticationProvider.java | 282 +- .../dao/ReflectionSaltSource.java | 138 +- .../authentication/dao/SaltSource.java | 20 +- .../dao/SystemWideSaltSource.java | 66 +- .../authentication/dao/package-info.java | 1 + .../encoding/BaseDigestPasswordEncoder.java | 37 +- .../encoding/BasePasswordEncoder.java | 131 +- .../encoding/LdapShaPasswordEncoder.java | 233 +- .../security/authentication/encoding/Md4.java | 278 +- .../encoding/Md4PasswordEncoder.java | 86 +- .../encoding/Md5PasswordEncoder.java | 24 +- .../MessageDigestPasswordEncoder.java | 206 +- .../encoding/PasswordEncoder.java | 104 +- .../encoding/PasswordEncoderUtils.java | 56 +- .../encoding/PlaintextPasswordEncoder.java | 107 +- .../encoding/ShaPasswordEncoder.java | 49 +- .../authentication/encoding/package-info.java | 1 + .../event/AbstractAuthenticationEvent.java | 38 +- .../AbstractAuthenticationFailureEvent.java | 32 +- ...henticationFailureBadCredentialsEvent.java | 17 +- ...icationFailureCredentialsExpiredEvent.java | 17 +- .../AuthenticationFailureDisabledEvent.java | 17 +- .../AuthenticationFailureExpiredEvent.java | 14 +- .../AuthenticationFailureLockedEvent.java | 14 +- ...nticationFailureProviderNotFoundEvent.java | 18 +- ...henticationFailureProxyUntrustedEvent.java | 18 +- ...nticationFailureServiceExceptionEvent.java | 18 +- .../event/AuthenticationSuccessEvent.java | 10 +- ...InteractiveAuthenticationSuccessEvent.java | 48 +- .../authentication/event/LoggerListener.java | 70 +- .../authentication/event/package-info.java | 1 + .../AbstractJaasAuthenticationProvider.java | 552 ++-- .../authentication/jaas/AuthorityGranter.java | 38 +- .../DefaultJaasAuthenticationProvider.java | 68 +- .../jaas/DefaultLoginExceptionResolver.java | 13 +- .../JaasAuthenticationCallbackHandler.java | 55 +- .../jaas/JaasAuthenticationProvider.java | 329 +-- .../jaas/JaasAuthenticationToken.java | 43 +- .../jaas/JaasGrantedAuthority.java | 66 +- .../jaas/JaasNameCallbackHandler.java | 66 +- .../jaas/JaasPasswordCallbackHandler.java | 53 +- .../jaas/LoginExceptionResolver.java | 33 +- .../jaas/SecurityContextLoginModule.java | 228 +- .../jaas/event/JaasAuthenticationEvent.java | 42 +- .../event/JaasAuthenticationFailedEvent.java | 29 +- .../event/JaasAuthenticationSuccessEvent.java | 17 +- .../jaas/event/package-info.java | 1 + .../jaas/memory/InMemoryConfiguration.java | 122 +- .../jaas/memory/package-info.java | 1 + .../authentication/jaas/package-info.java | 1 + .../security/authentication/package-info.java | 1 + .../rcp/RemoteAuthenticationException.java | 30 +- .../rcp/RemoteAuthenticationManager.java | 43 +- .../rcp/RemoteAuthenticationManagerImpl.java | 54 +- .../rcp/RemoteAuthenticationProvider.java | 83 +- .../authentication/rcp/package-info.java | 1 + ...tractDelegatingSecurityContextSupport.java | 40 +- .../DelegatingSecurityContextCallable.java | 111 +- .../DelegatingSecurityContextExecutor.java | 68 +- ...egatingSecurityContextExecutorService.java | 179 +- .../DelegatingSecurityContextRunnable.java | 107 +- ...curityContextScheduledExecutorService.java | 98 +- .../DelegatingApplicationListener.java | 53 +- .../security/core/Authentication.java | 184 +- .../core/AuthenticationException.java | 43 +- .../security/core/ComparableVersion.java | 801 +++--- .../security/core/CredentialsContainer.java | 15 +- .../security/core/GrantedAuthority.java | 39 +- .../core/SpringSecurityCoreVersion.java | 113 +- .../core/SpringSecurityMessageSource.java | 30 +- .../annotation/AuthenticationPrincipal.java | 20 +- .../core/authority/AuthorityUtils.java | 62 +- .../GrantedAuthoritiesContainer.java | 6 +- .../authority/SimpleGrantedAuthority.java | 48 +- .../Attributes2GrantedAuthoritiesMapper.java | 27 +- .../mapping/GrantedAuthoritiesMapper.java | 6 +- ...edAttributes2GrantedAuthoritiesMapper.java | 273 +- .../mapping/MappableAttributesRetriever.java | 18 +- .../mapping/NullAuthoritiesMapper.java | 7 +- ...leAttributes2GrantedAuthoritiesMapper.java | 139 +- .../mapping/SimpleAuthorityMapper.java | 158 +- .../SimpleMappableAttributesRetriever.java | 35 +- .../core/authority/mapping/package-info.java | 1 + .../security/core/authority/package-info.java | 1 + .../GlobalSecurityContextHolderStrategy.java | 48 +- ...eadLocalSecurityContextHolderStrategy.java | 52 +- .../core/context/SecurityContext.java | 36 +- .../core/context/SecurityContextHolder.java | 225 +- .../SecurityContextHolderStrategy.java | 54 +- .../core/context/SecurityContextImpl.java | 85 +- ...eadLocalSecurityContextHolderStrategy.java | 51 +- .../security/core/context/package-info.java | 1 + .../security/core/package-info.java | 1 + .../AnnotationParameterNameDiscoverer.java | 285 +- ...efaultSecurityParameterNameDiscoverer.java | 80 +- .../core/session/SessionCreationEvent.java | 10 +- .../core/session/SessionDestroyedEvent.java | 30 +- .../core/session/SessionInformation.java | 90 +- .../core/session/SessionRegistry.java | 106 +- .../core/session/SessionRegistryImpl.java | 218 +- .../security/core/session/package-info.java | 1 + .../security/core/token/DefaultToken.java | 76 +- .../KeyBasedPersistenceTokenService.java | 205 +- .../core/token/SecureRandomFactoryBean.java | 86 +- .../core/token/Sha512DigestUtils.java | 104 +- .../security/core/token/Token.java | 59 +- .../security/core/token/TokenService.java | 59 +- .../security/core/token/package-info.java | 1 + .../AuthenticationUserDetailsService.java | 21 +- .../security/core/userdetails/User.java | 327 +-- .../security/core/userdetails/UserCache.java | 75 +- .../core/userdetails/UserDetails.java | 115 +- .../UserDetailsByNameServiceWrapper.java | 91 +- .../core/userdetails/UserDetailsChecker.java | 24 +- .../core/userdetails/UserDetailsService.java | 38 +- .../UsernameNotFoundException.java | 43 +- .../cache/EhCacheBasedUserCache.java | 87 +- .../core/userdetails/cache/NullUserCache.java | 17 +- .../cache/SpringCacheBasedUserCache.java | 78 +- .../core/userdetails/cache/package-info.java | 1 + .../core/userdetails/jdbc/JdbcDaoImpl.java | 529 ++-- .../core/userdetails/jdbc/package-info.java | 1 + .../userdetails/memory/UserAttribute.java | 111 +- .../memory/UserAttributeEditor.java | 69 +- .../core/userdetails/memory/package-info.java | 1 + .../core/userdetails/package-info.java | 1 + .../security/provisioning/GroupManager.java | 118 +- .../InMemoryUserDetailsManager.java | 148 +- .../provisioning/JdbcUserDetailsManager.java | 941 +++---- .../security/provisioning/MutableUser.java | 63 +- .../provisioning/MutableUserDetails.java | 2 +- .../provisioning/UserDetailsManager.java | 52 +- .../security/provisioning/package-info.java | 1 + ...SecurityContextSchedulingTaskExecutor.java | 66 +- ...atingSecurityContextAsyncTaskExecutor.java | 83 +- ...DelegatingSecurityContextTaskExecutor.java | 47 +- .../security/util/FieldUtils.java | 139 +- .../security/util/InMemoryResource.java | 73 +- .../security/util/MethodInvocationUtils.java | 202 +- .../security/util/SimpleMethodInvocation.java | 59 +- .../security/util/package-info.java | 1 + .../security/ITargetObject.java | 13 +- .../security/OtherTargetObject.java | 40 +- .../security/PopulatedDatabase.java | 173 +- .../security/TargetObject.java | 97 +- .../security/TestDataSource.java | 26 +- ...ticationCredentialsNotFoundEventTests.java | 31 +- .../AuthorizationFailureEventTests.java | 57 +- .../security/access/AuthorizedEventTests.java | 28 +- .../security/access/SecurityConfigTests.java | 107 +- .../access/annotation/BusinessService.java | 45 +- .../annotation/BusinessServiceImpl.java | 64 +- .../security/access/annotation/Entity.java | 3 +- ...xpressionProtectedBusinessServiceImpl.java | 63 +- .../annotation/Jsr250BusinessServiceImpl.java | 61 +- ...r250MethodSecurityMetadataSourceTests.java | 373 +-- .../access/annotation/Jsr250VoterTests.java | 41 +- ...AnnotationSecurityMetadataSourceTests.java | 383 +-- .../annotation/sec2150/CrudRepository.java | 2 +- .../sec2150/MethodInvocationFactory.java | 27 +- .../annotation/sec2150/PersonRepository.java | 7 +- ...bstractSecurityExpressionHandlerTests.java | 73 +- .../SecurityExpressionRootTests.java | 179 +- ...tMethodSecurityExpressionHandlerTests.java | 56 +- .../method/MethodExpressionVoterTests.java | 215 +- .../MethodSecurityExpressionRootTests.java | 178 +- ...AnnotationSecurityMetadataSourceTests.java | 396 +-- .../expression/method/SecurityRules.java | 19 +- .../HierarchicalRolesTestHelper.java | 87 +- .../RoleHierarchyAuthoritiesMapperTests.java | 25 +- .../RoleHierarchyImplTests.java | 252 +- .../hierarchicalroles/TestHelperTests.java | 228 +- .../AbstractSecurityInterceptorTests.java | 102 +- .../AfterInvocationProviderManagerTests.java | 238 +- .../InterceptorStatusTokenTests.java | 23 +- .../intercept/NullRunAsManagerTests.java | 34 +- .../RunAsImplAuthenticationProviderTests.java | 78 +- .../intercept/RunAsManagerImplTests.java | 147 +- .../access/intercept/RunAsUserTokenTests.java | 78 +- .../MethodSecurityInterceptorTests.java | 490 ++-- ...hodSecurityMetadataSourceAdvisorTests.java | 39 +- ...AspectJMethodSecurityInterceptorTests.java | 263 +- ...asedMethodSecurityMetadataSourceTests.java | 62 +- ...thodInvocationPrivilegeEvaluatorTests.java | 124 +- .../method/MockMethodInvocation.java | 44 +- ...tingMethodSecurityMetadataSourceTests.java | 72 +- ...vocationAuthorizationAdviceVoterTests.java | 41 +- .../AbstractAccessDecisionManagerTests.java | 184 +- .../access/vote/AbstractAclVoterTests.java | 74 +- .../access/vote/AffirmativeBasedTests.java | 114 +- .../access/vote/AuthenticatedVoterTests.java | 114 +- .../access/vote/ConsensusBasedTests.java | 137 +- .../security/access/vote/DenyAgainVoter.java | 47 +- .../security/access/vote/DenyVoter.java | 57 +- .../access/vote/RoleHierarchyVoterTests.java | 20 +- .../security/access/vote/RoleVoterTests.java | 17 +- .../access/vote/SomeDomainObject.java | 23 +- .../access/vote/SomeDomainObjectManager.java | 10 +- .../access/vote/UnanimousBasedTests.java | 194 +- .../AbstractAuthenticationTokenTests.java | 185 +- .../AuthenticationTrustResolverImplTests.java | 55 +- ...aultAuthenticationEventPublisherTests.java | 176 +- .../authentication/ProviderManagerTests.java | 501 ++-- .../TestingAuthenticationProviderTests.java | 35 +- ...rnamePasswordAuthenticationTokenTests.java | 82 +- .../AnonymousAuthenticationProviderTests.java | 107 +- .../AnonymousAuthenticationTokenTests.java | 154 +- .../dao/DaoAuthenticationProviderTests.java | 1218 ++++----- .../authentication/dao/MockUserCache.java | 20 +- .../dao/salt/ReflectionSaltSourceTests.java | 55 +- .../dao/salt/SystemWideSaltSourceTests.java | 86 +- .../encoding/BasePasswordEncoderTests.java | 185 +- .../encoding/Md4PasswordEncoderTests.java | 87 +- .../encoding/Md5PasswordEncoderTests.java | 90 +- .../encoding/PasswordEncoderUtilsTests.java | 39 +- .../PlaintextPasswordEncoderTests.java | 66 +- .../encoding/ShaPasswordEncoderTests.java | 83 +- .../event/AuthenticationEventTests.java | 90 +- .../event/LoggerListenerTests.java | 43 +- ...efaultJaasAuthenticationProviderTests.java | 360 +-- .../jaas/JaasAuthenticationProviderTests.java | 398 +-- .../authentication/jaas/JaasEventCheck.java | 27 +- .../authentication/jaas/Sec760Tests.java | 64 +- .../jaas/SecurityContextLoginModuleTests.java | 131 +- .../jaas/TestAuthorityGranter.java | 20 +- .../jaas/TestCallbackHandler.java | 18 +- .../authentication/jaas/TestLoginModule.java | 100 +- .../memory/InMemoryConfigurationTests.java | 104 +- .../RemoteAuthenticationManagerImplTests.java | 63 +- .../RemoteAuthenticationProviderTests.java | 138 +- ...RememberMeAuthenticationProviderTests.java | 97 +- .../RememberMeAuthenticationTokenTests.java | 136 +- ...ngSecurityContextExecutorServiceTests.java | 225 +- ...elegatingSecurityContextExecutorTests.java | 46 +- ...yContextScheduledExecutorServiceTests.java | 100 +- ...tDelegatingSecurityContextTestSupport.java | 80 +- ...ngSecurityContextExecutorServiceTests.java | 22 +- ...elegatingSecurityContextExecutorTests.java | 21 +- ...yContextScheduledExecutorServiceTests.java | 21 +- ...elegatingSecurityContextCallableTests.java | 175 +- ...elegatingSecurityContextRunnableTests.java | 176 +- ...DelegatingSecurityContextSupportTests.java | 68 +- ...ngSecurityContextExecutorServiceTests.java | 22 +- ...elegatingSecurityContextExecutorTests.java | 21 +- ...yContextScheduledExecutorServiceTests.java | 22 +- .../DelegatingApplicationListenerTests.java | 77 +- .../security/core/JavaVersionTests.java | 42 +- .../core/SpringSecurityCoreVersionTests.java | 188 +- .../SpringSecurityMessageSourceTests.java | 38 +- .../core/authority/AuthorityUtilsTests.java | 22 +- .../SimpleGrantedAuthorityTests.java | 33 +- ...ributes2GrantedAuthoritiesMapperTests.java | 312 +-- .../mapping/SimpleAuthoritiesMapperTests.java | 107 +- .../SimpleMappableRolesRetrieverTests.java | 16 +- ...leRoles2GrantedAuthoritiesMapperTests.java | 190 +- .../context/SecurityContextHolderTests.java | 53 +- .../context/SecurityContextImplTests.java | 44 +- ...nnotationParameterNameDiscovererTests.java | 192 +- ...tSecurityParameterNameDiscovererTests.java | 68 +- .../core/session/SessionInformationTests.java | 29 +- .../session/SessionRegistryImplTests.java | 242 +- .../core/token/DefaultTokenTests.java | 46 +- .../KeyBasedPersistenceTokenServiceTests.java | 118 +- .../token/SecureRandomFactoryBeanTests.java | 59 +- .../userdetails/MockUserDetailsService.java | 37 +- .../UserDetailsByNameServiceWrapperTests.java | 62 +- .../security/core/userdetails/UserTests.java | 183 +- .../cache/EhCacheBasedUserCacheTests.java | 94 +- .../userdetails/cache/NullUserCacheTests.java | 24 +- .../cache/SpringCacheBasedUserCacheTests.java | 78 +- .../userdetails/jdbc/JdbcDaoImplTests.java | 223 +- .../memory/UserAttributeEditorTests.java | 145 +- .../JdbcUserDetailsManagerTests.java | 533 ++-- ...ityContextSchedulingTaskExecutorTests.java | 33 +- ...ityContextSchedulingTaskExecutorTests.java | 20 +- ...ityContextSchedulingTaskExecutorTests.java | 21 +- ...SecurityContextAsyncTaskExecutorTests.java | 60 +- ...SecurityContextAsyncTaskExecutorTests.java | 22 +- ...atingSecurityContextTaskExecutorTests.java | 31 +- ...SecurityContextAsyncTaskExecutorTests.java | 23 +- ...atingSecurityContextTaskExecutorTests.java | 33 +- .../security/util/FieldUtilsTests.java | 33 +- .../security/util/InMemoryResourceTests.java | 26 +- .../util/MethodInvocationUtilsTests.java | 84 +- .../security/crypto/bcrypt/BCrypt.java | 1264 +++++---- .../crypto/bcrypt/BCryptPasswordEncoder.java | 104 +- .../security/crypto/codec/Base64.java | 1241 +++++---- .../security/crypto/codec/Hex.java | 62 +- .../security/crypto/codec/Utf8.java | 50 +- .../security/crypto/codec/package-info.java | 1 + .../crypto/encrypt/AesBytesEncryptor.java | 101 +- .../crypto/encrypt/BytesEncryptor.java | 16 +- .../security/crypto/encrypt/CipherUtils.java | 184 +- .../security/crypto/encrypt/Encryptors.java | 117 +- .../encrypt/HexEncodingTextEncryptor.java | 26 +- .../crypto/encrypt/TextEncryptor.java | 16 +- .../crypto/keygen/BytesKeyGenerator.java | 18 +- .../keygen/HexEncodingStringKeyGenerator.java | 18 +- .../security/crypto/keygen/KeyGenerators.java | 67 +- .../keygen/SecureRandomBytesKeyGenerator.java | 52 +- .../crypto/keygen/SharedKeyGenerator.java | 20 +- .../crypto/keygen/StringKeyGenerator.java | 2 +- .../security/crypto/password/Digester.java | 50 +- .../crypto/password/NoOpPasswordEncoder.java | 34 +- .../crypto/password/PasswordEncoder.java | 32 +- .../password/StandardPasswordEncoder.java | 128 +- .../security/crypto/util/EncodingUtils.java | 60 +- .../bcrypt/BCryptPasswordEncoderTests.java | 95 +- .../security/crypto/bcrypt/BCryptTests.java | 508 ++-- .../security/crypto/codec/Base64Tests.java | 38 +- .../security/crypto/codec/Utf8Tests.java | 18 +- .../crypto/encrypt/EncryptorsTests.java | 68 +- .../crypto/keygen/KeyGeneratorsTests.java | 72 +- .../crypto/password/DigesterTests.java | 15 +- .../StandardPasswordEncoderTests.java | 34 +- .../crypto/util/EncodingUtilsTests.java | 60 +- .../SecurityEvaluationContextExtension.java | 97 +- ...curityEvaluationContextExtensionTests.java | 76 +- ...amespaceWithMultipleInterceptorsTests.java | 64 +- .../HttpPathParameterStrippingTests.java | 76 +- .../integration/MultiAnnotationTests.java | 110 +- .../SEC933ApplicationContextTests.java | 14 +- .../SEC936ApplicationContextTests.java | 19 +- .../integration/StubUserRepository.java | 4 +- .../PythonInterpreterBasedSecurityTests.java | 21 +- .../FilterChainPerformanceTests.java | 169 +- .../ProtectPointcutPerformanceTests.java | 53 +- .../integration/UserDetailsServiceImpl.java | 20 +- .../security/integration/UserRepository.java | 2 +- .../MultiAnnotationService.java | 16 +- .../MultiAnnotationServiceImpl.java | 16 +- .../multiannotation/PreAuthorizeService.java | 4 +- .../PreAuthorizeServiceImpl.java | 4 +- .../multiannotation/SecuredService.java | 4 +- .../multiannotation/SecuredServiceImpl.java | 4 +- ...PythonInterpreterPostInvocationAdvice.java | 12 +- .../PythonInterpreterPreInvocationAdvice.java | 69 +- ...thonInterpreterPreInvocationAttribute.java | 20 +- ...eterPrePostInvocationAttributeFactory.java | 24 +- .../integration/python/TestService.java | 4 +- .../integration/python/TestServiceImpl.java | 6 +- .../AbstractWebServerIntegrationTests.java | 215 +- .../integration/BasicAuthenticationTests.java | 29 +- .../ConcurrentSessionManagementTests.java | 59 +- ...ustomConcurrentSessionManagementTests.java | 74 +- .../InMemoryProviderWebAppTests.java | 104 +- .../security/integration/JspTaglibTests.java | 51 +- .../security/integration/LdapWebAppTests.java | 12 +- .../security/itest/web/TestController.java | 8 +- .../ldap/AbstractLdapIntegrationTests.java | 30 +- .../ldap/ApacheDSServerIntegrationTests.java | 197 +- ...faultSpringSecurityContextSourceTests.java | 214 +- .../SpringSecurityLdapTemplateITests.java | 310 +-- .../BindAuthenticatorTests.java | 180 +- .../PasswordComparisonAuthenticatorTests.java | 185 +- .../FilterBasedLdapUserSearchTests.java | 112 +- .../ldap/server/ApacheDSContainerTests.java | 135 +- .../DefaultLdapAuthoritiesPopulatorTests.java | 208 +- .../LdapUserDetailsManagerTests.java | 273 +- .../NestedLdapAuthoritiesPopulatorTests.java | 193 +- .../ldap/DefaultLdapUsernameToDnMapper.java | 44 +- .../DefaultSpringSecurityContextSource.java | 214 +- .../security/ldap/LdapEncoder.java | 336 +-- .../security/ldap/LdapUsernameToDnMapper.java | 2 +- .../security/ldap/LdapUtils.java | 251 +- .../ldap/SpringSecurityLdapTemplate.java | 562 ++-- .../AbstractLdapAuthenticationProvider.java | 186 +- .../AbstractLdapAuthenticator.java | 188 +- .../authentication/BindAuthenticator.java | 188 +- .../LdapAuthenticationProvider.java | 225 +- .../authentication/LdapAuthenticator.java | 22 +- .../ldap/authentication/LdapEncoder.java | 336 +-- .../NullLdapAuthoritiesPopulator.java | 7 +- .../PasswordComparisonAuthenticator.java | 209 +- .../SpringSecurityAuthenticationSource.java | 88 +- ...etailsServiceLdapAuthoritiesPopulator.java | 24 +- ...ctiveDirectoryAuthenticationException.java | 32 +- ...veDirectoryLdapAuthenticationProvider.java | 545 ++-- .../PasswordPolicyAwareContextSource.java | 106 +- .../ldap/ppolicy/PasswordPolicyControl.java | 95 +- .../PasswordPolicyControlExtractor.java | 34 +- .../ppolicy/PasswordPolicyControlFactory.java | 33 +- .../ldap/ppolicy/PasswordPolicyData.java | 4 +- .../ppolicy/PasswordPolicyErrorStatus.java | 52 +- .../ldap/ppolicy/PasswordPolicyException.java | 19 +- .../PasswordPolicyResponseControl.java | 533 ++-- .../search/FilterBasedLdapUserSearch.java | 244 +- .../security/ldap/search/LdapUserSearch.java | 30 +- .../ldap/server/ApacheDSContainer.java | 427 +-- .../DefaultLdapAuthoritiesPopulator.java | 518 ++-- .../ldap/userdetails/InetOrgPerson.java | 414 +-- .../InetOrgPersonContextMapper.java | 25 +- .../userdetails/LdapAuthoritiesPopulator.java | 27 +- .../ldap/userdetails/LdapAuthority.java | 220 +- .../ldap/userdetails/LdapUserDetails.java | 15 +- .../ldap/userdetails/LdapUserDetailsImpl.java | 368 +-- .../userdetails/LdapUserDetailsManager.java | 669 ++--- .../userdetails/LdapUserDetailsMapper.java | 247 +- .../userdetails/LdapUserDetailsService.java | 63 +- .../NestedLdapAuthoritiesPopulator.java | 286 +- .../security/ldap/userdetails/Person.java | 187 +- .../ldap/userdetails/PersonContextMapper.java | 23 +- .../userdetails/UserDetailsContextMapper.java | 37 +- .../security/ldap/LdapUtilsTests.java | 98 +- ...ringSecurityAuthenticationSourceTests.java | 83 +- .../ldap/SpringSecurityLdapTemplateTests.java | 51 +- .../LdapAuthenticationProviderTests.java | 287 ++- .../LdapShaPasswordEncoderTests.java | 160 +- .../ldap/authentication/MockUserSearch.java | 28 +- ...swordComparisonAuthenticatorMockTests.java | 47 +- ...ectoryLdapAuthenticationProviderTests.java | 772 +++--- .../ppolicy/OpenLDAPIntegrationTestSuite.java | 80 +- ...PasswordPolicyAwareContextSourceTests.java | 75 +- .../PasswordPolicyControlFactoryTests.java | 36 +- .../PasswordPolicyResponseControlTests.java | 177 +- .../ldap/userdetails/InetOrgPersonTests.java | 209 +- .../ldap/userdetails/LdapAuthorityTests.java | 63 +- .../LdapUserDetailsMapperTests.java | 76 +- .../LdapUserDetailsServiceTests.java | 67 +- ...sServiceLdapAuthoritiesPopulatorTests.java | 26 +- ...faultMessageSecurityExpressionHandler.java | 34 +- ...dMessageSecurityMetadataSourceFactory.java | 93 +- .../MessageExpressionConfigAttribute.java | 42 +- .../expression/MessageExpressionVoter.java | 74 +- .../MessageSecurityExpressionRoot.java | 10 +- .../intercept/ChannelSecurityInterceptor.java | 112 +- .../DefaultMessageSecurityMetadataSource.java | 62 +- ...thenticationPrincipalArgumentResolver.java | 127 +- .../SecurityContextChannelInterceptor.java | 193 +- .../AbstractMessageMatcherComposite.java | 61 +- .../util/matcher/AndMessageMatcher.java | 63 +- .../util/matcher/MessageMatcher.java | 34 +- .../util/matcher/OrMessageMatcher.java | 63 +- .../SimpDestinationMessageMatcher.java | 261 +- .../util/matcher/SimpMessageTypeMatcher.java | 78 +- .../web/csrf/CsrfChannelInterceptor.java | 45 +- .../server/CsrfTokenHandshakeInterceptor.java | 35 +- ...MessageSecurityExpressionHandlerTests.java | 110 +- ...ageSecurityMetadataSourceFactoryTests.java | 96 +- ...MessageExpressionConfigAttributeTests.java | 49 +- .../MessageExpressionVoterTests.java | 129 +- .../ChannelSecurityInterceptorTests.java | 195 +- ...ultMessageSecurityMetadataSourceTests.java | 90 +- ...icationPrincipalArgumentResolverTests.java | 287 ++- ...ecurityContextChannelInterceptorTests.java | 322 +-- .../util/matcher/AndMessageMatcherTest.java | 132 +- .../util/matcher/OrMessageMatcherTest.java | 132 +- .../SimpDestinationMessageMatcherTests.java | 153 +- .../matcher/SimpMessageTypeMatcherTests.java | 62 +- .../web/csrf/CsrfChannelInterceptorTests.java | 168 +- .../CsrfTokenHandshakeInterceptorTests.java | 57 +- .../AuthenticationCancelledException.java | 16 +- .../security/openid/AxFetchListFactory.java | 24 +- .../openid/NullAxFetchListFactory.java | 6 +- .../security/openid/OpenID4JavaConsumer.java | 271 +- .../security/openid/OpenIDAttribute.java | 135 +- .../openid/OpenIDAuthenticationFilter.java | 417 +-- .../openid/OpenIDAuthenticationProvider.java | 190 +- .../openid/OpenIDAuthenticationStatus.java | 40 +- .../openid/OpenIDAuthenticationToken.java | 138 +- .../security/openid/OpenIDConsumer.java | 32 +- .../openid/OpenIDConsumerException.java | 15 +- .../openid/RegexBasedAxFetchListFactory.java | 46 +- .../security/openid/MockOpenIDConsumer.java | 88 +- .../openid/OpenID4JavaConsumerTests.java | 310 ++- .../OpenIDAuthenticationFilterTests.java | 146 +- .../OpenIDAuthenticationProviderTests.java | 297 ++- .../dns/DnsEntryNotFoundException.java | 16 +- .../remoting/dns/DnsLookupException.java | 12 +- .../security/remoting/dns/DnsResolver.java | 101 +- .../remoting/dns/InitialContextFactory.java | 12 +- .../remoting/dns/JndiDnsResolver.java | 246 +- .../security/remoting/dns/package-info.java | 1 + ...ationSimpleHttpInvokerRequestExecutor.java | 108 +- .../remoting/httpinvoker/package-info.java | 1 + .../security/remoting/package-info.java | 1 + .../ContextPropagatingRemoteInvocation.java | 158 +- ...extPropagatingRemoteInvocationFactory.java | 20 +- .../security/remoting/rmi/package-info.java | 1 + .../remoting/dns/JndiDnsResolverTests.java | 135 +- ...SimpleHttpInvokerRequestExecutorTests.java | 134 +- ...ntextPropagatingRemoteInvocationTests.java | 121 +- .../sample/aspectj/AspectjSecurityConfig.java | 2 +- .../java/sample/aspectj/SecuredService.java | 6 +- .../src/main/java/sample/aspectj/Service.java | 14 +- .../aspectj/AspectJInterceptorTests.java | 110 +- .../java/sample/aspectj/SecuredService.java | 6 +- .../src/main/java/sample/aspectj/Service.java | 14 +- .../aspectj/AspectJInterceptorTests.java | 98 +- .../cas/web/ProxyTicketSampleServlet.java | 84 +- .../config/ChatApplicationInitializer.java | 44 +- ...ChatSecurityWebApplicationInitializer.java | 11 +- .../java/sample/config/DataSourceConfig.java | 64 +- .../sample/config/EmbeddedRedisConfig.java | 78 +- .../main/java/sample/config/RedisConfig.java | 13 +- .../config/RedisConnectionProperties.java | 2 +- .../sample/config/SessionAppInitializer.java | 11 +- .../sample/config/WebMvcConfiguration.java | 95 +- .../java/sample/config/WebSecurityConfig.java | 68 +- .../java/sample/config/WebSocketConfig.java | 44 +- .../config/WebSocketSecurityConfig.java | 39 +- .../java/sample/data/ActiveWebSocketUser.java | 13 +- .../data/ActiveWebSocketUserRepository.java | 3 +- .../main/java/sample/data/InstantMessage.java | 8 +- .../src/main/java/sample/data/User.java | 154 +- .../main/java/sample/data/UserRepository.java | 2 +- .../main/java/sample/mvc/CsrfController.java | 8 +- .../java/sample/mvc/MessageController.java | 43 +- .../java/sample/security/CurrentUser.java | 14 +- .../UserRepositoryUserDetailsService.java | 84 +- .../websocket/WebSocketConnectHandler.java | 37 +- .../websocket/WebSocketDisconnectHandler.java | 43 +- ...sageSecurityWebApplicationInitializer.java | 11 +- .../samples/config/SecurityConfig.java | 49 +- .../samples/config/SecurityConfigTests.java | 7 +- .../contact/AddDeleteContactController.java | 68 +- .../java/sample/contact/AddPermission.java | 49 +- .../contact/AddPermissionValidator.java | 52 +- .../contact/AdminPermissionController.java | 206 +- .../sample/contact/ClientApplication.java | 177 +- .../src/main/java/sample/contact/Contact.java | 109 +- .../main/java/sample/contact/ContactDao.java | 18 +- .../java/sample/contact/ContactDaoSpring.java | 131 +- .../java/sample/contact/ContactManager.java | 39 +- .../sample/contact/ContactManagerBackend.java | 217 +- .../sample/contact/DataSourcePopulator.java | 413 ++- .../java/sample/contact/IndexController.java | 103 +- .../main/java/sample/contact/WebContact.java | 34 +- .../sample/contact/WebContactValidator.java | 33 +- .../sample/contact/ContactManagerTests.java | 202 +- .../src/main/java/samples/DataConfig.java | 68 +- .../src/main/java/samples/data/Message.java | 81 +- .../java/samples/data/MessageRepository.java | 2 +- .../data/SecurityMessageRepository.java | 5 +- .../src/main/java/samples/data/User.java | 74 +- .../data/SecurityMessageRepositoryTests.java | 54 +- .../main/java/sample/dms/AbstractElement.java | 124 +- .../java/sample/dms/DataSourcePopulator.java | 236 +- .../src/main/java/sample/dms/Directory.java | 21 +- .../src/main/java/sample/dms/DocumentDao.java | 54 +- .../main/java/sample/dms/DocumentDaoImpl.java | 198 +- .../src/main/java/sample/dms/File.java | 34 +- .../secured/SecureDataSourcePopulator.java | 121 +- .../sample/dms/secured/SecureDocumentDao.java | 8 +- .../dms/secured/SecureDocumentDaoImpl.java | 59 +- .../src/test/java/DmsIntegrationTests.java | 152 +- .../test/java/SecureDmsIntegrationTests.java | 48 +- ...sageSecurityWebApplicationInitializer.java | 3 +- .../samples/config/SecurityConfig.java | 47 +- .../samples/config/SecurityConfigTests.java | 7 +- .../java/samples/gae/security/AppRole.java | 39 +- .../gae/security/GaeAuthenticationFilter.java | 124 +- .../gae/security/GaeUserAuthentication.java | 71 +- ...oogleAccountsAuthenticationEntryPoint.java | 10 +- .../GoogleAccountsAuthenticationProvider.java | 69 +- .../gae/users/GaeDatastoreUserRegistry.java | 113 +- .../main/java/samples/gae/users/GaeUser.java | 125 +- .../gae/users/InMemoryUserRegistry.java | 27 +- .../java/samples/gae/users/UserRegistry.java | 6 +- .../java/samples/gae/validation/Forename.java | 8 +- .../gae/validation/ForenameValidator.java | 11 +- .../java/samples/gae/validation/Surname.java | 8 +- .../gae/validation/SurnameValidator.java | 11 +- .../samples/gae/web/GaeAppController.java | 46 +- .../gae/web/RegistrationController.java | 53 +- .../samples/gae/web/RegistrationForm.java | 32 +- .../samples/gae/security/AppRoleTests.java | 25 +- .../users/GaeDataStoreUserRegistryTests.java | 53 +- ...sageSecurityWebApplicationInitializer.java | 3 +- .../samples/config/SecurityConfig.java | 18 +- .../samples/mvc/MessageJsonController.java | 57 +- .../samples/mvc/config/CustomMvcConfig.java | 14 +- .../samples/config/SecurityConfigTests.java | 7 +- ...sageSecurityWebApplicationInitializer.java | 3 +- .../samples/config/SecurityConfig.java | 17 +- .../samples/config/SecurityConfigTests.java | 135 +- .../samples/config/SecurityConfig.java | 16 +- .../SecurityWebApplicationInitializer.java | 9 +- ...sageSecurityWebApplicationInitializer.java | 3 +- .../samples/config/SecurityConfig.java | 20 +- .../samples/config/SecurityConfigTests.java | 78 +- .../samples/config/SecurityConfigTests.java | 33 +- .../jaas/RoleUserAuthorityGranter.java | 6 +- .../UsernameEqualsPasswordLoginModule.java | 107 +- ...sageSecurityWebApplicationInitializer.java | 3 +- .../samples/config/SecurityConfig.java | 25 +- ...sageSecurityWebApplicationInitializer.java | 3 +- .../samples/config/SecurityConfig.java | 20 +- .../samples/config/SecurityConfigTests.java | 16 +- .../samples/config/DataConfiguration.java | 61 +- .../MessageWebApplicationInitializer.java | 34 +- .../security/samples/data/Message.java | 64 +- .../samples/data/MessageRepository.java | 6 +- .../samples/mvc/DefaultController.java | 8 +- .../samples/mvc/MessageController.java | 67 +- .../mvc/config/WebMvcConfiguration.java | 90 +- ...sageSecurityWebApplicationInitializer.java | 3 +- .../samples/config/SecurityConfig.java | 93 +- .../security/samples/mvc/UserController.java | 10 +- .../security/CustomUserDetailsService.java | 12 +- .../samples/config/SecurityConfigTests.java | 16 +- .../samples/openid/CustomUserDetails.java | 49 +- .../openid/CustomUserDetailsService.java | 133 +- ...sageSecurityWebApplicationInitializer.java | 3 +- .../samples/config/SecurityConfig.java | 25 +- .../samples/config/SecurityConfigTests.java | 7 +- ...sageSecurityWebApplicationInitializer.java | 3 +- .../samples/config/SecurityConfig.java | 49 +- .../samples/config/SecurityConfigTests.java | 7 +- .../samples/servletapi/mvc/LoginForm.java | 31 +- .../servletapi/mvc/ServletApiController.java | 293 ++- .../src/main/java/bigbank/Account.java | 77 +- .../src/main/java/bigbank/BankDao.java | 8 +- .../src/main/java/bigbank/BankDaoStub.java | 42 +- .../src/main/java/bigbank/BankService.java | 12 +- .../main/java/bigbank/BankServiceImpl.java | 44 +- .../src/main/java/bigbank/SeedData.java | 24 +- .../main/java/bigbank/web/ListAccounts.java | 34 +- .../main/java/bigbank/web/PostAccounts.java | 37 +- ...sageSecurityWebApplicationInitializer.java | 3 +- .../samples/config/SecurityConfig.java | 41 +- .../samples/config/SecurityConfigTests.java | 7 +- .../security/taglibs/TagLibConfig.java | 72 +- .../taglibs/authz/AbstractAuthorizeTag.java | 298 ++- .../taglibs/authz/AccessControlListTag.java | 242 +- .../taglibs/authz/AuthenticationTag.java | 204 +- .../taglibs/authz/JspAuthorizeTag.java | 255 +- .../taglibs/csrf/AbstractCsrfTag.java | 28 +- .../security/taglibs/csrf/CsrfInputTag.java | 14 +- .../taglibs/csrf/CsrfMetaTagsTag.java | 17 +- .../authz/AbstractAuthorizeTagTests.java | 77 +- .../authz/AccessControlListTagTests.java | 192 +- .../taglibs/authz/AuthenticationTagTests.java | 198 +- .../taglibs/authz/AuthorizeTagTests.java | 186 +- .../taglibs/csrf/AbstractCsrfTagTests.java | 105 +- .../taglibs/csrf/CsrfInputTagTests.java | 49 +- .../taglibs/csrf/CsrfMetaTagsTagTests.java | 54 +- .../context/TestSecurityContextHolder.java | 110 +- .../test/context/support/WithMockUser.java | 63 +- .../WithMockUserSecurityContextFactory.java | 44 +- .../context/support/WithSecurityContext.java | 26 +- .../support/WithSecurityContextFactory.java | 20 +- ...hSecurityContextTestExecutionListener.java | 124 +- .../test/context/support/WithUserDetails.java | 30 +- ...WithUserDetailsSecurityContextFactory.java | 35 +- .../SecurityMockMvcRequestBuilders.java | 318 +-- .../SecurityMockMvcRequestPostProcessors.java | 1323 +++++----- .../SecurityMockMvcResultMatchers.java | 331 +-- .../setup/SecurityMockMvcConfigurer.java | 57 +- .../setup/SecurityMockMvcConfigurers.java | 57 +- .../test/web/support/WebTestUtils.java | 160 +- .../TestSecurityContextHolderTests.java | 56 +- .../context/showcase/CustomUserDetails.java | 4 +- .../context/showcase/WithMockCustomUser.java | 8 +- ...hMockCustomUserSecurityContextFactory.java | 10 +- .../context/showcase/WithMockUserTests.java | 12 +- .../showcase/WithUserDetailsTests.java | 10 +- .../showcase/service/HelloMessageService.java | 3 +- ...thMockUserSecurityContextFactoryTests.java | 85 +- .../context/support/WithMockUserTests.java | 22 +- ...ityContextTestExcecutionListenerTests.java | 63 +- ...serDetailsSecurityContextFactoryTests.java | 59 +- .../context/support/WithUserDetailsTests.java | 16 +- ...yMockMvcRequestBuildersFormLoginTests.java | 83 +- ...MockMvcRequestBuildersFormLogoutTests.java | 73 +- ...rocessorsAuthenticationStatelessTests.java | 95 +- ...uestPostProcessorsAuthenticationTests.java | 55 +- ...RequestPostProcessorsCertificateTests.java | 45 +- ...MockMvcRequestPostProcessorsCsrfTests.java | 87 +- ...ckMvcRequestPostProcessorsDigestTests.java | 141 +- ...estPostProcessorsSecurityContextTests.java | 55 +- ...sorsTestSecurityContextStatelessTests.java | 86 +- ...ostProcessorsTestSecurityContextTests.java | 62 +- ...RequestPostProcessorsUserDetailsTests.java | 58 +- ...MockMvcRequestPostProcessorsUserTests.java | 150 +- .../SecurityMockMvcResultMatchersTests.java | 79 +- .../setup/SecurityMockMvcConfigurerTests.java | 75 +- .../showcase/csrf/CsrfShowcaseTests.java | 92 +- .../csrf/CustomCsrfShowcaseTests.java | 105 +- .../csrf/DefaultCsrfShowcaseTests.java | 70 +- .../showcase/login/AuthenticationTests.java | 92 +- .../CustomConfigAuthenticationTests.java | 132 +- ...oginRequestBuilderAuthenticationTests.java | 104 +- .../DefaultfSecurityRequestsTests.java | 102 +- .../secured/SecurityRequestsTests.java | 148 +- .../secured/WithUserAuthenticationTests.java | 100 +- ...WithUserClassLevelAuthenticationTests.java | 97 +- .../WithUserDetailsAuthenticationTests.java | 112 +- ...rDetailsClassLevelAuthenticationTests.java | 109 +- .../test/web/support/WebTestUtilsTests.java | 188 +- .../web/AuthenticationEntryPoint.java | 39 +- .../security/web/DefaultRedirectStrategy.java | 96 +- .../web/DefaultSecurityFilterChain.java | 48 +- .../security/web/FilterChainProxy.java | 437 ++-- .../security/web/FilterInvocation.java | 274 +- .../security/web/PortMapper.java | 46 +- .../security/web/PortMapperImpl.java | 142 +- .../security/web/PortResolver.java | 30 +- .../security/web/PortResolverImpl.java | 68 +- .../security/web/RedirectStrategy.java | 18 +- .../security/web/SecurityFilterChain.java | 8 +- .../security/web/WebAttributes.java | 43 +- .../web/access/AccessDeniedHandler.java | 29 +- .../web/access/AccessDeniedHandlerImpl.java | 91 +- ...efaultWebInvocationPrivilegeEvaluator.java | 145 +- .../access/DelegatingAccessDeniedHandler.java | 75 +- .../access/ExceptionTranslationFilter.java | 299 ++- .../WebInvocationPrivilegeEvaluator.java | 52 +- .../channel/AbstractRetryEntryPoint.java | 123 +- .../channel/ChannelDecisionManager.java | 43 +- .../channel/ChannelDecisionManagerImpl.java | 109 +- .../web/access/channel/ChannelEntryPoint.java | 34 +- .../channel/ChannelProcessingFilter.java | 191 +- .../web/access/channel/ChannelProcessor.java | 51 +- .../channel/InsecureChannelProcessor.java | 89 +- .../channel/RetryWithHttpEntryPoint.java | 18 +- .../channel/RetryWithHttpsEntryPoint.java | 18 +- .../channel/SecureChannelProcessor.java | 86 +- .../DefaultWebSecurityExpressionHandler.java | 83 +- ...ilterInvocationSecurityMetadataSource.java | 67 +- .../WebExpressionConfigAttribute.java | 28 +- .../access/expression/WebExpressionVoter.java | 64 +- .../expression/WebSecurityExpressionRoot.java | 36 +- ...ilterInvocationSecurityMetadataSource.java | 96 +- ...ilterInvocationSecurityMetadataSource.java | 8 +- .../intercept/FilterSecurityInterceptor.java | 184 +- .../web/access/intercept/RequestKey.java | 92 +- ...bstractAuthenticationProcessingFilter.java | 623 ++--- ...AuthenticationTargetUrlRequestHandler.java | 266 +- .../AnonymousAuthenticationFilter.java | 149 +- .../AuthenticationFailureHandler.java | 27 +- .../AuthenticationSuccessHandler.java | 30 +- .../DelegatingAuthenticationEntryPoint.java | 92 +- ...elegatingAuthenticationFailureHandler.java | 86 +- ...onMappingAuthenticationFailureHandler.java | 75 +- .../Http403ForbiddenEntryPoint.java | 36 +- .../authentication/HttpStatusEntryPoint.java | 36 +- .../LoginUrlAuthenticationEntryPoint.java | 359 +-- .../NullRememberMeServices.java | 25 +- .../authentication/RememberMeServices.java | 116 +- ...uestAwareAuthenticationSuccessHandler.java | 99 +- ...SimpleUrlAuthenticationFailureHandler.java | 192 +- ...SimpleUrlAuthenticationSuccessHandler.java | 72 +- .../UsernamePasswordAuthenticationFilter.java | 234 +- .../WebAuthenticationDetails.java | 163 +- .../WebAuthenticationDetailsSource.java | 27 +- .../logout/CookieClearingLogoutHandler.java | 35 +- .../authentication/logout/LogoutFilter.java | 151 +- .../authentication/logout/LogoutHandler.java | 21 +- .../logout/LogoutSuccessHandler.java | 14 +- .../logout/SecurityContextLogoutHandler.java | 112 +- .../logout/SimpleUrlLogoutSuccessHandler.java | 16 +- ...tractPreAuthenticatedProcessingFilter.java | 419 +-- ...reAuthenticatedAuthenticationProvider.java | 187 +- .../PreAuthenticatedAuthenticationToken.java | 95 +- ...enticatedCredentialsNotFoundException.java | 22 +- ...dGrantedAuthoritiesUserDetailsService.java | 67 +- ...edAuthoritiesWebAuthenticationDetails.java | 40 +- .../RequestHeaderAuthenticationFilter.java | 123 +- ...ticatedWebAuthenticationDetailsSource.java | 133 +- .../J2eePreAuthenticatedProcessingFilter.java | 45 +- .../WebXmlMappableAttributesRetriever.java | 160 +- .../DefaultWASUsernameAndGroupsExtractor.java | 345 +-- .../WASUsernameAndGroupsExtractor.java | 8 +- ...pherePreAuthenticatedProcessingFilter.java | 69 +- ...ticatedWebAuthenticationDetailsSource.java | 78 +- .../x509/SubjectDnX509PrincipalExtractor.java | 102 +- .../x509/X509AuthenticationFilter.java | 55 +- .../preauth/x509/X509PrincipalExtractor.java | 8 +- .../AbstractRememberMeServices.java | 884 ++++--- .../rememberme/CookieTheftException.java | 6 +- .../InMemoryTokenRepositoryImpl.java | 60 +- .../rememberme/InvalidCookieException.java | 10 +- .../rememberme/JdbcTokenRepositoryImpl.java | 158 +- .../rememberme/PersistentRememberMeToken.java | 45 +- ...ersistentTokenBasedRememberMeServices.java | 271 +- .../rememberme/PersistentTokenRepository.java | 12 +- .../RememberMeAuthenticationException.java | 44 +- .../RememberMeAuthenticationFilter.java | 243 +- .../TokenBasedRememberMeServices.java | 369 +-- ...ractSessionFixationProtectionStrategy.java | 192 +- ...ChangeSessionIdAuthenticationStrategy.java | 45 +- ...ompositeSessionAuthenticationStrategy.java | 90 +- ...tSessionControlAuthenticationStrategy.java | 261 +- .../NullAuthenticatedSessionStrategy.java | 9 +- ...RegisterSessionAuthenticationStrategy.java | 56 +- .../SessionAuthenticationException.java | 12 +- .../SessionAuthenticationStrategy.java | 24 +- .../SessionFixationProtectionEvent.java | 74 +- .../SessionFixationProtectionStrategy.java | 229 +- .../AuthenticationSwitchUserEvent.java | 40 +- .../SwitchUserAuthorityChanger.java | 35 +- .../switchuser/SwitchUserFilter.java | 894 +++---- .../SwitchUserGrantedAuthority.java | 81 +- .../ui/DefaultLoginPageGeneratingFilter.java | 398 +-- .../www/BasicAuthenticationEntryPoint.java | 54 +- .../www/BasicAuthenticationFilter.java | 397 +-- .../authentication/www/DigestAuthUtils.java | 325 +-- .../www/DigestAuthenticationEntryPoint.java | 152 +- .../www/DigestAuthenticationFilter.java | 728 +++--- .../www/NonceExpiredException.java | 41 +- .../annotation/AuthenticationPrincipal.java | 24 +- ...thenticationPrincipalArgumentResolver.java | 133 +- ...ractSecurityWebApplicationInitializer.java | 482 ++-- .../context/HttpRequestResponseHolder.java | 44 +- .../HttpSessionSecurityContextRepository.java | 652 ++--- .../NullSecurityContextRepository.java | 17 +- ...ContextOnUpdateOrErrorResponseWrapper.java | 859 +++--- .../SecurityContextPersistenceFilter.java | 126 +- .../context/SecurityContextRepository.java | 79 +- ...yContextCallableProcessingInterceptor.java | 86 +- .../WebAsyncManagerIntegrationFilter.java | 29 +- .../web/csrf/CsrfAuthenticationStrategy.java | 189 +- .../security/web/csrf/CsrfException.java | 6 +- .../security/web/csrf/CsrfFilter.java | 350 +-- .../security/web/csrf/CsrfLogoutHandler.java | 43 +- .../security/web/csrf/CsrfToken.java | 36 +- .../web/csrf/CsrfTokenRepository.java | 62 +- .../security/web/csrf/DefaultCsrfToken.java | 77 +- .../csrf/HttpSessionCsrfTokenRepository.java | 156 +- .../web/csrf/InvalidCsrfTokenException.java | 23 +- .../web/csrf/MissingCsrfTokenException.java | 6 +- .../security/web/debug/DebugFilter.java | 219 +- .../security/web/debug/Logger.java | 40 +- .../web/firewall/DefaultHttpFirewall.java | 97 +- .../web/firewall/FirewalledRequest.java | 49 +- .../web/firewall/FirewalledResponse.java | 27 +- .../security/web/firewall/HttpFirewall.java | 37 +- .../firewall/RequestRejectedException.java | 6 +- .../security/web/firewall/RequestWrapper.java | 214 +- .../security/web/header/Header.java | 71 +- .../security/web/header/HeaderWriter.java | 14 +- .../web/header/HeaderWriterFilter.java | 47 +- .../writers/CacheControlHeadersWriter.java | 31 +- .../DelegatingRequestMatcherHeaderWriter.java | 68 +- .../web/header/writers/HstsHeaderWriter.java | 299 ++- .../header/writers/StaticHeadersWriter.java | 56 +- .../XContentTypeOptionsHeaderWriter.java | 17 +- .../writers/XXssProtectionHeaderWriter.java | 149 +- ...ractRequestParameterAllowFromStrategy.java | 74 +- .../frameoptions/AllowFromStrategy.java | 21 +- .../frameoptions/RegExpAllowFromStrategy.java | 40 +- .../frameoptions/StaticAllowFromStrategy.java | 14 +- .../WhiteListedAllowFromStrategy.java | 29 +- .../XFrameOptionsHeaderWriter.java | 146 +- .../web/jaasapi/JaasApiIntegrationFilter.java | 220 +- ...thenticationPrincipalArgumentResolver.java | 131 +- .../annotation/CsrfTokenArgumentResolver.java | 47 +- .../web/savedrequest/DefaultSavedRequest.java | 615 ++--- .../security/web/savedrequest/Enumerator.java | 193 +- .../web/savedrequest/FastHttpDateFormat.java | 310 +-- .../savedrequest/HttpSessionRequestCache.java | 149 +- .../web/savedrequest/NullRequestCache.java | 26 +- .../web/savedrequest/RequestCache.java | 65 +- .../savedrequest/RequestCacheAwareFilter.java | 42 +- .../web/savedrequest/SavedCookie.java | 120 +- .../web/savedrequest/SavedRequest.java | 29 +- .../SavedRequestAwareWrapper.java | 316 +-- .../csrf/CsrfRequestDataValueProcessor.java | 73 +- .../HttpServlet25RequestFactory.java | 21 +- .../HttpServlet3RequestFactory.java | 422 +-- .../servletapi/HttpServletRequestFactory.java | 21 +- ...curityContextHolderAwareRequestFilter.java | 254 +- ...urityContextHolderAwareRequestWrapper.java | 245 +- .../web/session/ConcurrentSessionFilter.java | 168 +- .../web/session/HttpSessionCreatedEvent.java | 18 +- .../session/HttpSessionDestroyedEvent.java | 56 +- .../session/HttpSessionEventPublisher.java | 81 +- .../InvalidSessionAccessDeniedHandler.java | 30 +- .../web/session/InvalidSessionStrategy.java | 7 +- .../web/session/SessionManagementFilter.java | 205 +- .../SimpleRedirectInvalidSessionStrategy.java | 57 +- .../security/web/util/RedirectUrlBuilder.java | 108 +- .../security/web/util/TextEscapeUtils.java | 96 +- .../security/web/util/ThrowableAnalyzer.java | 396 +-- .../web/util/ThrowableCauseExtractor.java | 21 +- .../security/web/util/UrlUtils.java | 188 +- .../web/util/matcher/AndRequestMatcher.java | 80 +- .../util/matcher/AntPathRequestMatcher.java | 370 +-- .../web/util/matcher/AnyRequestMatcher.java | 30 +- .../web/util/matcher/ELRequestMatcher.java | 45 +- .../util/matcher/ELRequestMatcherContext.java | 35 +- .../web/util/matcher/IpAddressMatcher.java | 120 +- .../util/matcher/MediaTypeRequestMatcher.java | 246 +- .../util/matcher/NegatedRequestMatcher.java | 50 +- .../web/util/matcher/OrRequestMatcher.java | 80 +- .../web/util/matcher/RegexRequestMatcher.java | 157 +- .../matcher/RequestHeaderRequestMatcher.java | 106 +- .../web/util/matcher/RequestMatcher.java | 14 +- .../util/matcher/RequestMatcherEditor.java | 12 +- .../security/MockFilterConfig.java | 50 +- .../security/MockPortResolver.java | 37 +- .../web/DefaultRedirectStrategyTests.java | 45 +- .../security/web/FilterChainProxyTests.java | 350 +-- .../security/web/FilterInvocationTests.java | 171 +- .../security/web/PortMapperImplTests.java | 115 +- .../security/web/PortResolverImplTests.java | 98 +- ...tWebInvocationPrivilegeEvaluatorTests.java | 117 +- .../DelegatingAccessDeniedHandlerTests.java | 75 +- .../ExceptionTranslationFilterTests.java | 315 +-- .../ChannelDecisionManagerImplTests.java | 290 ++- .../channel/ChannelProcessingFilterTests.java | 271 +- .../InsecureChannelProcessorTests.java | 174 +- .../channel/RetryWithHttpEntryPointTests.java | 179 +- .../RetryWithHttpsEntryPointTests.java | 169 +- .../channel/SecureChannelProcessorTests.java | 176 +- ...aultWebSecurityExpressionHandlerTests.java | 84 +- ...InvocationSecurityMetadataSourceTests.java | 48 +- .../expression/WebExpressionVoterTests.java | 114 +- .../WebSecurityExpressionRootTests.java | 86 +- ...InvocationSecurityMetadataSourceTests.java | 206 +- .../FilterSecurityInterceptorTests.java | 218 +- .../web/access/intercept/RequestKeyTests.java | 58 +- ...ctAuthenticationProcessingFilterTests.java | 758 +++--- .../AnonymousAuthenticationFilterTests.java | 128 +- ...DefaultLoginPageGeneratingFilterTests.java | 192 +- ...gAuthenticationEntryPointContextTests.java | 60 +- ...legatingAuthenticationEntryPointTests.java | 102 +- ...tingAuthenticationFailureHandlerTests.java | 136 +- ...pingAuthenticationFailureHandlerTests.java | 42 +- .../HttpStatusEntryPointTests.java | 43 +- ...LoginUrlAuthenticationEntryPointTests.java | 389 +-- ...wareAuthenticationSuccessHandlerTests.java | 56 +- ...eUrlAuthenticationFailureHandlerTests.java | 101 +- ...eUrlAuthenticationSuccessHandlerTests.java | 160 +- ...namePasswordAuthenticationFilterTests.java | 202 +- .../CookieClearingLogoutHandlerTests.java | 55 +- .../logout/LogoutHandlerTests.java | 44 +- .../SecurityContextLogoutHandlerTests.java | 67 +- .../SimpleUrlLogoutSuccessHandlerTests.java | 42 +- ...PreAuthenticatedProcessingFilterTests.java | 442 ++-- .../Http403ForbiddenEntryPointTests.java | 30 +- ...henticatedAuthenticationProviderTests.java | 171 +- ...AuthenticatedAuthenticationTokenTests.java | 71 +- ...tedAuthoritiesUserDetailsServiceTests.java | 95 +- ...horitiesWebAuthenticationDetailsTests.java | 56 +- ...equestHeaderAuthenticationFilterTests.java | 217 +- ...edWebAuthenticationDetailsSourceTests.java | 223 +- ...PreAuthenticatedProcessingFilterTests.java | 54 +- .../WebXmlJ2eeDefinedRolesRetrieverTests.java | 78 +- ...PreAuthenticatedProcessingFilterTests.java | 57 +- .../SubjectDnX509PrincipalExtractorTests.java | 65 +- .../preauth/x509/X509TestUtils.java | 210 +- ...stractRememberMeServicesServlet3Tests.java | 66 +- .../AbstractRememberMeServicesTests.java | 863 ++++--- .../JdbcTokenRepositoryImplTests.java | 233 +- .../NullRememberMeServicesTests.java | 18 +- ...tentTokenBasedRememberMeServicesTests.java | 223 +- .../RememberMeAuthenticationFilterTests.java | 214 +- .../TokenBasedRememberMeServicesTests.java | 476 ++-- ...eSessionIdAuthenticationStrategyTests.java | 37 +- ...iteSessionAuthenticationStrategyTests.java | 89 +- ...ionControlAuthenticationStrategyTests.java | 135 +- ...terSessionAuthenticationStrategyTests.java | 45 +- .../switchuser/SwitchUserFilterTests.java | 766 +++--- .../BasicAuthenticationEntryPointTests.java | 86 +- .../www/BasicAuthenticationFilterTests.java | 357 +-- .../www/DigestAuthUtilsTests.java | 193 +- .../DigestAuthenticationEntryPointTests.java | 178 +- .../www/DigestAuthenticationFilterTests.java | 796 +++--- ...icationPrincipalArgumentResolverTests.java | 292 ++- .../ConcurrentSessionFilterTests.java | 134 +- ...SessionSecurityContextRepositoryTests.java | 932 ++++--- ...xtOnUpdateOrErrorResponseWrapperTests.java | 259 +- ...SecurityContextPersistenceFilterTests.java | 180 +- ...extCallableProcessingInterceptorTests.java | 68 +- ...WebAsyncManagerIntegrationFilterTests.java | 165 +- .../csrf/CsrfAuthenticationStrategyTests.java | 113 +- .../security/web/csrf/CsrfFilterTests.java | 691 +++-- .../web/csrf/CsrfLogoutHandlerTests.java | 41 +- .../web/csrf/DefaultCsrfTokenTests.java | 54 +- .../HttpSessionCsrfTokenRepositoryTests.java | 181 +- .../csrf/MissingCsrfTokenExceptionTests.java | 10 +- .../security/web/debug/DebugFilterTest.java | 144 +- .../firewall/DefaultHttpFirewallTests.java | 54 +- .../web/firewall/FirewalledResponseTests.java | 47 +- .../web/firewall/RequestWrapperTests.java | 146 +- .../web/header/HeaderWriterFilterTests.java | 55 +- .../CacheControlHeadersWriterTests.java | 36 +- ...gatingRequestMatcherHeaderWriterTests.java | 66 +- .../header/writers/HstsHeaderWriterTests.java | 172 +- .../writers/StaticHeaderWriterTests.java | 95 +- .../XContentTypeOptionsHeaderWriterTests.java | 31 +- .../XXssProtectionHeaderWriterTests.java | 91 +- ...equestParameterAllowFromStrategyTests.java | 112 +- .../FrameOptionsHeaderWriterTests.java | 106 +- .../RegExpAllowFromStrategyTests.java | 62 +- .../StaticAllowFromStrategyTests.java | 12 +- .../WhiteListedAllowFromStrategyTests.java | 105 +- .../JaasApiIntegrationFilterTests.java | 280 +- ...icationPrincipalArgumentResolverTests.java | 292 ++- .../CsrfTokenArgumentResolverTests.java | 100 +- .../DefaultSavedRequestTests.java | 51 +- .../HttpSessionRequestCacheTests.java | 157 +- .../RequestCacheAwareFilterTests.java | 25 +- .../web/savedrequest/SavedCookieTests.java | 94 +- .../SavedRequestAwareWrapperTests.java | 257 +- .../CsrfRequestDataValueProcessorTests.java | 160 +- ...yContextHolderAwareRequestFilterTests.java | 479 ++-- ...ContextHolderAwareRequestWrapperTests.java | 119 +- ...ultSessionAuthenticationStrategyTests.java | 189 +- .../HttpSessionDestroyedEventTests.java | 60 +- .../HttpSessionEventPublisherTests.java | 95 +- .../web/session/MockApplicationListener.java | 50 +- .../session/SessionManagementFilterTests.java | 230 +- .../web/util/TextEscapeUtilsTests.java | 71 +- .../web/util/ThrowableAnalyzerTests.java | 388 +-- .../security/web/util/UrlUtilsTests.java | 18 +- .../util/matcher/AndRequestMatcherTests.java | 129 +- .../matcher/AntPathRequestMatcherTests.java | 302 +-- .../util/matcher/ELRequestMatcherTests.java | 93 +- .../util/matcher/IpAddressMatcherTests.java | 98 +- ...diaTypeRequestMatcherRequestHCNSTests.java | 187 +- .../matcher/MediaTypeRequestMatcherTests.java | 263 +- .../matcher/NegatedRequestMatcherTests.java | 42 +- .../util/matcher/OrRequestMatcherTests.java | 129 +- .../matcher/RegexRequestMatcherTests.java | 125 +- .../RequestHeaderRequestMatcherTests.java | 101 +- 1420 files changed, 92995 insertions(+), 85097 deletions(-) diff --git a/acl/src/main/java/org/springframework/security/acls/AclEntryVoter.java b/acl/src/main/java/org/springframework/security/acls/AclEntryVoter.java index 240f8e43e5..f4145d4b98 100644 --- a/acl/src/main/java/org/springframework/security/acls/AclEntryVoter.java +++ b/acl/src/main/java/org/springframework/security/acls/AclEntryVoter.java @@ -40,201 +40,234 @@ import org.springframework.security.core.Authentication; import org.springframework.util.Assert; import org.springframework.util.StringUtils; - /** *

- * Given a domain object instance passed as a method argument, ensures the principal has appropriate permission - * as indicated by the {@link AclService}. + * Given a domain object instance passed as a method argument, ensures the principal has + * appropriate permission as indicated by the {@link AclService}. *

- * The AclService is used to retrieve the access control list (ACL) permissions associated with a - * domain object instance for the current Authentication object. + * The AclService is used to retrieve the access control list (ACL) permissions + * associated with a domain object instance for the current Authentication + * object. *

- * The voter will vote if any {@link ConfigAttribute#getAttribute()} matches the {@link #processConfigAttribute}. - * The provider will then locate the first method argument of type {@link #processDomainObjectClass}. Assuming that - * method argument is non-null, the provider will then lookup the ACLs from the AclManager and ensure the - * principal is {@link Acl#isGranted(List, - * List, boolean)} when presenting the {@link #requirePermission} array to that - * method. + * The voter will vote if any {@link ConfigAttribute#getAttribute()} matches the + * {@link #processConfigAttribute}. The provider will then locate the first method + * argument of type {@link #processDomainObjectClass}. Assuming that method argument is + * non-null, the provider will then lookup the ACLs from the AclManager and + * ensure the principal is {@link Acl#isGranted(List, List, boolean)} when presenting the + * {@link #requirePermission} array to that method. *

- * If the method argument is null, the voter will abstain from voting. If the method argument - * could not be found, an {@link AuthorizationServiceException} will be thrown. + * If the method argument is null, the voter will abstain from voting. If the + * method argument could not be found, an {@link AuthorizationServiceException} will be + * thrown. *

- * In practical terms users will typically setup a number of AclEntryVoters. Each will have a - * different {@link #setProcessDomainObjectClass processDomainObjectClass}, {@link #processConfigAttribute} and - * {@link #requirePermission} combination. For example, a small application might employ the following instances of + * In practical terms users will typically setup a number of AclEntryVoters. Each + * will have a different {@link #setProcessDomainObjectClass processDomainObjectClass}, + * {@link #processConfigAttribute} and {@link #requirePermission} combination. For + * example, a small application might employ the following instances of * AclEntryVoter: - *

- * Alternatively, you could have used a common superclass or interface for the {@link #processDomainObjectClass} - * if both BankAccount and Customer had common parents.

- *

If the principal does not have sufficient permissions, the voter will vote to deny access.

- *

All comparisons and prefixes are case sensitive.

+ * + * Alternatively, you could have used a common superclass or interface for the + * {@link #processDomainObjectClass} if both BankAccount and + * Customer had common parents. + *

+ *

+ * If the principal does not have sufficient permissions, the voter will vote to deny + * access. + *

+ *

+ * All comparisons and prefixes are case sensitive. + *

* * @author Ben Alex */ public class AclEntryVoter extends AbstractAclVoter { - //~ Static fields/initializers ===================================================================================== + // ~ Static fields/initializers + // ===================================================================================== - private static final Log logger = LogFactory.getLog(AclEntryVoter.class); + private static final Log logger = LogFactory.getLog(AclEntryVoter.class); - //~ Instance fields ================================================================================================ + // ~ Instance fields + // ================================================================================================ - private AclService aclService; - private ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy = new ObjectIdentityRetrievalStrategyImpl(); - private SidRetrievalStrategy sidRetrievalStrategy = new SidRetrievalStrategyImpl(); - private String internalMethod; - private String processConfigAttribute; - private List requirePermission; + private AclService aclService; + private ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy = new ObjectIdentityRetrievalStrategyImpl(); + private SidRetrievalStrategy sidRetrievalStrategy = new SidRetrievalStrategyImpl(); + private String internalMethod; + private String processConfigAttribute; + private List requirePermission; - //~ Constructors =================================================================================================== + // ~ Constructors + // =================================================================================================== - public AclEntryVoter(AclService aclService, String processConfigAttribute, Permission[] requirePermission) { - Assert.notNull(processConfigAttribute, "A processConfigAttribute is mandatory"); - Assert.notNull(aclService, "An AclService is mandatory"); + public AclEntryVoter(AclService aclService, String processConfigAttribute, + Permission[] requirePermission) { + Assert.notNull(processConfigAttribute, "A processConfigAttribute is mandatory"); + Assert.notNull(aclService, "An AclService is mandatory"); - if ((requirePermission == null) || (requirePermission.length == 0)) { - throw new IllegalArgumentException("One or more requirePermission entries is mandatory"); - } + if ((requirePermission == null) || (requirePermission.length == 0)) { + throw new IllegalArgumentException( + "One or more requirePermission entries is mandatory"); + } - this.aclService = aclService; - this.processConfigAttribute = processConfigAttribute; - this.requirePermission = Arrays.asList(requirePermission); - } + this.aclService = aclService; + this.processConfigAttribute = processConfigAttribute; + this.requirePermission = Arrays.asList(requirePermission); + } - //~ Methods ======================================================================================================== + // ~ Methods + // ======================================================================================================== - /** - * Optionally specifies a method of the domain object that will be used to obtain a contained domain - * object. That contained domain object will be used for the ACL evaluation. This is useful if a domain object - * contains a parent that an ACL evaluation should be targeted for, instead of the child domain object (which - * perhaps is being created and as such does not yet have any ACL permissions) - * - * @return null to use the domain object, or the name of a method (that requires no arguments) that - * should be invoked to obtain an Object which will be the domain object used for ACL - * evaluation - */ - protected String getInternalMethod() { - return internalMethod; - } + /** + * Optionally specifies a method of the domain object that will be used to obtain a + * contained domain object. That contained domain object will be used for the ACL + * evaluation. This is useful if a domain object contains a parent that an ACL + * evaluation should be targeted for, instead of the child domain object (which + * perhaps is being created and as such does not yet have any ACL permissions) + * + * @return null to use the domain object, or the name of a method (that + * requires no arguments) that should be invoked to obtain an Object + * which will be the domain object used for ACL evaluation + */ + protected String getInternalMethod() { + return internalMethod; + } - public void setInternalMethod(String internalMethod) { - this.internalMethod = internalMethod; - } + public void setInternalMethod(String internalMethod) { + this.internalMethod = internalMethod; + } - protected String getProcessConfigAttribute() { - return processConfigAttribute; - } + protected String getProcessConfigAttribute() { + return processConfigAttribute; + } - public void setObjectIdentityRetrievalStrategy(ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy) { - Assert.notNull(objectIdentityRetrievalStrategy, "ObjectIdentityRetrievalStrategy required"); - this.objectIdentityRetrievalStrategy = objectIdentityRetrievalStrategy; - } + public void setObjectIdentityRetrievalStrategy( + ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy) { + Assert.notNull(objectIdentityRetrievalStrategy, + "ObjectIdentityRetrievalStrategy required"); + this.objectIdentityRetrievalStrategy = objectIdentityRetrievalStrategy; + } - public void setSidRetrievalStrategy(SidRetrievalStrategy sidRetrievalStrategy) { - Assert.notNull(sidRetrievalStrategy, "SidRetrievalStrategy required"); - this.sidRetrievalStrategy = sidRetrievalStrategy; - } + public void setSidRetrievalStrategy(SidRetrievalStrategy sidRetrievalStrategy) { + Assert.notNull(sidRetrievalStrategy, "SidRetrievalStrategy required"); + this.sidRetrievalStrategy = sidRetrievalStrategy; + } - public boolean supports(ConfigAttribute attribute) { - return (attribute.getAttribute() != null) && attribute.getAttribute().equals(getProcessConfigAttribute()); - } + public boolean supports(ConfigAttribute attribute) { + return (attribute.getAttribute() != null) + && attribute.getAttribute().equals(getProcessConfigAttribute()); + } - public int vote(Authentication authentication, MethodInvocation object, Collection attributes) { + public int vote(Authentication authentication, MethodInvocation object, + Collection attributes) { - for(ConfigAttribute attr : attributes) { + for (ConfigAttribute attr : attributes) { - if (!this.supports(attr)) { - continue; - } - // Need to make an access decision on this invocation - // Attempt to locate the domain object instance to process - Object domainObject = getDomainObjectInstance(object); + if (!this.supports(attr)) { + continue; + } + // Need to make an access decision on this invocation + // Attempt to locate the domain object instance to process + Object domainObject = getDomainObjectInstance(object); - // If domain object is null, vote to abstain - if (domainObject == null) { - if (logger.isDebugEnabled()) { - logger.debug("Voting to abstain - domainObject is null"); - } + // If domain object is null, vote to abstain + if (domainObject == null) { + if (logger.isDebugEnabled()) { + logger.debug("Voting to abstain - domainObject is null"); + } - return ACCESS_ABSTAIN; - } + return ACCESS_ABSTAIN; + } - // Evaluate if we are required to use an inner domain object - if (StringUtils.hasText(internalMethod)) { - try { - Class clazz = domainObject.getClass(); - Method method = clazz.getMethod(internalMethod, new Class[0]); - domainObject = method.invoke(domainObject); - } catch (NoSuchMethodException nsme) { - throw new AuthorizationServiceException("Object of class '" + domainObject.getClass() - + "' does not provide the requested internalMethod: " + internalMethod); - } catch (IllegalAccessException iae) { - logger.debug("IllegalAccessException", iae); + // Evaluate if we are required to use an inner domain object + if (StringUtils.hasText(internalMethod)) { + try { + Class clazz = domainObject.getClass(); + Method method = clazz.getMethod(internalMethod, new Class[0]); + domainObject = method.invoke(domainObject); + } + catch (NoSuchMethodException nsme) { + throw new AuthorizationServiceException("Object of class '" + + domainObject.getClass() + + "' does not provide the requested internalMethod: " + + internalMethod); + } + catch (IllegalAccessException iae) { + logger.debug("IllegalAccessException", iae); - throw new AuthorizationServiceException("Problem invoking internalMethod: " + internalMethod - + " for object: " + domainObject); - } catch (InvocationTargetException ite) { - logger.debug("InvocationTargetException", ite); + throw new AuthorizationServiceException( + "Problem invoking internalMethod: " + internalMethod + + " for object: " + domainObject); + } + catch (InvocationTargetException ite) { + logger.debug("InvocationTargetException", ite); - throw new AuthorizationServiceException("Problem invoking internalMethod: " + internalMethod - + " for object: " + domainObject); - } - } + throw new AuthorizationServiceException( + "Problem invoking internalMethod: " + internalMethod + + " for object: " + domainObject); + } + } - // Obtain the OID applicable to the domain object - ObjectIdentity objectIdentity = objectIdentityRetrievalStrategy.getObjectIdentity(domainObject); + // Obtain the OID applicable to the domain object + ObjectIdentity objectIdentity = objectIdentityRetrievalStrategy + .getObjectIdentity(domainObject); - // Obtain the SIDs applicable to the principal - List sids = sidRetrievalStrategy.getSids(authentication); + // Obtain the SIDs applicable to the principal + List sids = sidRetrievalStrategy.getSids(authentication); - Acl acl; + Acl acl; - try { - // Lookup only ACLs for SIDs we're interested in - acl = aclService.readAclById(objectIdentity, sids); - } catch (NotFoundException nfe) { - if (logger.isDebugEnabled()) { - logger.debug("Voting to deny access - no ACLs apply for this principal"); - } + try { + // Lookup only ACLs for SIDs we're interested in + acl = aclService.readAclById(objectIdentity, sids); + } + catch (NotFoundException nfe) { + if (logger.isDebugEnabled()) { + logger.debug("Voting to deny access - no ACLs apply for this principal"); + } - return ACCESS_DENIED; - } + return ACCESS_DENIED; + } - try { - if (acl.isGranted(requirePermission, sids, false)) { - if (logger.isDebugEnabled()) { - logger.debug("Voting to grant access"); - } + try { + if (acl.isGranted(requirePermission, sids, false)) { + if (logger.isDebugEnabled()) { + logger.debug("Voting to grant access"); + } - return ACCESS_GRANTED; - } else { - if (logger.isDebugEnabled()) { - logger.debug( - "Voting to deny access - ACLs returned, but insufficient permissions for this principal"); - } + return ACCESS_GRANTED; + } + else { + if (logger.isDebugEnabled()) { + logger.debug("Voting to deny access - ACLs returned, but insufficient permissions for this principal"); + } - return ACCESS_DENIED; - } - } catch (NotFoundException nfe) { - if (logger.isDebugEnabled()) { - logger.debug("Voting to deny access - no ACLs apply for this principal"); - } + return ACCESS_DENIED; + } + } + catch (NotFoundException nfe) { + if (logger.isDebugEnabled()) { + logger.debug("Voting to deny access - no ACLs apply for this principal"); + } - return ACCESS_DENIED; - } - } + return ACCESS_DENIED; + } + } - // No configuration attribute matched, so abstain - return ACCESS_ABSTAIN; - } + // No configuration attribute matched, so abstain + return ACCESS_ABSTAIN; + } } diff --git a/acl/src/main/java/org/springframework/security/acls/AclPermissionCacheOptimizer.java b/acl/src/main/java/org/springframework/security/acls/AclPermissionCacheOptimizer.java index 42f403fc78..857ea67669 100644 --- a/acl/src/main/java/org/springframework/security/acls/AclPermissionCacheOptimizer.java +++ b/acl/src/main/java/org/springframework/security/acls/AclPermissionCacheOptimizer.java @@ -23,44 +23,45 @@ import org.springframework.security.core.Authentication; * @since 3.1 */ public class AclPermissionCacheOptimizer implements PermissionCacheOptimizer { - private final Log logger = LogFactory.getLog(getClass()); - private final AclService aclService; - private SidRetrievalStrategy sidRetrievalStrategy = new SidRetrievalStrategyImpl(); - private ObjectIdentityRetrievalStrategy oidRetrievalStrategy = new ObjectIdentityRetrievalStrategyImpl(); + private final Log logger = LogFactory.getLog(getClass()); + private final AclService aclService; + private SidRetrievalStrategy sidRetrievalStrategy = new SidRetrievalStrategyImpl(); + private ObjectIdentityRetrievalStrategy oidRetrievalStrategy = new ObjectIdentityRetrievalStrategyImpl(); - public AclPermissionCacheOptimizer(AclService aclService) { - this.aclService = aclService; - } + public AclPermissionCacheOptimizer(AclService aclService) { + this.aclService = aclService; + } - public void cachePermissionsFor(Authentication authentication, Collection objects) { - if (objects.isEmpty()) { - return; - } + public void cachePermissionsFor(Authentication authentication, Collection objects) { + if (objects.isEmpty()) { + return; + } - List oidsToCache = new ArrayList(objects.size()); + List oidsToCache = new ArrayList(objects.size()); - for (Object domainObject : objects) { - if (domainObject == null) { - continue; - } - ObjectIdentity oid = oidRetrievalStrategy.getObjectIdentity(domainObject); - oidsToCache.add(oid); - } + for (Object domainObject : objects) { + if (domainObject == null) { + continue; + } + ObjectIdentity oid = oidRetrievalStrategy.getObjectIdentity(domainObject); + oidsToCache.add(oid); + } - List sids = sidRetrievalStrategy.getSids(authentication); + List sids = sidRetrievalStrategy.getSids(authentication); - if (logger.isDebugEnabled()) { - logger.debug("Eagerly loading Acls for " + oidsToCache.size() + " objects"); - } + if (logger.isDebugEnabled()) { + logger.debug("Eagerly loading Acls for " + oidsToCache.size() + " objects"); + } - aclService.readAclsById(oidsToCache, sids); - } + aclService.readAclsById(oidsToCache, sids); + } - public void setObjectIdentityRetrievalStrategy(ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy) { - this.oidRetrievalStrategy = objectIdentityRetrievalStrategy; - } + public void setObjectIdentityRetrievalStrategy( + ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy) { + this.oidRetrievalStrategy = objectIdentityRetrievalStrategy; + } - public void setSidRetrievalStrategy(SidRetrievalStrategy sidRetrievalStrategy) { - this.sidRetrievalStrategy = sidRetrievalStrategy; - } + public void setSidRetrievalStrategy(SidRetrievalStrategy sidRetrievalStrategy) { + this.sidRetrievalStrategy = sidRetrievalStrategy; + } } diff --git a/acl/src/main/java/org/springframework/security/acls/AclPermissionEvaluator.java b/acl/src/main/java/org/springframework/security/acls/AclPermissionEvaluator.java index adfddd1c6a..13ece9872f 100644 --- a/acl/src/main/java/org/springframework/security/acls/AclPermissionEvaluator.java +++ b/acl/src/main/java/org/springframework/security/acls/AclPermissionEvaluator.java @@ -23,8 +23,8 @@ import org.springframework.security.acls.model.SidRetrievalStrategy; import org.springframework.security.core.Authentication; /** - * Used by Spring Security's expression-based access control implementation to evaluate permissions for a particular - * object using the ACL module. Similar in behaviour to + * Used by Spring Security's expression-based access control implementation to evaluate + * permissions for a particular object using the ACL module. Similar in behaviour to * {@link org.springframework.security.acls.AclEntryVoter AclEntryVoter}. * * @author Luke Taylor @@ -32,120 +32,130 @@ import org.springframework.security.core.Authentication; */ public class AclPermissionEvaluator implements PermissionEvaluator { - private final Log logger = LogFactory.getLog(getClass()); + private final Log logger = LogFactory.getLog(getClass()); - private final AclService aclService; - private ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy = new ObjectIdentityRetrievalStrategyImpl(); - private ObjectIdentityGenerator objectIdentityGenerator = new ObjectIdentityRetrievalStrategyImpl(); - private SidRetrievalStrategy sidRetrievalStrategy = new SidRetrievalStrategyImpl(); - private PermissionFactory permissionFactory = new DefaultPermissionFactory(); + private final AclService aclService; + private ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy = new ObjectIdentityRetrievalStrategyImpl(); + private ObjectIdentityGenerator objectIdentityGenerator = new ObjectIdentityRetrievalStrategyImpl(); + private SidRetrievalStrategy sidRetrievalStrategy = new SidRetrievalStrategyImpl(); + private PermissionFactory permissionFactory = new DefaultPermissionFactory(); - public AclPermissionEvaluator(AclService aclService) { - this.aclService = aclService; - } + public AclPermissionEvaluator(AclService aclService) { + this.aclService = aclService; + } - /** - * Determines whether the user has the given permission(s) on the domain object using the ACL - * configuration. If the domain object is null, returns false (this can always be overridden using a null - * check in the expression itself). - */ - public boolean hasPermission(Authentication authentication, Object domainObject, Object permission) { - if (domainObject == null) { - return false; - } + /** + * Determines whether the user has the given permission(s) on the domain object using + * the ACL configuration. If the domain object is null, returns false (this can always + * be overridden using a null check in the expression itself). + */ + public boolean hasPermission(Authentication authentication, Object domainObject, + Object permission) { + if (domainObject == null) { + return false; + } - ObjectIdentity objectIdentity = objectIdentityRetrievalStrategy.getObjectIdentity(domainObject); + ObjectIdentity objectIdentity = objectIdentityRetrievalStrategy + .getObjectIdentity(domainObject); - return checkPermission(authentication, objectIdentity, permission); - } + return checkPermission(authentication, objectIdentity, permission); + } - public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permission) { - ObjectIdentity objectIdentity = objectIdentityGenerator.createObjectIdentity(targetId, targetType); + public boolean hasPermission(Authentication authentication, Serializable targetId, + String targetType, Object permission) { + ObjectIdentity objectIdentity = objectIdentityGenerator.createObjectIdentity( + targetId, targetType); - return checkPermission(authentication, objectIdentity, permission); - } + return checkPermission(authentication, objectIdentity, permission); + } - private boolean checkPermission(Authentication authentication, ObjectIdentity oid, Object permission) { - // Obtain the SIDs applicable to the principal - List sids = sidRetrievalStrategy.getSids(authentication); - List requiredPermission = resolvePermission(permission); + private boolean checkPermission(Authentication authentication, ObjectIdentity oid, + Object permission) { + // Obtain the SIDs applicable to the principal + List sids = sidRetrievalStrategy.getSids(authentication); + List requiredPermission = resolvePermission(permission); - final boolean debug = logger.isDebugEnabled(); + final boolean debug = logger.isDebugEnabled(); - if (debug) { - logger.debug("Checking permission '" + permission + "' for object '" + oid + "'"); - } + if (debug) { + logger.debug("Checking permission '" + permission + "' for object '" + oid + + "'"); + } - try { - // Lookup only ACLs for SIDs we're interested in - Acl acl = aclService.readAclById(oid, sids); + try { + // Lookup only ACLs for SIDs we're interested in + Acl acl = aclService.readAclById(oid, sids); - if (acl.isGranted(requiredPermission, sids, false)) { - if (debug) { - logger.debug("Access is granted"); - } + if (acl.isGranted(requiredPermission, sids, false)) { + if (debug) { + logger.debug("Access is granted"); + } - return true; - } + return true; + } - if (debug) { - logger.debug("Returning false - ACLs returned, but insufficient permissions for this principal"); - } + if (debug) { + logger.debug("Returning false - ACLs returned, but insufficient permissions for this principal"); + } - } catch (NotFoundException nfe) { - if (debug) { - logger.debug("Returning false - no ACLs apply for this principal"); - } - } + } + catch (NotFoundException nfe) { + if (debug) { + logger.debug("Returning false - no ACLs apply for this principal"); + } + } - return false; + return false; - } + } - List resolvePermission(Object permission) { - if (permission instanceof Integer) { - return Arrays.asList(permissionFactory.buildFromMask(((Integer)permission).intValue())); - } + List resolvePermission(Object permission) { + if (permission instanceof Integer) { + return Arrays.asList(permissionFactory.buildFromMask(((Integer) permission) + .intValue())); + } - if (permission instanceof Permission) { - return Arrays.asList((Permission)permission); - } + if (permission instanceof Permission) { + return Arrays.asList((Permission) permission); + } - if (permission instanceof Permission[]) { - return Arrays.asList((Permission[])permission); - } + if (permission instanceof Permission[]) { + return Arrays.asList((Permission[]) permission); + } - if (permission instanceof String) { - String permString = (String)permission; - Permission p; + if (permission instanceof String) { + String permString = (String) permission; + Permission p; - try { - p = permissionFactory.buildFromName(permString); - } catch(IllegalArgumentException notfound) { - p = permissionFactory.buildFromName(permString.toUpperCase()); - } + try { + p = permissionFactory.buildFromName(permString); + } + catch (IllegalArgumentException notfound) { + p = permissionFactory.buildFromName(permString.toUpperCase()); + } - if (p != null) { - return Arrays.asList(p); - } + if (p != null) { + return Arrays.asList(p); + } - } - throw new IllegalArgumentException("Unsupported permission: " + permission); - } + } + throw new IllegalArgumentException("Unsupported permission: " + permission); + } - public void setObjectIdentityRetrievalStrategy(ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy) { - this.objectIdentityRetrievalStrategy = objectIdentityRetrievalStrategy; - } + public void setObjectIdentityRetrievalStrategy( + ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy) { + this.objectIdentityRetrievalStrategy = objectIdentityRetrievalStrategy; + } - public void setObjectIdentityGenerator(ObjectIdentityGenerator objectIdentityGenerator) { - this.objectIdentityGenerator = objectIdentityGenerator; - } + public void setObjectIdentityGenerator(ObjectIdentityGenerator objectIdentityGenerator) { + this.objectIdentityGenerator = objectIdentityGenerator; + } - public void setSidRetrievalStrategy(SidRetrievalStrategy sidRetrievalStrategy) { - this.sidRetrievalStrategy = sidRetrievalStrategy; - } + public void setSidRetrievalStrategy(SidRetrievalStrategy sidRetrievalStrategy) { + this.sidRetrievalStrategy = sidRetrievalStrategy; + } - public void setPermissionFactory(PermissionFactory permissionFactory) { - this.permissionFactory = permissionFactory; - } + public void setPermissionFactory(PermissionFactory permissionFactory) { + this.permissionFactory = permissionFactory; + } } diff --git a/acl/src/main/java/org/springframework/security/acls/afterinvocation/AbstractAclProvider.java b/acl/src/main/java/org/springframework/security/acls/afterinvocation/AbstractAclProvider.java index 0e54862cb3..86cb373157 100644 --- a/acl/src/main/java/org/springframework/security/acls/afterinvocation/AbstractAclProvider.java +++ b/acl/src/main/java/org/springframework/security/acls/afterinvocation/AbstractAclProvider.java @@ -34,92 +34,103 @@ import org.springframework.security.acls.model.SidRetrievalStrategy; import org.springframework.security.core.Authentication; import org.springframework.util.Assert; - /** - * Abstract {@link AfterInvocationProvider} which provides commonly-used ACL-related services. + * Abstract {@link AfterInvocationProvider} which provides commonly-used ACL-related + * services. * * @author Ben Alex - */ + */ public abstract class AbstractAclProvider implements AfterInvocationProvider { - //~ Instance fields ================================================================================================ + // ~ Instance fields + // ================================================================================================ - protected final AclService aclService; - protected Class processDomainObjectClass = Object.class; - protected ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy = new ObjectIdentityRetrievalStrategyImpl(); - protected SidRetrievalStrategy sidRetrievalStrategy = new SidRetrievalStrategyImpl(); - protected String processConfigAttribute; - protected final List requirePermission; + protected final AclService aclService; + protected Class processDomainObjectClass = Object.class; + protected ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy = new ObjectIdentityRetrievalStrategyImpl(); + protected SidRetrievalStrategy sidRetrievalStrategy = new SidRetrievalStrategyImpl(); + protected String processConfigAttribute; + protected final List requirePermission; - //~ Constructors =================================================================================================== + // ~ Constructors + // =================================================================================================== - public AbstractAclProvider(AclService aclService, String processConfigAttribute, List requirePermission) { - Assert.hasText(processConfigAttribute, "A processConfigAttribute is mandatory"); - Assert.notNull(aclService, "An AclService is mandatory"); + public AbstractAclProvider(AclService aclService, String processConfigAttribute, + List requirePermission) { + Assert.hasText(processConfigAttribute, "A processConfigAttribute is mandatory"); + Assert.notNull(aclService, "An AclService is mandatory"); - if (requirePermission == null || requirePermission.isEmpty()) { - throw new IllegalArgumentException("One or more requirePermission entries is mandatory"); - } + if (requirePermission == null || requirePermission.isEmpty()) { + throw new IllegalArgumentException( + "One or more requirePermission entries is mandatory"); + } - this.aclService = aclService; - this.processConfigAttribute = processConfigAttribute; - this.requirePermission = requirePermission; - } + this.aclService = aclService; + this.processConfigAttribute = processConfigAttribute; + this.requirePermission = requirePermission; + } - //~ Methods ======================================================================================================== + // ~ Methods + // ======================================================================================================== - protected Class getProcessDomainObjectClass() { - return processDomainObjectClass; - } + protected Class getProcessDomainObjectClass() { + return processDomainObjectClass; + } - protected boolean hasPermission(Authentication authentication, Object domainObject) { - // Obtain the OID applicable to the domain object - ObjectIdentity objectIdentity = objectIdentityRetrievalStrategy.getObjectIdentity(domainObject); + protected boolean hasPermission(Authentication authentication, Object domainObject) { + // Obtain the OID applicable to the domain object + ObjectIdentity objectIdentity = objectIdentityRetrievalStrategy + .getObjectIdentity(domainObject); - // Obtain the SIDs applicable to the principal - List sids = sidRetrievalStrategy.getSids(authentication); + // Obtain the SIDs applicable to the principal + List sids = sidRetrievalStrategy.getSids(authentication); - try { - // Lookup only ACLs for SIDs we're interested in - Acl acl = aclService.readAclById(objectIdentity, sids); + try { + // Lookup only ACLs for SIDs we're interested in + Acl acl = aclService.readAclById(objectIdentity, sids); - return acl.isGranted(requirePermission, sids, false); - } catch (NotFoundException ignore) { - return false; - } - } + return acl.isGranted(requirePermission, sids, false); + } + catch (NotFoundException ignore) { + return false; + } + } - public void setObjectIdentityRetrievalStrategy(ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy) { - Assert.notNull(objectIdentityRetrievalStrategy, "ObjectIdentityRetrievalStrategy required"); - this.objectIdentityRetrievalStrategy = objectIdentityRetrievalStrategy; - } + public void setObjectIdentityRetrievalStrategy( + ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy) { + Assert.notNull(objectIdentityRetrievalStrategy, + "ObjectIdentityRetrievalStrategy required"); + this.objectIdentityRetrievalStrategy = objectIdentityRetrievalStrategy; + } - protected void setProcessConfigAttribute(String processConfigAttribute) { - Assert.hasText(processConfigAttribute, "A processConfigAttribute is mandatory"); - this.processConfigAttribute = processConfigAttribute; - } + protected void setProcessConfigAttribute(String processConfigAttribute) { + Assert.hasText(processConfigAttribute, "A processConfigAttribute is mandatory"); + this.processConfigAttribute = processConfigAttribute; + } - public void setProcessDomainObjectClass(Class processDomainObjectClass) { - Assert.notNull(processDomainObjectClass, "processDomainObjectClass cannot be set to null"); - this.processDomainObjectClass = processDomainObjectClass; - } + public void setProcessDomainObjectClass(Class processDomainObjectClass) { + Assert.notNull(processDomainObjectClass, + "processDomainObjectClass cannot be set to null"); + this.processDomainObjectClass = processDomainObjectClass; + } - public void setSidRetrievalStrategy(SidRetrievalStrategy sidRetrievalStrategy) { - Assert.notNull(sidRetrievalStrategy, "SidRetrievalStrategy required"); - this.sidRetrievalStrategy = sidRetrievalStrategy; - } + public void setSidRetrievalStrategy(SidRetrievalStrategy sidRetrievalStrategy) { + Assert.notNull(sidRetrievalStrategy, "SidRetrievalStrategy required"); + this.sidRetrievalStrategy = sidRetrievalStrategy; + } - public boolean supports(ConfigAttribute attribute) { - return processConfigAttribute.equals(attribute.getAttribute()); - } + public boolean supports(ConfigAttribute attribute) { + return processConfigAttribute.equals(attribute.getAttribute()); + } - /** - * This implementation supports any type of class, because it does not query the presented secure object. - * - * @param clazz the secure object - * - * @return always true - */ - public boolean supports(Class clazz) { - return true; - } + /** + * This implementation supports any type of class, because it does not query the + * presented secure object. + * + * @param clazz the secure object + * + * @return always true + */ + public boolean supports(Class clazz) { + return true; + } } diff --git a/acl/src/main/java/org/springframework/security/acls/afterinvocation/AclEntryAfterInvocationCollectionFilteringProvider.java b/acl/src/main/java/org/springframework/security/acls/afterinvocation/AclEntryAfterInvocationCollectionFilteringProvider.java index 2ddcf12230..673c753910 100644 --- a/acl/src/main/java/org/springframework/security/acls/afterinvocation/AclEntryAfterInvocationCollectionFilteringProvider.java +++ b/acl/src/main/java/org/springframework/security/acls/afterinvocation/AclEntryAfterInvocationCollectionFilteringProvider.java @@ -26,96 +26,113 @@ import org.springframework.security.acls.model.AclService; import org.springframework.security.acls.model.Permission; import org.springframework.security.core.Authentication; - /** *

- * Given a Collection of domain object instances returned from a secure object invocation, remove - * any Collection elements the principal does not have appropriate permission to access as defined by the - * {@link AclService}. + * Given a Collection of domain object instances returned from a secure + * object invocation, remove any Collection elements the principal does not + * have appropriate permission to access as defined by the {@link AclService}. *

- * The AclService is used to retrieve the access control list (ACL) permissions associated with - * each Collection domain object instance element for the current Authentication object. + * The AclService is used to retrieve the access control list (ACL) + * permissions associated with each Collection domain object instance element + * for the current Authentication object. *

- * This after invocation provider will fire if any {@link ConfigAttribute#getAttribute()} matches the {@link - * #processConfigAttribute}. The provider will then lookup the ACLs from the AclService and ensure the - * principal is {@link org.springframework.security.acls.model.Acl#isGranted(List, List, boolean) Acl.isGranted()} - * when presenting the {@link #requirePermission} array to that method. + * This after invocation provider will fire if any {@link ConfigAttribute#getAttribute()} + * matches the {@link #processConfigAttribute}. The provider will then lookup the ACLs + * from the AclService and ensure the principal is + * {@link org.springframework.security.acls.model.Acl#isGranted(List, List, boolean) + * Acl.isGranted()} when presenting the {@link #requirePermission} array to that method. *

- * If the principal does not have permission, that element will not be included in the returned - * Collection. + * If the principal does not have permission, that element will not be included in the + * returned Collection. *

- * Often users will setup a BasicAclEntryAfterInvocationProvider with a {@link - * #processConfigAttribute} of AFTER_ACL_COLLECTION_READ and a {@link #requirePermission} of - * BasePermission.READ. These are also the defaults. + * Often users will setup a BasicAclEntryAfterInvocationProvider with a + * {@link #processConfigAttribute} of AFTER_ACL_COLLECTION_READ and a + * {@link #requirePermission} of BasePermission.READ. These are also the + * defaults. *

- * If the provided returnObject is null, a nullCollection - * will be returned. If the provided returnObject is not a Collection, an {@link - * AuthorizationServiceException} will be thrown. + * If the provided returnObject is null, a null + * Collection will be returned. If the provided returnObject is + * not a Collection, an {@link AuthorizationServiceException} will be thrown. *

* All comparisons and prefixes are case sensitive. * * @author Ben Alex * @author Paulo Neves */ -public class AclEntryAfterInvocationCollectionFilteringProvider extends AbstractAclProvider { - //~ Static fields/initializers ===================================================================================== +public class AclEntryAfterInvocationCollectionFilteringProvider extends + AbstractAclProvider { + // ~ Static fields/initializers + // ===================================================================================== - protected static final Log logger = LogFactory.getLog(AclEntryAfterInvocationCollectionFilteringProvider.class); + protected static final Log logger = LogFactory + .getLog(AclEntryAfterInvocationCollectionFilteringProvider.class); - //~ Constructors =================================================================================================== + // ~ Constructors + // =================================================================================================== - public AclEntryAfterInvocationCollectionFilteringProvider(AclService aclService, List requirePermission) { - super(aclService, "AFTER_ACL_COLLECTION_READ", requirePermission); - } + public AclEntryAfterInvocationCollectionFilteringProvider(AclService aclService, + List requirePermission) { + super(aclService, "AFTER_ACL_COLLECTION_READ", requirePermission); + } - //~ Methods ======================================================================================================== + // ~ Methods + // ======================================================================================================== - @SuppressWarnings("unchecked") - public Object decide(Authentication authentication, Object object, Collection config, - Object returnedObject) throws AccessDeniedException { + @SuppressWarnings("unchecked") + public Object decide(Authentication authentication, Object object, + Collection config, Object returnedObject) + throws AccessDeniedException { - if (returnedObject == null) { - logger.debug("Return object is null, skipping"); + if (returnedObject == null) { + logger.debug("Return object is null, skipping"); - return null; - } + return null; + } - for (ConfigAttribute attr : config) { - if (!this.supports(attr)) { - continue; - } + for (ConfigAttribute attr : config) { + if (!this.supports(attr)) { + continue; + } - // Need to process the Collection for this invocation - Filterer filterer; + // Need to process the Collection for this invocation + Filterer filterer; - if (returnedObject instanceof Collection) { - filterer = new CollectionFilterer((Collection) returnedObject); - } else if (returnedObject.getClass().isArray()) { - filterer = new ArrayFilterer((Object[]) returnedObject); - } else { - throw new AuthorizationServiceException("A Collection or an array (or null) was required as the " - + "returnedObject, but the returnedObject was: " + returnedObject); - } + if (returnedObject instanceof Collection) { + filterer = new CollectionFilterer((Collection) returnedObject); + } + else if (returnedObject.getClass().isArray()) { + filterer = new ArrayFilterer((Object[]) returnedObject); + } + else { + throw new AuthorizationServiceException( + "A Collection or an array (or null) was required as the " + + "returnedObject, but the returnedObject was: " + + returnedObject); + } - // Locate unauthorised Collection elements - for (Object domainObject : filterer) { - // Ignore nulls or entries which aren't instances of the configured domain object class - if (domainObject == null || !getProcessDomainObjectClass().isAssignableFrom(domainObject.getClass())) { - continue; - } + // Locate unauthorised Collection elements + for (Object domainObject : filterer) { + // Ignore nulls or entries which aren't instances of the configured domain + // object class + if (domainObject == null + || !getProcessDomainObjectClass().isAssignableFrom( + domainObject.getClass())) { + continue; + } - if(!hasPermission(authentication, domainObject)) { - filterer.remove(domainObject); + if (!hasPermission(authentication, domainObject)) { + filterer.remove(domainObject); - if (logger.isDebugEnabled()) { - logger.debug("Principal is NOT authorised for element: " + domainObject); - } - } - } + if (logger.isDebugEnabled()) { + logger.debug("Principal is NOT authorised for element: " + + domainObject); + } + } + } - return filterer.getFilteredObject(); - } + return filterer.getFilteredObject(); + } - return returnedObject; - } + return returnedObject; + } } diff --git a/acl/src/main/java/org/springframework/security/acls/afterinvocation/AclEntryAfterInvocationProvider.java b/acl/src/main/java/org/springframework/security/acls/afterinvocation/AclEntryAfterInvocationProvider.java index e12cf3f307..80f21f2618 100644 --- a/acl/src/main/java/org/springframework/security/acls/afterinvocation/AclEntryAfterInvocationProvider.java +++ b/acl/src/main/java/org/springframework/security/acls/afterinvocation/AclEntryAfterInvocationProvider.java @@ -29,90 +29,103 @@ import org.springframework.security.acls.model.Permission; import org.springframework.security.core.Authentication; import org.springframework.security.core.SpringSecurityMessageSource; - /** - * Given a domain object instance returned from a secure object invocation, ensures the principal has - * appropriate permission as defined by the {@link AclService}. + * Given a domain object instance returned from a secure object invocation, ensures the + * principal has appropriate permission as defined by the {@link AclService}. *

- * The AclService is used to retrieve the access control list (ACL) permissions associated with a - * domain object instance for the current Authentication object. + * The AclService is used to retrieve the access control list (ACL) + * permissions associated with a domain object instance for the current + * Authentication object. *

- * This after invocation provider will fire if any {@link ConfigAttribute#getAttribute()} matches the {@link - * #processConfigAttribute}. The provider will then lookup the ACLs from the AclService and ensure the - * principal is {@link org.springframework.security.acls.model.Acl#isGranted(List, List, boolean) - * Acl.isGranted(List, List, boolean)} when presenting the {@link #requirePermission} array to that method. + * This after invocation provider will fire if any {@link ConfigAttribute#getAttribute()} + * matches the {@link #processConfigAttribute}. The provider will then lookup the ACLs + * from the AclService and ensure the principal is + * {@link org.springframework.security.acls.model.Acl#isGranted(List, List, boolean) + * Acl.isGranted(List, List, boolean)} when presenting the {@link #requirePermission} + * array to that method. *

- * Often users will set up an AclEntryAfterInvocationProvider with a {@link - * #processConfigAttribute} of AFTER_ACL_READ and a {@link #requirePermission} of - * BasePermission.READ. These are also the defaults. + * Often users will set up an AclEntryAfterInvocationProvider with a + * {@link #processConfigAttribute} of AFTER_ACL_READ and a + * {@link #requirePermission} of BasePermission.READ. These are also the + * defaults. *

- * If the principal does not have sufficient permissions, an AccessDeniedException will be thrown. + * If the principal does not have sufficient permissions, an + * AccessDeniedException will be thrown. *

- * If the provided returnedObject is null, permission will always be granted and - * null will be returned. + * If the provided returnedObject is null, permission will always be + * granted and null will be returned. *

* All comparisons and prefixes are case sensitive. */ -public class AclEntryAfterInvocationProvider extends AbstractAclProvider implements MessageSourceAware { - //~ Static fields/initializers ===================================================================================== +public class AclEntryAfterInvocationProvider extends AbstractAclProvider implements + MessageSourceAware { + // ~ Static fields/initializers + // ===================================================================================== - protected static final Log logger = LogFactory.getLog(AclEntryAfterInvocationProvider.class); + protected static final Log logger = LogFactory + .getLog(AclEntryAfterInvocationProvider.class); - //~ Instance fields ================================================================================================ + // ~ Instance fields + // ================================================================================================ - protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor(); + protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor(); - //~ Constructors =================================================================================================== + // ~ Constructors + // =================================================================================================== - public AclEntryAfterInvocationProvider(AclService aclService, List requirePermission) { - this(aclService, "AFTER_ACL_READ", requirePermission); - } + public AclEntryAfterInvocationProvider(AclService aclService, + List requirePermission) { + this(aclService, "AFTER_ACL_READ", requirePermission); + } - public AclEntryAfterInvocationProvider(AclService aclService, String processConfigAttribute, - List requirePermission) { - super(aclService, processConfigAttribute, requirePermission); - } + public AclEntryAfterInvocationProvider(AclService aclService, + String processConfigAttribute, List requirePermission) { + super(aclService, processConfigAttribute, requirePermission); + } - //~ Methods ======================================================================================================== + // ~ Methods + // ======================================================================================================== - public Object decide(Authentication authentication, Object object, Collection config, - Object returnedObject) throws AccessDeniedException { + public Object decide(Authentication authentication, Object object, + Collection config, Object returnedObject) + throws AccessDeniedException { - if (returnedObject == null) { - // AclManager interface contract prohibits nulls - // As they have permission to null/nothing, grant access - logger.debug("Return object is null, skipping"); + if (returnedObject == null) { + // AclManager interface contract prohibits nulls + // As they have permission to null/nothing, grant access + logger.debug("Return object is null, skipping"); - return null; - } + return null; + } - if (!getProcessDomainObjectClass().isAssignableFrom(returnedObject.getClass())) { - logger.debug("Return object is not applicable for this provider, skipping"); + if (!getProcessDomainObjectClass().isAssignableFrom(returnedObject.getClass())) { + logger.debug("Return object is not applicable for this provider, skipping"); - return returnedObject; - } + return returnedObject; + } - for (ConfigAttribute attr : config) { - if (!this.supports(attr)) { - continue; - } - // Need to make an access decision on this invocation + for (ConfigAttribute attr : config) { + if (!this.supports(attr)) { + continue; + } + // Need to make an access decision on this invocation - if (hasPermission(authentication, returnedObject)) { - return returnedObject; - } + if (hasPermission(authentication, returnedObject)) { + return returnedObject; + } - logger.debug("Denying access"); + logger.debug("Denying access"); - throw new AccessDeniedException(messages.getMessage("AclEntryAfterInvocationProvider.noPermission", - new Object[] {authentication.getName(), returnedObject}, - "Authentication {0} has NO permissions to the domain object {1}")); - } + throw new AccessDeniedException(messages.getMessage( + "AclEntryAfterInvocationProvider.noPermission", new Object[] { + authentication.getName(), returnedObject }, + "Authentication {0} has NO permissions to the domain object {1}")); + } - return returnedObject; - } + return returnedObject; + } - public void setMessageSource(MessageSource messageSource) { - this.messages = new MessageSourceAccessor(messageSource); - } + public void setMessageSource(MessageSource messageSource) { + this.messages = new MessageSourceAccessor(messageSource); + } } diff --git a/acl/src/main/java/org/springframework/security/acls/afterinvocation/ArrayFilterer.java b/acl/src/main/java/org/springframework/security/acls/afterinvocation/ArrayFilterer.java index 3cdd3c124d..45d782369d 100644 --- a/acl/src/main/java/org/springframework/security/acls/afterinvocation/ArrayFilterer.java +++ b/acl/src/main/java/org/springframework/security/acls/afterinvocation/ArrayFilterer.java @@ -24,7 +24,6 @@ import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; - /** * A filter used to filter arrays. * @@ -32,86 +31,91 @@ import org.apache.commons.logging.LogFactory; * @author Paulo Neves */ class ArrayFilterer implements Filterer { - //~ Static fields/initializers ===================================================================================== + // ~ Static fields/initializers + // ===================================================================================== - protected static final Log logger = LogFactory.getLog(ArrayFilterer.class); + protected static final Log logger = LogFactory.getLog(ArrayFilterer.class); - //~ Instance fields ================================================================================================ + // ~ Instance fields + // ================================================================================================ - private final Set removeList; - private final T[] list; + private final Set removeList; + private final T[] list; - //~ Constructors =================================================================================================== + // ~ Constructors + // =================================================================================================== - ArrayFilterer(T[] list) { - this.list = list; + ArrayFilterer(T[] list) { + this.list = list; - // Collect the removed objects to a HashSet so that - // it is fast to lookup them when a filtered array - // is constructed. - removeList = new HashSet(); - } + // Collect the removed objects to a HashSet so that + // it is fast to lookup them when a filtered array + // is constructed. + removeList = new HashSet(); + } - //~ Methods ======================================================================================================== + // ~ Methods + // ======================================================================================================== - /** - * - * @see org.springframework.security.acls.afterinvocation.Filterer#getFilteredObject() - */ - @SuppressWarnings("unchecked") - public T[] getFilteredObject() { - // Recreate an array of same type and filter the removed objects. - int originalSize = list.length; - int sizeOfResultingList = originalSize - removeList.size(); - T[] filtered = (T[]) Array.newInstance(list.getClass().getComponentType(), sizeOfResultingList); + /** + * + * @see org.springframework.security.acls.afterinvocation.Filterer#getFilteredObject() + */ + @SuppressWarnings("unchecked") + public T[] getFilteredObject() { + // Recreate an array of same type and filter the removed objects. + int originalSize = list.length; + int sizeOfResultingList = originalSize - removeList.size(); + T[] filtered = (T[]) Array.newInstance(list.getClass().getComponentType(), + sizeOfResultingList); - for (int i = 0, j = 0; i < list.length; i++) { - T object = list[i]; + for (int i = 0, j = 0; i < list.length; i++) { + T object = list[i]; - if (!removeList.contains(object)) { - filtered[j] = object; - j++; - } - } + if (!removeList.contains(object)) { + filtered[j] = object; + j++; + } + } - if (logger.isDebugEnabled()) { - logger.debug("Original array contained " + originalSize + " elements; now contains " + sizeOfResultingList - + " elements"); - } + if (logger.isDebugEnabled()) { + logger.debug("Original array contained " + originalSize + + " elements; now contains " + sizeOfResultingList + " elements"); + } - return filtered; - } + return filtered; + } - /** - * - * @see org.springframework.security.acls.afterinvocation.Filterer#iterator() - */ - public Iterator iterator() { - return new Iterator() { - private int index = 0; + /** + * + * @see org.springframework.security.acls.afterinvocation.Filterer#iterator() + */ + public Iterator iterator() { + return new Iterator() { + private int index = 0; - public boolean hasNext() { - return index < list.length; - } + public boolean hasNext() { + return index < list.length; + } - public T next() { - if (!hasNext()) { - throw new NoSuchElementException(); - } - return list[index++]; - } + public T next() { + if (!hasNext()) { + throw new NoSuchElementException(); + } + return list[index++]; + } - public void remove() { - throw new UnsupportedOperationException(); - } - }; - } + public void remove() { + throw new UnsupportedOperationException(); + } + }; + } - /** - * - * @see org.springframework.security.acls.afterinvocation.Filterer#remove(java.lang.Object) - */ - public void remove(T object) { - removeList.add(object); - } + /** + * + * @see org.springframework.security.acls.afterinvocation.Filterer#remove(java.lang.Object) + */ + public void remove(T object) { + removeList.add(object); + } } diff --git a/acl/src/main/java/org/springframework/security/acls/afterinvocation/CollectionFilterer.java b/acl/src/main/java/org/springframework/security/acls/afterinvocation/CollectionFilterer.java index 7a01322a49..58fcc9a400 100644 --- a/acl/src/main/java/org/springframework/security/acls/afterinvocation/CollectionFilterer.java +++ b/acl/src/main/java/org/springframework/security/acls/afterinvocation/CollectionFilterer.java @@ -23,7 +23,6 @@ import java.util.HashSet; import java.util.Iterator; import java.util.Set; - /** * A filter used to filter Collections. * @@ -31,68 +30,72 @@ import java.util.Set; * @author Paulo Neves */ class CollectionFilterer implements Filterer { - //~ Static fields/initializers ===================================================================================== + // ~ Static fields/initializers + // ===================================================================================== - protected static final Log logger = LogFactory.getLog(CollectionFilterer.class); + protected static final Log logger = LogFactory.getLog(CollectionFilterer.class); - //~ Instance fields ================================================================================================ + // ~ Instance fields + // ================================================================================================ - private final Collection collection; + private final Collection collection; - private final Set removeList; + private final Set removeList; - //~ Constructors =================================================================================================== + // ~ Constructors + // =================================================================================================== - CollectionFilterer(Collection collection) { - this.collection = collection; + CollectionFilterer(Collection collection) { + this.collection = collection; - // We create a Set of objects to be removed from the Collection, - // as ConcurrentModificationException prevents removal during - // iteration, and making a new Collection to be returned is - // problematic as the original Collection implementation passed - // to the method may not necessarily be re-constructable (as - // the Collection(collection) constructor is not guaranteed and - // manually adding may lose sort order or other capabilities) - removeList = new HashSet(); - } + // We create a Set of objects to be removed from the Collection, + // as ConcurrentModificationException prevents removal during + // iteration, and making a new Collection to be returned is + // problematic as the original Collection implementation passed + // to the method may not necessarily be re-constructable (as + // the Collection(collection) constructor is not guaranteed and + // manually adding may lose sort order or other capabilities) + removeList = new HashSet(); + } - //~ Methods ======================================================================================================== + // ~ Methods + // ======================================================================================================== - /** - * - * @see org.springframework.security.acls.afterinvocation.Filterer#getFilteredObject() - */ - public Object getFilteredObject() { - // Now the Iterator has ended, remove Objects from Collection - Iterator removeIter = removeList.iterator(); + /** + * + * @see org.springframework.security.acls.afterinvocation.Filterer#getFilteredObject() + */ + public Object getFilteredObject() { + // Now the Iterator has ended, remove Objects from Collection + Iterator removeIter = removeList.iterator(); - int originalSize = collection.size(); + int originalSize = collection.size(); - while (removeIter.hasNext()) { - collection.remove(removeIter.next()); - } + while (removeIter.hasNext()) { + collection.remove(removeIter.next()); + } - if (logger.isDebugEnabled()) { - logger.debug("Original collection contained " + originalSize + " elements; now contains " - + collection.size() + " elements"); - } + if (logger.isDebugEnabled()) { + logger.debug("Original collection contained " + originalSize + + " elements; now contains " + collection.size() + " elements"); + } - return collection; - } + return collection; + } - /** - * - * @see org.springframework.security.acls.afterinvocation.Filterer#iterator() - */ - public Iterator iterator() { - return collection.iterator(); - } + /** + * + * @see org.springframework.security.acls.afterinvocation.Filterer#iterator() + */ + public Iterator iterator() { + return collection.iterator(); + } - /** - * - * @see org.springframework.security.acls.afterinvocation.Filterer#remove(java.lang.Object) - */ - public void remove(T object) { - removeList.add(object); - } + /** + * + * @see org.springframework.security.acls.afterinvocation.Filterer#remove(java.lang.Object) + */ + public void remove(T object) { + removeList.add(object); + } } diff --git a/acl/src/main/java/org/springframework/security/acls/afterinvocation/Filterer.java b/acl/src/main/java/org/springframework/security/acls/afterinvocation/Filterer.java index 9c7f685ac0..610d7b6f45 100644 --- a/acl/src/main/java/org/springframework/security/acls/afterinvocation/Filterer.java +++ b/acl/src/main/java/org/springframework/security/acls/afterinvocation/Filterer.java @@ -17,7 +17,6 @@ package org.springframework.security.acls.afterinvocation; import java.util.Iterator; - /** * Filterer strategy interface. * @@ -25,26 +24,27 @@ import java.util.Iterator; * @author Paulo Neves */ interface Filterer extends Iterable { - //~ Methods ======================================================================================================== + // ~ Methods + // ======================================================================================================== - /** - * Gets the filtered collection or array. - * - * @return the filtered collection or array - */ - Object getFilteredObject(); + /** + * Gets the filtered collection or array. + * + * @return the filtered collection or array + */ + Object getFilteredObject(); - /** - * Returns an iterator over the filtered collection or array. - * - * @return an Iterator - */ - Iterator iterator(); + /** + * Returns an iterator over the filtered collection or array. + * + * @return an Iterator + */ + Iterator iterator(); - /** - * Removes the the given object from the resulting list. - * - * @param object the object to be removed - */ - void remove(T object); + /** + * Removes the the given object from the resulting list. + * + * @param object the object to be removed + */ + void remove(T object); } diff --git a/acl/src/main/java/org/springframework/security/acls/domain/AbstractPermission.java b/acl/src/main/java/org/springframework/security/acls/domain/AbstractPermission.java index 8d55f75fac..575ad5361a 100644 --- a/acl/src/main/java/org/springframework/security/acls/domain/AbstractPermission.java +++ b/acl/src/main/java/org/springframework/security/acls/domain/AbstractPermission.java @@ -10,63 +10,67 @@ import org.springframework.security.acls.model.Permission; */ public abstract class AbstractPermission implements Permission { - //~ Instance fields ================================================================================================ + // ~ Instance fields + // ================================================================================================ - protected final char code; - protected int mask; + protected final char code; + protected int mask; - //~ Constructors =================================================================================================== - /** - * Sets the permission mask and uses the '*' character to represent active bits when represented as a bit - * pattern string. - * - * @param mask the integer bit mask for the permission - */ - protected AbstractPermission(int mask) { - this.mask = mask; - this.code = '*'; - } + // ~ Constructors + // =================================================================================================== + /** + * Sets the permission mask and uses the '*' character to represent active bits when + * represented as a bit pattern string. + * + * @param mask the integer bit mask for the permission + */ + protected AbstractPermission(int mask) { + this.mask = mask; + this.code = '*'; + } - /** - * Sets the permission mask and uses the specified character for active bits. - * - * @param mask the integer bit mask for the permission - * @param code the character to print for each active bit in the mask (see {@link Permission#getPattern()}) - */ - protected AbstractPermission(int mask, char code) { - this.mask = mask; - this.code = code; - } + /** + * Sets the permission mask and uses the specified character for active bits. + * + * @param mask the integer bit mask for the permission + * @param code the character to print for each active bit in the mask (see + * {@link Permission#getPattern()}) + */ + protected AbstractPermission(int mask, char code) { + this.mask = mask; + this.code = code; + } - //~ Methods ======================================================================================================== + // ~ Methods + // ======================================================================================================== - public final boolean equals(Object arg0) { - if (arg0 == null) { - return false; - } + public final boolean equals(Object arg0) { + if (arg0 == null) { + return false; + } - if (!(arg0 instanceof Permission)) { - return false; - } + if (!(arg0 instanceof Permission)) { + return false; + } - Permission rhs = (Permission) arg0; + Permission rhs = (Permission) arg0; - return (this.mask == rhs.getMask()); - } + return (this.mask == rhs.getMask()); + } - public final int getMask() { - return mask; - } + public final int getMask() { + return mask; + } - public String getPattern() { - return AclFormattingUtils.printBinary(mask, code); - } + public String getPattern() { + return AclFormattingUtils.printBinary(mask, code); + } - public final String toString() { - return this.getClass().getSimpleName() + "[" + getPattern() + "=" + mask + "]"; - } + public final String toString() { + return this.getClass().getSimpleName() + "[" + getPattern() + "=" + mask + "]"; + } - public final int hashCode() { - return this.mask; - } + public final int hashCode() { + return this.mask; + } } diff --git a/acl/src/main/java/org/springframework/security/acls/domain/AccessControlEntryImpl.java b/acl/src/main/java/org/springframework/security/acls/domain/AccessControlEntryImpl.java index b19a9f6f2d..faa9189458 100644 --- a/acl/src/main/java/org/springframework/security/acls/domain/AccessControlEntryImpl.java +++ b/acl/src/main/java/org/springframework/security/acls/domain/AccessControlEntryImpl.java @@ -24,151 +24,161 @@ import org.springframework.util.Assert; import java.io.Serializable; - /** * An immutable default implementation of AccessControlEntry. * * @author Ben Alex */ -public class AccessControlEntryImpl implements AccessControlEntry, AuditableAccessControlEntry { - //~ Instance fields ================================================================================================ +public class AccessControlEntryImpl implements AccessControlEntry, + AuditableAccessControlEntry { + // ~ Instance fields + // ================================================================================================ - private final Acl acl; - private Permission permission; - private final Serializable id; - private final Sid sid; - private boolean auditFailure = false; - private boolean auditSuccess = false; - private final boolean granting; + private final Acl acl; + private Permission permission; + private final Serializable id; + private final Sid sid; + private boolean auditFailure = false; + private boolean auditSuccess = false; + private final boolean granting; - //~ Constructors =================================================================================================== + // ~ Constructors + // =================================================================================================== - public AccessControlEntryImpl(Serializable id, Acl acl, Sid sid, Permission permission, boolean granting, - boolean auditSuccess, boolean auditFailure) { - Assert.notNull(acl, "Acl required"); - Assert.notNull(sid, "Sid required"); - Assert.notNull(permission, "Permission required"); - this.id = id; - this.acl = acl; // can be null - this.sid = sid; - this.permission = permission; - this.granting = granting; - this.auditSuccess = auditSuccess; - this.auditFailure = auditFailure; - } + public AccessControlEntryImpl(Serializable id, Acl acl, Sid sid, + Permission permission, boolean granting, boolean auditSuccess, + boolean auditFailure) { + Assert.notNull(acl, "Acl required"); + Assert.notNull(sid, "Sid required"); + Assert.notNull(permission, "Permission required"); + this.id = id; + this.acl = acl; // can be null + this.sid = sid; + this.permission = permission; + this.granting = granting; + this.auditSuccess = auditSuccess; + this.auditFailure = auditFailure; + } - //~ Methods ======================================================================================================== + // ~ Methods + // ======================================================================================================== - public boolean equals(Object arg0) { - if (!(arg0 instanceof AccessControlEntryImpl)) { - return false; - } + public boolean equals(Object arg0) { + if (!(arg0 instanceof AccessControlEntryImpl)) { + return false; + } - AccessControlEntryImpl rhs = (AccessControlEntryImpl) arg0; + AccessControlEntryImpl rhs = (AccessControlEntryImpl) arg0; - if (this.acl == null) { - if (rhs.getAcl() != null) { - return false; - } - // Both this.acl and rhs.acl are null and thus equal - } else { - // this.acl is non-null - if (rhs.getAcl() == null) { - return false; - } + if (this.acl == null) { + if (rhs.getAcl() != null) { + return false; + } + // Both this.acl and rhs.acl are null and thus equal + } + else { + // this.acl is non-null + if (rhs.getAcl() == null) { + return false; + } - // Both this.acl and rhs.acl are non-null, so do a comparison - if (this.acl.getObjectIdentity() == null) { - if (rhs.acl.getObjectIdentity() != null) { - return false; - } - // Both this.acl and rhs.acl are null and thus equal - } else { - // Both this.acl.objectIdentity and rhs.acl.objectIdentity are non-null - if (!this.acl.getObjectIdentity().equals(rhs.getAcl().getObjectIdentity())) { - return false; - } - } - } + // Both this.acl and rhs.acl are non-null, so do a comparison + if (this.acl.getObjectIdentity() == null) { + if (rhs.acl.getObjectIdentity() != null) { + return false; + } + // Both this.acl and rhs.acl are null and thus equal + } + else { + // Both this.acl.objectIdentity and rhs.acl.objectIdentity are non-null + if (!this.acl.getObjectIdentity() + .equals(rhs.getAcl().getObjectIdentity())) { + return false; + } + } + } - if (this.id == null) { - if (rhs.id != null) { - return false; - } - // Both this.id and rhs.id are null and thus equal - } else { - // this.id is non-null - if (rhs.id == null) { - return false; - } + if (this.id == null) { + if (rhs.id != null) { + return false; + } + // Both this.id and rhs.id are null and thus equal + } + else { + // this.id is non-null + if (rhs.id == null) { + return false; + } - // Both this.id and rhs.id are non-null - if (!this.id.equals(rhs.id)) { - return false; - } - } + // Both this.id and rhs.id are non-null + if (!this.id.equals(rhs.id)) { + return false; + } + } - if ((this.auditFailure != rhs.isAuditFailure()) || (this.auditSuccess != rhs.isAuditSuccess()) - || (this.granting != rhs.isGranting()) - || !this.permission.equals(rhs.getPermission()) || !this.sid.equals(rhs.getSid())) { - return false; - } + if ((this.auditFailure != rhs.isAuditFailure()) + || (this.auditSuccess != rhs.isAuditSuccess()) + || (this.granting != rhs.isGranting()) + || !this.permission.equals(rhs.getPermission()) + || !this.sid.equals(rhs.getSid())) { + return false; + } - return true; - } + return true; + } - public Acl getAcl() { - return acl; - } + public Acl getAcl() { + return acl; + } - public Serializable getId() { - return id; - } + public Serializable getId() { + return id; + } - public Permission getPermission() { - return permission; - } + public Permission getPermission() { + return permission; + } - public Sid getSid() { - return sid; - } + public Sid getSid() { + return sid; + } - public boolean isAuditFailure() { - return auditFailure; - } + public boolean isAuditFailure() { + return auditFailure; + } - public boolean isAuditSuccess() { - return auditSuccess; - } + public boolean isAuditSuccess() { + return auditSuccess; + } - public boolean isGranting() { - return granting; - } + public boolean isGranting() { + return granting; + } - void setAuditFailure(boolean auditFailure) { - this.auditFailure = auditFailure; - } + void setAuditFailure(boolean auditFailure) { + this.auditFailure = auditFailure; + } - void setAuditSuccess(boolean auditSuccess) { - this.auditSuccess = auditSuccess; - } + void setAuditSuccess(boolean auditSuccess) { + this.auditSuccess = auditSuccess; + } - void setPermission(Permission permission) { - Assert.notNull(permission, "Permission required"); - this.permission = permission; - } + void setPermission(Permission permission) { + Assert.notNull(permission, "Permission required"); + this.permission = permission; + } - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("AccessControlEntryImpl["); - sb.append("id: ").append(this.id).append("; "); - sb.append("granting: ").append(this.granting).append("; "); - sb.append("sid: ").append(this.sid).append("; "); - sb.append("permission: ").append(this.permission).append("; "); - sb.append("auditSuccess: ").append(this.auditSuccess).append("; "); - sb.append("auditFailure: ").append(this.auditFailure); - sb.append("]"); + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("AccessControlEntryImpl["); + sb.append("id: ").append(this.id).append("; "); + sb.append("granting: ").append(this.granting).append("; "); + sb.append("sid: ").append(this.sid).append("; "); + sb.append("permission: ").append(this.permission).append("; "); + sb.append("auditSuccess: ").append(this.auditSuccess).append("; "); + sb.append("auditFailure: ").append(this.auditFailure); + sb.append("]"); - return sb.toString(); - } + return sb.toString(); + } } diff --git a/acl/src/main/java/org/springframework/security/acls/domain/AclAuthorizationStrategy.java b/acl/src/main/java/org/springframework/security/acls/domain/AclAuthorizationStrategy.java index a5cfcbd253..0541c16252 100644 --- a/acl/src/main/java/org/springframework/security/acls/domain/AclAuthorizationStrategy.java +++ b/acl/src/main/java/org/springframework/security/acls/domain/AclAuthorizationStrategy.java @@ -17,7 +17,6 @@ package org.springframework.security.acls.domain; import org.springframework.security.acls.model.Acl; - /** * Strategy used by {@link AclImpl} to determine whether a principal is permitted to call * adminstrative methods on the AclImpl. @@ -25,13 +24,15 @@ import org.springframework.security.acls.model.Acl; * @author Ben Alex */ public interface AclAuthorizationStrategy { - //~ Static fields/initializers ===================================================================================== + // ~ Static fields/initializers + // ===================================================================================== - int CHANGE_OWNERSHIP = 0; - int CHANGE_AUDITING = 1; - int CHANGE_GENERAL = 2; + int CHANGE_OWNERSHIP = 0; + int CHANGE_AUDITING = 1; + int CHANGE_GENERAL = 2; - //~ Methods ======================================================================================================== + // ~ Methods + // ======================================================================================================== - void securityCheck(Acl acl, int changeType); + void securityCheck(Acl acl, int changeType); } diff --git a/acl/src/main/java/org/springframework/security/acls/domain/AclAuthorizationStrategyImpl.java b/acl/src/main/java/org/springframework/security/acls/domain/AclAuthorizationStrategyImpl.java index 46e5601b0b..6514cd655e 100644 --- a/acl/src/main/java/org/springframework/security/acls/domain/AclAuthorizationStrategyImpl.java +++ b/acl/src/main/java/org/springframework/security/acls/domain/AclAuthorizationStrategyImpl.java @@ -27,115 +27,124 @@ import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.util.Assert; - /** * Default implementation of {@link AclAuthorizationStrategy}. *

- * Permission will be granted if at least one of the following conditions is true for the current - * principal. + * Permission will be granted if at least one of the following conditions is true for the + * current principal. *

    - *
  • is the owner (as defined by the ACL).
  • - *
  • holds the relevant system-wide {@link GrantedAuthority} injected into the - * constructor.
  • - *
  • has {@link BasePermission#ADMINISTRATION} permission (as defined by the ACL).
  • + *
  • is the owner (as defined by the ACL).
  • + *
  • holds the relevant system-wide {@link GrantedAuthority} injected into the + * constructor.
  • + *
  • has {@link BasePermission#ADMINISTRATION} permission (as defined by the ACL).
  • *
* * @author Ben Alex */ public class AclAuthorizationStrategyImpl implements AclAuthorizationStrategy { - //~ Instance fields ================================================================================================ + // ~ Instance fields + // ================================================================================================ - private final GrantedAuthority gaGeneralChanges; - private final GrantedAuthority gaModifyAuditing; - private final GrantedAuthority gaTakeOwnership; - private SidRetrievalStrategy sidRetrievalStrategy = new SidRetrievalStrategyImpl(); + private final GrantedAuthority gaGeneralChanges; + private final GrantedAuthority gaModifyAuditing; + private final GrantedAuthority gaTakeOwnership; + private SidRetrievalStrategy sidRetrievalStrategy = new SidRetrievalStrategyImpl(); - //~ Constructors =================================================================================================== + // ~ Constructors + // =================================================================================================== - /** - * Constructor. The only mandatory parameter relates to the system-wide {@link GrantedAuthority} instances that - * can be held to always permit ACL changes. - * - * @param auths the GrantedAuthoritys that have - * special permissions (index 0 is the authority needed to change - * ownership, index 1 is the authority needed to modify auditing details, - * index 2 is the authority needed to change other ACL and ACE details) (required) - *

- * Alternatively, a single value can be supplied for all three permissions. - */ - public AclAuthorizationStrategyImpl(GrantedAuthority... auths) { - Assert.isTrue(auths != null && (auths.length == 3 || auths.length == 1), - "One or three GrantedAuthority instances required"); - if (auths.length == 3) { - gaTakeOwnership = auths[0]; - gaModifyAuditing = auths[1]; - gaGeneralChanges = auths[2]; - } else { - gaTakeOwnership = gaModifyAuditing = gaGeneralChanges = auths[0]; - } - } + /** + * Constructor. The only mandatory parameter relates to the system-wide + * {@link GrantedAuthority} instances that can be held to always permit ACL changes. + * + * @param auths the GrantedAuthoritys that have special permissions + * (index 0 is the authority needed to change ownership, index 1 is the authority + * needed to modify auditing details, index 2 is the authority needed to change other + * ACL and ACE details) (required) + *

+ * Alternatively, a single value can be supplied for all three permissions. + */ + public AclAuthorizationStrategyImpl(GrantedAuthority... auths) { + Assert.isTrue(auths != null && (auths.length == 3 || auths.length == 1), + "One or three GrantedAuthority instances required"); + if (auths.length == 3) { + gaTakeOwnership = auths[0]; + gaModifyAuditing = auths[1]; + gaGeneralChanges = auths[2]; + } + else { + gaTakeOwnership = gaModifyAuditing = gaGeneralChanges = auths[0]; + } + } - //~ Methods ======================================================================================================== + // ~ Methods + // ======================================================================================================== - public void securityCheck(Acl acl, int changeType) { - if ((SecurityContextHolder.getContext() == null) - || (SecurityContextHolder.getContext().getAuthentication() == null) - || !SecurityContextHolder.getContext().getAuthentication().isAuthenticated()) { - throw new AccessDeniedException("Authenticated principal required to operate with ACLs"); - } + public void securityCheck(Acl acl, int changeType) { + if ((SecurityContextHolder.getContext() == null) + || (SecurityContextHolder.getContext().getAuthentication() == null) + || !SecurityContextHolder.getContext().getAuthentication() + .isAuthenticated()) { + throw new AccessDeniedException( + "Authenticated principal required to operate with ACLs"); + } - Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Authentication authentication = SecurityContextHolder.getContext() + .getAuthentication(); - // Check if authorized by virtue of ACL ownership - Sid currentUser = createCurrentUser(authentication); + // Check if authorized by virtue of ACL ownership + Sid currentUser = createCurrentUser(authentication); - if (currentUser.equals(acl.getOwner()) - && ((changeType == CHANGE_GENERAL) || (changeType == CHANGE_OWNERSHIP))) { - return; - } + if (currentUser.equals(acl.getOwner()) + && ((changeType == CHANGE_GENERAL) || (changeType == CHANGE_OWNERSHIP))) { + return; + } - // Not authorized by ACL ownership; try via adminstrative permissions - GrantedAuthority requiredAuthority; + // Not authorized by ACL ownership; try via adminstrative permissions + GrantedAuthority requiredAuthority; - if (changeType == CHANGE_AUDITING) { - requiredAuthority = this.gaModifyAuditing; - } else if (changeType == CHANGE_GENERAL) { - requiredAuthority = this.gaGeneralChanges; - } else if (changeType == CHANGE_OWNERSHIP) { - requiredAuthority = this.gaTakeOwnership; - } else { - throw new IllegalArgumentException("Unknown change type"); - } + if (changeType == CHANGE_AUDITING) { + requiredAuthority = this.gaModifyAuditing; + } + else if (changeType == CHANGE_GENERAL) { + requiredAuthority = this.gaGeneralChanges; + } + else if (changeType == CHANGE_OWNERSHIP) { + requiredAuthority = this.gaTakeOwnership; + } + else { + throw new IllegalArgumentException("Unknown change type"); + } - // Iterate this principal's authorities to determine right - if (authentication.getAuthorities().contains(requiredAuthority)) { - return; - } + // Iterate this principal's authorities to determine right + if (authentication.getAuthorities().contains(requiredAuthority)) { + return; + } - // Try to get permission via ACEs within the ACL - List sids = sidRetrievalStrategy.getSids(authentication); + // Try to get permission via ACEs within the ACL + List sids = sidRetrievalStrategy.getSids(authentication); - if (acl.isGranted(Arrays.asList(BasePermission.ADMINISTRATION), sids, false)) { - return; - } + if (acl.isGranted(Arrays.asList(BasePermission.ADMINISTRATION), sids, false)) { + return; + } - throw new AccessDeniedException( - "Principal does not have required ACL permissions to perform requested operation"); - } + throw new AccessDeniedException( + "Principal does not have required ACL permissions to perform requested operation"); + } - /** - * Creates a principal-like sid from the authentication information. - * - * @param authentication the authentication information that can provide principal and thus the sid's id will be - * dependant on the value inside - * @return a sid with the ID taken from the authentication information - */ - protected Sid createCurrentUser(Authentication authentication) { - return new PrincipalSid(authentication); - } + /** + * Creates a principal-like sid from the authentication information. + * + * @param authentication the authentication information that can provide principal and + * thus the sid's id will be dependant on the value inside + * @return a sid with the ID taken from the authentication information + */ + protected Sid createCurrentUser(Authentication authentication) { + return new PrincipalSid(authentication); + } - public void setSidRetrievalStrategy(SidRetrievalStrategy sidRetrievalStrategy) { - Assert.notNull(sidRetrievalStrategy, "SidRetrievalStrategy required"); - this.sidRetrievalStrategy = sidRetrievalStrategy; - } + public void setSidRetrievalStrategy(SidRetrievalStrategy sidRetrievalStrategy) { + Assert.notNull(sidRetrievalStrategy, "SidRetrievalStrategy required"); + this.sidRetrievalStrategy = sidRetrievalStrategy; + } } diff --git a/acl/src/main/java/org/springframework/security/acls/domain/AclFormattingUtils.java b/acl/src/main/java/org/springframework/security/acls/domain/AclFormattingUtils.java index 229f60be8b..04c663e7e0 100644 --- a/acl/src/main/java/org/springframework/security/acls/domain/AclFormattingUtils.java +++ b/acl/src/main/java/org/springframework/security/acls/domain/AclFormattingUtils.java @@ -17,7 +17,6 @@ package org.springframework.security.acls.domain; import org.springframework.security.acls.model.Permission; import org.springframework.util.Assert; - /** * Utility methods for displaying ACL information. * @@ -25,83 +24,88 @@ import org.springframework.util.Assert; */ public abstract class AclFormattingUtils { - public static String demergePatterns(String original, String removeBits) { - Assert.notNull(original, "Original string required"); - Assert.notNull(removeBits, "Bits To Remove string required"); - Assert.isTrue(original.length() == removeBits.length(), - "Original and Bits To Remove strings must be identical length"); + public static String demergePatterns(String original, String removeBits) { + Assert.notNull(original, "Original string required"); + Assert.notNull(removeBits, "Bits To Remove string required"); + Assert.isTrue(original.length() == removeBits.length(), + "Original and Bits To Remove strings must be identical length"); - char[] replacement = new char[original.length()]; + char[] replacement = new char[original.length()]; - for (int i = 0; i < original.length(); i++) { - if (removeBits.charAt(i) == Permission.RESERVED_OFF) { - replacement[i] = original.charAt(i); - } else { - replacement[i] = Permission.RESERVED_OFF; - } - } + for (int i = 0; i < original.length(); i++) { + if (removeBits.charAt(i) == Permission.RESERVED_OFF) { + replacement[i] = original.charAt(i); + } + else { + replacement[i] = Permission.RESERVED_OFF; + } + } - return new String(replacement); - } + return new String(replacement); + } - public static String mergePatterns(String original, String extraBits) { - Assert.notNull(original, "Original string required"); - Assert.notNull(extraBits, "Extra Bits string required"); - Assert.isTrue(original.length() == extraBits.length(), - "Original and Extra Bits strings must be identical length"); + public static String mergePatterns(String original, String extraBits) { + Assert.notNull(original, "Original string required"); + Assert.notNull(extraBits, "Extra Bits string required"); + Assert.isTrue(original.length() == extraBits.length(), + "Original and Extra Bits strings must be identical length"); - char[] replacement = new char[extraBits.length()]; + char[] replacement = new char[extraBits.length()]; - for (int i = 0; i < extraBits.length(); i++) { - if (extraBits.charAt(i) == Permission.RESERVED_OFF) { - replacement[i] = original.charAt(i); - } else { - replacement[i] = extraBits.charAt(i); - } - } + for (int i = 0; i < extraBits.length(); i++) { + if (extraBits.charAt(i) == Permission.RESERVED_OFF) { + replacement[i] = original.charAt(i); + } + else { + replacement[i] = extraBits.charAt(i); + } + } - return new String(replacement); - } + return new String(replacement); + } - /** - * Returns a representation of the active bits in the presented mask, with each active bit being denoted by - * character '*'. - *

- * Inactive bits will be denoted by character {@link Permission#RESERVED_OFF}. - * - * @param i the integer bit mask to print the active bits for - * - * @return a 32-character representation of the bit mask - */ - public static String printBinary(int i) { - return printBinary(i, '*', Permission.RESERVED_OFF); - } + /** + * Returns a representation of the active bits in the presented mask, with each active + * bit being denoted by character '*'. + *

+ * Inactive bits will be denoted by character {@link Permission#RESERVED_OFF}. + * + * @param i the integer bit mask to print the active bits for + * + * @return a 32-character representation of the bit mask + */ + public static String printBinary(int i) { + return printBinary(i, '*', Permission.RESERVED_OFF); + } - /** - * Returns a representation of the active bits in the presented mask, with each active bit being denoted by - * the passed character. - *

- * Inactive bits will be denoted by character {@link Permission#RESERVED_OFF}. - * - * @param mask the integer bit mask to print the active bits for - * @param code the character to print when an active bit is detected - * - * @return a 32-character representation of the bit mask - */ - public static String printBinary(int mask, char code) { - Assert.doesNotContain(Character.toString(code), Character.toString(Permission.RESERVED_ON), - Permission.RESERVED_ON + " is a reserved character code"); - Assert.doesNotContain(Character.toString(code), Character.toString(Permission.RESERVED_OFF), - Permission.RESERVED_OFF + " is a reserved character code"); + /** + * Returns a representation of the active bits in the presented mask, with each active + * bit being denoted by the passed character. + *

+ * Inactive bits will be denoted by character {@link Permission#RESERVED_OFF}. + * + * @param mask the integer bit mask to print the active bits for + * @param code the character to print when an active bit is detected + * + * @return a 32-character representation of the bit mask + */ + public static String printBinary(int mask, char code) { + Assert.doesNotContain(Character.toString(code), + Character.toString(Permission.RESERVED_ON), Permission.RESERVED_ON + + " is a reserved character code"); + Assert.doesNotContain(Character.toString(code), + Character.toString(Permission.RESERVED_OFF), Permission.RESERVED_OFF + + " is a reserved character code"); - return printBinary(mask, Permission.RESERVED_ON, Permission.RESERVED_OFF).replace(Permission.RESERVED_ON, code); - } + return printBinary(mask, Permission.RESERVED_ON, Permission.RESERVED_OFF) + .replace(Permission.RESERVED_ON, code); + } - private static String printBinary(int i, char on, char off) { - String s = Integer.toBinaryString(i); - String pattern = Permission.THIRTY_TWO_RESERVED_OFF; - String temp2 = pattern.substring(0, pattern.length() - s.length()) + s; + private static String printBinary(int i, char on, char off) { + String s = Integer.toBinaryString(i); + String pattern = Permission.THIRTY_TWO_RESERVED_OFF; + String temp2 = pattern.substring(0, pattern.length() - s.length()) + s; - return temp2.replace('0', off).replace('1', on); - } + return temp2.replace('0', off).replace('1', on); + } } diff --git a/acl/src/main/java/org/springframework/security/acls/domain/AclImpl.java b/acl/src/main/java/org/springframework/security/acls/domain/AclImpl.java index b6f915c0ab..9f6b94623d 100644 --- a/acl/src/main/java/org/springframework/security/acls/domain/AclImpl.java +++ b/acl/src/main/java/org/springframework/security/acls/domain/AclImpl.java @@ -31,297 +31,333 @@ import org.springframework.security.acls.model.Sid; import org.springframework.security.acls.model.UnloadedSidException; import org.springframework.util.Assert; - /** * Base implementation of Acl. * * @author Ben Alex */ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl { - //~ Instance fields ================================================================================================ + // ~ Instance fields + // ================================================================================================ - private Acl parentAcl; - private transient AclAuthorizationStrategy aclAuthorizationStrategy; - private transient PermissionGrantingStrategy permissionGrantingStrategy; - private final List aces = new ArrayList(); - private ObjectIdentity objectIdentity; - private Serializable id; - private Sid owner; // OwnershipAcl - private List loadedSids = null; // includes all SIDs the WHERE clause covered, even if there was no ACE for a SID - private boolean entriesInheriting = true; + private Acl parentAcl; + private transient AclAuthorizationStrategy aclAuthorizationStrategy; + private transient PermissionGrantingStrategy permissionGrantingStrategy; + private final List aces = new ArrayList(); + private ObjectIdentity objectIdentity; + private Serializable id; + private Sid owner; // OwnershipAcl + private List loadedSids = null; // includes all SIDs the WHERE clause covered, + // even if there was no ACE for a SID + private boolean entriesInheriting = true; - //~ Constructors =================================================================================================== + // ~ Constructors + // =================================================================================================== - /** - * Minimal constructor, which should be used {@link - * org.springframework.security.acls.model.MutableAclService#createAcl(ObjectIdentity)}. - * - * @param objectIdentity the object identity this ACL relates to (required) - * @param id the primary key assigned to this ACL (required) - * @param aclAuthorizationStrategy authorization strategy (required) - * @param auditLogger audit logger (required) - */ - public AclImpl(ObjectIdentity objectIdentity, Serializable id, AclAuthorizationStrategy aclAuthorizationStrategy, - AuditLogger auditLogger) { - Assert.notNull(objectIdentity, "Object Identity required"); - Assert.notNull(id, "Id required"); - Assert.notNull(aclAuthorizationStrategy, "AclAuthorizationStrategy required"); - Assert.notNull(auditLogger, "AuditLogger required"); - this.objectIdentity = objectIdentity; - this.id = id; - this.aclAuthorizationStrategy = aclAuthorizationStrategy; - this.permissionGrantingStrategy = new DefaultPermissionGrantingStrategy(auditLogger); - } + /** + * Minimal constructor, which should be used + * {@link org.springframework.security.acls.model.MutableAclService#createAcl(ObjectIdentity)} + * . + * + * @param objectIdentity the object identity this ACL relates to (required) + * @param id the primary key assigned to this ACL (required) + * @param aclAuthorizationStrategy authorization strategy (required) + * @param auditLogger audit logger (required) + */ + public AclImpl(ObjectIdentity objectIdentity, Serializable id, + AclAuthorizationStrategy aclAuthorizationStrategy, AuditLogger auditLogger) { + Assert.notNull(objectIdentity, "Object Identity required"); + Assert.notNull(id, "Id required"); + Assert.notNull(aclAuthorizationStrategy, "AclAuthorizationStrategy required"); + Assert.notNull(auditLogger, "AuditLogger required"); + this.objectIdentity = objectIdentity; + this.id = id; + this.aclAuthorizationStrategy = aclAuthorizationStrategy; + this.permissionGrantingStrategy = new DefaultPermissionGrantingStrategy( + auditLogger); + } - /** - * Full constructor, which should be used by persistence tools that do not - * provide field-level access features. - * - * @param objectIdentity the object identity this ACL relates to - * @param id the primary key assigned to this ACL - * @param aclAuthorizationStrategy authorization strategy - * @param grantingStrategy the {@code PermissionGrantingStrategy} which will be used by the {@code isGranted()} method - * @param parentAcl the parent (may be may be {@code null}) - * @param loadedSids the loaded SIDs if only a subset were loaded (may be {@code null}) - * @param entriesInheriting if ACEs from the parent should inherit into - * this ACL - * @param owner the owner (required) - */ - public AclImpl(ObjectIdentity objectIdentity, Serializable id, AclAuthorizationStrategy aclAuthorizationStrategy, - PermissionGrantingStrategy grantingStrategy, Acl parentAcl, List loadedSids, boolean entriesInheriting, Sid owner) { - Assert.notNull(objectIdentity, "Object Identity required"); - Assert.notNull(id, "Id required"); - Assert.notNull(aclAuthorizationStrategy, "AclAuthorizationStrategy required"); - Assert.notNull(owner, "Owner required"); + /** + * Full constructor, which should be used by persistence tools that do not provide + * field-level access features. + * + * @param objectIdentity the object identity this ACL relates to + * @param id the primary key assigned to this ACL + * @param aclAuthorizationStrategy authorization strategy + * @param grantingStrategy the {@code PermissionGrantingStrategy} which will be used + * by the {@code isGranted()} method + * @param parentAcl the parent (may be may be {@code null}) + * @param loadedSids the loaded SIDs if only a subset were loaded (may be {@code null} + * ) + * @param entriesInheriting if ACEs from the parent should inherit into this ACL + * @param owner the owner (required) + */ + public AclImpl(ObjectIdentity objectIdentity, Serializable id, + AclAuthorizationStrategy aclAuthorizationStrategy, + PermissionGrantingStrategy grantingStrategy, Acl parentAcl, + List loadedSids, boolean entriesInheriting, Sid owner) { + Assert.notNull(objectIdentity, "Object Identity required"); + Assert.notNull(id, "Id required"); + Assert.notNull(aclAuthorizationStrategy, "AclAuthorizationStrategy required"); + Assert.notNull(owner, "Owner required"); - this.objectIdentity = objectIdentity; - this.id = id; - this.aclAuthorizationStrategy = aclAuthorizationStrategy; - this.parentAcl = parentAcl; // may be null - this.loadedSids = loadedSids; // may be null - this.entriesInheriting = entriesInheriting; - this.owner = owner; - this.permissionGrantingStrategy = grantingStrategy; - } + this.objectIdentity = objectIdentity; + this.id = id; + this.aclAuthorizationStrategy = aclAuthorizationStrategy; + this.parentAcl = parentAcl; // may be null + this.loadedSids = loadedSids; // may be null + this.entriesInheriting = entriesInheriting; + this.owner = owner; + this.permissionGrantingStrategy = grantingStrategy; + } - /** - * Private no-argument constructor for use by reflection-based persistence - * tools along with field-level access. - */ - @SuppressWarnings("unused") - private AclImpl() {} + /** + * Private no-argument constructor for use by reflection-based persistence tools along + * with field-level access. + */ + @SuppressWarnings("unused") + private AclImpl() { + } - //~ Methods ======================================================================================================== + // ~ Methods + // ======================================================================================================== - public void deleteAce(int aceIndex) throws NotFoundException { - aclAuthorizationStrategy.securityCheck(this, AclAuthorizationStrategy.CHANGE_GENERAL); - verifyAceIndexExists(aceIndex); + public void deleteAce(int aceIndex) throws NotFoundException { + aclAuthorizationStrategy.securityCheck(this, + AclAuthorizationStrategy.CHANGE_GENERAL); + verifyAceIndexExists(aceIndex); - synchronized (aces) { - this.aces.remove(aceIndex); - } - } + synchronized (aces) { + this.aces.remove(aceIndex); + } + } - private void verifyAceIndexExists(int aceIndex) { - if (aceIndex < 0) { - throw new NotFoundException("aceIndex must be greater than or equal to zero"); - } - if (aceIndex >= this.aces.size()) { - throw new NotFoundException("aceIndex must refer to an index of the AccessControlEntry list. " + - "List size is " + aces.size() + ", index was " + aceIndex); - } - } + private void verifyAceIndexExists(int aceIndex) { + if (aceIndex < 0) { + throw new NotFoundException("aceIndex must be greater than or equal to zero"); + } + if (aceIndex >= this.aces.size()) { + throw new NotFoundException( + "aceIndex must refer to an index of the AccessControlEntry list. " + + "List size is " + aces.size() + ", index was " + aceIndex); + } + } - public void insertAce(int atIndexLocation, Permission permission, Sid sid, boolean granting) throws NotFoundException { - aclAuthorizationStrategy.securityCheck(this, AclAuthorizationStrategy.CHANGE_GENERAL); - Assert.notNull(permission, "Permission required"); - Assert.notNull(sid, "Sid required"); - if (atIndexLocation < 0) { - throw new NotFoundException("atIndexLocation must be greater than or equal to zero"); - } - if (atIndexLocation > this.aces.size()) { - throw new NotFoundException("atIndexLocation must be less than or equal to the size of the AccessControlEntry collection"); - } + public void insertAce(int atIndexLocation, Permission permission, Sid sid, + boolean granting) throws NotFoundException { + aclAuthorizationStrategy.securityCheck(this, + AclAuthorizationStrategy.CHANGE_GENERAL); + Assert.notNull(permission, "Permission required"); + Assert.notNull(sid, "Sid required"); + if (atIndexLocation < 0) { + throw new NotFoundException( + "atIndexLocation must be greater than or equal to zero"); + } + if (atIndexLocation > this.aces.size()) { + throw new NotFoundException( + "atIndexLocation must be less than or equal to the size of the AccessControlEntry collection"); + } - AccessControlEntryImpl ace = new AccessControlEntryImpl(null, this, sid, permission, granting, false, false); + AccessControlEntryImpl ace = new AccessControlEntryImpl(null, this, sid, + permission, granting, false, false); - synchronized (aces) { - this.aces.add(atIndexLocation, ace); - } - } + synchronized (aces) { + this.aces.add(atIndexLocation, ace); + } + } - public List getEntries() { - // Can safely return AccessControlEntry directly, as they're immutable outside the ACL package - return new ArrayList(aces); - } + public List getEntries() { + // Can safely return AccessControlEntry directly, as they're immutable outside the + // ACL package + return new ArrayList(aces); + } - public Serializable getId() { - return this.id; - } + public Serializable getId() { + return this.id; + } - public ObjectIdentity getObjectIdentity() { - return objectIdentity; - } + public ObjectIdentity getObjectIdentity() { + return objectIdentity; + } - public boolean isEntriesInheriting() { - return entriesInheriting; - } + public boolean isEntriesInheriting() { + return entriesInheriting; + } - /** - * Delegates to the {@link PermissionGrantingStrategy}. - * - * @throws UnloadedSidException if the passed SIDs are unknown to this ACL because the ACL was only loaded for a - * subset of SIDs - * @see DefaultPermissionGrantingStrategy - */ - public boolean isGranted(List permission, List sids, boolean administrativeMode) - throws NotFoundException, UnloadedSidException { - Assert.notEmpty(permission, "Permissions required"); - Assert.notEmpty(sids, "SIDs required"); + /** + * Delegates to the {@link PermissionGrantingStrategy}. + * + * @throws UnloadedSidException if the passed SIDs are unknown to this ACL because the + * ACL was only loaded for a subset of SIDs + * @see DefaultPermissionGrantingStrategy + */ + public boolean isGranted(List permission, List sids, + boolean administrativeMode) throws NotFoundException, UnloadedSidException { + Assert.notEmpty(permission, "Permissions required"); + Assert.notEmpty(sids, "SIDs required"); - if (!this.isSidLoaded(sids)) { - throw new UnloadedSidException("ACL was not loaded for one or more SID"); - } + if (!this.isSidLoaded(sids)) { + throw new UnloadedSidException("ACL was not loaded for one or more SID"); + } - return permissionGrantingStrategy.isGranted(this, permission, sids, administrativeMode); - } + return permissionGrantingStrategy.isGranted(this, permission, sids, + administrativeMode); + } - public boolean isSidLoaded(List sids) { - // If loadedSides is null, this indicates all SIDs were loaded - // Also return true if the caller didn't specify a SID to find - if ((this.loadedSids == null) || (sids == null) || (sids.size() == 0)) { - return true; - } + public boolean isSidLoaded(List sids) { + // If loadedSides is null, this indicates all SIDs were loaded + // Also return true if the caller didn't specify a SID to find + if ((this.loadedSids == null) || (sids == null) || (sids.size() == 0)) { + return true; + } - // This ACL applies to a SID subset only. Iterate to check it applies. - for (Sid sid: sids) { - boolean found = false; + // This ACL applies to a SID subset only. Iterate to check it applies. + for (Sid sid : sids) { + boolean found = false; - for (Sid loadedSid : loadedSids) { - if (sid.equals(loadedSid)) { - // this SID is OK - found = true; + for (Sid loadedSid : loadedSids) { + if (sid.equals(loadedSid)) { + // this SID is OK + found = true; - break; // out of loadedSids for loop - } - } + break; // out of loadedSids for loop + } + } - if (!found) { - return false; - } - } + if (!found) { + return false; + } + } - return true; - } + return true; + } - public void setEntriesInheriting(boolean entriesInheriting) { - aclAuthorizationStrategy.securityCheck(this, AclAuthorizationStrategy.CHANGE_GENERAL); - this.entriesInheriting = entriesInheriting; - } + public void setEntriesInheriting(boolean entriesInheriting) { + aclAuthorizationStrategy.securityCheck(this, + AclAuthorizationStrategy.CHANGE_GENERAL); + this.entriesInheriting = entriesInheriting; + } - public void setOwner(Sid newOwner) { - aclAuthorizationStrategy.securityCheck(this, AclAuthorizationStrategy.CHANGE_OWNERSHIP); - Assert.notNull(newOwner, "Owner required"); - this.owner = newOwner; - } + public void setOwner(Sid newOwner) { + aclAuthorizationStrategy.securityCheck(this, + AclAuthorizationStrategy.CHANGE_OWNERSHIP); + Assert.notNull(newOwner, "Owner required"); + this.owner = newOwner; + } - public Sid getOwner() { - return this.owner; - } + public Sid getOwner() { + return this.owner; + } - public void setParent(Acl newParent) { - aclAuthorizationStrategy.securityCheck(this, AclAuthorizationStrategy.CHANGE_GENERAL); - Assert.isTrue(newParent == null || !newParent.equals(this), "Cannot be the parent of yourself"); - this.parentAcl = newParent; - } + public void setParent(Acl newParent) { + aclAuthorizationStrategy.securityCheck(this, + AclAuthorizationStrategy.CHANGE_GENERAL); + Assert.isTrue(newParent == null || !newParent.equals(this), + "Cannot be the parent of yourself"); + this.parentAcl = newParent; + } - public Acl getParentAcl() { - return parentAcl; - } + public Acl getParentAcl() { + return parentAcl; + } - public void updateAce(int aceIndex, Permission permission) - throws NotFoundException { - aclAuthorizationStrategy.securityCheck(this, AclAuthorizationStrategy.CHANGE_GENERAL); - verifyAceIndexExists(aceIndex); + public void updateAce(int aceIndex, Permission permission) throws NotFoundException { + aclAuthorizationStrategy.securityCheck(this, + AclAuthorizationStrategy.CHANGE_GENERAL); + verifyAceIndexExists(aceIndex); - synchronized (aces) { - AccessControlEntryImpl ace = (AccessControlEntryImpl) aces.get(aceIndex); - ace.setPermission(permission); - } - } + synchronized (aces) { + AccessControlEntryImpl ace = (AccessControlEntryImpl) aces.get(aceIndex); + ace.setPermission(permission); + } + } - public void updateAuditing(int aceIndex, boolean auditSuccess, boolean auditFailure) { - aclAuthorizationStrategy.securityCheck(this, AclAuthorizationStrategy.CHANGE_AUDITING); - verifyAceIndexExists(aceIndex); + public void updateAuditing(int aceIndex, boolean auditSuccess, boolean auditFailure) { + aclAuthorizationStrategy.securityCheck(this, + AclAuthorizationStrategy.CHANGE_AUDITING); + verifyAceIndexExists(aceIndex); - synchronized (aces) { - AccessControlEntryImpl ace = (AccessControlEntryImpl) aces.get(aceIndex); - ace.setAuditSuccess(auditSuccess); - ace.setAuditFailure(auditFailure); - } - } + synchronized (aces) { + AccessControlEntryImpl ace = (AccessControlEntryImpl) aces.get(aceIndex); + ace.setAuditSuccess(auditSuccess); + ace.setAuditFailure(auditFailure); + } + } - public boolean equals(Object obj) { - if (obj instanceof AclImpl) { - AclImpl rhs = (AclImpl) obj; - if (this.aces.equals(rhs.aces)) { - if ((this.parentAcl == null && rhs.parentAcl == null) || (this.parentAcl !=null && this.parentAcl.equals(rhs.parentAcl))) { - if ((this.objectIdentity == null && rhs.objectIdentity == null) || (this.objectIdentity != null && this.objectIdentity.equals(rhs.objectIdentity))) { - if ((this.id == null && rhs.id == null) || (this.id != null && this.id.equals(rhs.id))) { - if ((this.owner == null && rhs.owner == null) || (this.owner != null && this.owner.equals(rhs.owner))) { - if (this.entriesInheriting == rhs.entriesInheriting) { - if ((this.loadedSids == null && rhs.loadedSids == null)) { - return true; - } - if (this.loadedSids != null && (this.loadedSids.size() == rhs.loadedSids.size())) { - for (int i = 0; i < this.loadedSids.size(); i++) { - if (!this.loadedSids.get(i).equals(rhs.loadedSids.get(i))) { - return false; - } - } - return true; - } - } - } - } - } - } - } - } - return false; - } + public boolean equals(Object obj) { + if (obj instanceof AclImpl) { + AclImpl rhs = (AclImpl) obj; + if (this.aces.equals(rhs.aces)) { + if ((this.parentAcl == null && rhs.parentAcl == null) + || (this.parentAcl != null && this.parentAcl + .equals(rhs.parentAcl))) { + if ((this.objectIdentity == null && rhs.objectIdentity == null) + || (this.objectIdentity != null && this.objectIdentity + .equals(rhs.objectIdentity))) { + if ((this.id == null && rhs.id == null) + || (this.id != null && this.id.equals(rhs.id))) { + if ((this.owner == null && rhs.owner == null) + || (this.owner != null && this.owner + .equals(rhs.owner))) { + if (this.entriesInheriting == rhs.entriesInheriting) { + if ((this.loadedSids == null && rhs.loadedSids == null)) { + return true; + } + if (this.loadedSids != null + && (this.loadedSids.size() == rhs.loadedSids + .size())) { + for (int i = 0; i < this.loadedSids.size(); i++) { + if (!this.loadedSids.get(i).equals( + rhs.loadedSids.get(i))) { + return false; + } + } + return true; + } + } + } + } + } + } + } + } + return false; + } - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("AclImpl["); - sb.append("id: ").append(this.id).append("; "); - sb.append("objectIdentity: ").append(this.objectIdentity).append("; "); - sb.append("owner: ").append(this.owner).append("; "); + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("AclImpl["); + sb.append("id: ").append(this.id).append("; "); + sb.append("objectIdentity: ").append(this.objectIdentity).append("; "); + sb.append("owner: ").append(this.owner).append("; "); - int count = 0; + int count = 0; - for (AccessControlEntry ace : aces) { - count++; + for (AccessControlEntry ace : aces) { + count++; - if (count == 1) { - sb.append("\n"); - } + if (count == 1) { + sb.append("\n"); + } - sb.append(ace).append("\n"); - } + sb.append(ace).append("\n"); + } - if (count == 0) { - sb.append("no ACEs; "); - } + if (count == 0) { + sb.append("no ACEs; "); + } - sb.append("inheriting: ").append(this.entriesInheriting).append("; "); - sb.append("parent: ").append((this.parentAcl == null) ? "Null" : this.parentAcl.getObjectIdentity().toString()); - sb.append("; "); - sb.append("aclAuthorizationStrategy: ").append(this.aclAuthorizationStrategy).append("; "); - sb.append("permissionGrantingStrategy: ").append(this.permissionGrantingStrategy); - sb.append("]"); + sb.append("inheriting: ").append(this.entriesInheriting).append("; "); + sb.append("parent: ").append( + (this.parentAcl == null) ? "Null" : this.parentAcl.getObjectIdentity() + .toString()); + sb.append("; "); + sb.append("aclAuthorizationStrategy: ").append(this.aclAuthorizationStrategy) + .append("; "); + sb.append("permissionGrantingStrategy: ").append(this.permissionGrantingStrategy); + sb.append("]"); - return sb.toString(); - } + return sb.toString(); + } } diff --git a/acl/src/main/java/org/springframework/security/acls/domain/AuditLogger.java b/acl/src/main/java/org/springframework/security/acls/domain/AuditLogger.java index e233cfa99e..4f767639ca 100644 --- a/acl/src/main/java/org/springframework/security/acls/domain/AuditLogger.java +++ b/acl/src/main/java/org/springframework/security/acls/domain/AuditLogger.java @@ -16,7 +16,6 @@ package org.springframework.security.acls.domain; import org.springframework.security.acls.model.AccessControlEntry; - /** * Used by AclImpl to log audit events. * @@ -24,7 +23,8 @@ import org.springframework.security.acls.model.AccessControlEntry; * */ public interface AuditLogger { - //~ Methods ======================================================================================================== + // ~ Methods + // ======================================================================================================== - void logIfNeeded(boolean granted, AccessControlEntry ace); + void logIfNeeded(boolean granted, AccessControlEntry ace); } diff --git a/acl/src/main/java/org/springframework/security/acls/domain/BasePermission.java b/acl/src/main/java/org/springframework/security/acls/domain/BasePermission.java index a1fe8f0fb1..6953027f8e 100644 --- a/acl/src/main/java/org/springframework/security/acls/domain/BasePermission.java +++ b/acl/src/main/java/org/springframework/security/acls/domain/BasePermission.java @@ -16,7 +16,6 @@ package org.springframework.security.acls.domain; import org.springframework.security.acls.model.Permission; - /** * A set of standard permissions. * @@ -28,17 +27,17 @@ import org.springframework.security.acls.model.Permission; * @author Ben Alex */ public class BasePermission extends AbstractPermission { - public static final Permission READ = new BasePermission(1 << 0, 'R'); // 1 - public static final Permission WRITE = new BasePermission(1 << 1, 'W'); // 2 - public static final Permission CREATE = new BasePermission(1 << 2, 'C'); // 4 - public static final Permission DELETE = new BasePermission(1 << 3, 'D'); // 8 - public static final Permission ADMINISTRATION = new BasePermission(1 << 4, 'A'); // 16 + public static final Permission READ = new BasePermission(1 << 0, 'R'); // 1 + public static final Permission WRITE = new BasePermission(1 << 1, 'W'); // 2 + public static final Permission CREATE = new BasePermission(1 << 2, 'C'); // 4 + public static final Permission DELETE = new BasePermission(1 << 3, 'D'); // 8 + public static final Permission ADMINISTRATION = new BasePermission(1 << 4, 'A'); // 16 - protected BasePermission(int mask) { - super(mask); - } + protected BasePermission(int mask) { + super(mask); + } - protected BasePermission(int mask, char code) { - super(mask, code); - } + protected BasePermission(int mask, char code) { + super(mask, code); + } } diff --git a/acl/src/main/java/org/springframework/security/acls/domain/ConsoleAuditLogger.java b/acl/src/main/java/org/springframework/security/acls/domain/ConsoleAuditLogger.java index 5c0b059b02..482f49f71e 100644 --- a/acl/src/main/java/org/springframework/security/acls/domain/ConsoleAuditLogger.java +++ b/acl/src/main/java/org/springframework/security/acls/domain/ConsoleAuditLogger.java @@ -19,26 +19,27 @@ import org.springframework.security.acls.model.AuditableAccessControlEntry; import org.springframework.util.Assert; - /** * A basic implementation of {@link AuditLogger}. * * @author Ben Alex */ public class ConsoleAuditLogger implements AuditLogger { - //~ Methods ======================================================================================================== + // ~ Methods + // ======================================================================================================== - public void logIfNeeded(boolean granted, AccessControlEntry ace) { - Assert.notNull(ace, "AccessControlEntry required"); + public void logIfNeeded(boolean granted, AccessControlEntry ace) { + Assert.notNull(ace, "AccessControlEntry required"); - if (ace instanceof AuditableAccessControlEntry) { - AuditableAccessControlEntry auditableAce = (AuditableAccessControlEntry) ace; + if (ace instanceof AuditableAccessControlEntry) { + AuditableAccessControlEntry auditableAce = (AuditableAccessControlEntry) ace; - if (granted && auditableAce.isAuditSuccess()) { - System.out.println("GRANTED due to ACE: " + ace); - } else if (!granted && auditableAce.isAuditFailure()) { - System.out.println("DENIED due to ACE: " + ace); - } - } - } + if (granted && auditableAce.isAuditSuccess()) { + System.out.println("GRANTED due to ACE: " + ace); + } + else if (!granted && auditableAce.isAuditFailure()) { + System.out.println("DENIED due to ACE: " + ace); + } + } + } } diff --git a/acl/src/main/java/org/springframework/security/acls/domain/CumulativePermission.java b/acl/src/main/java/org/springframework/security/acls/domain/CumulativePermission.java index 554989dabf..158fd4150f 100644 --- a/acl/src/main/java/org/springframework/security/acls/domain/CumulativePermission.java +++ b/acl/src/main/java/org/springframework/security/acls/domain/CumulativePermission.java @@ -16,45 +16,49 @@ package org.springframework.security.acls.domain; import org.springframework.security.acls.model.Permission; - /** - * Represents a Permission that is constructed at runtime from other permissions. + * Represents a Permission that is constructed at runtime from other + * permissions. * - *

Methods return this, in order to facilitate method chaining.

+ *

+ * Methods return this, in order to facilitate method chaining. + *

* * @author Ben Alex */ public class CumulativePermission extends AbstractPermission { - private String pattern = THIRTY_TWO_RESERVED_OFF; + private String pattern = THIRTY_TWO_RESERVED_OFF; - public CumulativePermission() { - super(0, ' '); - } + public CumulativePermission() { + super(0, ' '); + } - public CumulativePermission clear(Permission permission) { - this.mask &= ~permission.getMask(); - this.pattern = AclFormattingUtils.demergePatterns(this.pattern, permission.getPattern()); + public CumulativePermission clear(Permission permission) { + this.mask &= ~permission.getMask(); + this.pattern = AclFormattingUtils.demergePatterns(this.pattern, + permission.getPattern()); - return this; - } + return this; + } - public CumulativePermission clear() { - this.mask = 0; - this.pattern = THIRTY_TWO_RESERVED_OFF; + public CumulativePermission clear() { + this.mask = 0; + this.pattern = THIRTY_TWO_RESERVED_OFF; - return this; - } + return this; + } - public CumulativePermission set(Permission permission) { - this.mask |= permission.getMask(); - this.pattern = AclFormattingUtils.mergePatterns(this.pattern, permission.getPattern()); + public CumulativePermission set(Permission permission) { + this.mask |= permission.getMask(); + this.pattern = AclFormattingUtils.mergePatterns(this.pattern, + permission.getPattern()); - return this; - } + return this; + } - public String getPattern() { - return this.pattern; - } + public String getPattern() { + return this.pattern; + } } diff --git a/acl/src/main/java/org/springframework/security/acls/domain/DefaultPermissionFactory.java b/acl/src/main/java/org/springframework/security/acls/domain/DefaultPermissionFactory.java index c64e7c0652..ec3150406f 100644 --- a/acl/src/main/java/org/springframework/security/acls/domain/DefaultPermissionFactory.java +++ b/acl/src/main/java/org/springframework/security/acls/domain/DefaultPermissionFactory.java @@ -13,8 +13,8 @@ import org.springframework.util.Assert; /** * Default implementation of {@link PermissionFactory}. *

- * Used as a strategy by classes which wish to map integer masks and permission names to Permission - * instances for use with the ACL implementation. + * Used as a strategy by classes which wish to map integer masks and permission names to + * Permission instances for use with the ACL implementation. *

* Maintains a registry of permission names and masks to Permission instances. * @@ -23,125 +23,131 @@ import org.springframework.util.Assert; * @since 2.0.3 */ public class DefaultPermissionFactory implements PermissionFactory { - private final Map registeredPermissionsByInteger = new HashMap(); - private final Map registeredPermissionsByName = new HashMap(); + private final Map registeredPermissionsByInteger = new HashMap(); + private final Map registeredPermissionsByName = new HashMap(); - /** - * Registers the Permission fields from the BasePermission class. - */ - public DefaultPermissionFactory() { - registerPublicPermissions(BasePermission.class); - } + /** + * Registers the Permission fields from the BasePermission class. + */ + public DefaultPermissionFactory() { + registerPublicPermissions(BasePermission.class); + } - /** - * Registers the Permission fields from the supplied class. - */ - public DefaultPermissionFactory(Class permissionClass) { - registerPublicPermissions(permissionClass); - } + /** + * Registers the Permission fields from the supplied class. + */ + public DefaultPermissionFactory(Class permissionClass) { + registerPublicPermissions(permissionClass); + } - /** - * Registers a map of named Permission instances. - * - * @param namedPermissions the map of Permissions, keyed by name. - */ - public DefaultPermissionFactory(Map namedPermissions) { - for (String name : namedPermissions.keySet()) { - registerPermission(namedPermissions.get(name), name); - } - } + /** + * Registers a map of named Permission instances. + * + * @param namedPermissions the map of Permissions, keyed by name. + */ + public DefaultPermissionFactory(Map namedPermissions) { + for (String name : namedPermissions.keySet()) { + registerPermission(namedPermissions.get(name), name); + } + } - /** - * Registers the public static fields of type {@link Permission} for a give class. - *

- * These permissions will be registered under the name of the field. See {@link BasePermission} - * for an example. - * - * @param clazz a {@link Permission} class with public static fields to register - */ - protected void registerPublicPermissions(Class clazz) { - Assert.notNull(clazz, "Class required"); + /** + * Registers the public static fields of type {@link Permission} for a give class. + *

+ * These permissions will be registered under the name of the field. See + * {@link BasePermission} for an example. + * + * @param clazz a {@link Permission} class with public static fields to register + */ + protected void registerPublicPermissions(Class clazz) { + Assert.notNull(clazz, "Class required"); - Field[] fields = clazz.getFields(); + Field[] fields = clazz.getFields(); - for (Field field : fields) { - try { - Object fieldValue = field.get(null); + for (Field field : fields) { + try { + Object fieldValue = field.get(null); - if (Permission.class.isAssignableFrom(fieldValue.getClass())) { - // Found a Permission static field - Permission perm = (Permission) fieldValue; - String permissionName = field.getName(); + if (Permission.class.isAssignableFrom(fieldValue.getClass())) { + // Found a Permission static field + Permission perm = (Permission) fieldValue; + String permissionName = field.getName(); - registerPermission(perm, permissionName); - } - } catch (Exception ignore) { - } - } - } + registerPermission(perm, permissionName); + } + } + catch (Exception ignore) { + } + } + } - protected void registerPermission(Permission perm, String permissionName) { - Assert.notNull(perm, "Permission required"); - Assert.hasText(permissionName, "Permission name required"); + protected void registerPermission(Permission perm, String permissionName) { + Assert.notNull(perm, "Permission required"); + Assert.hasText(permissionName, "Permission name required"); - Integer mask = Integer.valueOf(perm.getMask()); + Integer mask = Integer.valueOf(perm.getMask()); - // Ensure no existing Permission uses this integer or code - Assert.isTrue(!registeredPermissionsByInteger.containsKey(mask), "An existing Permission already provides mask " + mask); - Assert.isTrue(!registeredPermissionsByName.containsKey(permissionName), "An existing Permission already provides name '" + permissionName + "'"); + // Ensure no existing Permission uses this integer or code + Assert.isTrue(!registeredPermissionsByInteger.containsKey(mask), + "An existing Permission already provides mask " + mask); + Assert.isTrue(!registeredPermissionsByName.containsKey(permissionName), + "An existing Permission already provides name '" + permissionName + "'"); - // Register the new Permission - registeredPermissionsByInteger.put(mask, perm); - registeredPermissionsByName.put(permissionName, perm); - } + // Register the new Permission + registeredPermissionsByInteger.put(mask, perm); + registeredPermissionsByName.put(permissionName, perm); + } - public Permission buildFromMask(int mask) { - if (registeredPermissionsByInteger.containsKey(Integer.valueOf(mask))) { - // The requested mask has an exact match against a statically-defined Permission, so return it - return registeredPermissionsByInteger.get(Integer.valueOf(mask)); - } + public Permission buildFromMask(int mask) { + if (registeredPermissionsByInteger.containsKey(Integer.valueOf(mask))) { + // The requested mask has an exact match against a statically-defined + // Permission, so return it + return registeredPermissionsByInteger.get(Integer.valueOf(mask)); + } - // To get this far, we have to use a CumulativePermission - CumulativePermission permission = new CumulativePermission(); + // To get this far, we have to use a CumulativePermission + CumulativePermission permission = new CumulativePermission(); - for (int i = 0; i < 32; i++) { - int permissionToCheck = 1 << i; + for (int i = 0; i < 32; i++) { + int permissionToCheck = 1 << i; - if ((mask & permissionToCheck) == permissionToCheck) { - Permission p = registeredPermissionsByInteger.get(Integer.valueOf(permissionToCheck)); + if ((mask & permissionToCheck) == permissionToCheck) { + Permission p = registeredPermissionsByInteger.get(Integer + .valueOf(permissionToCheck)); - if (p == null) { - throw new IllegalStateException("Mask '" + permissionToCheck + "' does not have a corresponding static Permission"); - } - permission.set(p); - } - } + if (p == null) { + throw new IllegalStateException("Mask '" + permissionToCheck + + "' does not have a corresponding static Permission"); + } + permission.set(p); + } + } - return permission; - } + return permission; + } - public Permission buildFromName(String name) { - Permission p = registeredPermissionsByName.get(name); + public Permission buildFromName(String name) { + Permission p = registeredPermissionsByName.get(name); - if (p == null) { - throw new IllegalArgumentException("Unknown permission '" + name + "'"); - } + if (p == null) { + throw new IllegalArgumentException("Unknown permission '" + name + "'"); + } - return p; - } + return p; + } - public List buildFromNames(List names) { - if ((names == null) || (names.size() == 0)) { - return Collections.emptyList(); - } + public List buildFromNames(List names) { + if ((names == null) || (names.size() == 0)) { + return Collections.emptyList(); + } - List permissions = new ArrayList(names.size()); + List permissions = new ArrayList(names.size()); - for (String name : names) { - permissions.add(buildFromName(name)); - } + for (String name : names) { + permissions.add(buildFromName(name)); + } - return permissions; - } + return permissions; + } } diff --git a/acl/src/main/java/org/springframework/security/acls/domain/DefaultPermissionGrantingStrategy.java b/acl/src/main/java/org/springframework/security/acls/domain/DefaultPermissionGrantingStrategy.java index 915dcde32f..1167f3b4ae 100644 --- a/acl/src/main/java/org/springframework/security/acls/domain/DefaultPermissionGrantingStrategy.java +++ b/acl/src/main/java/org/springframework/security/acls/domain/DefaultPermissionGrantingStrategy.java @@ -12,108 +12,119 @@ import org.springframework.util.Assert; public class DefaultPermissionGrantingStrategy implements PermissionGrantingStrategy { - private final transient AuditLogger auditLogger; + private final transient AuditLogger auditLogger; - /** - * Creates an instance with the logger which will be used to record granting and denial of requested permissions. - */ - public DefaultPermissionGrantingStrategy(AuditLogger auditLogger) { - Assert.notNull(auditLogger, "auditLogger cannot be null"); - this.auditLogger = auditLogger; - } + /** + * Creates an instance with the logger which will be used to record granting and + * denial of requested permissions. + */ + public DefaultPermissionGrantingStrategy(AuditLogger auditLogger) { + Assert.notNull(auditLogger, "auditLogger cannot be null"); + this.auditLogger = auditLogger; + } - /** - * Determines authorization. The order of the permission and sid arguments is - * extremely important! The method will iterate through each of the permissions in the order - * specified. For each iteration, all of the sids will be considered, again in the order they are - * presented. A search will then be performed for the first {@link AccessControlEntry} object that directly - * matches that permission:sid combination. When the first full match is found (ie an ACE - * that has the SID currently being searched for and the exact permission bit mask being search for), the grant or - * deny flag for that ACE will prevail. If the ACE specifies to grant access, the method will return - * true. If the ACE specifies to deny access, the loop will stop and the next permission - * iteration will be performed. If each permission indicates to deny access, the first deny ACE found will be - * considered the reason for the failure (as it was the first match found, and is therefore the one most logically - * requiring changes - although not always). If absolutely no matching ACE was found at all for any permission, - * the parent ACL will be tried (provided that there is a parent and {@link Acl#isEntriesInheriting()} is - * true. The parent ACL will also scan its parent and so on. If ultimately no matching ACE is found, - * a NotFoundException will be thrown and the caller will need to decide how to handle the permission - * check. Similarly, if any of the SID arguments presented to the method were not loaded by the ACL, - * UnloadedSidException will be thrown. - * - * @param permission the exact permissions to scan for (order is important) - * @param sids the exact SIDs to scan for (order is important) - * @param administrativeMode if true denotes the query is for administrative purposes and no auditing - * will be undertaken - * - * @return true if one of the permissions has been granted, false if one of the - * permissions has been specifically revoked - * - * @throws NotFoundException if an exact ACE for one of the permission bit masks and SID combination could not be - * found - */ - public boolean isGranted(Acl acl, List permission, List sids, boolean administrativeMode) - throws NotFoundException { + /** + * Determines authorization. The order of the permission and + * sid arguments is extremely important! The method will iterate + * through each of the permissions in the order specified. For each + * iteration, all of the sids will be considered, again in the order they + * are presented. A search will then be performed for the first + * {@link AccessControlEntry} object that directly matches that + * permission:sid combination. When the first full match is + * found (ie an ACE that has the SID currently being searched for and the exact + * permission bit mask being search for), the grant or deny flag for that ACE will + * prevail. If the ACE specifies to grant access, the method will return + * true. If the ACE specifies to deny access, the loop will stop and the + * next permission iteration will be performed. If each permission + * indicates to deny access, the first deny ACE found will be considered the reason + * for the failure (as it was the first match found, and is therefore the one most + * logically requiring changes - although not always). If absolutely no matching ACE + * was found at all for any permission, the parent ACL will be tried (provided that + * there is a parent and {@link Acl#isEntriesInheriting()} is true. The + * parent ACL will also scan its parent and so on. If ultimately no matching ACE is + * found, a NotFoundException will be thrown and the caller will need to + * decide how to handle the permission check. Similarly, if any of the SID arguments + * presented to the method were not loaded by the ACL, + * UnloadedSidException will be thrown. + * + * @param permission the exact permissions to scan for (order is important) + * @param sids the exact SIDs to scan for (order is important) + * @param administrativeMode if true denotes the query is for + * administrative purposes and no auditing will be undertaken + * + * @return true if one of the permissions has been granted, + * false if one of the permissions has been specifically revoked + * + * @throws NotFoundException if an exact ACE for one of the permission bit masks and + * SID combination could not be found + */ + public boolean isGranted(Acl acl, List permission, List sids, + boolean administrativeMode) throws NotFoundException { - final List aces = acl.getEntries(); + final List aces = acl.getEntries(); - AccessControlEntry firstRejection = null; + AccessControlEntry firstRejection = null; - for (Permission p : permission) { - for (Sid sid: sids) { - // Attempt to find exact match for this permission mask and SID - boolean scanNextSid = true; + for (Permission p : permission) { + for (Sid sid : sids) { + // Attempt to find exact match for this permission mask and SID + boolean scanNextSid = true; - for (AccessControlEntry ace : aces ) { + for (AccessControlEntry ace : aces) { - if ((ace.getPermission().getMask() == p.getMask()) && ace.getSid().equals(sid)) { - // Found a matching ACE, so its authorization decision will prevail - if (ace.isGranting()) { - // Success - if (!administrativeMode) { - auditLogger.logIfNeeded(true, ace); - } + if ((ace.getPermission().getMask() == p.getMask()) + && ace.getSid().equals(sid)) { + // Found a matching ACE, so its authorization decision will + // prevail + if (ace.isGranting()) { + // Success + if (!administrativeMode) { + auditLogger.logIfNeeded(true, ace); + } - return true; - } + return true; + } - // Failure for this permission, so stop search - // We will see if they have a different permission - // (this permission is 100% rejected for this SID) - if (firstRejection == null) { - // Store first rejection for auditing reasons - firstRejection = ace; - } + // Failure for this permission, so stop search + // We will see if they have a different permission + // (this permission is 100% rejected for this SID) + if (firstRejection == null) { + // Store first rejection for auditing reasons + firstRejection = ace; + } - scanNextSid = false; // helps break the loop + scanNextSid = false; // helps break the loop - break; // exit aces loop - } - } + break; // exit aces loop + } + } - if (!scanNextSid) { - break; // exit SID for loop (now try next permission) - } - } - } + if (!scanNextSid) { + break; // exit SID for loop (now try next permission) + } + } + } - if (firstRejection != null) { - // We found an ACE to reject the request at this point, as no - // other ACEs were found that granted a different permission - if (!administrativeMode) { - auditLogger.logIfNeeded(false, firstRejection); - } + if (firstRejection != null) { + // We found an ACE to reject the request at this point, as no + // other ACEs were found that granted a different permission + if (!administrativeMode) { + auditLogger.logIfNeeded(false, firstRejection); + } - return false; - } + return false; + } - // No matches have been found so far - if (acl.isEntriesInheriting() && (acl.getParentAcl() != null)) { - // We have a parent, so let them try to find a matching ACE - return acl.getParentAcl().isGranted(permission, sids, false); - } else { - // We either have no parent, or we're the uppermost parent - throw new NotFoundException("Unable to locate a matching ACE for passed permissions and SIDs"); - } - } + // No matches have been found so far + if (acl.isEntriesInheriting() && (acl.getParentAcl() != null)) { + // We have a parent, so let them try to find a matching ACE + return acl.getParentAcl().isGranted(permission, sids, false); + } + else { + // We either have no parent, or we're the uppermost parent + throw new NotFoundException( + "Unable to locate a matching ACE for passed permissions and SIDs"); + } + } } diff --git a/acl/src/main/java/org/springframework/security/acls/domain/EhCacheBasedAclCache.java b/acl/src/main/java/org/springframework/security/acls/domain/EhCacheBasedAclCache.java index 64ed55f3a4..d84459c74a 100644 --- a/acl/src/main/java/org/springframework/security/acls/domain/EhCacheBasedAclCache.java +++ b/acl/src/main/java/org/springframework/security/acls/domain/EhCacheBasedAclCache.java @@ -27,124 +27,135 @@ import org.springframework.security.acls.model.PermissionGrantingStrategy; import org.springframework.security.util.FieldUtils; import org.springframework.util.Assert; - /** * Simple implementation of {@link AclCache} that delegates to EH-CACHE. *

- * Designed to handle the transient fields in {@link AclImpl}. Note that this implementation assumes all - * {@link AclImpl} instances share the same {@link PermissionGrantingStrategy} and {@link AclAuthorizationStrategy} - * instances. + * Designed to handle the transient fields in {@link AclImpl}. Note that this + * implementation assumes all {@link AclImpl} instances share the same + * {@link PermissionGrantingStrategy} and {@link AclAuthorizationStrategy} instances. * * @author Ben Alex */ public class EhCacheBasedAclCache implements AclCache { - //~ Instance fields ================================================================================================ + // ~ Instance fields + // ================================================================================================ - private final Ehcache cache; - private PermissionGrantingStrategy permissionGrantingStrategy; - private AclAuthorizationStrategy aclAuthorizationStrategy; + private final Ehcache cache; + private PermissionGrantingStrategy permissionGrantingStrategy; + private AclAuthorizationStrategy aclAuthorizationStrategy; - //~ Constructors =================================================================================================== + // ~ Constructors + // =================================================================================================== - public EhCacheBasedAclCache(Ehcache cache, PermissionGrantingStrategy permissionGrantingStrategy, - AclAuthorizationStrategy aclAuthorizationStrategy) { - Assert.notNull(cache, "Cache required"); - Assert.notNull(permissionGrantingStrategy, "PermissionGrantingStrategy required"); - Assert.notNull(aclAuthorizationStrategy, "AclAuthorizationStrategy required"); - this.cache = cache; - this.permissionGrantingStrategy = permissionGrantingStrategy; - this.aclAuthorizationStrategy = aclAuthorizationStrategy; - } + public EhCacheBasedAclCache(Ehcache cache, + PermissionGrantingStrategy permissionGrantingStrategy, + AclAuthorizationStrategy aclAuthorizationStrategy) { + Assert.notNull(cache, "Cache required"); + Assert.notNull(permissionGrantingStrategy, "PermissionGrantingStrategy required"); + Assert.notNull(aclAuthorizationStrategy, "AclAuthorizationStrategy required"); + this.cache = cache; + this.permissionGrantingStrategy = permissionGrantingStrategy; + this.aclAuthorizationStrategy = aclAuthorizationStrategy; + } - //~ Methods ======================================================================================================== + // ~ Methods + // ======================================================================================================== - public void evictFromCache(Serializable pk) { - Assert.notNull(pk, "Primary key (identifier) required"); + public void evictFromCache(Serializable pk) { + Assert.notNull(pk, "Primary key (identifier) required"); - MutableAcl acl = getFromCache(pk); + MutableAcl acl = getFromCache(pk); - if (acl != null) { - cache.remove(acl.getId()); - cache.remove(acl.getObjectIdentity()); - } - } + if (acl != null) { + cache.remove(acl.getId()); + cache.remove(acl.getObjectIdentity()); + } + } - public void evictFromCache(ObjectIdentity objectIdentity) { - Assert.notNull(objectIdentity, "ObjectIdentity required"); + public void evictFromCache(ObjectIdentity objectIdentity) { + Assert.notNull(objectIdentity, "ObjectIdentity required"); - MutableAcl acl = getFromCache(objectIdentity); + MutableAcl acl = getFromCache(objectIdentity); - if (acl != null) { - cache.remove(acl.getId()); - cache.remove(acl.getObjectIdentity()); - } - } + if (acl != null) { + cache.remove(acl.getId()); + cache.remove(acl.getObjectIdentity()); + } + } - public MutableAcl getFromCache(ObjectIdentity objectIdentity) { - Assert.notNull(objectIdentity, "ObjectIdentity required"); + public MutableAcl getFromCache(ObjectIdentity objectIdentity) { + Assert.notNull(objectIdentity, "ObjectIdentity required"); - Element element = null; + Element element = null; - try { - element = cache.get(objectIdentity); - } catch (CacheException ignored) {} + try { + element = cache.get(objectIdentity); + } + catch (CacheException ignored) { + } - if (element == null) { - return null; - } + if (element == null) { + return null; + } - return initializeTransientFields((MutableAcl)element.getValue()); - } + return initializeTransientFields((MutableAcl) element.getValue()); + } - public MutableAcl getFromCache(Serializable pk) { - Assert.notNull(pk, "Primary key (identifier) required"); + public MutableAcl getFromCache(Serializable pk) { + Assert.notNull(pk, "Primary key (identifier) required"); - Element element = null; + Element element = null; - try { - element = cache.get(pk); - } catch (CacheException ignored) {} + try { + element = cache.get(pk); + } + catch (CacheException ignored) { + } - if (element == null) { - return null; - } + if (element == null) { + return null; + } - return initializeTransientFields((MutableAcl) element.getValue()); - } + return initializeTransientFields((MutableAcl) element.getValue()); + } - public void putInCache(MutableAcl acl) { - Assert.notNull(acl, "Acl required"); - Assert.notNull(acl.getObjectIdentity(), "ObjectIdentity required"); - Assert.notNull(acl.getId(), "ID required"); + public void putInCache(MutableAcl acl) { + Assert.notNull(acl, "Acl required"); + Assert.notNull(acl.getObjectIdentity(), "ObjectIdentity required"); + Assert.notNull(acl.getId(), "ID required"); - if (this.aclAuthorizationStrategy == null) { - if (acl instanceof AclImpl) { - this.aclAuthorizationStrategy = (AclAuthorizationStrategy) FieldUtils.getProtectedFieldValue("aclAuthorizationStrategy", acl); - this.permissionGrantingStrategy = (PermissionGrantingStrategy) FieldUtils.getProtectedFieldValue("permissionGrantingStrategy", acl); - } - } + if (this.aclAuthorizationStrategy == null) { + if (acl instanceof AclImpl) { + this.aclAuthorizationStrategy = (AclAuthorizationStrategy) FieldUtils + .getProtectedFieldValue("aclAuthorizationStrategy", acl); + this.permissionGrantingStrategy = (PermissionGrantingStrategy) FieldUtils + .getProtectedFieldValue("permissionGrantingStrategy", acl); + } + } - if ((acl.getParentAcl() != null) && (acl.getParentAcl() instanceof MutableAcl)) { - putInCache((MutableAcl) acl.getParentAcl()); - } + if ((acl.getParentAcl() != null) && (acl.getParentAcl() instanceof MutableAcl)) { + putInCache((MutableAcl) acl.getParentAcl()); + } - cache.put(new Element(acl.getObjectIdentity(), acl)); - cache.put(new Element(acl.getId(), acl)); - } + cache.put(new Element(acl.getObjectIdentity(), acl)); + cache.put(new Element(acl.getId(), acl)); + } - private MutableAcl initializeTransientFields(MutableAcl value) { - if (value instanceof AclImpl) { - FieldUtils.setProtectedFieldValue("aclAuthorizationStrategy", value, this.aclAuthorizationStrategy); - FieldUtils.setProtectedFieldValue("permissionGrantingStrategy", value, this.permissionGrantingStrategy); - } + private MutableAcl initializeTransientFields(MutableAcl value) { + if (value instanceof AclImpl) { + FieldUtils.setProtectedFieldValue("aclAuthorizationStrategy", value, + this.aclAuthorizationStrategy); + FieldUtils.setProtectedFieldValue("permissionGrantingStrategy", value, + this.permissionGrantingStrategy); + } - if (value.getParentAcl() != null) { - initializeTransientFields((MutableAcl) value.getParentAcl()); - } - return value; - } + if (value.getParentAcl() != null) { + initializeTransientFields((MutableAcl) value.getParentAcl()); + } + return value; + } - public void clearCache() { - cache.removeAll(); - } + public void clearCache() { + cache.removeAll(); + } } diff --git a/acl/src/main/java/org/springframework/security/acls/domain/GrantedAuthoritySid.java b/acl/src/main/java/org/springframework/security/acls/domain/GrantedAuthoritySid.java index e31f265c93..ecaaf68133 100644 --- a/acl/src/main/java/org/springframework/security/acls/domain/GrantedAuthoritySid.java +++ b/acl/src/main/java/org/springframework/security/acls/domain/GrantedAuthoritySid.java @@ -19,53 +19,61 @@ import org.springframework.security.core.GrantedAuthority; import org.springframework.util.Assert; - /** - * Represents a GrantedAuthority as a Sid.

This is a basic implementation that simply - * uses the String-based principal for Sid comparison. More complex principal objects may - * wish to provide an alternative Sid implementation that uses some other identifier.

+ * Represents a GrantedAuthority as a Sid. + *

+ * This is a basic implementation that simply uses the String-based principal + * for Sid comparison. More complex principal objects may wish to provide an + * alternative Sid implementation that uses some other identifier. + *

* * @author Ben Alex */ public class GrantedAuthoritySid implements Sid { - //~ Instance fields ================================================================================================ + // ~ Instance fields + // ================================================================================================ - private final String grantedAuthority; + private final String grantedAuthority; - //~ Constructors =================================================================================================== + // ~ Constructors + // =================================================================================================== - public GrantedAuthoritySid(String grantedAuthority) { - Assert.hasText(grantedAuthority, "GrantedAuthority required"); - this.grantedAuthority = grantedAuthority; - } + public GrantedAuthoritySid(String grantedAuthority) { + Assert.hasText(grantedAuthority, "GrantedAuthority required"); + this.grantedAuthority = grantedAuthority; + } - public GrantedAuthoritySid(GrantedAuthority grantedAuthority) { - Assert.notNull(grantedAuthority, "GrantedAuthority required"); - Assert.notNull(grantedAuthority.getAuthority(), - "This Sid is only compatible with GrantedAuthoritys that provide a non-null getAuthority()"); - this.grantedAuthority = grantedAuthority.getAuthority(); - } + public GrantedAuthoritySid(GrantedAuthority grantedAuthority) { + Assert.notNull(grantedAuthority, "GrantedAuthority required"); + Assert.notNull( + grantedAuthority.getAuthority(), + "This Sid is only compatible with GrantedAuthoritys that provide a non-null getAuthority()"); + this.grantedAuthority = grantedAuthority.getAuthority(); + } - //~ Methods ======================================================================================================== + // ~ Methods + // ======================================================================================================== - public boolean equals(Object object) { - if ((object == null) || !(object instanceof GrantedAuthoritySid)) { - return false; - } + public boolean equals(Object object) { + if ((object == null) || !(object instanceof GrantedAuthoritySid)) { + return false; + } - // Delegate to getGrantedAuthority() to perform actual comparison (both should be identical) - return ((GrantedAuthoritySid) object).getGrantedAuthority().equals(this.getGrantedAuthority()); - } + // Delegate to getGrantedAuthority() to perform actual comparison (both should be + // identical) + return ((GrantedAuthoritySid) object).getGrantedAuthority().equals( + this.getGrantedAuthority()); + } - public int hashCode() { - return this.getGrantedAuthority().hashCode(); - } + public int hashCode() { + return this.getGrantedAuthority().hashCode(); + } - public String getGrantedAuthority() { - return grantedAuthority; - } + public String getGrantedAuthority() { + return grantedAuthority; + } - public String toString() { - return "GrantedAuthoritySid[" + this.grantedAuthority + "]"; - } + public String toString() { + return "GrantedAuthoritySid[" + this.grantedAuthority + "]"; + } } diff --git a/acl/src/main/java/org/springframework/security/acls/domain/IdentityUnavailableException.java b/acl/src/main/java/org/springframework/security/acls/domain/IdentityUnavailableException.java index 18e7383c42..9ede4f33aa 100644 --- a/acl/src/main/java/org/springframework/security/acls/domain/IdentityUnavailableException.java +++ b/acl/src/main/java/org/springframework/security/acls/domain/IdentityUnavailableException.java @@ -20,25 +20,26 @@ package org.springframework.security.acls.domain; * @author Ben Alex */ public class IdentityUnavailableException extends RuntimeException { - //~ Constructors =================================================================================================== + // ~ Constructors + // =================================================================================================== - /** - * Constructs an IdentityUnavailableException with the specified message. - * - * @param msg the detail message - */ - public IdentityUnavailableException(String msg) { - super(msg); - } + /** + * Constructs an IdentityUnavailableException with the specified message. + * + * @param msg the detail message + */ + public IdentityUnavailableException(String msg) { + super(msg); + } - /** - * Constructs an IdentityUnavailableException with the specified message - * and root cause. - * - * @param msg the detail message - * @param t root cause - */ - public IdentityUnavailableException(String msg, Throwable t) { - super(msg, t); - } + /** + * Constructs an IdentityUnavailableException with the specified message + * and root cause. + * + * @param msg the detail message + * @param t root cause + */ + public IdentityUnavailableException(String msg, Throwable t) { + super(msg, t); + } } diff --git a/acl/src/main/java/org/springframework/security/acls/domain/ObjectIdentityImpl.java b/acl/src/main/java/org/springframework/security/acls/domain/ObjectIdentityImpl.java index 9026696325..2e485a670e 100644 --- a/acl/src/main/java/org/springframework/security/acls/domain/ObjectIdentityImpl.java +++ b/acl/src/main/java/org/springframework/security/acls/domain/ObjectIdentityImpl.java @@ -21,137 +21,145 @@ import org.springframework.security.acls.model.ObjectIdentity; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; - /** * Simple implementation of {@link ObjectIdentity}. *

- * Uses Strings to store the identity of the domain object instance. Also offers a constructor that uses - * reflection to build the identity information. + * Uses Strings to store the identity of the domain object instance. Also + * offers a constructor that uses reflection to build the identity information. * * @author Ben Alex */ public class ObjectIdentityImpl implements ObjectIdentity { - //~ Instance fields ================================================================================================ + // ~ Instance fields + // ================================================================================================ - private final String type; - private Serializable identifier; + private final String type; + private Serializable identifier; - //~ Constructors =================================================================================================== + // ~ Constructors + // =================================================================================================== - public ObjectIdentityImpl(String type, Serializable identifier) { - Assert.hasText(type, "Type required"); - Assert.notNull(identifier, "identifier required"); + public ObjectIdentityImpl(String type, Serializable identifier) { + Assert.hasText(type, "Type required"); + Assert.notNull(identifier, "identifier required"); - this.identifier = identifier; - this.type = type; - } + this.identifier = identifier; + this.type = type; + } - /** - * Constructor which uses the name of the supplied class as the type property. - */ - public ObjectIdentityImpl(Class javaType, Serializable identifier) { - Assert.notNull(javaType, "Java Type required"); - Assert.notNull(identifier, "identifier required"); - this.type = javaType.getName(); - this.identifier = identifier; - } + /** + * Constructor which uses the name of the supplied class as the type + * property. + */ + public ObjectIdentityImpl(Class javaType, Serializable identifier) { + Assert.notNull(javaType, "Java Type required"); + Assert.notNull(identifier, "identifier required"); + this.type = javaType.getName(); + this.identifier = identifier; + } - /** - * Creates the ObjectIdentityImpl based on the passed - * object instance. The passed object must provide a getId() - * method, otherwise an exception will be thrown. - *

- * The class name of the object passed will be considered the {@link #type}, so if more control is required, - * a different constructor should be used. - * - * @param object the domain object instance to create an identity for. - * - * @throws IdentityUnavailableException if identity could not be extracted - */ - public ObjectIdentityImpl(Object object) throws IdentityUnavailableException { - Assert.notNull(object, "object cannot be null"); + /** + * Creates the ObjectIdentityImpl based on the passed object instance. + * The passed object must provide a getId() method, otherwise an + * exception will be thrown. + *

+ * The class name of the object passed will be considered the {@link #type}, so if + * more control is required, a different constructor should be used. + * + * @param object the domain object instance to create an identity for. + * + * @throws IdentityUnavailableException if identity could not be extracted + */ + public ObjectIdentityImpl(Object object) throws IdentityUnavailableException { + Assert.notNull(object, "object cannot be null"); - Class typeClass = ClassUtils.getUserClass(object.getClass()); - type = typeClass.getName(); + Class typeClass = ClassUtils.getUserClass(object.getClass()); + type = typeClass.getName(); - Object result; + Object result; - try { - Method method = typeClass.getMethod("getId", new Class[] {}); - result = method.invoke(object); - } catch (Exception e) { - throw new IdentityUnavailableException("Could not extract identity from object " + object, e); - } + try { + Method method = typeClass.getMethod("getId", new Class[] {}); + result = method.invoke(object); + } + catch (Exception e) { + throw new IdentityUnavailableException( + "Could not extract identity from object " + object, e); + } - Assert.notNull(result, "getId() is required to return a non-null value"); - Assert.isInstanceOf(Serializable.class, result, "Getter must provide a return value of type Serializable"); - this.identifier = (Serializable) result; - } + Assert.notNull(result, "getId() is required to return a non-null value"); + Assert.isInstanceOf(Serializable.class, result, + "Getter must provide a return value of type Serializable"); + this.identifier = (Serializable) result; + } - //~ Methods ======================================================================================================== + // ~ Methods + // ======================================================================================================== - /** - * Important so caching operates properly. - *

- * Considers an object of the same class equal if it has the same classname and - * id properties. - *

- * Numeric identities (Integer and Long values) are considered equal if they are numerically equal. Other - * serializable types are evaluated using a simple equality. - * - * @param arg0 object to compare - * - * @return true if the presented object matches this object - */ - public boolean equals(Object arg0) { - if (arg0 == null || !(arg0 instanceof ObjectIdentityImpl)) { - return false; - } + /** + * Important so caching operates properly. + *

+ * Considers an object of the same class equal if it has the same + * classname and id properties. + *

+ * Numeric identities (Integer and Long values) are considered equal if they are + * numerically equal. Other serializable types are evaluated using a simple equality. + * + * @param arg0 object to compare + * + * @return true if the presented object matches this object + */ + public boolean equals(Object arg0) { + if (arg0 == null || !(arg0 instanceof ObjectIdentityImpl)) { + return false; + } - ObjectIdentityImpl other = (ObjectIdentityImpl) arg0; + ObjectIdentityImpl other = (ObjectIdentityImpl) arg0; - if (identifier instanceof Number && other.identifier instanceof Number) { - // Integers and Longs with same value should be considered equal - if (((Number)identifier).longValue() != ((Number)other.identifier).longValue()) { - return false; - } - } else { - // Use plain equality for other serializable types - if (!identifier.equals(other.identifier)) { - return false; - } - } + if (identifier instanceof Number && other.identifier instanceof Number) { + // Integers and Longs with same value should be considered equal + if (((Number) identifier).longValue() != ((Number) other.identifier) + .longValue()) { + return false; + } + } + else { + // Use plain equality for other serializable types + if (!identifier.equals(other.identifier)) { + return false; + } + } - return type.equals(other.type); - } + return type.equals(other.type); + } - public Serializable getIdentifier() { - return identifier; - } + public Serializable getIdentifier() { + return identifier; + } - public String getType() { - return type; - } + public String getType() { + return type; + } - /** - * Important so caching operates properly. - * - * @return the hash - */ - public int hashCode() { - int code = 31; - code ^= this.type.hashCode(); - code ^= this.identifier.hashCode(); + /** + * Important so caching operates properly. + * + * @return the hash + */ + public int hashCode() { + int code = 31; + code ^= this.type.hashCode(); + code ^= this.identifier.hashCode(); - return code; - } + return code; + } - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append(this.getClass().getName()).append("["); - sb.append("Type: ").append(this.type); - sb.append("; Identifier: ").append(this.identifier).append("]"); + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append(this.getClass().getName()).append("["); + sb.append("Type: ").append(this.type); + sb.append("; Identifier: ").append(this.identifier).append("]"); - return sb.toString(); - } + return sb.toString(); + } } diff --git a/acl/src/main/java/org/springframework/security/acls/domain/ObjectIdentityRetrievalStrategyImpl.java b/acl/src/main/java/org/springframework/security/acls/domain/ObjectIdentityRetrievalStrategyImpl.java index 8854f2c65c..e4345547c6 100644 --- a/acl/src/main/java/org/springframework/security/acls/domain/ObjectIdentityRetrievalStrategyImpl.java +++ b/acl/src/main/java/org/springframework/security/acls/domain/ObjectIdentityRetrievalStrategyImpl.java @@ -22,19 +22,22 @@ import org.springframework.security.acls.model.ObjectIdentityGenerator; import org.springframework.security.acls.model.ObjectIdentityRetrievalStrategy; /** - * Basic implementation of {@link ObjectIdentityRetrievalStrategy} and ObjectIdentityGenerator - * that uses the constructors of {@link ObjectIdentityImpl} to create the {@link ObjectIdentity}. + * Basic implementation of {@link ObjectIdentityRetrievalStrategy} and + * ObjectIdentityGenerator that uses the constructors of + * {@link ObjectIdentityImpl} to create the {@link ObjectIdentity}. * * @author Ben Alex */ -public class ObjectIdentityRetrievalStrategyImpl implements ObjectIdentityRetrievalStrategy, ObjectIdentityGenerator { - //~ Methods ======================================================================================================== +public class ObjectIdentityRetrievalStrategyImpl implements + ObjectIdentityRetrievalStrategy, ObjectIdentityGenerator { + // ~ Methods + // ======================================================================================================== - public ObjectIdentity getObjectIdentity(Object domainObject) { - return new ObjectIdentityImpl(domainObject); - } + public ObjectIdentity getObjectIdentity(Object domainObject) { + return new ObjectIdentityImpl(domainObject); + } - public ObjectIdentity createObjectIdentity(Serializable id, String type) { - return new ObjectIdentityImpl(type, id); - } + public ObjectIdentity createObjectIdentity(Serializable id, String type) { + return new ObjectIdentityImpl(type, id); + } } diff --git a/acl/src/main/java/org/springframework/security/acls/domain/PermissionFactory.java b/acl/src/main/java/org/springframework/security/acls/domain/PermissionFactory.java index 92797f66f5..2d98a85f34 100644 --- a/acl/src/main/java/org/springframework/security/acls/domain/PermissionFactory.java +++ b/acl/src/main/java/org/springframework/security/acls/domain/PermissionFactory.java @@ -5,7 +5,8 @@ import java.util.List; import org.springframework.security.acls.model.Permission; /** - * Provides a simple mechanism to retrieve {@link Permission} instances from integer masks. + * Provides a simple mechanism to retrieve {@link Permission} instances from integer + * masks. * * @author Ben Alex * @since 2.0.3 @@ -13,19 +14,17 @@ import org.springframework.security.acls.model.Permission; */ public interface PermissionFactory { - /** - * Dynamically creates a CumulativePermission or BasePermission representing the - * active bits in the passed mask. - * - * @param mask to build - * - * @return a Permission representing the requested object - */ - Permission buildFromMask(int mask); + /** + * Dynamically creates a CumulativePermission or + * BasePermission representing the active bits in the passed mask. + * + * @param mask to build + * + * @return a Permission representing the requested object + */ + Permission buildFromMask(int mask); + Permission buildFromName(String name); - Permission buildFromName(String name); - - - List buildFromNames(List names); + List buildFromNames(List names); } diff --git a/acl/src/main/java/org/springframework/security/acls/domain/PrincipalSid.java b/acl/src/main/java/org/springframework/security/acls/domain/PrincipalSid.java index d9253c7302..2708162139 100644 --- a/acl/src/main/java/org/springframework/security/acls/domain/PrincipalSid.java +++ b/acl/src/main/java/org/springframework/security/acls/domain/PrincipalSid.java @@ -14,64 +14,70 @@ */ package org.springframework.security.acls.domain; - import org.springframework.security.acls.model.Sid; import org.springframework.security.core.Authentication; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.util.Assert; - /** - * Represents an Authentication.getPrincipal() as a Sid.

This is a basic implementation - * that simply uses the String-based principal for Sid comparison. More complex principal - * objects may wish to provide an alternative Sid implementation that uses some other identifier.

+ * Represents an Authentication.getPrincipal() as a Sid. + *

+ * This is a basic implementation that simply uses the String-based principal + * for Sid comparison. More complex principal objects may wish to provide an + * alternative Sid implementation that uses some other identifier. + *

* * @author Ben Alex */ public class PrincipalSid implements Sid { - //~ Instance fields ================================================================================================ + // ~ Instance fields + // ================================================================================================ - private final String principal; + private final String principal; - //~ Constructors =================================================================================================== + // ~ Constructors + // =================================================================================================== - public PrincipalSid(String principal) { - Assert.hasText(principal, "Principal required"); - this.principal = principal; - } + public PrincipalSid(String principal) { + Assert.hasText(principal, "Principal required"); + this.principal = principal; + } - public PrincipalSid(Authentication authentication) { - Assert.notNull(authentication, "Authentication required"); - Assert.notNull(authentication.getPrincipal(), "Principal required"); + public PrincipalSid(Authentication authentication) { + Assert.notNull(authentication, "Authentication required"); + Assert.notNull(authentication.getPrincipal(), "Principal required"); - if (authentication.getPrincipal() instanceof UserDetails) { - this.principal = ((UserDetails) authentication.getPrincipal()).getUsername(); - } else { - this.principal = authentication.getPrincipal().toString(); - } - } + if (authentication.getPrincipal() instanceof UserDetails) { + this.principal = ((UserDetails) authentication.getPrincipal()).getUsername(); + } + else { + this.principal = authentication.getPrincipal().toString(); + } + } - //~ Methods ======================================================================================================== + // ~ Methods + // ======================================================================================================== - public boolean equals(Object object) { - if ((object == null) || !(object instanceof PrincipalSid)) { - return false; - } + public boolean equals(Object object) { + if ((object == null) || !(object instanceof PrincipalSid)) { + return false; + } - // Delegate to getPrincipal() to perform actual comparison (both should be identical) - return ((PrincipalSid) object).getPrincipal().equals(this.getPrincipal()); - } + // Delegate to getPrincipal() to perform actual comparison (both should be + // identical) + return ((PrincipalSid) object).getPrincipal().equals(this.getPrincipal()); + } - public int hashCode() { - return this.getPrincipal().hashCode(); - } + public int hashCode() { + return this.getPrincipal().hashCode(); + } - public String getPrincipal() { - return principal; - } + public String getPrincipal() { + return principal; + } - public String toString() { - return "PrincipalSid[" + this.principal + "]"; - } + public String toString() { + return "PrincipalSid[" + this.principal + "]"; + } } diff --git a/acl/src/main/java/org/springframework/security/acls/domain/SidRetrievalStrategyImpl.java b/acl/src/main/java/org/springframework/security/acls/domain/SidRetrievalStrategyImpl.java index 4c0c0d6a81..b5621257e2 100644 --- a/acl/src/main/java/org/springframework/security/acls/domain/SidRetrievalStrategyImpl.java +++ b/acl/src/main/java/org/springframework/security/acls/domain/SidRetrievalStrategyImpl.java @@ -28,38 +28,42 @@ import org.springframework.security.core.GrantedAuthority; import org.springframework.util.Assert; /** - * Basic implementation of {@link SidRetrievalStrategy} that creates a {@link Sid} for the principal, as well as - * every granted authority the principal holds. Can optionally have a RoleHierarchy injected in order to - * determine the extended list of authorities that the principal is assigned. + * Basic implementation of {@link SidRetrievalStrategy} that creates a {@link Sid} for the + * principal, as well as every granted authority the principal holds. Can optionally have + * a RoleHierarchy injected in order to determine the extended list of + * authorities that the principal is assigned. *

- * The returned array will always contain the {@link PrincipalSid} before any {@link GrantedAuthoritySid} elements. + * The returned array will always contain the {@link PrincipalSid} before any + * {@link GrantedAuthoritySid} elements. * * @author Ben Alex */ public class SidRetrievalStrategyImpl implements SidRetrievalStrategy { - private RoleHierarchy roleHierarchy = new NullRoleHierarchy(); + private RoleHierarchy roleHierarchy = new NullRoleHierarchy(); - public SidRetrievalStrategyImpl() { - } + public SidRetrievalStrategyImpl() { + } - public SidRetrievalStrategyImpl(RoleHierarchy roleHierarchy) { - Assert.notNull(roleHierarchy, "RoleHierarchy must not be null"); - this.roleHierarchy = roleHierarchy; - } + public SidRetrievalStrategyImpl(RoleHierarchy roleHierarchy) { + Assert.notNull(roleHierarchy, "RoleHierarchy must not be null"); + this.roleHierarchy = roleHierarchy; + } - //~ Methods ======================================================================================================== + // ~ Methods + // ======================================================================================================== - public List getSids(Authentication authentication) { - Collection authorities = roleHierarchy.getReachableGrantedAuthorities(authentication.getAuthorities()); - List sids = new ArrayList(authorities.size() + 1); + public List getSids(Authentication authentication) { + Collection authorities = roleHierarchy + .getReachableGrantedAuthorities(authentication.getAuthorities()); + List sids = new ArrayList(authorities.size() + 1); - sids.add(new PrincipalSid(authentication)); + sids.add(new PrincipalSid(authentication)); - for (GrantedAuthority authority : authorities) { - sids.add(new GrantedAuthoritySid(authority)); - } + for (GrantedAuthority authority : authorities) { + sids.add(new GrantedAuthoritySid(authority)); + } - return sids; - } + return sids; + } } diff --git a/acl/src/main/java/org/springframework/security/acls/domain/SpringCacheBasedAclCache.java b/acl/src/main/java/org/springframework/security/acls/domain/SpringCacheBasedAclCache.java index b266ab9142..900409ddda 100644 --- a/acl/src/main/java/org/springframework/security/acls/domain/SpringCacheBasedAclCache.java +++ b/acl/src/main/java/org/springframework/security/acls/domain/SpringCacheBasedAclCache.java @@ -25,106 +25,114 @@ import org.springframework.util.Assert; import java.io.Serializable; - /** - * Simple implementation of {@link org.springframework.security.acls.model.AclCache} that delegates to {@link Cache} implementation. + * Simple implementation of {@link org.springframework.security.acls.model.AclCache} that + * delegates to {@link Cache} implementation. *

- * Designed to handle the transient fields in {@link org.springframework.security.acls.domain.AclImpl}. Note that this implementation assumes all - * {@link org.springframework.security.acls.domain.AclImpl} instances share the same {@link org.springframework.security.acls.model.PermissionGrantingStrategy} and {@link org.springframework.security.acls.domain.AclAuthorizationStrategy} - * instances. + * Designed to handle the transient fields in + * {@link org.springframework.security.acls.domain.AclImpl}. Note that this implementation + * assumes all {@link org.springframework.security.acls.domain.AclImpl} instances share + * the same {@link org.springframework.security.acls.model.PermissionGrantingStrategy} and + * {@link org.springframework.security.acls.domain.AclAuthorizationStrategy} instances. * * @author Marten Deinum * @since 3.2 */ public class SpringCacheBasedAclCache implements AclCache { - //~ Instance fields ================================================================================================ + // ~ Instance fields + // ================================================================================================ - private final Cache cache; - private PermissionGrantingStrategy permissionGrantingStrategy; - private AclAuthorizationStrategy aclAuthorizationStrategy; + private final Cache cache; + private PermissionGrantingStrategy permissionGrantingStrategy; + private AclAuthorizationStrategy aclAuthorizationStrategy; - //~ Constructors =================================================================================================== + // ~ Constructors + // =================================================================================================== - public SpringCacheBasedAclCache(Cache cache, PermissionGrantingStrategy permissionGrantingStrategy, - AclAuthorizationStrategy aclAuthorizationStrategy) { - Assert.notNull(cache, "Cache required"); - Assert.notNull(permissionGrantingStrategy, "PermissionGrantingStrategy required"); - Assert.notNull(aclAuthorizationStrategy, "AclAuthorizationStrategy required"); - this.cache = cache; - this.permissionGrantingStrategy = permissionGrantingStrategy; - this.aclAuthorizationStrategy = aclAuthorizationStrategy; - } + public SpringCacheBasedAclCache(Cache cache, + PermissionGrantingStrategy permissionGrantingStrategy, + AclAuthorizationStrategy aclAuthorizationStrategy) { + Assert.notNull(cache, "Cache required"); + Assert.notNull(permissionGrantingStrategy, "PermissionGrantingStrategy required"); + Assert.notNull(aclAuthorizationStrategy, "AclAuthorizationStrategy required"); + this.cache = cache; + this.permissionGrantingStrategy = permissionGrantingStrategy; + this.aclAuthorizationStrategy = aclAuthorizationStrategy; + } - //~ Methods ======================================================================================================== + // ~ Methods + // ======================================================================================================== - public void evictFromCache(Serializable pk) { - Assert.notNull(pk, "Primary key (identifier) required"); + public void evictFromCache(Serializable pk) { + Assert.notNull(pk, "Primary key (identifier) required"); - MutableAcl acl = getFromCache(pk); + MutableAcl acl = getFromCache(pk); - if (acl != null) { - cache.evict(acl.getId()); - cache.evict(acl.getObjectIdentity()); - } - } + if (acl != null) { + cache.evict(acl.getId()); + cache.evict(acl.getObjectIdentity()); + } + } - public void evictFromCache(ObjectIdentity objectIdentity) { - Assert.notNull(objectIdentity, "ObjectIdentity required"); + public void evictFromCache(ObjectIdentity objectIdentity) { + Assert.notNull(objectIdentity, "ObjectIdentity required"); - MutableAcl acl = getFromCache(objectIdentity); + MutableAcl acl = getFromCache(objectIdentity); - if (acl != null) { - cache.evict(acl.getId()); - cache.evict(acl.getObjectIdentity()); - } - } + if (acl != null) { + cache.evict(acl.getId()); + cache.evict(acl.getObjectIdentity()); + } + } - public MutableAcl getFromCache(ObjectIdentity objectIdentity) { - Assert.notNull(objectIdentity, "ObjectIdentity required"); - return getFromCache((Object)objectIdentity); - } + public MutableAcl getFromCache(ObjectIdentity objectIdentity) { + Assert.notNull(objectIdentity, "ObjectIdentity required"); + return getFromCache((Object) objectIdentity); + } - public MutableAcl getFromCache(Serializable pk) { - Assert.notNull(pk, "Primary key (identifier) required"); - return getFromCache((Object)pk); - } + public MutableAcl getFromCache(Serializable pk) { + Assert.notNull(pk, "Primary key (identifier) required"); + return getFromCache((Object) pk); + } - public void putInCache(MutableAcl acl) { - Assert.notNull(acl, "Acl required"); - Assert.notNull(acl.getObjectIdentity(), "ObjectIdentity required"); - Assert.notNull(acl.getId(), "ID required"); + public void putInCache(MutableAcl acl) { + Assert.notNull(acl, "Acl required"); + Assert.notNull(acl.getObjectIdentity(), "ObjectIdentity required"); + Assert.notNull(acl.getId(), "ID required"); - if ((acl.getParentAcl() != null) && (acl.getParentAcl() instanceof MutableAcl)) { - putInCache((MutableAcl) acl.getParentAcl()); - } + if ((acl.getParentAcl() != null) && (acl.getParentAcl() instanceof MutableAcl)) { + putInCache((MutableAcl) acl.getParentAcl()); + } - cache.put(acl.getObjectIdentity(), acl); - cache.put(acl.getId(), acl); - } + cache.put(acl.getObjectIdentity(), acl); + cache.put(acl.getId(), acl); + } - private MutableAcl getFromCache(Object key) { - Cache.ValueWrapper element = cache.get(key); + private MutableAcl getFromCache(Object key) { + Cache.ValueWrapper element = cache.get(key); - if (element == null) { - return null; - } + if (element == null) { + return null; + } - return initializeTransientFields((MutableAcl) element.get()); - } + return initializeTransientFields((MutableAcl) element.get()); + } - private MutableAcl initializeTransientFields(MutableAcl value) { - if (value instanceof AclImpl) { - FieldUtils.setProtectedFieldValue("aclAuthorizationStrategy", value, this.aclAuthorizationStrategy); - FieldUtils.setProtectedFieldValue("permissionGrantingStrategy", value, this.permissionGrantingStrategy); - } + private MutableAcl initializeTransientFields(MutableAcl value) { + if (value instanceof AclImpl) { + FieldUtils.setProtectedFieldValue("aclAuthorizationStrategy", value, + this.aclAuthorizationStrategy); + FieldUtils.setProtectedFieldValue("permissionGrantingStrategy", value, + this.permissionGrantingStrategy); + } - if (value.getParentAcl() != null) { - initializeTransientFields((MutableAcl) value.getParentAcl()); - } - return value; - } + if (value.getParentAcl() != null) { + initializeTransientFields((MutableAcl) value.getParentAcl()); + } + return value; + } - public void clearCache() { - cache.clear(); - } + public void clearCache() { + cache.clear(); + } } diff --git a/acl/src/main/java/org/springframework/security/acls/jdbc/BasicLookupStrategy.java b/acl/src/main/java/org/springframework/security/acls/jdbc/BasicLookupStrategy.java index aaf742cb41..ce8178f6e6 100644 --- a/acl/src/main/java/org/springframework/security/acls/jdbc/BasicLookupStrategy.java +++ b/acl/src/main/java/org/springframework/security/acls/jdbc/BasicLookupStrategy.java @@ -55,600 +55,650 @@ import org.springframework.security.acls.model.UnloadedSidException; import org.springframework.security.util.FieldUtils; import org.springframework.util.Assert; - /** * Performs lookups in a manner that is compatible with ANSI SQL. *

- * NB: This implementation does attempt to provide reasonably optimised lookups - within the constraints of a normalised - * database and standard ANSI SQL features. If you are willing to sacrifice either of these constraints - * (e.g. use a particular database feature such as hierarchical queries or materalized views, or reduce normalisation) - * you are likely to achieve better performance. In such situations you will need to provide your own custom - * LookupStrategy. This class does not support subclassing, as it is likely to change in future releases - * and therefore subclassing is unsupported. + * NB: This implementation does attempt to provide reasonably optimised lookups - within + * the constraints of a normalised database and standard ANSI SQL features. If you are + * willing to sacrifice either of these constraints (e.g. use a particular database + * feature such as hierarchical queries or materalized views, or reduce normalisation) you + * are likely to achieve better performance. In such situations you will need to provide + * your own custom LookupStrategy. This class does not support subclassing, + * as it is likely to change in future releases and therefore subclassing is unsupported. *

- * There are two SQL queries executed, one in the lookupPrimaryKeys method and one in - * lookupObjectIdentities. These are built from the same select and "order by" clause, using a different - * where clause in each case. In order to use custom schema or column names, each of these SQL clauses can be - * customized, but they must be consistent with each other and with the expected result set - * generated by the the default values. + * There are two SQL queries executed, one in the lookupPrimaryKeys method and + * one in lookupObjectIdentities. These are built from the same select and + * "order by" clause, using a different where clause in each case. In order to use custom + * schema or column names, each of these SQL clauses can be customized, but they must be + * consistent with each other and with the expected result set generated by the the + * default values. * * @author Ben Alex */ public class BasicLookupStrategy implements LookupStrategy { - public final static String DEFAULT_SELECT_CLAUSE = "select acl_object_identity.object_id_identity, " - + "acl_entry.ace_order, " - + "acl_object_identity.id as acl_id, " - + "acl_object_identity.parent_object, " - + "acl_object_identity.entries_inheriting, " - + "acl_entry.id as ace_id, " - + "acl_entry.mask, " - + "acl_entry.granting, " - + "acl_entry.audit_success, " - + "acl_entry.audit_failure, " - + "acl_sid.principal as ace_principal, " - + "acl_sid.sid as ace_sid, " - + "acli_sid.principal as acl_principal, " - + "acli_sid.sid as acl_sid, " - + "acl_class.class " - + "from acl_object_identity " - + "left join acl_sid acli_sid on acli_sid.id = acl_object_identity.owner_sid " - + "left join acl_class on acl_class.id = acl_object_identity.object_id_class " - + "left join acl_entry on acl_object_identity.id = acl_entry.acl_object_identity " - + "left join acl_sid on acl_entry.sid = acl_sid.id " - + "where ( "; - - private final static String DEFAULT_LOOKUP_KEYS_WHERE_CLAUSE = "(acl_object_identity.id = ?)"; - - private final static String DEFAULT_LOOKUP_IDENTITIES_WHERE_CLAUSE = "(acl_object_identity.object_id_identity = ? and acl_class.class = ?)"; - - public final static String DEFAULT_ORDER_BY_CLAUSE = ") order by acl_object_identity.object_id_identity" - + " asc, acl_entry.ace_order asc"; - - //~ Instance fields ================================================================================================ - - private final AclAuthorizationStrategy aclAuthorizationStrategy; - private PermissionFactory permissionFactory = new DefaultPermissionFactory(); - private final AclCache aclCache; - private final PermissionGrantingStrategy grantingStrategy; - private final JdbcTemplate jdbcTemplate; - private int batchSize = 50; - - private final Field fieldAces = FieldUtils.getField(AclImpl.class, "aces"); - private final Field fieldAcl = FieldUtils.getField(AccessControlEntryImpl.class, "acl"); - - // SQL Customization fields - private String selectClause = DEFAULT_SELECT_CLAUSE; - private String lookupPrimaryKeysWhereClause = DEFAULT_LOOKUP_KEYS_WHERE_CLAUSE; - private String lookupObjectIdentitiesWhereClause = DEFAULT_LOOKUP_IDENTITIES_WHERE_CLAUSE; - private String orderByClause = DEFAULT_ORDER_BY_CLAUSE; - - //~ Constructors =================================================================================================== - - /** - * Constructor accepting mandatory arguments - * - * @param dataSource to access the database - * @param aclCache the cache where fully-loaded elements can be stored - * @param aclAuthorizationStrategy authorization strategy (required) - */ - public BasicLookupStrategy(DataSource dataSource, AclCache aclCache, - AclAuthorizationStrategy aclAuthorizationStrategy, AuditLogger auditLogger) { - this(dataSource, aclCache, aclAuthorizationStrategy, new DefaultPermissionGrantingStrategy(auditLogger)); - } - - /** - * Creates a new instance - * - * @param dataSource to access the database - * @param aclCache the cache where fully-loaded elements can be stored - * @param aclAuthorizationStrategy authorization strategy (required) - * @param grantingStrategy the PermissionGrantingStrategy - */ - public BasicLookupStrategy(DataSource dataSource, AclCache aclCache, - AclAuthorizationStrategy aclAuthorizationStrategy, PermissionGrantingStrategy grantingStrategy) { - Assert.notNull(dataSource, "DataSource required"); - Assert.notNull(aclCache, "AclCache required"); - Assert.notNull(aclAuthorizationStrategy, "AclAuthorizationStrategy required"); - Assert.notNull(grantingStrategy, "grantingStrategy required"); - jdbcTemplate = new JdbcTemplate(dataSource); - this.aclCache = aclCache; - this.aclAuthorizationStrategy = aclAuthorizationStrategy; - this.grantingStrategy = grantingStrategy; - fieldAces.setAccessible(true); - fieldAcl.setAccessible(true); - - } - - //~ Methods ======================================================================================================== - - private String computeRepeatingSql(String repeatingSql, int requiredRepetitions) { - assert requiredRepetitions > 0 : "requiredRepetitions must be > 0"; - - final String startSql = selectClause; - - final String endSql = orderByClause; - - StringBuilder sqlStringBldr = - new StringBuilder(startSql.length() + endSql.length() + requiredRepetitions * (repeatingSql.length() + 4)); - sqlStringBldr.append(startSql); - - for (int i = 1; i <= requiredRepetitions; i++) { - sqlStringBldr.append(repeatingSql); - - if (i != requiredRepetitions) { - sqlStringBldr.append(" or "); - } - } - - sqlStringBldr.append(endSql); - - return sqlStringBldr.toString(); - } - - @SuppressWarnings("unchecked") - private List readAces(AclImpl acl) { - try { - return (List) fieldAces.get(acl); - } catch (IllegalAccessException e) { - throw new IllegalStateException("Could not obtain AclImpl.aces field", e); - } - } - - private void setAclOnAce(AccessControlEntryImpl ace, AclImpl acl) { - try { - fieldAcl.set(ace, acl); - } catch (IllegalAccessException e) { - throw new IllegalStateException("Could not or set AclImpl on AccessControlEntryImpl fields", e); - } - } - - private void setAces(AclImpl acl, List aces) { - try { - fieldAces.set(acl, aces); - } catch (IllegalAccessException e) { - throw new IllegalStateException("Could not set AclImpl entries", e); - } - } - - /** - * Locates the primary key IDs specified in "findNow", adding AclImpl instances with StubAclParents to the - * "acls" Map. - * - * @param acls the AclImpls (with StubAclParents) - * @param findNow Long-based primary keys to retrieve - * @param sids - */ - private void lookupPrimaryKeys(final Map acls, final Set findNow, final List sids) { - Assert.notNull(acls, "ACLs are required"); - Assert.notEmpty(findNow, "Items to find now required"); - - String sql = computeRepeatingSql(lookupPrimaryKeysWhereClause, findNow.size()); - - Set parentsToLookup = jdbcTemplate.query(sql, - new PreparedStatementSetter() { - public void setValues(PreparedStatement ps) throws SQLException { - int i = 0; - - for (Long toFind : findNow) { - i++; - ps.setLong(i, toFind); - } - } - }, new ProcessResultSet(acls, sids)); - - // Lookup the parents, now that our JdbcTemplate has released the database connection (SEC-547) - if (parentsToLookup.size() > 0) { - lookupPrimaryKeys(acls, parentsToLookup, sids); - } - } - - /** - * The main method. - *

- * WARNING: This implementation completely disregards the "sids" argument! Every item in the cache is expected to - * contain all SIDs. If you have serious performance needs (e.g. a very large number of - * SIDs per object identity), you'll probably want to develop a custom {@link LookupStrategy} implementation - * instead. - *

- * The implementation works in batch sizes specified by {@link #batchSize}. - * - * @param objects the identities to lookup (required) - * @param sids the SIDs for which identities are required (ignored by this implementation) - * - * @return a Map where keys represent the {@link ObjectIdentity} of the located {@link Acl} and values - * are the located {@link Acl} (never null although some entries may be missing; this method - * should not throw {@link NotFoundException}, as a chain of {@link LookupStrategy}s may be used - * to automatically create entries if required) - */ - public final Map readAclsById(List objects, List sids) { - Assert.isTrue(batchSize >= 1, "BatchSize must be >= 1"); - Assert.notEmpty(objects, "Objects to lookup required"); - - // Map - Map result = new HashMap(); // contains FULLY loaded Acl objects - - Set currentBatchToLoad = new HashSet(); - - for (int i = 0; i < objects.size(); i++) { - final ObjectIdentity oid = objects.get(i); - boolean aclFound = false; - - // Check we don't already have this ACL in the results - if (result.containsKey(oid)) { - aclFound = true; - } - - // Check cache for the present ACL entry - if (!aclFound) { - Acl acl = aclCache.getFromCache(oid); - - // Ensure any cached element supports all the requested SIDs - // (they should always, as our base impl doesn't filter on SID) - if (acl != null) { - if (acl.isSidLoaded(sids)) { - result.put(acl.getObjectIdentity(), acl); - aclFound = true; - } else { - throw new IllegalStateException( - "Error: SID-filtered element detected when implementation does not perform SID filtering " - + "- have you added something to the cache manually?"); - } - } - } - - // Load the ACL from the database - if (!aclFound) { - currentBatchToLoad.add(oid); - } - - // Is it time to load from JDBC the currentBatchToLoad? - if ((currentBatchToLoad.size() == this.batchSize) || ((i + 1) == objects.size())) { - if (currentBatchToLoad.size() > 0) { - Map loadedBatch = lookupObjectIdentities(currentBatchToLoad, sids); - - // Add loaded batch (all elements 100% initialized) to results - result.putAll(loadedBatch); - - // Add the loaded batch to the cache - - for (Acl loadedAcl : loadedBatch.values()) { - aclCache.putInCache((AclImpl) loadedAcl); - } - - currentBatchToLoad.clear(); - } - } - } - - return result; - } - - /** - * Looks up a batch of ObjectIdentitys directly from the database. - *

- * The caller is responsible for optimization issues, such as selecting the identities to lookup, ensuring the - * cache doesn't contain them already, and adding the returned elements to the cache etc. - *

- * This subclass is required to return fully valid Acls, including properly-configured - * parent ACLs. - * - */ - private Map lookupObjectIdentities(final Collection objectIdentities, List sids) { - Assert.notEmpty(objectIdentities, "Must provide identities to lookup"); - - final Map acls = new HashMap(); // contains Acls with StubAclParents - - // Make the "acls" map contain all requested objectIdentities - // (including markers to each parent in the hierarchy) - String sql = computeRepeatingSql(lookupObjectIdentitiesWhereClause, objectIdentities.size()); - - Set parentsToLookup = jdbcTemplate.query(sql, - new PreparedStatementSetter() { - public void setValues(PreparedStatement ps) throws SQLException { - int i = 0; - for (ObjectIdentity oid : objectIdentities) { - // Determine prepared statement values for this iteration - String type = oid.getType(); - - // No need to check for nulls, as guaranteed non-null by ObjectIdentity.getIdentifier() interface contract - String identifier = oid.getIdentifier().toString(); - long id = (Long.valueOf(identifier)).longValue(); - - // Inject values - ps.setLong((2 * i) + 1, id); - ps.setString((2 * i) + 2, type); - i++; - } - } - }, new ProcessResultSet(acls, sids)); - - // Lookup the parents, now that our JdbcTemplate has released the database connection (SEC-547) - if (parentsToLookup.size() > 0) { - lookupPrimaryKeys(acls, parentsToLookup, sids); - } - - // Finally, convert our "acls" containing StubAclParents into true Acls - Map resultMap = new HashMap(); - - for (Acl inputAcl : acls.values()) { - Assert.isInstanceOf(AclImpl.class, inputAcl, "Map should have contained an AclImpl"); - Assert.isInstanceOf(Long.class, ((AclImpl) inputAcl).getId(), "Acl.getId() must be Long"); - - Acl result = convert(acls, (Long) ((AclImpl) inputAcl).getId()); - resultMap.put(result.getObjectIdentity(), result); - } - - return resultMap; - } - - /** - * The final phase of converting the Map of AclImpl instances which contain - * StubAclParents into proper, valid AclImpls with correct ACL parents. - * - * @param inputMap the unconverted AclImpls - * @param currentIdentity the currentAcl that we wish to convert (this may be - * - */ - private AclImpl convert(Map inputMap, Long currentIdentity) { - Assert.notEmpty(inputMap, "InputMap required"); - Assert.notNull(currentIdentity, "CurrentIdentity required"); - - // Retrieve this Acl from the InputMap - Acl uncastAcl = inputMap.get(currentIdentity); - Assert.isInstanceOf(AclImpl.class, uncastAcl, "The inputMap contained a non-AclImpl"); - - AclImpl inputAcl = (AclImpl) uncastAcl; - - Acl parent = inputAcl.getParentAcl(); - - if ((parent != null) && parent instanceof StubAclParent) { - // Lookup the parent - StubAclParent stubAclParent = (StubAclParent) parent; - parent = convert(inputMap, stubAclParent.getId()); - } - - // Now we have the parent (if there is one), create the true AclImpl - AclImpl result = new AclImpl(inputAcl.getObjectIdentity(), (Long) inputAcl.getId(), aclAuthorizationStrategy, - grantingStrategy, parent, null, inputAcl.isEntriesInheriting(), inputAcl.getOwner()); - - // Copy the "aces" from the input to the destination - - // Obtain the "aces" from the input ACL - List aces = readAces(inputAcl); - - // Create a list in which to store the "aces" for the "result" AclImpl instance - List acesNew = new ArrayList(); - - // Iterate over the "aces" input and replace each nested AccessControlEntryImpl.getAcl() with the new "result" AclImpl instance - // This ensures StubAclParent instances are removed, as per SEC-951 - for (AccessControlEntryImpl ace : aces) { - setAclOnAce(ace, result); - acesNew.add(ace); - } - - // Finally, now that the "aces" have been converted to have the "result" AclImpl instance, modify the "result" AclImpl instance - setAces(result, acesNew); - - return result; - } - - /** - * Creates a particular implementation of {@link Sid} depending on the arguments. - * - * @param sid the name of the sid representing its unique identifier. In typical ACL database schema it's - * located in table {@code acl_sid} table, {@code sid} column. - * @param isPrincipal whether it's a user or granted authority like role - * @return the instance of Sid with the {@code sidName} as an identifier - */ - protected Sid createSid(boolean isPrincipal, String sid) { - if (isPrincipal) { - return new PrincipalSid(sid); - } else { - return new GrantedAuthoritySid(sid); - } - } - - /** - * Sets the {@code PermissionFactory} instance which will be used to convert loaded permission - * data values to {@code Permission}s. A {@code DefaultPermissionFactory} will be used by default. - * - * @param permissionFactory - */ - public final void setPermissionFactory(PermissionFactory permissionFactory) { - this.permissionFactory = permissionFactory; - } - - public final void setBatchSize(int batchSize) { - this.batchSize = batchSize; - } - - /** - * The SQL for the select clause. If customizing in order to modify - * column names, schema etc, the other SQL customization fields must also be set to match. - * - * @param selectClause the select clause, which defaults to {@link #DEFAULT_SELECT_CLAUSE}. - */ - public final void setSelectClause(String selectClause) { - this.selectClause = selectClause; - } - - /** - * The SQL for the where clause used in the lookupPrimaryKey method. - */ - public final void setLookupPrimaryKeysWhereClause(String lookupPrimaryKeysWhereClause) { - this.lookupPrimaryKeysWhereClause = lookupPrimaryKeysWhereClause; - } - - /** - * The SQL for the where clause used in the lookupObjectIdentities method. - */ - public final void setLookupObjectIdentitiesWhereClause(String lookupObjectIdentitiesWhereClause) { - this.lookupObjectIdentitiesWhereClause = lookupObjectIdentitiesWhereClause; - } - - /** - * The SQL for the "order by" clause used in both queries. - */ - public final void setOrderByClause(String orderByClause) { - this.orderByClause = orderByClause; - } - - //~ Inner Classes ================================================================================================== - - private class ProcessResultSet implements ResultSetExtractor> { - private final Map acls; - private final List sids; - - public ProcessResultSet(Map acls, List sids) { - Assert.notNull(acls, "ACLs cannot be null"); - this.acls = acls; - this.sids = sids; // can be null - } - - /** - * Implementation of {@link ResultSetExtractor#extractData(ResultSet)}. - * Creates an {@link Acl} for each row in the {@link ResultSet} and - * ensures it is in member field acls. Any {@link Acl} with - * a parent will have the parents id returned in a set. The returned - * set of ids may requires further processing. - * @param rs The {@link ResultSet} to be processed - * @return a list of parent IDs remaining to be looked up (may be empty, but never null) - * @throws SQLException - */ - public Set extractData(ResultSet rs) throws SQLException { - Set parentIdsToLookup = new HashSet(); // Set of parent_id Longs - - while (rs.next()) { - // Convert current row into an Acl (albeit with a StubAclParent) - convertCurrentResultIntoObject(acls, rs); - - // Figure out if this row means we need to lookup another parent - long parentId = rs.getLong("parent_object"); - - if (parentId != 0) { - // See if it's already in the "acls" - if (acls.containsKey(new Long(parentId))) { - continue; // skip this while iteration - } - - // Now try to find it in the cache - MutableAcl cached = aclCache.getFromCache(new Long(parentId)); - - if ((cached == null) || !cached.isSidLoaded(sids)) { - parentIdsToLookup.add(new Long(parentId)); - } else { - // Pop into the acls map, so our convert method doesn't - // need to deal with an unsynchronized AclCache - acls.put(cached.getId(), cached); - } - } - } - - // Return the parents left to lookup to the caller - return parentIdsToLookup; - } - - /** - * Accepts the current ResultSet row, and converts it into an AclImpl that - * contains a StubAclParent - * - * @param acls the Map we should add the converted Acl to - * @param rs the ResultSet focused on a current row - * - * @throws SQLException if something goes wrong converting values - */ - private void convertCurrentResultIntoObject(Map acls, ResultSet rs) throws SQLException { - Long id = new Long(rs.getLong("acl_id")); - - // If we already have an ACL for this ID, just create the ACE - Acl acl = acls.get(id); - - if (acl == null) { - // Make an AclImpl and pop it into the Map - ObjectIdentity objectIdentity = new ObjectIdentityImpl(rs.getString("class"), - Long.valueOf(rs.getLong("object_id_identity"))); - - Acl parentAcl = null; - long parentAclId = rs.getLong("parent_object"); - - if (parentAclId != 0) { - parentAcl = new StubAclParent(Long.valueOf(parentAclId)); - } - - boolean entriesInheriting = rs.getBoolean("entries_inheriting"); - Sid owner = createSid(rs.getBoolean("acl_principal"), rs.getString("acl_sid")); - - acl = new AclImpl(objectIdentity, id, aclAuthorizationStrategy, grantingStrategy, parentAcl, null, - entriesInheriting, owner); - - acls.put(id, acl); - } - - // Add an extra ACE to the ACL (ORDER BY maintains the ACE list order) - // It is permissible to have no ACEs in an ACL (which is detected by a null ACE_SID) - if (rs.getString("ace_sid") != null) { - Long aceId = new Long(rs.getLong("ace_id")); - Sid recipient = createSid(rs.getBoolean("ace_principal"), rs.getString("ace_sid")); - - int mask = rs.getInt("mask"); - Permission permission = permissionFactory.buildFromMask(mask); - boolean granting = rs.getBoolean("granting"); - boolean auditSuccess = rs.getBoolean("audit_success"); - boolean auditFailure = rs.getBoolean("audit_failure"); - - AccessControlEntryImpl ace = new AccessControlEntryImpl(aceId, acl, recipient, permission, granting, - auditSuccess, auditFailure); - - //Field acesField = FieldUtils.getField(AclImpl.class, "aces"); - List aces = readAces((AclImpl)acl); - - // Add the ACE if it doesn't already exist in the ACL.aces field - if (!aces.contains(ace)) { - aces.add(ace); - } - } - } - } - - private class StubAclParent implements Acl { - private final Long id; - - public StubAclParent(Long id) { - this.id = id; - } - - public List getEntries() { - throw new UnsupportedOperationException("Stub only"); - } - - public Long getId() { - return id; - } - - public ObjectIdentity getObjectIdentity() { - throw new UnsupportedOperationException("Stub only"); - } - - public Sid getOwner() { - throw new UnsupportedOperationException("Stub only"); - } - - public Acl getParentAcl() { - throw new UnsupportedOperationException("Stub only"); - } - - public boolean isEntriesInheriting() { - throw new UnsupportedOperationException("Stub only"); - } - - public boolean isGranted(List permission, List sids, boolean administrativeMode) - throws NotFoundException, UnloadedSidException { - throw new UnsupportedOperationException("Stub only"); - } - - public boolean isSidLoaded(List sids) { - throw new UnsupportedOperationException("Stub only"); - } - } + public final static String DEFAULT_SELECT_CLAUSE = "select acl_object_identity.object_id_identity, " + + "acl_entry.ace_order, " + + "acl_object_identity.id as acl_id, " + + "acl_object_identity.parent_object, " + + "acl_object_identity.entries_inheriting, " + + "acl_entry.id as ace_id, " + + "acl_entry.mask, " + + "acl_entry.granting, " + + "acl_entry.audit_success, " + + "acl_entry.audit_failure, " + + "acl_sid.principal as ace_principal, " + + "acl_sid.sid as ace_sid, " + + "acli_sid.principal as acl_principal, " + + "acli_sid.sid as acl_sid, " + + "acl_class.class " + + "from acl_object_identity " + + "left join acl_sid acli_sid on acli_sid.id = acl_object_identity.owner_sid " + + "left join acl_class on acl_class.id = acl_object_identity.object_id_class " + + "left join acl_entry on acl_object_identity.id = acl_entry.acl_object_identity " + + "left join acl_sid on acl_entry.sid = acl_sid.id " + "where ( "; + + private final static String DEFAULT_LOOKUP_KEYS_WHERE_CLAUSE = "(acl_object_identity.id = ?)"; + + private final static String DEFAULT_LOOKUP_IDENTITIES_WHERE_CLAUSE = "(acl_object_identity.object_id_identity = ? and acl_class.class = ?)"; + + public final static String DEFAULT_ORDER_BY_CLAUSE = ") order by acl_object_identity.object_id_identity" + + " asc, acl_entry.ace_order asc"; + + // ~ Instance fields + // ================================================================================================ + + private final AclAuthorizationStrategy aclAuthorizationStrategy; + private PermissionFactory permissionFactory = new DefaultPermissionFactory(); + private final AclCache aclCache; + private final PermissionGrantingStrategy grantingStrategy; + private final JdbcTemplate jdbcTemplate; + private int batchSize = 50; + + private final Field fieldAces = FieldUtils.getField(AclImpl.class, "aces"); + private final Field fieldAcl = FieldUtils.getField(AccessControlEntryImpl.class, + "acl"); + + // SQL Customization fields + private String selectClause = DEFAULT_SELECT_CLAUSE; + private String lookupPrimaryKeysWhereClause = DEFAULT_LOOKUP_KEYS_WHERE_CLAUSE; + private String lookupObjectIdentitiesWhereClause = DEFAULT_LOOKUP_IDENTITIES_WHERE_CLAUSE; + private String orderByClause = DEFAULT_ORDER_BY_CLAUSE; + + // ~ Constructors + // =================================================================================================== + + /** + * Constructor accepting mandatory arguments + * + * @param dataSource to access the database + * @param aclCache the cache where fully-loaded elements can be stored + * @param aclAuthorizationStrategy authorization strategy (required) + */ + public BasicLookupStrategy(DataSource dataSource, AclCache aclCache, + AclAuthorizationStrategy aclAuthorizationStrategy, AuditLogger auditLogger) { + this(dataSource, aclCache, aclAuthorizationStrategy, + new DefaultPermissionGrantingStrategy(auditLogger)); + } + + /** + * Creates a new instance + * + * @param dataSource to access the database + * @param aclCache the cache where fully-loaded elements can be stored + * @param aclAuthorizationStrategy authorization strategy (required) + * @param grantingStrategy the PermissionGrantingStrategy + */ + public BasicLookupStrategy(DataSource dataSource, AclCache aclCache, + AclAuthorizationStrategy aclAuthorizationStrategy, + PermissionGrantingStrategy grantingStrategy) { + Assert.notNull(dataSource, "DataSource required"); + Assert.notNull(aclCache, "AclCache required"); + Assert.notNull(aclAuthorizationStrategy, "AclAuthorizationStrategy required"); + Assert.notNull(grantingStrategy, "grantingStrategy required"); + jdbcTemplate = new JdbcTemplate(dataSource); + this.aclCache = aclCache; + this.aclAuthorizationStrategy = aclAuthorizationStrategy; + this.grantingStrategy = grantingStrategy; + fieldAces.setAccessible(true); + fieldAcl.setAccessible(true); + + } + + // ~ Methods + // ======================================================================================================== + + private String computeRepeatingSql(String repeatingSql, int requiredRepetitions) { + assert requiredRepetitions > 0 : "requiredRepetitions must be > 0"; + + final String startSql = selectClause; + + final String endSql = orderByClause; + + StringBuilder sqlStringBldr = new StringBuilder(startSql.length() + + endSql.length() + requiredRepetitions * (repeatingSql.length() + 4)); + sqlStringBldr.append(startSql); + + for (int i = 1; i <= requiredRepetitions; i++) { + sqlStringBldr.append(repeatingSql); + + if (i != requiredRepetitions) { + sqlStringBldr.append(" or "); + } + } + + sqlStringBldr.append(endSql); + + return sqlStringBldr.toString(); + } + + @SuppressWarnings("unchecked") + private List readAces(AclImpl acl) { + try { + return (List) fieldAces.get(acl); + } + catch (IllegalAccessException e) { + throw new IllegalStateException("Could not obtain AclImpl.aces field", e); + } + } + + private void setAclOnAce(AccessControlEntryImpl ace, AclImpl acl) { + try { + fieldAcl.set(ace, acl); + } + catch (IllegalAccessException e) { + throw new IllegalStateException( + "Could not or set AclImpl on AccessControlEntryImpl fields", e); + } + } + + private void setAces(AclImpl acl, List aces) { + try { + fieldAces.set(acl, aces); + } + catch (IllegalAccessException e) { + throw new IllegalStateException("Could not set AclImpl entries", e); + } + } + + /** + * Locates the primary key IDs specified in "findNow", adding AclImpl instances with + * StubAclParents to the "acls" Map. + * + * @param acls the AclImpls (with StubAclParents) + * @param findNow Long-based primary keys to retrieve + * @param sids + */ + private void lookupPrimaryKeys(final Map acls, + final Set findNow, final List sids) { + Assert.notNull(acls, "ACLs are required"); + Assert.notEmpty(findNow, "Items to find now required"); + + String sql = computeRepeatingSql(lookupPrimaryKeysWhereClause, findNow.size()); + + Set parentsToLookup = jdbcTemplate.query(sql, + new PreparedStatementSetter() { + public void setValues(PreparedStatement ps) throws SQLException { + int i = 0; + + for (Long toFind : findNow) { + i++; + ps.setLong(i, toFind); + } + } + }, new ProcessResultSet(acls, sids)); + + // Lookup the parents, now that our JdbcTemplate has released the database + // connection (SEC-547) + if (parentsToLookup.size() > 0) { + lookupPrimaryKeys(acls, parentsToLookup, sids); + } + } + + /** + * The main method. + *

+ * WARNING: This implementation completely disregards the "sids" argument! Every item + * in the cache is expected to contain all SIDs. If you have serious performance needs + * (e.g. a very large number of SIDs per object identity), you'll probably want to + * develop a custom {@link LookupStrategy} implementation instead. + *

+ * The implementation works in batch sizes specified by {@link #batchSize}. + * + * @param objects the identities to lookup (required) + * @param sids the SIDs for which identities are required (ignored by this + * implementation) + * + * @return a Map where keys represent the {@link ObjectIdentity} of the + * located {@link Acl} and values are the located {@link Acl} (never null + * although some entries may be missing; this method should not throw + * {@link NotFoundException}, as a chain of {@link LookupStrategy}s may be used to + * automatically create entries if required) + */ + public final Map readAclsById(List objects, + List sids) { + Assert.isTrue(batchSize >= 1, "BatchSize must be >= 1"); + Assert.notEmpty(objects, "Objects to lookup required"); + + // Map + Map result = new HashMap(); // contains + // FULLY + // loaded + // Acl + // objects + + Set currentBatchToLoad = new HashSet(); + + for (int i = 0; i < objects.size(); i++) { + final ObjectIdentity oid = objects.get(i); + boolean aclFound = false; + + // Check we don't already have this ACL in the results + if (result.containsKey(oid)) { + aclFound = true; + } + + // Check cache for the present ACL entry + if (!aclFound) { + Acl acl = aclCache.getFromCache(oid); + + // Ensure any cached element supports all the requested SIDs + // (they should always, as our base impl doesn't filter on SID) + if (acl != null) { + if (acl.isSidLoaded(sids)) { + result.put(acl.getObjectIdentity(), acl); + aclFound = true; + } + else { + throw new IllegalStateException( + "Error: SID-filtered element detected when implementation does not perform SID filtering " + + "- have you added something to the cache manually?"); + } + } + } + + // Load the ACL from the database + if (!aclFound) { + currentBatchToLoad.add(oid); + } + + // Is it time to load from JDBC the currentBatchToLoad? + if ((currentBatchToLoad.size() == this.batchSize) + || ((i + 1) == objects.size())) { + if (currentBatchToLoad.size() > 0) { + Map loadedBatch = lookupObjectIdentities( + currentBatchToLoad, sids); + + // Add loaded batch (all elements 100% initialized) to results + result.putAll(loadedBatch); + + // Add the loaded batch to the cache + + for (Acl loadedAcl : loadedBatch.values()) { + aclCache.putInCache((AclImpl) loadedAcl); + } + + currentBatchToLoad.clear(); + } + } + } + + return result; + } + + /** + * Looks up a batch of ObjectIdentitys directly from the database. + *

+ * The caller is responsible for optimization issues, such as selecting the identities + * to lookup, ensuring the cache doesn't contain them already, and adding the returned + * elements to the cache etc. + *

+ * This subclass is required to return fully valid Acls, including + * properly-configured parent ACLs. + * + */ + private Map lookupObjectIdentities( + final Collection objectIdentities, List sids) { + Assert.notEmpty(objectIdentities, "Must provide identities to lookup"); + + final Map acls = new HashMap(); // contains + // Acls + // with + // StubAclParents + + // Make the "acls" map contain all requested objectIdentities + // (including markers to each parent in the hierarchy) + String sql = computeRepeatingSql(lookupObjectIdentitiesWhereClause, + objectIdentities.size()); + + Set parentsToLookup = jdbcTemplate.query(sql, + new PreparedStatementSetter() { + public void setValues(PreparedStatement ps) throws SQLException { + int i = 0; + for (ObjectIdentity oid : objectIdentities) { + // Determine prepared statement values for this iteration + String type = oid.getType(); + + // No need to check for nulls, as guaranteed non-null by + // ObjectIdentity.getIdentifier() interface contract + String identifier = oid.getIdentifier().toString(); + long id = (Long.valueOf(identifier)).longValue(); + + // Inject values + ps.setLong((2 * i) + 1, id); + ps.setString((2 * i) + 2, type); + i++; + } + } + }, new ProcessResultSet(acls, sids)); + + // Lookup the parents, now that our JdbcTemplate has released the database + // connection (SEC-547) + if (parentsToLookup.size() > 0) { + lookupPrimaryKeys(acls, parentsToLookup, sids); + } + + // Finally, convert our "acls" containing StubAclParents into true Acls + Map resultMap = new HashMap(); + + for (Acl inputAcl : acls.values()) { + Assert.isInstanceOf(AclImpl.class, inputAcl, + "Map should have contained an AclImpl"); + Assert.isInstanceOf(Long.class, ((AclImpl) inputAcl).getId(), + "Acl.getId() must be Long"); + + Acl result = convert(acls, (Long) ((AclImpl) inputAcl).getId()); + resultMap.put(result.getObjectIdentity(), result); + } + + return resultMap; + } + + /** + * The final phase of converting the Map of AclImpl + * instances which contain StubAclParents into proper, valid + * AclImpls with correct ACL parents. + * + * @param inputMap the unconverted AclImpls + * @param currentIdentity the currentAcl that we wish to convert (this + * may be + * + */ + private AclImpl convert(Map inputMap, Long currentIdentity) { + Assert.notEmpty(inputMap, "InputMap required"); + Assert.notNull(currentIdentity, "CurrentIdentity required"); + + // Retrieve this Acl from the InputMap + Acl uncastAcl = inputMap.get(currentIdentity); + Assert.isInstanceOf(AclImpl.class, uncastAcl, + "The inputMap contained a non-AclImpl"); + + AclImpl inputAcl = (AclImpl) uncastAcl; + + Acl parent = inputAcl.getParentAcl(); + + if ((parent != null) && parent instanceof StubAclParent) { + // Lookup the parent + StubAclParent stubAclParent = (StubAclParent) parent; + parent = convert(inputMap, stubAclParent.getId()); + } + + // Now we have the parent (if there is one), create the true AclImpl + AclImpl result = new AclImpl(inputAcl.getObjectIdentity(), + (Long) inputAcl.getId(), aclAuthorizationStrategy, grantingStrategy, + parent, null, inputAcl.isEntriesInheriting(), inputAcl.getOwner()); + + // Copy the "aces" from the input to the destination + + // Obtain the "aces" from the input ACL + List aces = readAces(inputAcl); + + // Create a list in which to store the "aces" for the "result" AclImpl instance + List acesNew = new ArrayList(); + + // Iterate over the "aces" input and replace each nested + // AccessControlEntryImpl.getAcl() with the new "result" AclImpl instance + // This ensures StubAclParent instances are removed, as per SEC-951 + for (AccessControlEntryImpl ace : aces) { + setAclOnAce(ace, result); + acesNew.add(ace); + } + + // Finally, now that the "aces" have been converted to have the "result" AclImpl + // instance, modify the "result" AclImpl instance + setAces(result, acesNew); + + return result; + } + + /** + * Creates a particular implementation of {@link Sid} depending on the arguments. + * + * @param sid the name of the sid representing its unique identifier. In typical ACL + * database schema it's located in table {@code acl_sid} table, {@code sid} column. + * @param isPrincipal whether it's a user or granted authority like role + * @return the instance of Sid with the {@code sidName} as an identifier + */ + protected Sid createSid(boolean isPrincipal, String sid) { + if (isPrincipal) { + return new PrincipalSid(sid); + } + else { + return new GrantedAuthoritySid(sid); + } + } + + /** + * Sets the {@code PermissionFactory} instance which will be used to convert loaded + * permission data values to {@code Permission}s. A {@code DefaultPermissionFactory} + * will be used by default. + * + * @param permissionFactory + */ + public final void setPermissionFactory(PermissionFactory permissionFactory) { + this.permissionFactory = permissionFactory; + } + + public final void setBatchSize(int batchSize) { + this.batchSize = batchSize; + } + + /** + * The SQL for the select clause. If customizing in order to modify column names, + * schema etc, the other SQL customization fields must also be set to match. + * + * @param selectClause the select clause, which defaults to + * {@link #DEFAULT_SELECT_CLAUSE}. + */ + public final void setSelectClause(String selectClause) { + this.selectClause = selectClause; + } + + /** + * The SQL for the where clause used in the lookupPrimaryKey method. + */ + public final void setLookupPrimaryKeysWhereClause(String lookupPrimaryKeysWhereClause) { + this.lookupPrimaryKeysWhereClause = lookupPrimaryKeysWhereClause; + } + + /** + * The SQL for the where clause used in the lookupObjectIdentities method. + */ + public final void setLookupObjectIdentitiesWhereClause( + String lookupObjectIdentitiesWhereClause) { + this.lookupObjectIdentitiesWhereClause = lookupObjectIdentitiesWhereClause; + } + + /** + * The SQL for the "order by" clause used in both queries. + */ + public final void setOrderByClause(String orderByClause) { + this.orderByClause = orderByClause; + } + + // ~ Inner Classes + // ================================================================================================== + + private class ProcessResultSet implements ResultSetExtractor> { + private final Map acls; + private final List sids; + + public ProcessResultSet(Map acls, List sids) { + Assert.notNull(acls, "ACLs cannot be null"); + this.acls = acls; + this.sids = sids; // can be null + } + + /** + * Implementation of {@link ResultSetExtractor#extractData(ResultSet)}. Creates an + * {@link Acl} for each row in the {@link ResultSet} and ensures it is in member + * field acls. Any {@link Acl} with a parent will have the parents id + * returned in a set. The returned set of ids may requires further processing. + * @param rs The {@link ResultSet} to be processed + * @return a list of parent IDs remaining to be looked up (may be empty, but never + * null) + * @throws SQLException + */ + public Set extractData(ResultSet rs) throws SQLException { + Set parentIdsToLookup = new HashSet(); // Set of parent_id Longs + + while (rs.next()) { + // Convert current row into an Acl (albeit with a StubAclParent) + convertCurrentResultIntoObject(acls, rs); + + // Figure out if this row means we need to lookup another parent + long parentId = rs.getLong("parent_object"); + + if (parentId != 0) { + // See if it's already in the "acls" + if (acls.containsKey(new Long(parentId))) { + continue; // skip this while iteration + } + + // Now try to find it in the cache + MutableAcl cached = aclCache.getFromCache(new Long(parentId)); + + if ((cached == null) || !cached.isSidLoaded(sids)) { + parentIdsToLookup.add(new Long(parentId)); + } + else { + // Pop into the acls map, so our convert method doesn't + // need to deal with an unsynchronized AclCache + acls.put(cached.getId(), cached); + } + } + } + + // Return the parents left to lookup to the caller + return parentIdsToLookup; + } + + /** + * Accepts the current ResultSet row, and converts it into an + * AclImpl that contains a StubAclParent + * + * @param acls the Map we should add the converted Acl to + * @param rs the ResultSet focused on a current row + * + * @throws SQLException if something goes wrong converting values + */ + private void convertCurrentResultIntoObject(Map acls, + ResultSet rs) throws SQLException { + Long id = new Long(rs.getLong("acl_id")); + + // If we already have an ACL for this ID, just create the ACE + Acl acl = acls.get(id); + + if (acl == null) { + // Make an AclImpl and pop it into the Map + ObjectIdentity objectIdentity = new ObjectIdentityImpl( + rs.getString("class"), Long.valueOf(rs + .getLong("object_id_identity"))); + + Acl parentAcl = null; + long parentAclId = rs.getLong("parent_object"); + + if (parentAclId != 0) { + parentAcl = new StubAclParent(Long.valueOf(parentAclId)); + } + + boolean entriesInheriting = rs.getBoolean("entries_inheriting"); + Sid owner = createSid(rs.getBoolean("acl_principal"), + rs.getString("acl_sid")); + + acl = new AclImpl(objectIdentity, id, aclAuthorizationStrategy, + grantingStrategy, parentAcl, null, entriesInheriting, owner); + + acls.put(id, acl); + } + + // Add an extra ACE to the ACL (ORDER BY maintains the ACE list order) + // It is permissible to have no ACEs in an ACL (which is detected by a null + // ACE_SID) + if (rs.getString("ace_sid") != null) { + Long aceId = new Long(rs.getLong("ace_id")); + Sid recipient = createSid(rs.getBoolean("ace_principal"), + rs.getString("ace_sid")); + + int mask = rs.getInt("mask"); + Permission permission = permissionFactory.buildFromMask(mask); + boolean granting = rs.getBoolean("granting"); + boolean auditSuccess = rs.getBoolean("audit_success"); + boolean auditFailure = rs.getBoolean("audit_failure"); + + AccessControlEntryImpl ace = new AccessControlEntryImpl(aceId, acl, + recipient, permission, granting, auditSuccess, auditFailure); + + // Field acesField = FieldUtils.getField(AclImpl.class, "aces"); + List aces = readAces((AclImpl) acl); + + // Add the ACE if it doesn't already exist in the ACL.aces field + if (!aces.contains(ace)) { + aces.add(ace); + } + } + } + } + + private class StubAclParent implements Acl { + private final Long id; + + public StubAclParent(Long id) { + this.id = id; + } + + public List getEntries() { + throw new UnsupportedOperationException("Stub only"); + } + + public Long getId() { + return id; + } + + public ObjectIdentity getObjectIdentity() { + throw new UnsupportedOperationException("Stub only"); + } + + public Sid getOwner() { + throw new UnsupportedOperationException("Stub only"); + } + + public Acl getParentAcl() { + throw new UnsupportedOperationException("Stub only"); + } + + public boolean isEntriesInheriting() { + throw new UnsupportedOperationException("Stub only"); + } + + public boolean isGranted(List permission, List sids, + boolean administrativeMode) throws NotFoundException, + UnloadedSidException { + throw new UnsupportedOperationException("Stub only"); + } + + public boolean isSidLoaded(List sids) { + throw new UnsupportedOperationException("Stub only"); + } + } } diff --git a/acl/src/main/java/org/springframework/security/acls/jdbc/JdbcAclService.java b/acl/src/main/java/org/springframework/security/acls/jdbc/JdbcAclService.java index b94ca9e5ff..413332d2da 100644 --- a/acl/src/main/java/org/springframework/security/acls/jdbc/JdbcAclService.java +++ b/acl/src/main/java/org/springframework/security/acls/jdbc/JdbcAclService.java @@ -34,96 +34,107 @@ import org.springframework.security.acls.model.ObjectIdentity; import org.springframework.security.acls.model.Sid; import org.springframework.util.Assert; - /** * Simple JDBC-based implementation of AclService. *

- * Requires the "dirty" flags in {@link org.springframework.security.acls.domain.AclImpl} and - * {@link org.springframework.security.acls.domain.AccessControlEntryImpl} to be set, so that the implementation can - * detect changed parameters easily. + * Requires the "dirty" flags in {@link org.springframework.security.acls.domain.AclImpl} + * and {@link org.springframework.security.acls.domain.AccessControlEntryImpl} to be set, + * so that the implementation can detect changed parameters easily. * * @author Ben Alex */ public class JdbcAclService implements AclService { - //~ Static fields/initializers ===================================================================================== + // ~ Static fields/initializers + // ===================================================================================== - protected static final Log log = LogFactory.getLog(JdbcAclService.class); - private static final String DEFAULT_SELECT_ACL_WITH_PARENT_SQL = "select obj.object_id_identity as obj_id, class.class as class " - + "from acl_object_identity obj, acl_object_identity parent, acl_class class " - + "where obj.parent_object = parent.id and obj.object_id_class = class.id " - + "and parent.object_id_identity = ? and parent.object_id_class = (" - + "select id FROM acl_class where acl_class.class = ?)"; + protected static final Log log = LogFactory.getLog(JdbcAclService.class); + private static final String DEFAULT_SELECT_ACL_WITH_PARENT_SQL = "select obj.object_id_identity as obj_id, class.class as class " + + "from acl_object_identity obj, acl_object_identity parent, acl_class class " + + "where obj.parent_object = parent.id and obj.object_id_class = class.id " + + "and parent.object_id_identity = ? and parent.object_id_class = (" + + "select id FROM acl_class where acl_class.class = ?)"; - //~ Instance fields ================================================================================================ + // ~ Instance fields + // ================================================================================================ - protected final JdbcTemplate jdbcTemplate; - private final LookupStrategy lookupStrategy; - private String findChildrenSql = DEFAULT_SELECT_ACL_WITH_PARENT_SQL; + protected final JdbcTemplate jdbcTemplate; + private final LookupStrategy lookupStrategy; + private String findChildrenSql = DEFAULT_SELECT_ACL_WITH_PARENT_SQL; - //~ Constructors =================================================================================================== + // ~ Constructors + // =================================================================================================== - public JdbcAclService(DataSource dataSource, LookupStrategy lookupStrategy) { - Assert.notNull(dataSource, "DataSource required"); - Assert.notNull(lookupStrategy, "LookupStrategy required"); - this.jdbcTemplate = new JdbcTemplate(dataSource); - this.lookupStrategy = lookupStrategy; - } + public JdbcAclService(DataSource dataSource, LookupStrategy lookupStrategy) { + Assert.notNull(dataSource, "DataSource required"); + Assert.notNull(lookupStrategy, "LookupStrategy required"); + this.jdbcTemplate = new JdbcTemplate(dataSource); + this.lookupStrategy = lookupStrategy; + } - //~ Methods ======================================================================================================== + // ~ Methods + // ======================================================================================================== - public List findChildren(ObjectIdentity parentIdentity) { - Object[] args = {parentIdentity.getIdentifier(), parentIdentity.getType()}; - List objects = jdbcTemplate.query(findChildrenSql, args, - new RowMapper() { - public ObjectIdentity mapRow(ResultSet rs, int rowNum) throws SQLException { - String javaType = rs.getString("class"); - Long identifier = new Long(rs.getLong("obj_id")); + public List findChildren(ObjectIdentity parentIdentity) { + Object[] args = { parentIdentity.getIdentifier(), parentIdentity.getType() }; + List objects = jdbcTemplate.query(findChildrenSql, args, + new RowMapper() { + public ObjectIdentity mapRow(ResultSet rs, int rowNum) + throws SQLException { + String javaType = rs.getString("class"); + Long identifier = new Long(rs.getLong("obj_id")); - return new ObjectIdentityImpl(javaType, identifier); - } - }); + return new ObjectIdentityImpl(javaType, identifier); + } + }); - if (objects.size() == 0) { - return null; - } + if (objects.size() == 0) { + return null; + } - return objects; - } + return objects; + } - public Acl readAclById(ObjectIdentity object, List sids) throws NotFoundException { - Map map = readAclsById(Arrays.asList(object), sids); - Assert.isTrue(map.containsKey(object), "There should have been an Acl entry for ObjectIdentity " + object); + public Acl readAclById(ObjectIdentity object, List sids) + throws NotFoundException { + Map map = readAclsById(Arrays.asList(object), sids); + Assert.isTrue(map.containsKey(object), + "There should have been an Acl entry for ObjectIdentity " + object); - return (Acl) map.get(object); - } + return (Acl) map.get(object); + } - public Acl readAclById(ObjectIdentity object) throws NotFoundException { - return readAclById(object, null); - } + public Acl readAclById(ObjectIdentity object) throws NotFoundException { + return readAclById(object, null); + } - public Map readAclsById(List objects) throws NotFoundException { - return readAclsById(objects, null); - } + public Map readAclsById(List objects) + throws NotFoundException { + return readAclsById(objects, null); + } - public Map readAclsById(List objects, List sids) throws NotFoundException { - Map result = lookupStrategy.readAclsById(objects, sids); + public Map readAclsById(List objects, + List sids) throws NotFoundException { + Map result = lookupStrategy.readAclsById(objects, sids); - // Check every requested object identity was found (throw NotFoundException if needed) - for (ObjectIdentity oid : objects) { - if (!result.containsKey(oid)) { - throw new NotFoundException("Unable to find ACL information for object identity '" + oid + "'"); - } - } + // Check every requested object identity was found (throw NotFoundException if + // needed) + for (ObjectIdentity oid : objects) { + if (!result.containsKey(oid)) { + throw new NotFoundException( + "Unable to find ACL information for object identity '" + oid + + "'"); + } + } - return result; - } + return result; + } - /** - * Allows customization of the SQL query used to find child object identities. - * - * @param findChildrenSql - */ - public void setFindChildrenQuery(String findChildrenSql) { - this.findChildrenSql = findChildrenSql; - } + /** + * Allows customization of the SQL query used to find child object identities. + * + * @param findChildrenSql + */ + public void setFindChildrenQuery(String findChildrenSql) { + this.findChildrenSql = findChildrenSql; + } } diff --git a/acl/src/main/java/org/springframework/security/acls/jdbc/JdbcMutableAclService.java b/acl/src/main/java/org/springframework/security/acls/jdbc/JdbcMutableAclService.java index e12b2c3b4d..7ca8ba3f90 100644 --- a/acl/src/main/java/org/springframework/security/acls/jdbc/JdbcMutableAclService.java +++ b/acl/src/main/java/org/springframework/security/acls/jdbc/JdbcMutableAclService.java @@ -41,409 +41,447 @@ import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.transaction.support.TransactionSynchronizationManager; import org.springframework.util.Assert; - /** * Provides a base JDBC implementation of {@link MutableAclService}. *

- * The default settings are for HSQLDB. If you are using a different database you - * will probably need to set the {@link #setSidIdentityQuery(String) sidIdentityQuery} and - * {@link #setClassIdentityQuery(String) classIdentityQuery} properties appropriately. The other queries, - * SQL inserts and updates can also be customized to accomodate schema variations, but must produce results - * consistent with those expected by the defaults. + * The default settings are for HSQLDB. If you are using a different database you will + * probably need to set the {@link #setSidIdentityQuery(String) sidIdentityQuery} and + * {@link #setClassIdentityQuery(String) classIdentityQuery} properties appropriately. The + * other queries, SQL inserts and updates can also be customized to accomodate schema + * variations, but must produce results consistent with those expected by the defaults. *

- * See the appendix of the Spring Security reference manual for more information on the expected schema - * and how it is used. Information on using PostgreSQL is also included. + * See the appendix of the Spring Security reference manual for more information on the + * expected schema and how it is used. Information on using PostgreSQL is also included. * * @author Ben Alex * @author Johannes Zlattinger */ public class JdbcMutableAclService extends JdbcAclService implements MutableAclService { - //~ Instance fields ================================================================================================ + // ~ Instance fields + // ================================================================================================ - private boolean foreignKeysInDatabase = true; - private final AclCache aclCache; - private String deleteEntryByObjectIdentityForeignKey = "delete from acl_entry where acl_object_identity=?"; - private String deleteObjectIdentityByPrimaryKey = "delete from acl_object_identity where id=?"; - private String classIdentityQuery = "call identity()"; - private String sidIdentityQuery = "call identity()"; - private String insertClass = "insert into acl_class (class) values (?)"; - private String insertEntry = "insert into acl_entry " - + "(acl_object_identity, ace_order, sid, mask, granting, audit_success, audit_failure)" - + "values (?, ?, ?, ?, ?, ?, ?)"; - private String insertObjectIdentity = "insert into acl_object_identity " - + "(object_id_class, object_id_identity, owner_sid, entries_inheriting) " + "values (?, ?, ?, ?)"; - private String insertSid = "insert into acl_sid (principal, sid) values (?, ?)"; - private String selectClassPrimaryKey = "select id from acl_class where class=?"; - private String selectObjectIdentityPrimaryKey = "select acl_object_identity.id from acl_object_identity, acl_class " - + "where acl_object_identity.object_id_class = acl_class.id and acl_class.class=? " - + "and acl_object_identity.object_id_identity = ?"; - private String selectSidPrimaryKey = "select id from acl_sid where principal=? and sid=?"; - private String updateObjectIdentity = "update acl_object_identity set " - + "parent_object = ?, owner_sid = ?, entries_inheriting = ?" + " where id = ?"; + private boolean foreignKeysInDatabase = true; + private final AclCache aclCache; + private String deleteEntryByObjectIdentityForeignKey = "delete from acl_entry where acl_object_identity=?"; + private String deleteObjectIdentityByPrimaryKey = "delete from acl_object_identity where id=?"; + private String classIdentityQuery = "call identity()"; + private String sidIdentityQuery = "call identity()"; + private String insertClass = "insert into acl_class (class) values (?)"; + private String insertEntry = "insert into acl_entry " + + "(acl_object_identity, ace_order, sid, mask, granting, audit_success, audit_failure)" + + "values (?, ?, ?, ?, ?, ?, ?)"; + private String insertObjectIdentity = "insert into acl_object_identity " + + "(object_id_class, object_id_identity, owner_sid, entries_inheriting) " + + "values (?, ?, ?, ?)"; + private String insertSid = "insert into acl_sid (principal, sid) values (?, ?)"; + private String selectClassPrimaryKey = "select id from acl_class where class=?"; + private String selectObjectIdentityPrimaryKey = "select acl_object_identity.id from acl_object_identity, acl_class " + + "where acl_object_identity.object_id_class = acl_class.id and acl_class.class=? " + + "and acl_object_identity.object_id_identity = ?"; + private String selectSidPrimaryKey = "select id from acl_sid where principal=? and sid=?"; + private String updateObjectIdentity = "update acl_object_identity set " + + "parent_object = ?, owner_sid = ?, entries_inheriting = ?" + + " where id = ?"; - //~ Constructors =================================================================================================== + // ~ Constructors + // =================================================================================================== - public JdbcMutableAclService(DataSource dataSource, LookupStrategy lookupStrategy, AclCache aclCache) { - super(dataSource, lookupStrategy); - Assert.notNull(aclCache, "AclCache required"); - this.aclCache = aclCache; - } + public JdbcMutableAclService(DataSource dataSource, LookupStrategy lookupStrategy, + AclCache aclCache) { + super(dataSource, lookupStrategy); + Assert.notNull(aclCache, "AclCache required"); + this.aclCache = aclCache; + } - //~ Methods ======================================================================================================== + // ~ Methods + // ======================================================================================================== - public MutableAcl createAcl(ObjectIdentity objectIdentity) throws AlreadyExistsException { - Assert.notNull(objectIdentity, "Object Identity required"); + public MutableAcl createAcl(ObjectIdentity objectIdentity) + throws AlreadyExistsException { + Assert.notNull(objectIdentity, "Object Identity required"); - // Check this object identity hasn't already been persisted - if (retrieveObjectIdentityPrimaryKey(objectIdentity) != null) { - throw new AlreadyExistsException("Object identity '" + objectIdentity + "' already exists"); - } + // Check this object identity hasn't already been persisted + if (retrieveObjectIdentityPrimaryKey(objectIdentity) != null) { + throw new AlreadyExistsException("Object identity '" + objectIdentity + + "' already exists"); + } - // Need to retrieve the current principal, in order to know who "owns" this ACL (can be changed later on) - Authentication auth = SecurityContextHolder.getContext().getAuthentication(); - PrincipalSid sid = new PrincipalSid(auth); + // Need to retrieve the current principal, in order to know who "owns" this ACL + // (can be changed later on) + Authentication auth = SecurityContextHolder.getContext().getAuthentication(); + PrincipalSid sid = new PrincipalSid(auth); - // Create the acl_object_identity row - createObjectIdentity(objectIdentity, sid); + // Create the acl_object_identity row + createObjectIdentity(objectIdentity, sid); - // Retrieve the ACL via superclass (ensures cache registration, proper retrieval etc) - Acl acl = readAclById(objectIdentity); - Assert.isInstanceOf(MutableAcl.class, acl, "MutableAcl should be been returned"); + // Retrieve the ACL via superclass (ensures cache registration, proper retrieval + // etc) + Acl acl = readAclById(objectIdentity); + Assert.isInstanceOf(MutableAcl.class, acl, "MutableAcl should be been returned"); - return (MutableAcl) acl; - } + return (MutableAcl) acl; + } - /** - * Creates a new row in acl_entry for every ACE defined in the passed MutableAcl object. - * - * @param acl containing the ACEs to insert - */ - protected void createEntries(final MutableAcl acl) { - if(acl.getEntries().isEmpty()) { - return; - } - jdbcTemplate.batchUpdate(insertEntry, - new BatchPreparedStatementSetter() { - public int getBatchSize() { - return acl.getEntries().size(); - } + /** + * Creates a new row in acl_entry for every ACE defined in the passed MutableAcl + * object. + * + * @param acl containing the ACEs to insert + */ + protected void createEntries(final MutableAcl acl) { + if (acl.getEntries().isEmpty()) { + return; + } + jdbcTemplate.batchUpdate(insertEntry, new BatchPreparedStatementSetter() { + public int getBatchSize() { + return acl.getEntries().size(); + } - public void setValues(PreparedStatement stmt, int i) throws SQLException { - AccessControlEntry entry_ = acl.getEntries().get(i); - Assert.isTrue(entry_ instanceof AccessControlEntryImpl, "Unknown ACE class"); - AccessControlEntryImpl entry = (AccessControlEntryImpl) entry_; + public void setValues(PreparedStatement stmt, int i) throws SQLException { + AccessControlEntry entry_ = acl.getEntries().get(i); + Assert.isTrue(entry_ instanceof AccessControlEntryImpl, + "Unknown ACE class"); + AccessControlEntryImpl entry = (AccessControlEntryImpl) entry_; - stmt.setLong(1, ((Long) acl.getId()).longValue()); - stmt.setInt(2, i); - stmt.setLong(3, createOrRetrieveSidPrimaryKey(entry.getSid(), true).longValue()); - stmt.setInt(4, entry.getPermission().getMask()); - stmt.setBoolean(5, entry.isGranting()); - stmt.setBoolean(6, entry.isAuditSuccess()); - stmt.setBoolean(7, entry.isAuditFailure()); - } - }); - } + stmt.setLong(1, ((Long) acl.getId()).longValue()); + stmt.setInt(2, i); + stmt.setLong(3, createOrRetrieveSidPrimaryKey(entry.getSid(), true) + .longValue()); + stmt.setInt(4, entry.getPermission().getMask()); + stmt.setBoolean(5, entry.isGranting()); + stmt.setBoolean(6, entry.isAuditSuccess()); + stmt.setBoolean(7, entry.isAuditFailure()); + } + }); + } - /** - * Creates an entry in the acl_object_identity table for the passed ObjectIdentity. The Sid is also - * necessary, as acl_object_identity has defined the sid column as non-null. - * - * @param object to represent an acl_object_identity for - * @param owner for the SID column (will be created if there is no acl_sid entry for this particular Sid already) - */ - protected void createObjectIdentity(ObjectIdentity object, Sid owner) { - Long sidId = createOrRetrieveSidPrimaryKey(owner, true); - Long classId = createOrRetrieveClassPrimaryKey(object.getType(), true); - jdbcTemplate.update(insertObjectIdentity, classId, object.getIdentifier(), sidId, Boolean.TRUE); - } + /** + * Creates an entry in the acl_object_identity table for the passed ObjectIdentity. + * The Sid is also necessary, as acl_object_identity has defined the sid column as + * non-null. + * + * @param object to represent an acl_object_identity for + * @param owner for the SID column (will be created if there is no acl_sid entry for + * this particular Sid already) + */ + protected void createObjectIdentity(ObjectIdentity object, Sid owner) { + Long sidId = createOrRetrieveSidPrimaryKey(owner, true); + Long classId = createOrRetrieveClassPrimaryKey(object.getType(), true); + jdbcTemplate.update(insertObjectIdentity, classId, object.getIdentifier(), sidId, + Boolean.TRUE); + } - /** - * Retrieves the primary key from {@code acl_class}, creating a new row if needed and the - * {@code allowCreate} property is {@code true}. - * - * @param type to find or create an entry for (often the fully-qualified class name) - * @param allowCreate true if creation is permitted if not found - * - * @return the primary key or null if not found - */ - protected Long createOrRetrieveClassPrimaryKey(String type, boolean allowCreate) { - List classIds = jdbcTemplate.queryForList(selectClassPrimaryKey, new Object[] {type}, Long.class); + /** + * Retrieves the primary key from {@code acl_class}, creating a new row if needed and + * the {@code allowCreate} property is {@code true}. + * + * @param type to find or create an entry for (often the fully-qualified class name) + * @param allowCreate true if creation is permitted if not found + * + * @return the primary key or null if not found + */ + protected Long createOrRetrieveClassPrimaryKey(String type, boolean allowCreate) { + List classIds = jdbcTemplate.queryForList(selectClassPrimaryKey, + new Object[] { type }, Long.class); - if (!classIds.isEmpty()) { - return classIds.get(0); - } + if (!classIds.isEmpty()) { + return classIds.get(0); + } - if (allowCreate) { - jdbcTemplate.update(insertClass, type); - Assert.isTrue(TransactionSynchronizationManager.isSynchronizationActive(), - "Transaction must be running"); - return new Long(jdbcTemplate.queryForLong(classIdentityQuery)); - } + if (allowCreate) { + jdbcTemplate.update(insertClass, type); + Assert.isTrue(TransactionSynchronizationManager.isSynchronizationActive(), + "Transaction must be running"); + return new Long(jdbcTemplate.queryForLong(classIdentityQuery)); + } - return null; - } + return null; + } - /** - * Retrieves the primary key from acl_sid, creating a new row if needed and the allowCreate property is - * true. - * - * @param sid to find or create - * @param allowCreate true if creation is permitted if not found - * - * @return the primary key or null if not found - * - * @throws IllegalArgumentException if the Sid is not a recognized implementation. - */ - protected Long createOrRetrieveSidPrimaryKey(Sid sid, boolean allowCreate) { - Assert.notNull(sid, "Sid required"); + /** + * Retrieves the primary key from acl_sid, creating a new row if needed and the + * allowCreate property is true. + * + * @param sid to find or create + * @param allowCreate true if creation is permitted if not found + * + * @return the primary key or null if not found + * + * @throws IllegalArgumentException if the Sid is not a recognized + * implementation. + */ + protected Long createOrRetrieveSidPrimaryKey(Sid sid, boolean allowCreate) { + Assert.notNull(sid, "Sid required"); - String sidName; - boolean sidIsPrincipal = true; + String sidName; + boolean sidIsPrincipal = true; - if (sid instanceof PrincipalSid) { - sidName = ((PrincipalSid) sid).getPrincipal(); - } else if (sid instanceof GrantedAuthoritySid) { - sidName = ((GrantedAuthoritySid) sid).getGrantedAuthority(); - sidIsPrincipal = false; - } else { - throw new IllegalArgumentException("Unsupported implementation of Sid"); - } + if (sid instanceof PrincipalSid) { + sidName = ((PrincipalSid) sid).getPrincipal(); + } + else if (sid instanceof GrantedAuthoritySid) { + sidName = ((GrantedAuthoritySid) sid).getGrantedAuthority(); + sidIsPrincipal = false; + } + else { + throw new IllegalArgumentException("Unsupported implementation of Sid"); + } - return createOrRetrieveSidPrimaryKey(sidName, sidIsPrincipal, allowCreate); - } + return createOrRetrieveSidPrimaryKey(sidName, sidIsPrincipal, allowCreate); + } - /** - * Retrieves the primary key from acl_sid, creating a new row if needed and the allowCreate property is - * true. - * @param sidName name of Sid to find or to create - * @param sidIsPrincipal whether it's a user or granted authority like role - * @param allowCreate true if creation is permitted if not found - * @return the primary key or null if not found - */ - protected Long createOrRetrieveSidPrimaryKey(String sidName, boolean sidIsPrincipal, boolean allowCreate) { + /** + * Retrieves the primary key from acl_sid, creating a new row if needed and the + * allowCreate property is true. + * @param sidName name of Sid to find or to create + * @param sidIsPrincipal whether it's a user or granted authority like role + * @param allowCreate true if creation is permitted if not found + * @return the primary key or null if not found + */ + protected Long createOrRetrieveSidPrimaryKey(String sidName, boolean sidIsPrincipal, + boolean allowCreate) { - List sidIds = jdbcTemplate.queryForList(selectSidPrimaryKey, - new Object[] {Boolean.valueOf(sidIsPrincipal), sidName}, Long.class); + List sidIds = jdbcTemplate.queryForList(selectSidPrimaryKey, new Object[] { + Boolean.valueOf(sidIsPrincipal), sidName }, Long.class); - if (!sidIds.isEmpty()) { - return sidIds.get(0); - } + if (!sidIds.isEmpty()) { + return sidIds.get(0); + } - if (allowCreate) { - jdbcTemplate.update(insertSid, Boolean.valueOf(sidIsPrincipal), sidName); - Assert.isTrue(TransactionSynchronizationManager.isSynchronizationActive(), "Transaction must be running"); - return new Long(jdbcTemplate.queryForLong(sidIdentityQuery)); - } + if (allowCreate) { + jdbcTemplate.update(insertSid, Boolean.valueOf(sidIsPrincipal), sidName); + Assert.isTrue(TransactionSynchronizationManager.isSynchronizationActive(), + "Transaction must be running"); + return new Long(jdbcTemplate.queryForLong(sidIdentityQuery)); + } - return null; - } + return null; + } - public void deleteAcl(ObjectIdentity objectIdentity, boolean deleteChildren) throws ChildrenExistException { - Assert.notNull(objectIdentity, "Object Identity required"); - Assert.notNull(objectIdentity.getIdentifier(), "Object Identity doesn't provide an identifier"); + public void deleteAcl(ObjectIdentity objectIdentity, boolean deleteChildren) + throws ChildrenExistException { + Assert.notNull(objectIdentity, "Object Identity required"); + Assert.notNull(objectIdentity.getIdentifier(), + "Object Identity doesn't provide an identifier"); - if (deleteChildren) { - List children = findChildren(objectIdentity); - if (children != null) { - for (ObjectIdentity child : children) { - deleteAcl(child, true); - } - } - } else { - if (!foreignKeysInDatabase) { - // We need to perform a manual verification for what a FK would normally do - // We generally don't do this, in the interests of deadlock management - List children = findChildren(objectIdentity); - if (children != null) { - throw new ChildrenExistException("Cannot delete '" + objectIdentity + "' (has " + children.size() - + " children)"); - } - } - } + if (deleteChildren) { + List children = findChildren(objectIdentity); + if (children != null) { + for (ObjectIdentity child : children) { + deleteAcl(child, true); + } + } + } + else { + if (!foreignKeysInDatabase) { + // We need to perform a manual verification for what a FK would normally + // do + // We generally don't do this, in the interests of deadlock management + List children = findChildren(objectIdentity); + if (children != null) { + throw new ChildrenExistException("Cannot delete '" + objectIdentity + + "' (has " + children.size() + " children)"); + } + } + } - Long oidPrimaryKey = retrieveObjectIdentityPrimaryKey(objectIdentity); + Long oidPrimaryKey = retrieveObjectIdentityPrimaryKey(objectIdentity); - // Delete this ACL's ACEs in the acl_entry table - deleteEntries(oidPrimaryKey); + // Delete this ACL's ACEs in the acl_entry table + deleteEntries(oidPrimaryKey); - // Delete this ACL's acl_object_identity row - deleteObjectIdentity(oidPrimaryKey); + // Delete this ACL's acl_object_identity row + deleteObjectIdentity(oidPrimaryKey); - // Clear the cache - aclCache.evictFromCache(objectIdentity); - } + // Clear the cache + aclCache.evictFromCache(objectIdentity); + } - /** - * Deletes all ACEs defined in the acl_entry table belonging to the presented ObjectIdentity primary key. - * - * @param oidPrimaryKey the rows in acl_entry to delete - */ - protected void deleteEntries(Long oidPrimaryKey) { - jdbcTemplate.update(deleteEntryByObjectIdentityForeignKey, oidPrimaryKey); - } + /** + * Deletes all ACEs defined in the acl_entry table belonging to the presented + * ObjectIdentity primary key. + * + * @param oidPrimaryKey the rows in acl_entry to delete + */ + protected void deleteEntries(Long oidPrimaryKey) { + jdbcTemplate.update(deleteEntryByObjectIdentityForeignKey, oidPrimaryKey); + } - /** - * Deletes a single row from acl_object_identity that is associated with the presented ObjectIdentity primary key. - *

- * We do not delete any entries from acl_class, even if no classes are using that class any longer. This is a - * deadlock avoidance approach. - * - * @param oidPrimaryKey to delete the acl_object_identity - */ - protected void deleteObjectIdentity(Long oidPrimaryKey) { - // Delete the acl_object_identity row - jdbcTemplate.update(deleteObjectIdentityByPrimaryKey, oidPrimaryKey); - } + /** + * Deletes a single row from acl_object_identity that is associated with the presented + * ObjectIdentity primary key. + *

+ * We do not delete any entries from acl_class, even if no classes are using that + * class any longer. This is a deadlock avoidance approach. + * + * @param oidPrimaryKey to delete the acl_object_identity + */ + protected void deleteObjectIdentity(Long oidPrimaryKey) { + // Delete the acl_object_identity row + jdbcTemplate.update(deleteObjectIdentityByPrimaryKey, oidPrimaryKey); + } - /** - * Retrieves the primary key from the acl_object_identity table for the passed ObjectIdentity. Unlike some - * other methods in this implementation, this method will NOT create a row (use {@link - * #createObjectIdentity(ObjectIdentity, Sid)} instead). - * - * @param oid to find - * - * @return the object identity or null if not found - */ - protected Long retrieveObjectIdentityPrimaryKey(ObjectIdentity oid) { - try { - return new Long(jdbcTemplate.queryForLong(selectObjectIdentityPrimaryKey, oid.getType(), oid.getIdentifier())); - } catch (DataAccessException notFound) { - return null; - } - } + /** + * Retrieves the primary key from the acl_object_identity table for the passed + * ObjectIdentity. Unlike some other methods in this implementation, this method will + * NOT create a row (use {@link #createObjectIdentity(ObjectIdentity, Sid)} instead). + * + * @param oid to find + * + * @return the object identity or null if not found + */ + protected Long retrieveObjectIdentityPrimaryKey(ObjectIdentity oid) { + try { + return new Long(jdbcTemplate.queryForLong(selectObjectIdentityPrimaryKey, + oid.getType(), oid.getIdentifier())); + } + catch (DataAccessException notFound) { + return null; + } + } - /** - * This implementation will simply delete all ACEs in the database and recreate them on each invocation of - * this method. A more comprehensive implementation might use dirty state checking, or more likely use ORM - * capabilities for create, update and delete operations of {@link MutableAcl}. - */ - public MutableAcl updateAcl(MutableAcl acl) throws NotFoundException { - Assert.notNull(acl.getId(), "Object Identity doesn't provide an identifier"); + /** + * This implementation will simply delete all ACEs in the database and recreate them + * on each invocation of this method. A more comprehensive implementation might use + * dirty state checking, or more likely use ORM capabilities for create, update and + * delete operations of {@link MutableAcl}. + */ + public MutableAcl updateAcl(MutableAcl acl) throws NotFoundException { + Assert.notNull(acl.getId(), "Object Identity doesn't provide an identifier"); - // Delete this ACL's ACEs in the acl_entry table - deleteEntries(retrieveObjectIdentityPrimaryKey(acl.getObjectIdentity())); + // Delete this ACL's ACEs in the acl_entry table + deleteEntries(retrieveObjectIdentityPrimaryKey(acl.getObjectIdentity())); - // Create this ACL's ACEs in the acl_entry table - createEntries(acl); + // Create this ACL's ACEs in the acl_entry table + createEntries(acl); - // Change the mutable columns in acl_object_identity - updateObjectIdentity(acl); + // Change the mutable columns in acl_object_identity + updateObjectIdentity(acl); - // Clear the cache, including children - clearCacheIncludingChildren(acl.getObjectIdentity()); + // Clear the cache, including children + clearCacheIncludingChildren(acl.getObjectIdentity()); - // Retrieve the ACL via superclass (ensures cache registration, proper retrieval etc) - return (MutableAcl) super.readAclById(acl.getObjectIdentity()); - } + // Retrieve the ACL via superclass (ensures cache registration, proper retrieval + // etc) + return (MutableAcl) super.readAclById(acl.getObjectIdentity()); + } - private void clearCacheIncludingChildren(ObjectIdentity objectIdentity) { - Assert.notNull(objectIdentity, "ObjectIdentity required"); - List children = findChildren(objectIdentity); - if (children != null) { - for (ObjectIdentity child : children) { - clearCacheIncludingChildren(child); - } - } - aclCache.evictFromCache(objectIdentity); - } + private void clearCacheIncludingChildren(ObjectIdentity objectIdentity) { + Assert.notNull(objectIdentity, "ObjectIdentity required"); + List children = findChildren(objectIdentity); + if (children != null) { + for (ObjectIdentity child : children) { + clearCacheIncludingChildren(child); + } + } + aclCache.evictFromCache(objectIdentity); + } - /** - * Updates an existing acl_object_identity row, with new information presented in the passed MutableAcl - * object. Also will create an acl_sid entry if needed for the Sid that owns the MutableAcl. - * - * @param acl to modify (a row must already exist in acl_object_identity) - * - * @throws NotFoundException if the ACL could not be found to update. - */ - protected void updateObjectIdentity(MutableAcl acl) { - Long parentId = null; + /** + * Updates an existing acl_object_identity row, with new information presented in the + * passed MutableAcl object. Also will create an acl_sid entry if needed for the Sid + * that owns the MutableAcl. + * + * @param acl to modify (a row must already exist in acl_object_identity) + * + * @throws NotFoundException if the ACL could not be found to update. + */ + protected void updateObjectIdentity(MutableAcl acl) { + Long parentId = null; - if (acl.getParentAcl() != null) { - Assert.isInstanceOf(ObjectIdentityImpl.class, acl.getParentAcl().getObjectIdentity(), - "Implementation only supports ObjectIdentityImpl"); + if (acl.getParentAcl() != null) { + Assert.isInstanceOf(ObjectIdentityImpl.class, acl.getParentAcl() + .getObjectIdentity(), + "Implementation only supports ObjectIdentityImpl"); - ObjectIdentityImpl oii = (ObjectIdentityImpl) acl.getParentAcl().getObjectIdentity(); - parentId = retrieveObjectIdentityPrimaryKey(oii); - } + ObjectIdentityImpl oii = (ObjectIdentityImpl) acl.getParentAcl() + .getObjectIdentity(); + parentId = retrieveObjectIdentityPrimaryKey(oii); + } - Assert.notNull(acl.getOwner(), "Owner is required in this implementation"); + Assert.notNull(acl.getOwner(), "Owner is required in this implementation"); - Long ownerSid = createOrRetrieveSidPrimaryKey(acl.getOwner(), true); - int count = jdbcTemplate.update(updateObjectIdentity, - parentId, ownerSid, Boolean.valueOf(acl.isEntriesInheriting()), acl.getId()); + Long ownerSid = createOrRetrieveSidPrimaryKey(acl.getOwner(), true); + int count = jdbcTemplate.update(updateObjectIdentity, parentId, ownerSid, + Boolean.valueOf(acl.isEntriesInheriting()), acl.getId()); - if (count != 1) { - throw new NotFoundException("Unable to locate ACL to update"); - } - } + if (count != 1) { + throw new NotFoundException("Unable to locate ACL to update"); + } + } - /** - * Sets the query that will be used to retrieve the identity of a newly created row in the acl_class - * table. - * - * @param classIdentityQuery the query, which should return the identifier. Defaults to call identity() - */ - public void setClassIdentityQuery(String classIdentityQuery) { - Assert.hasText(classIdentityQuery, "New classIdentityQuery query is required"); - this.classIdentityQuery = classIdentityQuery; - } + /** + * Sets the query that will be used to retrieve the identity of a newly created row in + * the acl_class table. + * + * @param classIdentityQuery the query, which should return the identifier. Defaults + * to call identity() + */ + public void setClassIdentityQuery(String classIdentityQuery) { + Assert.hasText(classIdentityQuery, "New classIdentityQuery query is required"); + this.classIdentityQuery = classIdentityQuery; + } - /** - * Sets the query that will be used to retrieve the identity of a newly created row in the acl_sid - * table. - * - * @param sidIdentityQuery the query, which should return the identifier. Defaults to call identity() - */ - public void setSidIdentityQuery(String sidIdentityQuery) { - Assert.hasText(sidIdentityQuery, "New sidIdentityQuery query is required"); - this.sidIdentityQuery = sidIdentityQuery; - } + /** + * Sets the query that will be used to retrieve the identity of a newly created row in + * the acl_sid table. + * + * @param sidIdentityQuery the query, which should return the identifier. Defaults to + * call identity() + */ + public void setSidIdentityQuery(String sidIdentityQuery) { + Assert.hasText(sidIdentityQuery, "New sidIdentityQuery query is required"); + this.sidIdentityQuery = sidIdentityQuery; + } - public void setDeleteEntryByObjectIdentityForeignKeySql(String deleteEntryByObjectIdentityForeignKey) { - this.deleteEntryByObjectIdentityForeignKey = deleteEntryByObjectIdentityForeignKey; - } + public void setDeleteEntryByObjectIdentityForeignKeySql( + String deleteEntryByObjectIdentityForeignKey) { + this.deleteEntryByObjectIdentityForeignKey = deleteEntryByObjectIdentityForeignKey; + } - public void setDeleteObjectIdentityByPrimaryKeySql(String deleteObjectIdentityByPrimaryKey) { - this.deleteObjectIdentityByPrimaryKey = deleteObjectIdentityByPrimaryKey; - } + public void setDeleteObjectIdentityByPrimaryKeySql( + String deleteObjectIdentityByPrimaryKey) { + this.deleteObjectIdentityByPrimaryKey = deleteObjectIdentityByPrimaryKey; + } - public void setInsertClassSql(String insertClass) { - this.insertClass = insertClass; - } + public void setInsertClassSql(String insertClass) { + this.insertClass = insertClass; + } - public void setInsertEntrySql(String insertEntry) { - this.insertEntry = insertEntry; - } + public void setInsertEntrySql(String insertEntry) { + this.insertEntry = insertEntry; + } - public void setInsertObjectIdentitySql(String insertObjectIdentity) { - this.insertObjectIdentity = insertObjectIdentity; - } + public void setInsertObjectIdentitySql(String insertObjectIdentity) { + this.insertObjectIdentity = insertObjectIdentity; + } - public void setInsertSidSql(String insertSid) { - this.insertSid = insertSid; - } + public void setInsertSidSql(String insertSid) { + this.insertSid = insertSid; + } - public void setClassPrimaryKeyQuery(String selectClassPrimaryKey) { - this.selectClassPrimaryKey = selectClassPrimaryKey; - } + public void setClassPrimaryKeyQuery(String selectClassPrimaryKey) { + this.selectClassPrimaryKey = selectClassPrimaryKey; + } - public void setObjectIdentityPrimaryKeyQuery(String selectObjectIdentityPrimaryKey) { - this.selectObjectIdentityPrimaryKey = selectObjectIdentityPrimaryKey; - } + public void setObjectIdentityPrimaryKeyQuery(String selectObjectIdentityPrimaryKey) { + this.selectObjectIdentityPrimaryKey = selectObjectIdentityPrimaryKey; + } - public void setSidPrimaryKeyQuery(String selectSidPrimaryKey) { - this.selectSidPrimaryKey = selectSidPrimaryKey; - } + public void setSidPrimaryKeyQuery(String selectSidPrimaryKey) { + this.selectSidPrimaryKey = selectSidPrimaryKey; + } - public void setUpdateObjectIdentity(String updateObjectIdentity) { - this.updateObjectIdentity = updateObjectIdentity; - } + public void setUpdateObjectIdentity(String updateObjectIdentity) { + this.updateObjectIdentity = updateObjectIdentity; + } - /** - * @param foreignKeysInDatabase if false this class will perform additional FK constrain checking, which may - * cause deadlocks (the default is true, so deadlocks are avoided but the database is expected to enforce FKs) - */ - public void setForeignKeysInDatabase(boolean foreignKeysInDatabase) { - this.foreignKeysInDatabase = foreignKeysInDatabase; - } + /** + * @param foreignKeysInDatabase if false this class will perform additional FK + * constrain checking, which may cause deadlocks (the default is true, so deadlocks + * are avoided but the database is expected to enforce FKs) + */ + public void setForeignKeysInDatabase(boolean foreignKeysInDatabase) { + this.foreignKeysInDatabase = foreignKeysInDatabase; + } } diff --git a/acl/src/main/java/org/springframework/security/acls/jdbc/LookupStrategy.java b/acl/src/main/java/org/springframework/security/acls/jdbc/LookupStrategy.java index 9a11599627..61f7d59a1d 100644 --- a/acl/src/main/java/org/springframework/security/acls/jdbc/LookupStrategy.java +++ b/acl/src/main/java/org/springframework/security/acls/jdbc/LookupStrategy.java @@ -22,26 +22,27 @@ import org.springframework.security.acls.model.Sid; import java.util.List; import java.util.Map; - /** * Performs lookups for {@link org.springframework.security.acls.model.AclService}. * * @author Ben Alex */ public interface LookupStrategy { - //~ Methods ======================================================================================================== + // ~ Methods + // ======================================================================================================== - /** - * Perform database-specific optimized lookup. - * - * @param objects the identities to lookup (required) - * @param sids the SIDs for which identities are required (may be null - implementations may elect not - * to provide SID optimisations) - * - * @return a Map where keys represent the {@link ObjectIdentity} of the located {@link Acl} and values - * are the located {@link Acl} (never null although some entries may be missing; this method - * should not throw {@link NotFoundException}, as a chain of {@link LookupStrategy}s may be used - * to automatically create entries if required) - */ - Map readAclsById(List objects, List sids); + /** + * Perform database-specific optimized lookup. + * + * @param objects the identities to lookup (required) + * @param sids the SIDs for which identities are required (may be null - + * implementations may elect not to provide SID optimisations) + * + * @return a Map where keys represent the {@link ObjectIdentity} of the + * located {@link Acl} and values are the located {@link Acl} (never null + * although some entries may be missing; this method should not throw + * {@link NotFoundException}, as a chain of {@link LookupStrategy}s may be used to + * automatically create entries if required) + */ + Map readAclsById(List objects, List sids); } diff --git a/acl/src/main/java/org/springframework/security/acls/model/AccessControlEntry.java b/acl/src/main/java/org/springframework/security/acls/model/AccessControlEntry.java index 5c157d46a5..c8c3ee4796 100644 --- a/acl/src/main/java/org/springframework/security/acls/model/AccessControlEntry.java +++ b/acl/src/main/java/org/springframework/security/acls/model/AccessControlEntry.java @@ -14,42 +14,41 @@ */ package org.springframework.security.acls.model; - import java.io.Serializable; - /** * Represents an individual permission assignment within an {@link Acl}. * *

- * Instances MUST be immutable, as they are returned by Acl - * and should not allow client modification. + * Instances MUST be immutable, as they are returned by Acl and should not + * allow client modification. *

* * @author Ben Alex * */ public interface AccessControlEntry extends Serializable { - //~ Methods ======================================================================================================== + // ~ Methods + // ======================================================================================================== - Acl getAcl(); + Acl getAcl(); - /** - * Obtains an identifier that represents this ACE. - * - * @return the identifier, or null if unsaved - */ - Serializable getId(); + /** + * Obtains an identifier that represents this ACE. + * + * @return the identifier, or null if unsaved + */ + Serializable getId(); - Permission getPermission(); + Permission getPermission(); - Sid getSid(); + Sid getSid(); - /** - * Indicates the a Permission is being granted to the relevant Sid. If false, indicates the permission is - * being revoked/blocked. - * - * @return true if being granted, false otherwise - */ - boolean isGranting(); + /** + * Indicates the a Permission is being granted to the relevant Sid. If false, + * indicates the permission is being revoked/blocked. + * + * @return true if being granted, false otherwise + */ + boolean isGranting(); } diff --git a/acl/src/main/java/org/springframework/security/acls/model/Acl.java b/acl/src/main/java/org/springframework/security/acls/model/Acl.java index 7946e0b388..98cbe300c8 100644 --- a/acl/src/main/java/org/springframework/security/acls/model/Acl.java +++ b/acl/src/main/java/org/springframework/security/acls/model/Acl.java @@ -14,155 +14,188 @@ */ package org.springframework.security.acls.model; - import java.io.Serializable; import java.util.List; - /** * Represents an access control list (ACL) for a domain object. * *

- * An Acl represents all ACL entries for a given domain object. In - * order to avoid needing references to the domain object itself, this - * interface handles indirection between a domain object and an ACL object - * identity via the {@link - * org.springframework.security.acls.model.ObjectIdentity} interface. + * An Acl represents all ACL entries for a given domain object. In order to avoid + * needing references to the domain object itself, this interface handles indirection + * between a domain object and an ACL object identity via the + * {@link org.springframework.security.acls.model.ObjectIdentity} interface. *

* *

* Implementing classes may elect to return instances that represent - * {@link org.springframework.security.acls.model.Permission} information for either - * some OR all {@link org.springframework.security.acls.model.Sid} - * instances. Therefore, an instance may NOT necessarily contain ALL Sids - * for a given domain object. + * {@link org.springframework.security.acls.model.Permission} information for either some + * OR all {@link org.springframework.security.acls.model.Sid} instances. Therefore, an + * instance may NOT necessarily contain ALL Sids for a given domain object. *

* * @author Ben Alex */ public interface Acl extends Serializable { - /** - * Returns all of the entries represented by the present Acl. Entries associated with - * the Acl parents are not returned. - * - *

This method is typically used for administrative purposes.

- * - *

The order that entries appear in the array is important for methods declared in the - * {@link MutableAcl} interface. Furthermore, some implementations MAY use ordering as - * part of advanced permission checking.

- * - *

Do NOT use this method for making authorization decisions. Instead use {@link - * #isGranted(List, List, boolean)}.

- * - *

This method must operate correctly even if the Acl only represents a subset of - * Sids. The caller is responsible for correctly handling the result if only a subset of - * Sids is represented.

- * - * @return the list of entries represented by the Acl, or null if there are - * no entries presently associated with this Acl. - */ - List getEntries(); + /** + * Returns all of the entries represented by the present Acl. Entries + * associated with the Acl parents are not returned. + * + *

+ * This method is typically used for administrative purposes. + *

+ * + *

+ * The order that entries appear in the array is important for methods declared in the + * {@link MutableAcl} interface. Furthermore, some implementations MAY use ordering as + * part of advanced permission checking. + *

+ * + *

+ * Do NOT use this method for making authorization decisions. Instead use + * {@link #isGranted(List, List, boolean)}. + *

+ * + *

+ * This method must operate correctly even if the Acl only represents a + * subset of Sids. The caller is responsible for correctly handling the + * result if only a subset of Sids is represented. + *

+ * + * @return the list of entries represented by the Acl, or null if + * there are no entries presently associated with this Acl. + */ + List getEntries(); - /** - * Obtains the domain object this Acl provides entries for. This is immutable once an - * Acl is created. - * - * @return the object identity (never null) - */ - ObjectIdentity getObjectIdentity(); + /** + * Obtains the domain object this Acl provides entries for. This is immutable + * once an Acl is created. + * + * @return the object identity (never null) + */ + ObjectIdentity getObjectIdentity(); - /** - * Determines the owner of the Acl. The meaning of ownership varies by implementation and is - * unspecified. - * - * @return the owner (may be null if the implementation does not use ownership concepts) - */ - Sid getOwner(); + /** + * Determines the owner of the Acl. The meaning of ownership varies by + * implementation and is unspecified. + * + * @return the owner (may be null if the implementation does not use + * ownership concepts) + */ + Sid getOwner(); - /** - * A domain object may have a parent for the purpose of ACL inheritance. If there is a parent, its ACL can - * be accessed via this method. In turn, the parent's parent (grandparent) can be accessed and so on. - * - *

This method solely represents the presence of a navigation hierarchy between the parent Acl and this - * Acl. For actual inheritance to take place, the {@link #isEntriesInheriting()} must also be - * true.

- * - *

This method must operate correctly even if the Acl only represents a subset of - * Sids. The caller is responsible for correctly handling the result if only a subset of - * Sids is represented.

- * - * @return the parent Acl (may be null if this Acl does not have a parent) - */ - Acl getParentAcl(); + /** + * A domain object may have a parent for the purpose of ACL inheritance. If there is a + * parent, its ACL can be accessed via this method. In turn, the parent's parent + * (grandparent) can be accessed and so on. + * + *

+ * This method solely represents the presence of a navigation hierarchy between the + * parent Acl and this Acl. For actual inheritance to take place, + * the {@link #isEntriesInheriting()} must also be true. + *

+ * + *

+ * This method must operate correctly even if the Acl only represents a + * subset of Sids. The caller is responsible for correctly handling the + * result if only a subset of Sids is represented. + *

+ * + * @return the parent Acl (may be null if this Acl does not + * have a parent) + */ + Acl getParentAcl(); - /** - * Indicates whether the ACL entries from the {@link #getParentAcl()} should flow down into the current - * Acl.

The mere link between an Acl and a parent Acl on its own - * is insufficient to cause ACL entries to inherit down. This is because a domain object may wish to have entirely - * independent entries, but maintain the link with the parent for navigation purposes. Thus, this method denotes - * whether or not the navigation relationship also extends to the actual inheritance of entries.

- * - * @return true if parent ACL entries inherit into the current Acl - */ - boolean isEntriesInheriting(); + /** + * Indicates whether the ACL entries from the {@link #getParentAcl()} should flow down + * into the current Acl. + *

+ * The mere link between an Acl and a parent Acl on its own is + * insufficient to cause ACL entries to inherit down. This is because a domain object + * may wish to have entirely independent entries, but maintain the link with the + * parent for navigation purposes. Thus, this method denotes whether or not the + * navigation relationship also extends to the actual inheritance of entries. + *

+ * + * @return true if parent ACL entries inherit into the current Acl + */ + boolean isEntriesInheriting(); - /** - * This is the actual authorization logic method, and must be used whenever ACL authorization decisions are - * required. - * - *

An array of Sids are presented, representing security identifies of the current - * principal. In addition, an array of Permissions is presented which will have one or more bits set - * in order to indicate the permissions needed for an affirmative authorization decision. An array is presented - * because holding any of the Permissions inside the array will be sufficient for an - * affirmative authorization.

- * - *

The actual approach used to make authorization decisions is left to the implementation and is not - * specified by this interface. For example, an implementation MAY search the current ACL in the order - * the ACL entries have been stored. If a single entry is found that has the same active bits as are shown in a - * passed Permission, that entry's grant or deny state may determine the authorization decision. If - * the case of a deny state, the deny decision will only be relevant if all other Permissions passed - * in the array have also been unsuccessfully searched. If no entry is found that match the bits in the current - * ACL, provided that {@link #isEntriesInheriting()} is true, the authorization decision may be - * passed to the parent ACL. If there is no matching entry, the implementation MAY throw an exception, or make a - * predefined authorization decision.

- * - *

This method must operate correctly even if the Acl only represents a subset of Sids, - * although the implementation is permitted to throw one of the signature-defined exceptions if the method - * is called requesting an authorization decision for a {@link Sid} that was never loaded in this Acl. - *

- * - * @param permission the permission or permissions required (at least one entry required) - * @param sids the security identities held by the principal (at least one entry required) - * @param administrativeMode if true denotes the query is for administrative purposes and no logging - * or auditing (if supported by the implementation) should be undertaken - * - * @return true if authorization is granted - * - * @throws NotFoundException MUST be thrown if an implementation cannot make an authoritative authorization - * decision, usually because there is no ACL information for this particular permission and/or SID - * @throws UnloadedSidException thrown if the Acl does not have details for one or more of the - * Sids passed as arguments - */ - boolean isGranted(List permission, List sids, boolean administrativeMode) - throws NotFoundException, UnloadedSidException; + /** + * This is the actual authorization logic method, and must be used whenever ACL + * authorization decisions are required. + * + *

+ * An array of Sids are presented, representing security identifies of the + * current principal. In addition, an array of Permissions is presented which + * will have one or more bits set in order to indicate the permissions needed for an + * affirmative authorization decision. An array is presented because holding + * any of the Permissions inside the array will be sufficient for an + * affirmative authorization. + *

+ * + *

+ * The actual approach used to make authorization decisions is left to the + * implementation and is not specified by this interface. For example, an + * implementation MAY search the current ACL in the order the ACL entries + * have been stored. If a single entry is found that has the same active bits as are + * shown in a passed Permission, that entry's grant or deny state may + * determine the authorization decision. If the case of a deny state, the deny + * decision will only be relevant if all other Permissions passed in the + * array have also been unsuccessfully searched. If no entry is found that match the + * bits in the current ACL, provided that {@link #isEntriesInheriting()} is + * true, the authorization decision may be passed to the parent ACL. If there + * is no matching entry, the implementation MAY throw an exception, or make a + * predefined authorization decision. + *

+ * + *

+ * This method must operate correctly even if the Acl only represents a + * subset of Sids, although the implementation is permitted to throw one of + * the signature-defined exceptions if the method is called requesting an + * authorization decision for a {@link Sid} that was never loaded in this Acl + * . + *

+ * + * @param permission the permission or permissions required (at least one entry + * required) + * @param sids the security identities held by the principal (at least one entry + * required) + * @param administrativeMode if true denotes the query is for administrative + * purposes and no logging or auditing (if supported by the implementation) should be + * undertaken + * + * @return true if authorization is granted + * + * @throws NotFoundException MUST be thrown if an implementation cannot make an + * authoritative authorization decision, usually because there is no ACL information + * for this particular permission and/or SID + * @throws UnloadedSidException thrown if the Acl does not have details for + * one or more of the Sids passed as arguments + */ + boolean isGranted(List permission, List sids, + boolean administrativeMode) throws NotFoundException, UnloadedSidException; - /** - * For efficiency reasons an Acl may be loaded and not contain entries for every - * Sid in the system. If an Acl has been loaded and does not represent every - * Sid, all methods of the Acl can only be used within the limited scope of the - * Sid instances it actually represents. - *

- * It is normal to load an Acl for only particular Sids if read-only authorization - * decisions are being made. However, if user interface reporting or modification of Acls are - * desired, an Acl should be loaded with all Sids. This method denotes whether or - * not the specified Sids have been loaded or not. - *

- * - * @param sids one or more security identities the caller is interest in knowing whether this Sid - * supports - * - * @return true if every passed Sid is represented by this Acl instance - */ - boolean isSidLoaded(List sids); + /** + * For efficiency reasons an Acl may be loaded and not contain + * entries for every Sid in the system. If an Acl has been loaded + * and does not represent every Sid, all methods of the Acl can only + * be used within the limited scope of the Sid instances it actually + * represents. + *

+ * It is normal to load an Acl for only particular Sids if read-only + * authorization decisions are being made. However, if user interface reporting or + * modification of Acls are desired, an Acl should be loaded with + * all Sids. This method denotes whether or not the specified Sids + * have been loaded or not. + *

+ * + * @param sids one or more security identities the caller is interest in knowing + * whether this Sid supports + * + * @return true if every passed Sid is represented by this + * Acl instance + */ + boolean isSidLoaded(List sids); } diff --git a/acl/src/main/java/org/springframework/security/acls/model/AclCache.java b/acl/src/main/java/org/springframework/security/acls/model/AclCache.java index f8ef303838..b3bdef81fd 100644 --- a/acl/src/main/java/org/springframework/security/acls/model/AclCache.java +++ b/acl/src/main/java/org/springframework/security/acls/model/AclCache.java @@ -18,7 +18,6 @@ import org.springframework.security.acls.jdbc.JdbcAclService; import java.io.Serializable; - /** * A caching layer for {@link JdbcAclService}. * @@ -26,17 +25,18 @@ import java.io.Serializable; * */ public interface AclCache { - //~ Methods ======================================================================================================== + // ~ Methods + // ======================================================================================================== - void evictFromCache(Serializable pk); + void evictFromCache(Serializable pk); - void evictFromCache(ObjectIdentity objectIdentity); + void evictFromCache(ObjectIdentity objectIdentity); - MutableAcl getFromCache(ObjectIdentity objectIdentity); + MutableAcl getFromCache(ObjectIdentity objectIdentity); - MutableAcl getFromCache(Serializable pk); + MutableAcl getFromCache(Serializable pk); - void putInCache(MutableAcl acl); + void putInCache(MutableAcl acl); - void clearCache(); + void clearCache(); } diff --git a/acl/src/main/java/org/springframework/security/acls/model/AclDataAccessException.java b/acl/src/main/java/org/springframework/security/acls/model/AclDataAccessException.java index 9ae2b4fd79..10b4bae1e2 100644 --- a/acl/src/main/java/org/springframework/security/acls/model/AclDataAccessException.java +++ b/acl/src/main/java/org/springframework/security/acls/model/AclDataAccessException.java @@ -8,24 +8,24 @@ package org.springframework.security.acls.model; */ public abstract class AclDataAccessException extends RuntimeException { - /** - * Constructs an AclDataAccessException with the specified - * message and root cause. - * - * @param msg the detail message - * @param cause the root cause - */ - public AclDataAccessException(String msg, Throwable cause) { - super(msg, cause); - } + /** + * Constructs an AclDataAccessException with the specified message and + * root cause. + * + * @param msg the detail message + * @param cause the root cause + */ + public AclDataAccessException(String msg, Throwable cause) { + super(msg, cause); + } - /** - * Constructs an AclDataAccessException with the specified - * message and no root cause. - * - * @param msg the detail message - */ - public AclDataAccessException(String msg) { - super(msg); - } + /** + * Constructs an AclDataAccessException with the specified message and no + * root cause. + * + * @param msg the detail message + */ + public AclDataAccessException(String msg) { + super(msg); + } } diff --git a/acl/src/main/java/org/springframework/security/acls/model/AclService.java b/acl/src/main/java/org/springframework/security/acls/model/AclService.java index a54d05c171..c7f11ff84c 100644 --- a/acl/src/main/java/org/springframework/security/acls/model/AclService.java +++ b/acl/src/main/java/org/springframework/security/acls/model/AclService.java @@ -14,85 +14,105 @@ */ package org.springframework.security.acls.model; - import java.util.List; import java.util.Map; - /** * Provides retrieval of {@link Acl} instances. * * @author Ben Alex */ public interface AclService { - //~ Methods ======================================================================================================== + // ~ Methods + // ======================================================================================================== - /** - * Locates all object identities that use the specified parent. This is useful for administration tools. - * - * @param parentIdentity to locate children of - * - * @return the children (or null if none were found) - */ - List findChildren(ObjectIdentity parentIdentity); + /** + * Locates all object identities that use the specified parent. This is useful for + * administration tools. + * + * @param parentIdentity to locate children of + * + * @return the children (or null if none were found) + */ + List findChildren(ObjectIdentity parentIdentity); - /** - * Same as {@link #readAclsById(List)} except it returns only a single Acl. - *

- * This method should not be called as it does not leverage the underlying implementation's potential ability to - * filter Acl entries based on a {@link Sid} parameter.

- * - * @param object to locate an {@link Acl} for - * - * @return the {@link Acl} for the requested {@link ObjectIdentity} (never null) - * - * @throws NotFoundException if an {@link Acl} was not found for the requested {@link ObjectIdentity} - */ - Acl readAclById(ObjectIdentity object) throws NotFoundException; + /** + * Same as {@link #readAclsById(List)} except it returns only a single Acl. + *

+ * This method should not be called as it does not leverage the underlying + * implementation's potential ability to filter Acl entries based on a + * {@link Sid} parameter. + *

+ * + * @param object to locate an {@link Acl} for + * + * @return the {@link Acl} for the requested {@link ObjectIdentity} (never + * null) + * + * @throws NotFoundException if an {@link Acl} was not found for the requested + * {@link ObjectIdentity} + */ + Acl readAclById(ObjectIdentity object) throws NotFoundException; - /** - * Same as {@link #readAclsById(List, List)} except it returns only a single Acl. - * - * @param object to locate an {@link Acl} for - * @param sids the security identities for which {@link Acl} information is required - * (may be null to denote all entries) - * - * @return the {@link Acl} for the requested {@link ObjectIdentity} (never null) - * - * @throws NotFoundException if an {@link Acl} was not found for the requested {@link ObjectIdentity} - */ - Acl readAclById(ObjectIdentity object, List sids) throws NotFoundException; + /** + * Same as {@link #readAclsById(List, List)} except it returns only a single Acl. + * + * @param object to locate an {@link Acl} for + * @param sids the security identities for which {@link Acl} information is required + * (may be null to denote all entries) + * + * @return the {@link Acl} for the requested {@link ObjectIdentity} (never + * null) + * + * @throws NotFoundException if an {@link Acl} was not found for the requested + * {@link ObjectIdentity} + */ + Acl readAclById(ObjectIdentity object, List sids) throws NotFoundException; - /** - * Obtains all the Acls that apply for the passed Objects.

The returned map is - * keyed on the passed objects, with the values being the Acl instances. Any unknown objects will not - * have a map key.

- * - * @param objects the objects to find {@link Acl} information for - * - * @return a map with exactly one element for each {@link ObjectIdentity} passed as an argument (never null) - * - * @throws NotFoundException if an {@link Acl} was not found for each requested {@link ObjectIdentity} - */ - Map readAclsById(List objects) throws NotFoundException; + /** + * Obtains all the Acls that apply for the passed Objects. + *

+ * The returned map is keyed on the passed objects, with the values being the + * Acl instances. Any unknown objects will not have a map key. + *

+ * + * @param objects the objects to find {@link Acl} information for + * + * @return a map with exactly one element for each {@link ObjectIdentity} passed as an + * argument (never null) + * + * @throws NotFoundException if an {@link Acl} was not found for each requested + * {@link ObjectIdentity} + */ + Map readAclsById(List objects) + throws NotFoundException; - /** - * Obtains all the Acls that apply for the passed Objects, but only for the - * security identifies passed.

Implementations MAY provide a subset of the ACLs via this method - * although this is NOT a requirement. This is intended to allow performance optimisations within implementations. - * Callers should therefore use this method in preference to the alternative overloaded version which does not - * have performance optimisation opportunities.

- *

The returned map is keyed on the passed objects, with the values being the Acl - * instances. Any unknown objects (or objects for which the interested Sids do not have entries) will - * not have a map key.

- * - * @param objects the objects to find {@link Acl} information for - * @param sids the security identities for which {@link Acl} information is required - * (may be null to denote all entries) - * - * @return a map with exactly one element for each {@link ObjectIdentity} passed as an argument (never null) - * - * @throws NotFoundException if an {@link Acl} was not found for each requested {@link ObjectIdentity} - */ - Map readAclsById(List objects, List sids) throws NotFoundException; + /** + * Obtains all the Acls that apply for the passed Objects, but only + * for the security identifies passed. + *

+ * Implementations MAY provide a subset of the ACLs via this method although + * this is NOT a requirement. This is intended to allow performance optimisations + * within implementations. Callers should therefore use this method in preference to + * the alternative overloaded version which does not have performance optimisation + * opportunities. + *

+ *

+ * The returned map is keyed on the passed objects, with the values being the + * Acl instances. Any unknown objects (or objects for which the interested + * Sids do not have entries) will not have a map key. + *

+ * + * @param objects the objects to find {@link Acl} information for + * @param sids the security identities for which {@link Acl} information is required + * (may be null to denote all entries) + * + * @return a map with exactly one element for each {@link ObjectIdentity} passed as an + * argument (never null) + * + * @throws NotFoundException if an {@link Acl} was not found for each requested + * {@link ObjectIdentity} + */ + Map readAclsById(List objects, List sids) + throws NotFoundException; } diff --git a/acl/src/main/java/org/springframework/security/acls/model/AlreadyExistsException.java b/acl/src/main/java/org/springframework/security/acls/model/AlreadyExistsException.java index a61b1b564a..059d080983 100644 --- a/acl/src/main/java/org/springframework/security/acls/model/AlreadyExistsException.java +++ b/acl/src/main/java/org/springframework/security/acls/model/AlreadyExistsException.java @@ -14,32 +14,32 @@ */ package org.springframework.security.acls.model; - /** * Thrown if an Acl entry already exists for the object. * * @author Ben Alex */ public class AlreadyExistsException extends AclDataAccessException { - //~ Constructors =================================================================================================== + // ~ Constructors + // =================================================================================================== - /** - * Constructs an AlreadyExistsException with the specified message. - * - * @param msg the detail message - */ - public AlreadyExistsException(String msg) { - super(msg); - } + /** + * Constructs an AlreadyExistsException with the specified message. + * + * @param msg the detail message + */ + public AlreadyExistsException(String msg) { + super(msg); + } - /** - * Constructs an AlreadyExistsException with the specified message - * and root cause. - * - * @param msg the detail message - * @param t root cause - */ - public AlreadyExistsException(String msg, Throwable t) { - super(msg, t); - } + /** + * Constructs an AlreadyExistsException with the specified message and + * root cause. + * + * @param msg the detail message + * @param t root cause + */ + public AlreadyExistsException(String msg, Throwable t) { + super(msg, t); + } } diff --git a/acl/src/main/java/org/springframework/security/acls/model/AuditableAccessControlEntry.java b/acl/src/main/java/org/springframework/security/acls/model/AuditableAccessControlEntry.java index e03607ae44..84d353eb9e 100644 --- a/acl/src/main/java/org/springframework/security/acls/model/AuditableAccessControlEntry.java +++ b/acl/src/main/java/org/springframework/security/acls/model/AuditableAccessControlEntry.java @@ -14,7 +14,6 @@ */ package org.springframework.security.acls.model; - /** * Represents an ACE that provides auditing information. * @@ -22,9 +21,10 @@ package org.springframework.security.acls.model; * */ public interface AuditableAccessControlEntry extends AccessControlEntry { - //~ Methods ======================================================================================================== + // ~ Methods + // ======================================================================================================== - boolean isAuditFailure(); + boolean isAuditFailure(); - boolean isAuditSuccess(); + boolean isAuditSuccess(); } diff --git a/acl/src/main/java/org/springframework/security/acls/model/AuditableAcl.java b/acl/src/main/java/org/springframework/security/acls/model/AuditableAcl.java index c256278c12..5d573419c5 100644 --- a/acl/src/main/java/org/springframework/security/acls/model/AuditableAcl.java +++ b/acl/src/main/java/org/springframework/security/acls/model/AuditableAcl.java @@ -14,7 +14,6 @@ */ package org.springframework.security.acls.model; - /** * A mutable ACL that provides audit capabilities. * @@ -22,7 +21,8 @@ package org.springframework.security.acls.model; * */ public interface AuditableAcl extends MutableAcl { - //~ Methods ======================================================================================================== + // ~ Methods + // ======================================================================================================== - void updateAuditing(int aceIndex, boolean auditSuccess, boolean auditFailure); + void updateAuditing(int aceIndex, boolean auditSuccess, boolean auditFailure); } diff --git a/acl/src/main/java/org/springframework/security/acls/model/ChildrenExistException.java b/acl/src/main/java/org/springframework/security/acls/model/ChildrenExistException.java index 2b05c53c47..9f15c8b9e1 100644 --- a/acl/src/main/java/org/springframework/security/acls/model/ChildrenExistException.java +++ b/acl/src/main/java/org/springframework/security/acls/model/ChildrenExistException.java @@ -14,33 +14,32 @@ */ package org.springframework.security.acls.model; - /** * Thrown if an {@link Acl} cannot be deleted because children Acls exist. * * @author Ben Alex */ public class ChildrenExistException extends AclDataAccessException { - //~ Constructors =================================================================================================== + // ~ Constructors + // =================================================================================================== - /** - * Constructs an ChildrenExistException with the specified - * message. - * - * @param msg the detail message - */ - public ChildrenExistException(String msg) { - super(msg); - } + /** + * Constructs an ChildrenExistException with the specified message. + * + * @param msg the detail message + */ + public ChildrenExistException(String msg) { + super(msg); + } - /** - * Constructs an ChildrenExistException with the specified - * message and root cause. - * - * @param msg the detail message - * @param t root cause - */ - public ChildrenExistException(String msg, Throwable t) { - super(msg, t); - } + /** + * Constructs an ChildrenExistException with the specified message and + * root cause. + * + * @param msg the detail message + * @param t root cause + */ + public ChildrenExistException(String msg, Throwable t) { + super(msg, t); + } } diff --git a/acl/src/main/java/org/springframework/security/acls/model/MutableAcl.java b/acl/src/main/java/org/springframework/security/acls/model/MutableAcl.java index 5fdf98ae92..ad98cb19f6 100644 --- a/acl/src/main/java/org/springframework/security/acls/model/MutableAcl.java +++ b/acl/src/main/java/org/springframework/security/acls/model/MutableAcl.java @@ -16,52 +16,50 @@ package org.springframework.security.acls.model; import java.io.Serializable; - - /** * A mutable Acl. *

- * A mutable ACL must ensure that appropriate security checks are performed - * before allowing access to its methods. + * A mutable ACL must ensure that appropriate security checks are performed before + * allowing access to its methods. * * @author Ben Alex */ public interface MutableAcl extends Acl { - //~ Methods ======================================================================================================== + // ~ Methods + // ======================================================================================================== - void deleteAce(int aceIndex) throws NotFoundException; + void deleteAce(int aceIndex) throws NotFoundException; - /** - * Obtains an identifier that represents this MutableAcl. - * - * @return the identifier, or null if unsaved - */ - Serializable getId(); + /** + * Obtains an identifier that represents this MutableAcl. + * + * @return the identifier, or null if unsaved + */ + Serializable getId(); - void insertAce(int atIndexLocation, Permission permission, Sid sid, boolean granting) - throws NotFoundException; + void insertAce(int atIndexLocation, Permission permission, Sid sid, boolean granting) + throws NotFoundException; - /** - * Changes the present owner to a different owner. - * - * @param newOwner the new owner (mandatory; cannot be null) - */ - void setOwner(Sid newOwner); + /** + * Changes the present owner to a different owner. + * + * @param newOwner the new owner (mandatory; cannot be null) + */ + void setOwner(Sid newOwner); - /** - * Change the value returned by {@link Acl#isEntriesInheriting()}. - * - * @param entriesInheriting the new value - */ - void setEntriesInheriting(boolean entriesInheriting); + /** + * Change the value returned by {@link Acl#isEntriesInheriting()}. + * + * @param entriesInheriting the new value + */ + void setEntriesInheriting(boolean entriesInheriting); - /** - * Changes the parent of this ACL. - * - * @param newParent the new parent - */ - void setParent(Acl newParent); + /** + * Changes the parent of this ACL. + * + * @param newParent the new parent + */ + void setParent(Acl newParent); - void updateAce(int aceIndex, Permission permission) - throws NotFoundException; + void updateAce(int aceIndex, Permission permission) throws NotFoundException; } diff --git a/acl/src/main/java/org/springframework/security/acls/model/MutableAclService.java b/acl/src/main/java/org/springframework/security/acls/model/MutableAclService.java index 323979814d..949bcb53b2 100644 --- a/acl/src/main/java/org/springframework/security/acls/model/MutableAclService.java +++ b/acl/src/main/java/org/springframework/security/acls/model/MutableAclService.java @@ -14,48 +14,47 @@ */ package org.springframework.security.acls.model; - - /** * Provides support for creating and storing Acl instances. * * @author Ben Alex */ public interface MutableAclService extends AclService { - //~ Methods ======================================================================================================== + // ~ Methods + // ======================================================================================================== - /** - * Creates an empty Acl object in the database. It will have no entries. The returned object - * will then be used to add entries. - * - * @param objectIdentity the object identity to create - * - * @return an ACL object with its ID set - * - * @throws AlreadyExistsException if the passed object identity already has a record - */ - MutableAcl createAcl(ObjectIdentity objectIdentity) - throws AlreadyExistsException; + /** + * Creates an empty Acl object in the database. It will have no entries. + * The returned object will then be used to add entries. + * + * @param objectIdentity the object identity to create + * + * @return an ACL object with its ID set + * + * @throws AlreadyExistsException if the passed object identity already has a record + */ + MutableAcl createAcl(ObjectIdentity objectIdentity) throws AlreadyExistsException; - /** - * Removes the specified entry from the database. - * - * @param objectIdentity the object identity to remove - * @param deleteChildren whether to cascade the delete to children - * - * @throws ChildrenExistException if the deleteChildren argument was false but children exist - */ - void deleteAcl(ObjectIdentity objectIdentity, boolean deleteChildren) - throws ChildrenExistException; + /** + * Removes the specified entry from the database. + * + * @param objectIdentity the object identity to remove + * @param deleteChildren whether to cascade the delete to children + * + * @throws ChildrenExistException if the deleteChildren argument was + * false but children exist + */ + void deleteAcl(ObjectIdentity objectIdentity, boolean deleteChildren) + throws ChildrenExistException; - /** - * Changes an existing Acl in the database. - * - * @param acl to modify - * - * @throws NotFoundException if the relevant record could not be found (did you remember to use {@link - * #createAcl(ObjectIdentity)} to create the object, rather than creating it with the new - * keyword?) - */ - MutableAcl updateAcl(MutableAcl acl) throws NotFoundException; + /** + * Changes an existing Acl in the database. + * + * @param acl to modify + * + * @throws NotFoundException if the relevant record could not be found (did you + * remember to use {@link #createAcl(ObjectIdentity)} to create the object, rather + * than creating it with the new keyword?) + */ + MutableAcl updateAcl(MutableAcl acl) throws NotFoundException; } diff --git a/acl/src/main/java/org/springframework/security/acls/model/NotFoundException.java b/acl/src/main/java/org/springframework/security/acls/model/NotFoundException.java index a2f3323698..d96c1e7c50 100644 --- a/acl/src/main/java/org/springframework/security/acls/model/NotFoundException.java +++ b/acl/src/main/java/org/springframework/security/acls/model/NotFoundException.java @@ -14,32 +14,32 @@ */ package org.springframework.security.acls.model; - /** * Thrown if an ACL-related object cannot be found. * * @author Ben Alex */ public class NotFoundException extends AclDataAccessException { - //~ Constructors =================================================================================================== + // ~ Constructors + // =================================================================================================== - /** - * Constructs an NotFoundException with the specified message. - * - * @param msg the detail message - */ - public NotFoundException(String msg) { - super(msg); - } + /** + * Constructs an NotFoundException with the specified message. + * + * @param msg the detail message + */ + public NotFoundException(String msg) { + super(msg); + } - /** - * Constructs an NotFoundException with the specified message - * and root cause. - * - * @param msg the detail message - * @param t root cause - */ - public NotFoundException(String msg, Throwable t) { - super(msg, t); - } + /** + * Constructs an NotFoundException with the specified message and root + * cause. + * + * @param msg the detail message + * @param t root cause + */ + public NotFoundException(String msg, Throwable t) { + super(msg, t); + } } diff --git a/acl/src/main/java/org/springframework/security/acls/model/ObjectIdentity.java b/acl/src/main/java/org/springframework/security/acls/model/ObjectIdentity.java index 97003b11a5..855ae6883b 100644 --- a/acl/src/main/java/org/springframework/security/acls/model/ObjectIdentity.java +++ b/acl/src/main/java/org/springframework/security/acls/model/ObjectIdentity.java @@ -16,56 +16,59 @@ package org.springframework.security.acls.model; import java.io.Serializable; - /** * Represents the identity of an individual domain object instance. * *

- * As implementations of ObjectIdentity are used as the key to represent - * domain objects in the ACL subsystem, it is essential that implementations provide - * methods so that object-equality rather than reference-equality can be relied upon - * reliably. In other words, the ACL subsystem can consider two - * ObjectIdentitys equal if identity1.equals(identity2), rather than - * reference-equality of identity1==identity2. + * As implementations of ObjectIdentity are used as the key to represent domain + * objects in the ACL subsystem, it is essential that implementations provide methods so + * that object-equality rather than reference-equality can be relied upon reliably. In + * other words, the ACL subsystem can consider two ObjectIdentitys equal if + * identity1.equals(identity2), rather than reference-equality of + * identity1==identity2. *

* * @author Ben Alex */ public interface ObjectIdentity extends Serializable { - //~ Methods ======================================================================================================== + // ~ Methods + // ======================================================================================================== - /** - * @param obj to be compared - * - * @return true if the objects are equal, false otherwise - * @see Object#equals(Object) - */ - boolean equals(Object obj); + /** + * @param obj to be compared + * + * @return true if the objects are equal, false otherwise + * @see Object#equals(Object) + */ + boolean equals(Object obj); - /** - * Obtains the actual identifier. This identifier must not be reused to represent other domain objects with - * the same javaType. - * - *

Because ACLs are largely immutable, it is strongly recommended to use - * a synthetic identifier (such as a database sequence number for the primary key). Do not use an identifier with - * business meaning, as that business meaning may change in the future such change will cascade to the ACL - * subsystem data.

- * - * @return the identifier (unique within this type; never null) - */ - Serializable getIdentifier(); + /** + * Obtains the actual identifier. This identifier must not be reused to represent + * other domain objects with the same javaType. + * + *

+ * Because ACLs are largely immutable, it is strongly recommended to use a synthetic + * identifier (such as a database sequence number for the primary key). Do not use an + * identifier with business meaning, as that business meaning may change in the future + * such change will cascade to the ACL subsystem data. + *

+ * + * @return the identifier (unique within this type; never null) + */ + Serializable getIdentifier(); - /** - * Obtains the "type" metadata for the domain object. This will often be a Java type name (an interface or a class) - * – traditionally it is the name of the domain object implementation class. - * - * @return the "type" of the domain object (never null). - */ - String getType(); + /** + * Obtains the "type" metadata for the domain object. This will often be a Java type + * name (an interface or a class) – traditionally it is the name of the domain + * object implementation class. + * + * @return the "type" of the domain object (never null). + */ + String getType(); - /** - * @return a hash code representation of the ObjectIdentity - * @see Object#hashCode() - */ - int hashCode(); + /** + * @return a hash code representation of the ObjectIdentity + * @see Object#hashCode() + */ + int hashCode(); } diff --git a/acl/src/main/java/org/springframework/security/acls/model/ObjectIdentityGenerator.java b/acl/src/main/java/org/springframework/security/acls/model/ObjectIdentityGenerator.java index e6609c52a8..cb9330d30f 100644 --- a/acl/src/main/java/org/springframework/security/acls/model/ObjectIdentityGenerator.java +++ b/acl/src/main/java/org/springframework/security/acls/model/ObjectIdentityGenerator.java @@ -2,25 +2,25 @@ package org.springframework.security.acls.model; import java.io.Serializable; - /** - * Strategy which creates an {@link ObjectIdentity} from an object identifier (such as a primary key) - * and type information. + * Strategy which creates an {@link ObjectIdentity} from an object identifier (such as a + * primary key) and type information. *

- * Differs from {@link ObjectIdentityRetrievalStrategy} in that it is used in situations when the actual object - * instance isn't available. + * Differs from {@link ObjectIdentityRetrievalStrategy} in that it is used in situations + * when the actual object instance isn't available. * * @author Luke Taylor * @since 3.0 */ public interface ObjectIdentityGenerator { - /** - * - * @param id the identifier of the domain object, not null - * @param type the type of the object (often a class name), not null - * @return the identity constructed using the supplied identifier and type information. - */ - ObjectIdentity createObjectIdentity(Serializable id, String type); + /** + * + * @param id the identifier of the domain object, not null + * @param type the type of the object (often a class name), not null + * @return the identity constructed using the supplied identifier and type + * information. + */ + ObjectIdentity createObjectIdentity(Serializable id, String type); } diff --git a/acl/src/main/java/org/springframework/security/acls/model/ObjectIdentityRetrievalStrategy.java b/acl/src/main/java/org/springframework/security/acls/model/ObjectIdentityRetrievalStrategy.java index 3e2e7353a6..395c7e3d6a 100644 --- a/acl/src/main/java/org/springframework/security/acls/model/ObjectIdentityRetrievalStrategy.java +++ b/acl/src/main/java/org/springframework/security/acls/model/ObjectIdentityRetrievalStrategy.java @@ -15,7 +15,6 @@ package org.springframework.security.acls.model; - /** * Strategy interface that provides the ability to determine which {@link ObjectIdentity} * will be returned for a particular domain object @@ -24,7 +23,8 @@ package org.springframework.security.acls.model; * */ public interface ObjectIdentityRetrievalStrategy { - //~ Methods ======================================================================================================== + // ~ Methods + // ======================================================================================================== - ObjectIdentity getObjectIdentity(Object domainObject); + ObjectIdentity getObjectIdentity(Object domainObject); } diff --git a/acl/src/main/java/org/springframework/security/acls/model/OwnershipAcl.java b/acl/src/main/java/org/springframework/security/acls/model/OwnershipAcl.java index a0953c18db..ecd79a65bc 100644 --- a/acl/src/main/java/org/springframework/security/acls/model/OwnershipAcl.java +++ b/acl/src/main/java/org/springframework/security/acls/model/OwnershipAcl.java @@ -14,19 +14,18 @@ */ package org.springframework.security.acls.model; - - /** * A mutable ACL that provides ownership capabilities. * *

- * Generally the owner of an ACL is able to call any ACL mutator method, as - * well as assign a new owner. + * Generally the owner of an ACL is able to call any ACL mutator method, as well as assign + * a new owner. * * @author Ben Alex */ public interface OwnershipAcl extends MutableAcl { - //~ Methods ======================================================================================================== + // ~ Methods + // ======================================================================================================== - void setOwner(Sid newOwner); + void setOwner(Sid newOwner); } diff --git a/acl/src/main/java/org/springframework/security/acls/model/Permission.java b/acl/src/main/java/org/springframework/security/acls/model/Permission.java index 15426b43c1..625f5aeb6d 100644 --- a/acl/src/main/java/org/springframework/security/acls/model/Permission.java +++ b/acl/src/main/java/org/springframework/security/acls/model/Permission.java @@ -22,36 +22,41 @@ import java.io.Serializable; * @author Ben Alex */ public interface Permission extends Serializable { - //~ Static fields/initializers ===================================================================================== + // ~ Static fields/initializers + // ===================================================================================== - char RESERVED_ON = '~'; - char RESERVED_OFF = '.'; - String THIRTY_TWO_RESERVED_OFF = "................................"; + char RESERVED_ON = '~'; + char RESERVED_OFF = '.'; + String THIRTY_TWO_RESERVED_OFF = "................................"; - //~ Methods ======================================================================================================== + // ~ Methods + // ======================================================================================================== - /** - * Returns the bits that represents the permission. - * - * @return the bits that represent the permission - */ - int getMask(); + /** + * Returns the bits that represents the permission. + * + * @return the bits that represent the permission + */ + int getMask(); - /** - * Returns a 32-character long bit pattern String representing this permission. - *

- * Implementations are free to format the pattern as they see fit, although under no circumstances may - * {@link #RESERVED_OFF} or {@link #RESERVED_ON} be used within the pattern. An exemption is in the case of - * {@link #RESERVED_OFF} which is used to denote a bit that is off (clear). - * Implementations may also elect to use {@link #RESERVED_ON} internally for computation purposes, - * although this method may not return any String containing {@link #RESERVED_ON}. - *

- * The returned String must be 32 characters in length. - *

- * This method is only used for user interface and logging purposes. It is not used in any permission - * calculations. Therefore, duplication of characters within the output is permitted. - * - * @return a 32-character bit pattern - */ - String getPattern(); + /** + * Returns a 32-character long bit pattern String representing this + * permission. + *

+ * Implementations are free to format the pattern as they see fit, although under no + * circumstances may {@link #RESERVED_OFF} or {@link #RESERVED_ON} be used within the + * pattern. An exemption is in the case of {@link #RESERVED_OFF} which is used to + * denote a bit that is off (clear). Implementations may also elect to use + * {@link #RESERVED_ON} internally for computation purposes, although this method may + * not return any String containing {@link #RESERVED_ON}. + *

+ * The returned String must be 32 characters in length. + *

+ * This method is only used for user interface and logging purposes. It is not used in + * any permission calculations. Therefore, duplication of characters within the output + * is permitted. + * + * @return a 32-character bit pattern + */ + String getPattern(); } diff --git a/acl/src/main/java/org/springframework/security/acls/model/PermissionGrantingStrategy.java b/acl/src/main/java/org/springframework/security/acls/model/PermissionGrantingStrategy.java index c2be569fe0..9ea73cccbf 100644 --- a/acl/src/main/java/org/springframework/security/acls/model/PermissionGrantingStrategy.java +++ b/acl/src/main/java/org/springframework/security/acls/model/PermissionGrantingStrategy.java @@ -3,18 +3,19 @@ package org.springframework.security.acls.model; import java.util.List; /** - * Allow customization of the logic for determining whether a permission or permissions are granted to a particular - * sid or sids by an {@link Acl}. + * Allow customization of the logic for determining whether a permission or permissions + * are granted to a particular sid or sids by an {@link Acl}. * * @author Luke Taylor * @since 3.0.2 */ public interface PermissionGrantingStrategy { - /** - * Returns true if the the supplied strategy decides that the supplied {@code Acl} grants access - * based on the supplied list of permissions and sids. - */ - boolean isGranted(Acl acl, List permission, List sids, boolean administrativeMode); + /** + * Returns true if the the supplied strategy decides that the supplied {@code Acl} + * grants access based on the supplied list of permissions and sids. + */ + boolean isGranted(Acl acl, List permission, List sids, + boolean administrativeMode); } diff --git a/acl/src/main/java/org/springframework/security/acls/model/Sid.java b/acl/src/main/java/org/springframework/security/acls/model/Sid.java index 2fb0633235..be18753a9e 100644 --- a/acl/src/main/java/org/springframework/security/acls/model/Sid.java +++ b/acl/src/main/java/org/springframework/security/acls/model/Sid.java @@ -20,32 +20,34 @@ import java.io.Serializable; * A security identity recognised by the ACL system. * *

- * This interface provides indirection between actual security objects (eg - * principals, roles, groups etc) and what is stored inside an - * Acl. This is because an Acl will not store an - * entire security object, but only an abstraction of it. This interface - * therefore provides a simple way to compare these abstracted security + * This interface provides indirection between actual security objects (eg principals, + * roles, groups etc) and what is stored inside an Acl. This is because an + * Acl will not store an entire security object, but only an abstraction of + * it. This interface therefore provides a simple way to compare these abstracted security * identities with other security identities and actual security objects. *

* * @author Ben Alex */ public interface Sid extends Serializable { - //~ Methods ======================================================================================================== + // ~ Methods + // ======================================================================================================== - /** - * Refer to the java.lang.Object documentation for the interface contract. - * - * @param obj to be compared - * - * @return true if the objects are equal, false otherwise - */ - boolean equals(Object obj); + /** + * Refer to the java.lang.Object documentation for the interface + * contract. + * + * @param obj to be compared + * + * @return true if the objects are equal, false otherwise + */ + boolean equals(Object obj); - /** - * Refer to the java.lang.Object documentation for the interface contract. - * - * @return a hash code representation of this object - */ - int hashCode(); + /** + * Refer to the java.lang.Object documentation for the interface + * contract. + * + * @return a hash code representation of this object + */ + int hashCode(); } diff --git a/acl/src/main/java/org/springframework/security/acls/model/SidRetrievalStrategy.java b/acl/src/main/java/org/springframework/security/acls/model/SidRetrievalStrategy.java index 310935cbb0..fc48bfdb7d 100644 --- a/acl/src/main/java/org/springframework/security/acls/model/SidRetrievalStrategy.java +++ b/acl/src/main/java/org/springframework/security/acls/model/SidRetrievalStrategy.java @@ -19,15 +19,15 @@ import java.util.List; import org.springframework.security.core.Authentication; - /** - * Strategy interface that provides an ability to determine the {@link Sid} instances applicable - * for an {@link Authentication}. + * Strategy interface that provides an ability to determine the {@link Sid} instances + * applicable for an {@link Authentication}. * * @author Ben Alex */ public interface SidRetrievalStrategy { - //~ Methods ======================================================================================================== + // ~ Methods + // ======================================================================================================== - List getSids(Authentication authentication); + List getSids(Authentication authentication); } diff --git a/acl/src/main/java/org/springframework/security/acls/model/UnloadedSidException.java b/acl/src/main/java/org/springframework/security/acls/model/UnloadedSidException.java index 6e49ad962c..e92f1e8710 100644 --- a/acl/src/main/java/org/springframework/security/acls/model/UnloadedSidException.java +++ b/acl/src/main/java/org/springframework/security/acls/model/UnloadedSidException.java @@ -14,33 +14,34 @@ */ package org.springframework.security.acls.model; - /** - * Thrown if an {@link Acl} cannot perform an operation because it only loaded a subset of Sids and - * the caller has requested details for an unloaded Sid. + * Thrown if an {@link Acl} cannot perform an operation because it only loaded a subset of + * Sids and the caller has requested details for an unloaded Sid + * . * * @author Ben Alex */ public class UnloadedSidException extends AclDataAccessException { - //~ Constructors =================================================================================================== + // ~ Constructors + // =================================================================================================== - /** - * Constructs an NotFoundException with the specified message. - * - * @param msg the detail message - */ - public UnloadedSidException(String msg) { - super(msg); - } + /** + * Constructs an NotFoundException with the specified message. + * + * @param msg the detail message + */ + public UnloadedSidException(String msg) { + super(msg); + } - /** - * Constructs an NotFoundException with the specified message - * and root cause. - * - * @param msg the detail message - * @param t root cause - */ - public UnloadedSidException(String msg, Throwable t) { - super(msg, t); - } + /** + * Constructs an NotFoundException with the specified message and root + * cause. + * + * @param msg the detail message + * @param t root cause + */ + public UnloadedSidException(String msg, Throwable t) { + super(msg, t); + } } diff --git a/acl/src/test/java/org/springframework/security/acls/AclFormattingUtilsTests.java b/acl/src/test/java/org/springframework/security/acls/AclFormattingUtilsTests.java index a72ea09605..15389e7359 100644 --- a/acl/src/test/java/org/springframework/security/acls/AclFormattingUtilsTests.java +++ b/acl/src/test/java/org/springframework/security/acls/AclFormattingUtilsTests.java @@ -13,123 +13,132 @@ import junit.framework.TestCase; */ public class AclFormattingUtilsTests extends TestCase { - //~ Methods ======================================================================================================== + // ~ Methods + // ======================================================================================================== - public final void testDemergePatternsParametersConstraints() throws Exception { - try { - AclFormattingUtils.demergePatterns(null, "SOME STRING"); - Assert.fail("It should have thrown IllegalArgumentException"); - } - catch (IllegalArgumentException expected) { - Assert.assertTrue(true); - } + public final void testDemergePatternsParametersConstraints() throws Exception { + try { + AclFormattingUtils.demergePatterns(null, "SOME STRING"); + Assert.fail("It should have thrown IllegalArgumentException"); + } + catch (IllegalArgumentException expected) { + Assert.assertTrue(true); + } - try { - AclFormattingUtils.demergePatterns("SOME STRING", null); - Assert.fail("It should have thrown IllegalArgumentException"); - } - catch (IllegalArgumentException expected) { - Assert.assertTrue(true); - } + try { + AclFormattingUtils.demergePatterns("SOME STRING", null); + Assert.fail("It should have thrown IllegalArgumentException"); + } + catch (IllegalArgumentException expected) { + Assert.assertTrue(true); + } - try { - AclFormattingUtils.demergePatterns("SOME STRING", "LONGER SOME STRING"); - Assert.fail("It should have thrown IllegalArgumentException"); - } - catch (IllegalArgumentException expected) { - Assert.assertTrue(true); - } + try { + AclFormattingUtils.demergePatterns("SOME STRING", "LONGER SOME STRING"); + Assert.fail("It should have thrown IllegalArgumentException"); + } + catch (IllegalArgumentException expected) { + Assert.assertTrue(true); + } - try { - AclFormattingUtils.demergePatterns("SOME STRING", "SAME LENGTH"); - Assert.assertTrue(true); - } - catch (IllegalArgumentException notExpected) { - Assert.fail("It shouldn't have thrown IllegalArgumentException"); - } - } + try { + AclFormattingUtils.demergePatterns("SOME STRING", "SAME LENGTH"); + Assert.assertTrue(true); + } + catch (IllegalArgumentException notExpected) { + Assert.fail("It shouldn't have thrown IllegalArgumentException"); + } + } - public final void testDemergePatterns() throws Exception { - String original = "...........................A...R"; - String removeBits = "...............................R"; - Assert.assertEquals("...........................A....", AclFormattingUtils - .demergePatterns(original, removeBits)); + public final void testDemergePatterns() throws Exception { + String original = "...........................A...R"; + String removeBits = "...............................R"; + Assert.assertEquals("...........................A....", + AclFormattingUtils.demergePatterns(original, removeBits)); - Assert.assertEquals("ABCDEF", AclFormattingUtils.demergePatterns("ABCDEF", "......")); - Assert.assertEquals("......", AclFormattingUtils.demergePatterns("ABCDEF", "GHIJKL")); - } + Assert.assertEquals("ABCDEF", + AclFormattingUtils.demergePatterns("ABCDEF", "......")); + Assert.assertEquals("......", + AclFormattingUtils.demergePatterns("ABCDEF", "GHIJKL")); + } - public final void testMergePatternsParametersConstraints() throws Exception { - try { - AclFormattingUtils.mergePatterns(null, "SOME STRING"); - Assert.fail("It should have thrown IllegalArgumentException"); - } - catch (IllegalArgumentException expected) { - Assert.assertTrue(true); - } + public final void testMergePatternsParametersConstraints() throws Exception { + try { + AclFormattingUtils.mergePatterns(null, "SOME STRING"); + Assert.fail("It should have thrown IllegalArgumentException"); + } + catch (IllegalArgumentException expected) { + Assert.assertTrue(true); + } - try { - AclFormattingUtils.mergePatterns("SOME STRING", null); - Assert.fail("It should have thrown IllegalArgumentException"); - } - catch (IllegalArgumentException expected) { - Assert.assertTrue(true); - } + try { + AclFormattingUtils.mergePatterns("SOME STRING", null); + Assert.fail("It should have thrown IllegalArgumentException"); + } + catch (IllegalArgumentException expected) { + Assert.assertTrue(true); + } - try { - AclFormattingUtils.mergePatterns("SOME STRING", "LONGER SOME STRING"); - Assert.fail("It should have thrown IllegalArgumentException"); - } - catch (IllegalArgumentException expected) { - Assert.assertTrue(true); - } + try { + AclFormattingUtils.mergePatterns("SOME STRING", "LONGER SOME STRING"); + Assert.fail("It should have thrown IllegalArgumentException"); + } + catch (IllegalArgumentException expected) { + Assert.assertTrue(true); + } - try { - AclFormattingUtils.mergePatterns("SOME STRING", "SAME LENGTH"); - Assert.assertTrue(true); - } - catch (IllegalArgumentException notExpected) { - Assert.fail("It shouldn't have thrown IllegalArgumentException"); - } - } + try { + AclFormattingUtils.mergePatterns("SOME STRING", "SAME LENGTH"); + Assert.assertTrue(true); + } + catch (IllegalArgumentException notExpected) { + Assert.fail("It shouldn't have thrown IllegalArgumentException"); + } + } - public final void testMergePatterns() throws Exception { - String original = "...............................R"; - String extraBits = "...........................A...."; - Assert.assertEquals("...........................A...R", AclFormattingUtils - .mergePatterns(original, extraBits)); + public final void testMergePatterns() throws Exception { + String original = "...............................R"; + String extraBits = "...........................A...."; + Assert.assertEquals("...........................A...R", + AclFormattingUtils.mergePatterns(original, extraBits)); - Assert.assertEquals("ABCDEF", AclFormattingUtils.mergePatterns("ABCDEF", "......")); - Assert.assertEquals("GHIJKL", AclFormattingUtils.mergePatterns("ABCDEF", "GHIJKL")); - } + Assert.assertEquals("ABCDEF", + AclFormattingUtils.mergePatterns("ABCDEF", "......")); + Assert.assertEquals("GHIJKL", + AclFormattingUtils.mergePatterns("ABCDEF", "GHIJKL")); + } - public final void testBinaryPrints() throws Exception { - Assert.assertEquals("............................****", AclFormattingUtils.printBinary(15)); + public final void testBinaryPrints() throws Exception { + Assert.assertEquals("............................****", + AclFormattingUtils.printBinary(15)); - try { - AclFormattingUtils.printBinary(15, Permission.RESERVED_ON); - Assert.fail("It should have thrown IllegalArgumentException"); - } - catch (IllegalArgumentException notExpected) { - Assert.assertTrue(true); - } + try { + AclFormattingUtils.printBinary(15, Permission.RESERVED_ON); + Assert.fail("It should have thrown IllegalArgumentException"); + } + catch (IllegalArgumentException notExpected) { + Assert.assertTrue(true); + } - try { - AclFormattingUtils.printBinary(15, Permission.RESERVED_OFF); - Assert.fail("It should have thrown IllegalArgumentException"); - } - catch (IllegalArgumentException notExpected) { - Assert.assertTrue(true); - } + try { + AclFormattingUtils.printBinary(15, Permission.RESERVED_OFF); + Assert.fail("It should have thrown IllegalArgumentException"); + } + catch (IllegalArgumentException notExpected) { + Assert.assertTrue(true); + } - Assert.assertEquals("............................xxxx", AclFormattingUtils.printBinary(15, 'x')); - } + Assert.assertEquals("............................xxxx", + AclFormattingUtils.printBinary(15, 'x')); + } - public void testPrintBinaryNegative() { - Assert.assertEquals("*...............................", AclFormattingUtils.printBinary(0x80000000)); - } + public void testPrintBinaryNegative() { + Assert.assertEquals("*...............................", + AclFormattingUtils.printBinary(0x80000000)); + } - public void testPrintBinaryMinusOne() { - Assert.assertEquals("********************************", AclFormattingUtils.printBinary(0xffffffff)); - } + public void testPrintBinaryMinusOne() { + Assert.assertEquals("********************************", + AclFormattingUtils.printBinary(0xffffffff)); + } } diff --git a/acl/src/test/java/org/springframework/security/acls/AclPermissionCacheOptimizerTests.java b/acl/src/test/java/org/springframework/security/acls/AclPermissionCacheOptimizerTests.java index a9f987ab3d..aad5162a6f 100644 --- a/acl/src/test/java/org/springframework/security/acls/AclPermissionCacheOptimizerTests.java +++ b/acl/src/test/java/org/springframework/security/acls/AclPermissionCacheOptimizerTests.java @@ -17,40 +17,41 @@ import java.util.List; /** * @author Luke Taylor */ -@SuppressWarnings({"unchecked"}) +@SuppressWarnings({ "unchecked" }) public class AclPermissionCacheOptimizerTests { - @Test - public void eagerlyLoadsRequiredAcls() throws Exception { - AclService service = mock(AclService.class); - AclPermissionCacheOptimizer pco = new AclPermissionCacheOptimizer(service); - ObjectIdentityRetrievalStrategy oidStrat = mock(ObjectIdentityRetrievalStrategy.class); - SidRetrievalStrategy sidStrat = mock(SidRetrievalStrategy.class); - pco.setObjectIdentityRetrievalStrategy(oidStrat); - pco.setSidRetrievalStrategy(sidStrat); - Object[] dos = {new Object(), null, new Object()}; - ObjectIdentity[] oids = {new ObjectIdentityImpl("A", "1"), new ObjectIdentityImpl("A", "2")}; - when(oidStrat.getObjectIdentity(dos[0])).thenReturn(oids[0]); - when(oidStrat.getObjectIdentity(dos[2])).thenReturn(oids[1]); + @Test + public void eagerlyLoadsRequiredAcls() throws Exception { + AclService service = mock(AclService.class); + AclPermissionCacheOptimizer pco = new AclPermissionCacheOptimizer(service); + ObjectIdentityRetrievalStrategy oidStrat = mock(ObjectIdentityRetrievalStrategy.class); + SidRetrievalStrategy sidStrat = mock(SidRetrievalStrategy.class); + pco.setObjectIdentityRetrievalStrategy(oidStrat); + pco.setSidRetrievalStrategy(sidStrat); + Object[] dos = { new Object(), null, new Object() }; + ObjectIdentity[] oids = { new ObjectIdentityImpl("A", "1"), + new ObjectIdentityImpl("A", "2") }; + when(oidStrat.getObjectIdentity(dos[0])).thenReturn(oids[0]); + when(oidStrat.getObjectIdentity(dos[2])).thenReturn(oids[1]); - pco.cachePermissionsFor(mock(Authentication.class), Arrays.asList(dos)); + pco.cachePermissionsFor(mock(Authentication.class), Arrays.asList(dos)); - // AclService should be invoked with the list of required Oids - verify(service).readAclsById(eq(Arrays.asList(oids)), any(List.class)); - } + // AclService should be invoked with the list of required Oids + verify(service).readAclsById(eq(Arrays.asList(oids)), any(List.class)); + } - @Test - public void ignoresEmptyCollection() { - AclService service = mock(AclService.class); - AclPermissionCacheOptimizer pco = new AclPermissionCacheOptimizer(service); - ObjectIdentityRetrievalStrategy oids = mock(ObjectIdentityRetrievalStrategy.class); - SidRetrievalStrategy sids = mock(SidRetrievalStrategy.class); - pco.setObjectIdentityRetrievalStrategy(oids); - pco.setSidRetrievalStrategy(sids); + @Test + public void ignoresEmptyCollection() { + AclService service = mock(AclService.class); + AclPermissionCacheOptimizer pco = new AclPermissionCacheOptimizer(service); + ObjectIdentityRetrievalStrategy oids = mock(ObjectIdentityRetrievalStrategy.class); + SidRetrievalStrategy sids = mock(SidRetrievalStrategy.class); + pco.setObjectIdentityRetrievalStrategy(oids); + pco.setSidRetrievalStrategy(sids); - pco.cachePermissionsFor(mock(Authentication.class), Collections.emptyList()); + pco.cachePermissionsFor(mock(Authentication.class), Collections.emptyList()); - verifyZeroInteractions(service, sids, oids); - } + verifyZeroInteractions(service, sids, oids); + } } diff --git a/acl/src/test/java/org/springframework/security/acls/AclPermissionEvaluatorTests.java b/acl/src/test/java/org/springframework/security/acls/AclPermissionEvaluatorTests.java index d07db14622..e6d0ffdfd5 100644 --- a/acl/src/test/java/org/springframework/security/acls/AclPermissionEvaluatorTests.java +++ b/acl/src/test/java/org/springframework/security/acls/AclPermissionEvaluatorTests.java @@ -19,21 +19,21 @@ import org.springframework.security.core.Authentication; */ public class AclPermissionEvaluatorTests { - @Test - @SuppressWarnings("unchecked") - public void hasPermissionReturnsTrueIfAclGrantsPermission() throws Exception { - AclService service = mock(AclService.class); - AclPermissionEvaluator pe = new AclPermissionEvaluator(service); - ObjectIdentity oid = mock(ObjectIdentity.class); - ObjectIdentityRetrievalStrategy oidStrategy = mock(ObjectIdentityRetrievalStrategy.class); - when(oidStrategy.getObjectIdentity(anyObject())).thenReturn(oid); - pe.setObjectIdentityRetrievalStrategy(oidStrategy); - pe.setSidRetrievalStrategy(mock(SidRetrievalStrategy.class)); - Acl acl = mock(Acl.class); + @Test + @SuppressWarnings("unchecked") + public void hasPermissionReturnsTrueIfAclGrantsPermission() throws Exception { + AclService service = mock(AclService.class); + AclPermissionEvaluator pe = new AclPermissionEvaluator(service); + ObjectIdentity oid = mock(ObjectIdentity.class); + ObjectIdentityRetrievalStrategy oidStrategy = mock(ObjectIdentityRetrievalStrategy.class); + when(oidStrategy.getObjectIdentity(anyObject())).thenReturn(oid); + pe.setObjectIdentityRetrievalStrategy(oidStrategy); + pe.setSidRetrievalStrategy(mock(SidRetrievalStrategy.class)); + Acl acl = mock(Acl.class); - when(service.readAclById(any(ObjectIdentity.class), anyList())).thenReturn(acl); - when(acl.isGranted(anyList(), anyList(), eq(false))).thenReturn(true); + when(service.readAclById(any(ObjectIdentity.class), anyList())).thenReturn(acl); + when(acl.isGranted(anyList(), anyList(), eq(false))).thenReturn(true); - assertTrue(pe.hasPermission(mock(Authentication.class), new Object(), "READ")); - } + assertTrue(pe.hasPermission(mock(Authentication.class), new Object(), "READ")); + } } diff --git a/acl/src/test/java/org/springframework/security/acls/afterinvocation/AclEntryAfterInvocationCollectionFilteringProviderTests.java b/acl/src/test/java/org/springframework/security/acls/afterinvocation/AclEntryAfterInvocationCollectionFilteringProviderTests.java index 4a53134feb..7d1297f34e 100644 --- a/acl/src/test/java/org/springframework/security/acls/afterinvocation/AclEntryAfterInvocationCollectionFilteringProviderTests.java +++ b/acl/src/test/java/org/springframework/security/acls/afterinvocation/AclEntryAfterInvocationCollectionFilteringProviderTests.java @@ -23,42 +23,55 @@ import java.util.List; /** * @author Luke Taylor */ -@SuppressWarnings({"unchecked"}) +@SuppressWarnings({ "unchecked" }) public class AclEntryAfterInvocationCollectionFilteringProviderTests { - @Test - public void objectsAreRemovedIfPermissionDenied() throws Exception { - AclService service = mock(AclService.class); - Acl acl = mock(Acl.class); - when(acl.isGranted(any(List.class), any(List.class), anyBoolean())).thenReturn(false); - when(service.readAclById(any(ObjectIdentity.class), any(List.class))).thenReturn(acl); - AclEntryAfterInvocationCollectionFilteringProvider provider = new AclEntryAfterInvocationCollectionFilteringProvider(service, Arrays.asList(mock(Permission.class))); - provider.setObjectIdentityRetrievalStrategy(mock(ObjectIdentityRetrievalStrategy.class)); - provider.setProcessDomainObjectClass(Object.class); - provider.setSidRetrievalStrategy(mock(SidRetrievalStrategy.class)); + @Test + public void objectsAreRemovedIfPermissionDenied() throws Exception { + AclService service = mock(AclService.class); + Acl acl = mock(Acl.class); + when(acl.isGranted(any(List.class), any(List.class), anyBoolean())).thenReturn( + false); + when(service.readAclById(any(ObjectIdentity.class), any(List.class))).thenReturn( + acl); + AclEntryAfterInvocationCollectionFilteringProvider provider = new AclEntryAfterInvocationCollectionFilteringProvider( + service, Arrays.asList(mock(Permission.class))); + provider.setObjectIdentityRetrievalStrategy(mock(ObjectIdentityRetrievalStrategy.class)); + provider.setProcessDomainObjectClass(Object.class); + provider.setSidRetrievalStrategy(mock(SidRetrievalStrategy.class)); - Object returned = provider.decide(mock(Authentication.class), new Object(), SecurityConfig.createList("AFTER_ACL_COLLECTION_READ"), new ArrayList(Arrays.asList(new Object(), new Object()))); - assertTrue(returned instanceof List); - assertTrue(((List)returned).isEmpty()); - returned = provider.decide(mock(Authentication.class), new Object(), SecurityConfig.createList("UNSUPPORTED", "AFTER_ACL_COLLECTION_READ"), new Object[] {new Object(), new Object()}); - assertTrue(returned instanceof Object[]); - assertTrue(((Object[])returned).length == 0); - } + Object returned = provider.decide(mock(Authentication.class), new Object(), + SecurityConfig.createList("AFTER_ACL_COLLECTION_READ"), new ArrayList( + Arrays.asList(new Object(), new Object()))); + assertTrue(returned instanceof List); + assertTrue(((List) returned).isEmpty()); + returned = provider.decide(mock(Authentication.class), new Object(), + SecurityConfig.createList("UNSUPPORTED", "AFTER_ACL_COLLECTION_READ"), + new Object[] { new Object(), new Object() }); + assertTrue(returned instanceof Object[]); + assertTrue(((Object[]) returned).length == 0); + } - @Test - public void accessIsGrantedIfNoAttributesDefined() throws Exception { - AclEntryAfterInvocationCollectionFilteringProvider provider = new AclEntryAfterInvocationCollectionFilteringProvider(mock(AclService.class), Arrays.asList(mock(Permission.class))); - Object returned = new Object(); + @Test + public void accessIsGrantedIfNoAttributesDefined() throws Exception { + AclEntryAfterInvocationCollectionFilteringProvider provider = new AclEntryAfterInvocationCollectionFilteringProvider( + mock(AclService.class), Arrays.asList(mock(Permission.class))); + Object returned = new Object(); - assertSame(returned, provider.decide(mock(Authentication.class), new Object(), Collections.emptyList(), returned)); - } + assertSame( + returned, + provider.decide(mock(Authentication.class), new Object(), + Collections. emptyList(), returned)); + } - @Test - public void nullReturnObjectIsIgnored() throws Exception { - AclService service = mock(AclService.class); - AclEntryAfterInvocationCollectionFilteringProvider provider = new AclEntryAfterInvocationCollectionFilteringProvider(service, Arrays.asList(mock(Permission.class))); + @Test + public void nullReturnObjectIsIgnored() throws Exception { + AclService service = mock(AclService.class); + AclEntryAfterInvocationCollectionFilteringProvider provider = new AclEntryAfterInvocationCollectionFilteringProvider( + service, Arrays.asList(mock(Permission.class))); - assertNull(provider.decide(mock(Authentication.class), new Object(), SecurityConfig.createList("AFTER_ACL_COLLECTION_READ"), null)); - verify(service, never()).readAclById(any(ObjectIdentity.class), any(List.class)); - } + assertNull(provider.decide(mock(Authentication.class), new Object(), + SecurityConfig.createList("AFTER_ACL_COLLECTION_READ"), null)); + verify(service, never()).readAclById(any(ObjectIdentity.class), any(List.class)); + } } diff --git a/acl/src/test/java/org/springframework/security/acls/afterinvocation/AclEntryAfterInvocationProviderTests.java b/acl/src/test/java/org/springframework/security/acls/afterinvocation/AclEntryAfterInvocationProviderTests.java index 53a99f395f..6cb6f438a6 100644 --- a/acl/src/test/java/org/springframework/security/acls/afterinvocation/AclEntryAfterInvocationProviderTests.java +++ b/acl/src/test/java/org/springframework/security/acls/afterinvocation/AclEntryAfterInvocationProviderTests.java @@ -19,83 +19,108 @@ import java.util.List; /** * @author Luke Taylor */ -@SuppressWarnings({"unchecked"}) +@SuppressWarnings({ "unchecked" }) public class AclEntryAfterInvocationProviderTests { - @Test(expected=IllegalArgumentException.class) - public void rejectsMissingPermissions() throws Exception { - try { - new AclEntryAfterInvocationProvider(mock(AclService.class), null); - fail("Exception expected"); - } catch (IllegalArgumentException expected) { - } - new AclEntryAfterInvocationProvider(mock(AclService.class), Collections.emptyList()); - } + @Test(expected = IllegalArgumentException.class) + public void rejectsMissingPermissions() throws Exception { + try { + new AclEntryAfterInvocationProvider(mock(AclService.class), null); + fail("Exception expected"); + } + catch (IllegalArgumentException expected) { + } + new AclEntryAfterInvocationProvider(mock(AclService.class), + Collections. emptyList()); + } - @Test - public void accessIsAllowedIfPermissionIsGranted() { - AclService service = mock(AclService.class); - Acl acl = mock(Acl.class); - when(acl.isGranted(any(List.class), any(List.class), anyBoolean())).thenReturn(true); - when(service.readAclById(any(ObjectIdentity.class), any(List.class))).thenReturn(acl); - AclEntryAfterInvocationProvider provider = new AclEntryAfterInvocationProvider(service, Arrays.asList(mock(Permission.class))); - provider.setMessageSource(new SpringSecurityMessageSource()); - provider.setObjectIdentityRetrievalStrategy(mock(ObjectIdentityRetrievalStrategy.class)); - provider.setProcessDomainObjectClass(Object.class); - provider.setSidRetrievalStrategy(mock(SidRetrievalStrategy.class)); - Object returned = new Object(); + @Test + public void accessIsAllowedIfPermissionIsGranted() { + AclService service = mock(AclService.class); + Acl acl = mock(Acl.class); + when(acl.isGranted(any(List.class), any(List.class), anyBoolean())).thenReturn( + true); + when(service.readAclById(any(ObjectIdentity.class), any(List.class))).thenReturn( + acl); + AclEntryAfterInvocationProvider provider = new AclEntryAfterInvocationProvider( + service, Arrays.asList(mock(Permission.class))); + provider.setMessageSource(new SpringSecurityMessageSource()); + provider.setObjectIdentityRetrievalStrategy(mock(ObjectIdentityRetrievalStrategy.class)); + provider.setProcessDomainObjectClass(Object.class); + provider.setSidRetrievalStrategy(mock(SidRetrievalStrategy.class)); + Object returned = new Object(); - assertSame(returned, provider.decide(mock(Authentication.class), new Object(), SecurityConfig.createList("AFTER_ACL_READ"), returned)); - } + assertSame( + returned, + provider.decide(mock(Authentication.class), new Object(), + SecurityConfig.createList("AFTER_ACL_READ"), returned)); + } - @Test - public void accessIsGrantedIfNoAttributesDefined() throws Exception { - AclEntryAfterInvocationProvider provider = new AclEntryAfterInvocationProvider(mock(AclService.class), Arrays.asList(mock(Permission.class))); - Object returned = new Object(); + @Test + public void accessIsGrantedIfNoAttributesDefined() throws Exception { + AclEntryAfterInvocationProvider provider = new AclEntryAfterInvocationProvider( + mock(AclService.class), Arrays.asList(mock(Permission.class))); + Object returned = new Object(); - assertSame(returned, provider.decide(mock(Authentication.class), new Object(), Collections.emptyList(), returned)); - } + assertSame( + returned, + provider.decide(mock(Authentication.class), new Object(), + Collections. emptyList(), returned)); + } - @Test - public void accessIsGrantedIfObjectTypeNotSupported() throws Exception { - AclEntryAfterInvocationProvider provider = new AclEntryAfterInvocationProvider(mock(AclService.class), Arrays.asList(mock(Permission.class))); - provider.setProcessDomainObjectClass(String.class); - // Not a String - Object returned = new Object(); + @Test + public void accessIsGrantedIfObjectTypeNotSupported() throws Exception { + AclEntryAfterInvocationProvider provider = new AclEntryAfterInvocationProvider( + mock(AclService.class), Arrays.asList(mock(Permission.class))); + provider.setProcessDomainObjectClass(String.class); + // Not a String + Object returned = new Object(); - assertSame(returned, provider.decide(mock(Authentication.class), new Object(), SecurityConfig.createList("AFTER_ACL_READ"), returned)); - } + assertSame( + returned, + provider.decide(mock(Authentication.class), new Object(), + SecurityConfig.createList("AFTER_ACL_READ"), returned)); + } + @Test(expected = AccessDeniedException.class) + public void accessIsDeniedIfPermissionIsNotGranted() { + AclService service = mock(AclService.class); + Acl acl = mock(Acl.class); + when(acl.isGranted(any(List.class), any(List.class), anyBoolean())).thenReturn( + false); + // Try a second time with no permissions found + when(acl.isGranted(any(List.class), any(List.class), anyBoolean())).thenThrow( + new NotFoundException("")); + when(service.readAclById(any(ObjectIdentity.class), any(List.class))).thenReturn( + acl); + AclEntryAfterInvocationProvider provider = new AclEntryAfterInvocationProvider( + service, Arrays.asList(mock(Permission.class))); + provider.setProcessConfigAttribute("MY_ATTRIBUTE"); + provider.setMessageSource(new SpringSecurityMessageSource()); + provider.setObjectIdentityRetrievalStrategy(mock(ObjectIdentityRetrievalStrategy.class)); + provider.setProcessDomainObjectClass(Object.class); + provider.setSidRetrievalStrategy(mock(SidRetrievalStrategy.class)); + try { + provider.decide(mock(Authentication.class), new Object(), + SecurityConfig.createList("UNSUPPORTED", "MY_ATTRIBUTE"), + new Object()); + fail(); + } + catch (AccessDeniedException expected) { + } + // Second scenario with no acls found + provider.decide(mock(Authentication.class), new Object(), + SecurityConfig.createList("UNSUPPORTED", "MY_ATTRIBUTE"), new Object()); + } - @Test(expected= AccessDeniedException.class) - public void accessIsDeniedIfPermissionIsNotGranted() { - AclService service = mock(AclService.class); - Acl acl = mock(Acl.class); - when(acl.isGranted(any(List.class), any(List.class), anyBoolean())).thenReturn(false); - // Try a second time with no permissions found - when(acl.isGranted(any(List.class), any(List.class), anyBoolean())).thenThrow(new NotFoundException("")); - when(service.readAclById(any(ObjectIdentity.class), any(List.class))).thenReturn(acl); - AclEntryAfterInvocationProvider provider = new AclEntryAfterInvocationProvider(service, Arrays.asList(mock(Permission.class))); - provider.setProcessConfigAttribute("MY_ATTRIBUTE"); - provider.setMessageSource(new SpringSecurityMessageSource()); - provider.setObjectIdentityRetrievalStrategy(mock(ObjectIdentityRetrievalStrategy.class)); - provider.setProcessDomainObjectClass(Object.class); - provider.setSidRetrievalStrategy(mock(SidRetrievalStrategy.class)); - try { - provider.decide(mock(Authentication.class), new Object(), SecurityConfig.createList("UNSUPPORTED", "MY_ATTRIBUTE"), new Object()); - fail(); - } catch (AccessDeniedException expected) { - } - // Second scenario with no acls found - provider.decide(mock(Authentication.class), new Object(), SecurityConfig.createList("UNSUPPORTED", "MY_ATTRIBUTE"), new Object()); - } + @Test + public void nullReturnObjectIsIgnored() throws Exception { + AclService service = mock(AclService.class); + AclEntryAfterInvocationProvider provider = new AclEntryAfterInvocationProvider( + service, Arrays.asList(mock(Permission.class))); - @Test - public void nullReturnObjectIsIgnored() throws Exception { - AclService service = mock(AclService.class); - AclEntryAfterInvocationProvider provider = new AclEntryAfterInvocationProvider(service, Arrays.asList(mock(Permission.class))); - - assertNull(provider.decide(mock(Authentication.class), new Object(), SecurityConfig.createList("AFTER_ACL_COLLECTION_READ"), null)); - verify(service, never()).readAclById(any(ObjectIdentity.class), any(List.class)); - } + assertNull(provider.decide(mock(Authentication.class), new Object(), + SecurityConfig.createList("AFTER_ACL_COLLECTION_READ"), null)); + verify(service, never()).readAclById(any(ObjectIdentity.class), any(List.class)); + } } diff --git a/acl/src/test/java/org/springframework/security/acls/domain/AccessControlImplEntryTests.java b/acl/src/test/java/org/springframework/security/acls/domain/AccessControlImplEntryTests.java index 830e090d00..9fdc262450 100644 --- a/acl/src/test/java/org/springframework/security/acls/domain/AccessControlImplEntryTests.java +++ b/acl/src/test/java/org/springframework/security/acls/domain/AccessControlImplEntryTests.java @@ -17,84 +17,86 @@ import org.springframework.security.acls.model.Sid; */ public class AccessControlImplEntryTests { - //~ Methods ======================================================================================================== + // ~ Methods + // ======================================================================================================== - @Test - public void testConstructorRequiredFields() { - // Check Acl field is present - try { - new AccessControlEntryImpl(null, null, new PrincipalSid("johndoe"), - BasePermission.ADMINISTRATION, true, true, true); - fail("It should have thrown IllegalArgumentException"); - } - catch (IllegalArgumentException expected) { - } + @Test + public void testConstructorRequiredFields() { + // Check Acl field is present + try { + new AccessControlEntryImpl(null, null, new PrincipalSid("johndoe"), + BasePermission.ADMINISTRATION, true, true, true); + fail("It should have thrown IllegalArgumentException"); + } + catch (IllegalArgumentException expected) { + } - // Check Sid field is present - try { - new AccessControlEntryImpl(null, mock(Acl.class), null, - BasePermission.ADMINISTRATION, true, true, true); - fail("It should have thrown IllegalArgumentException"); - } - catch (IllegalArgumentException expected) { - } + // Check Sid field is present + try { + new AccessControlEntryImpl(null, mock(Acl.class), null, + BasePermission.ADMINISTRATION, true, true, true); + fail("It should have thrown IllegalArgumentException"); + } + catch (IllegalArgumentException expected) { + } - // Check Permission field is present - try { - new AccessControlEntryImpl(null, mock(Acl.class), new PrincipalSid("johndoe"), null, - true, true, true); - fail("It should have thrown IllegalArgumentException"); - } - catch (IllegalArgumentException expected) { - } - } + // Check Permission field is present + try { + new AccessControlEntryImpl(null, mock(Acl.class), + new PrincipalSid("johndoe"), null, true, true, true); + fail("It should have thrown IllegalArgumentException"); + } + catch (IllegalArgumentException expected) { + } + } - @Test - public void testAccessControlEntryImplGetters() { - Acl mockAcl = mock(Acl.class); - Sid sid = new PrincipalSid("johndoe"); + @Test + public void testAccessControlEntryImplGetters() { + Acl mockAcl = mock(Acl.class); + Sid sid = new PrincipalSid("johndoe"); - // Create a sample entry - AccessControlEntry ace = new AccessControlEntryImpl(Long.valueOf(1), mockAcl, sid, BasePermission.ADMINISTRATION, - true, true, true); + // Create a sample entry + AccessControlEntry ace = new AccessControlEntryImpl(Long.valueOf(1), mockAcl, + sid, BasePermission.ADMINISTRATION, true, true, true); - // and check every get() method - assertEquals(new Long(1), ace.getId()); - assertEquals(mockAcl, ace.getAcl()); - assertEquals(sid, ace.getSid()); - assertTrue(ace.isGranting()); - assertEquals(BasePermission.ADMINISTRATION, ace.getPermission()); - assertTrue(((AuditableAccessControlEntry) ace).isAuditFailure()); - assertTrue(((AuditableAccessControlEntry) ace).isAuditSuccess()); - } + // and check every get() method + assertEquals(new Long(1), ace.getId()); + assertEquals(mockAcl, ace.getAcl()); + assertEquals(sid, ace.getSid()); + assertTrue(ace.isGranting()); + assertEquals(BasePermission.ADMINISTRATION, ace.getPermission()); + assertTrue(((AuditableAccessControlEntry) ace).isAuditFailure()); + assertTrue(((AuditableAccessControlEntry) ace).isAuditSuccess()); + } - @Test - public void testEquals() { - final Acl mockAcl = mock(Acl.class); - final ObjectIdentity oid = mock(ObjectIdentity.class); + @Test + public void testEquals() { + final Acl mockAcl = mock(Acl.class); + final ObjectIdentity oid = mock(ObjectIdentity.class); - when(mockAcl.getObjectIdentity()).thenReturn(oid); - Sid sid = new PrincipalSid("johndoe"); + when(mockAcl.getObjectIdentity()).thenReturn(oid); + Sid sid = new PrincipalSid("johndoe"); - AccessControlEntry ace = new AccessControlEntryImpl(Long.valueOf(1), mockAcl, sid, BasePermission.ADMINISTRATION, - true, true, true); + AccessControlEntry ace = new AccessControlEntryImpl(Long.valueOf(1), mockAcl, + sid, BasePermission.ADMINISTRATION, true, true, true); - assertFalse(ace.equals(null)); - assertFalse(ace.equals(Long.valueOf(100))); - assertTrue(ace.equals(ace)); - assertTrue(ace.equals(new AccessControlEntryImpl(Long.valueOf(1), mockAcl, sid, - BasePermission.ADMINISTRATION, true, true, true))); - assertFalse(ace.equals(new AccessControlEntryImpl(Long.valueOf(2), mockAcl, sid, - BasePermission.ADMINISTRATION, true, true, true))); - assertFalse(ace.equals(new AccessControlEntryImpl(Long.valueOf(1), mockAcl, new PrincipalSid("scott"), - BasePermission.ADMINISTRATION, true, true, true))); - assertFalse(ace.equals(new AccessControlEntryImpl(Long.valueOf(1), mockAcl, sid, BasePermission.WRITE, true, - true, true))); - assertFalse(ace.equals(new AccessControlEntryImpl(Long.valueOf(1), mockAcl, sid, - BasePermission.ADMINISTRATION, false, true, true))); - assertFalse(ace.equals(new AccessControlEntryImpl(Long.valueOf(1), mockAcl, sid, - BasePermission.ADMINISTRATION, true, false, true))); - assertFalse(ace.equals(new AccessControlEntryImpl(Long.valueOf(1), mockAcl, sid, - BasePermission.ADMINISTRATION, true, true, false))); - } + assertFalse(ace.equals(null)); + assertFalse(ace.equals(Long.valueOf(100))); + assertTrue(ace.equals(ace)); + assertTrue(ace.equals(new AccessControlEntryImpl(Long.valueOf(1), mockAcl, sid, + BasePermission.ADMINISTRATION, true, true, true))); + assertFalse(ace.equals(new AccessControlEntryImpl(Long.valueOf(2), mockAcl, sid, + BasePermission.ADMINISTRATION, true, true, true))); + assertFalse(ace.equals(new AccessControlEntryImpl(Long.valueOf(1), mockAcl, + new PrincipalSid("scott"), BasePermission.ADMINISTRATION, true, true, + true))); + assertFalse(ace.equals(new AccessControlEntryImpl(Long.valueOf(1), mockAcl, sid, + BasePermission.WRITE, true, true, true))); + assertFalse(ace.equals(new AccessControlEntryImpl(Long.valueOf(1), mockAcl, sid, + BasePermission.ADMINISTRATION, false, true, true))); + assertFalse(ace.equals(new AccessControlEntryImpl(Long.valueOf(1), mockAcl, sid, + BasePermission.ADMINISTRATION, true, false, true))); + assertFalse(ace.equals(new AccessControlEntryImpl(Long.valueOf(1), mockAcl, sid, + BasePermission.ADMINISTRATION, true, true, false))); + } } diff --git a/acl/src/test/java/org/springframework/security/acls/domain/AclImplTests.java b/acl/src/test/java/org/springframework/security/acls/domain/AclImplTests.java index a3fa1f0976..0d3f8a3f7e 100644 --- a/acl/src/test/java/org/springframework/security/acls/domain/AclImplTests.java +++ b/acl/src/test/java/org/springframework/security/acls/domain/AclImplTests.java @@ -14,519 +14,603 @@ import org.springframework.security.util.FieldUtils; import java.lang.reflect.Field; import java.util.*; - /** * Tests for {@link AclImpl}. * * @author Andrei Stefan */ public class AclImplTests { - private static final String TARGET_CLASS = "org.springframework.security.acls.TargetObject"; - private static final List READ = Arrays.asList(BasePermission.READ ); - private static final List WRITE = Arrays.asList(BasePermission.WRITE); - private static final List CREATE = Arrays.asList(BasePermission.CREATE ); - private static final List DELETE = Arrays.asList(BasePermission.DELETE ); - private static final List SCOTT = Arrays.asList((Sid)new PrincipalSid("scott")); - private static final List BEN = Arrays.asList((Sid)new PrincipalSid("ben")); - - Authentication auth = new TestingAuthenticationToken("joe", "ignored", "ROLE_ADMINISTRATOR"); - AclAuthorizationStrategy authzStrategy; - PermissionGrantingStrategy pgs; - AuditLogger mockAuditLogger; - ObjectIdentity objectIdentity = new ObjectIdentityImpl(TARGET_CLASS, 100); - - // ~ Methods ======================================================================================================== - - @Before - public void setUp() throws Exception { - SecurityContextHolder.getContext().setAuthentication(auth); - authzStrategy = mock(AclAuthorizationStrategy.class); - mockAuditLogger = mock(AuditLogger.class); - pgs = new DefaultPermissionGrantingStrategy(mockAuditLogger); - auth.setAuthenticated(true); - } - - @After - public void tearDown() throws Exception { - SecurityContextHolder.clearContext(); - } - - @Test(expected=IllegalArgumentException.class) - public void constructorsRejectNullObjectIdentity() throws Exception { - try { - new AclImpl(null, 1, authzStrategy, pgs, null, null, true, new PrincipalSid("joe")); - fail("Should have thrown IllegalArgumentException"); - } - catch (IllegalArgumentException expected) { - } - new AclImpl(null, 1, authzStrategy, mockAuditLogger); - } - - @Test(expected=IllegalArgumentException.class) - public void constructorsRejectNullId() throws Exception { - try { - new AclImpl(objectIdentity, null, authzStrategy, pgs, null, null, true, new PrincipalSid("joe")); - fail("Should have thrown IllegalArgumentException"); - } - catch (IllegalArgumentException expected) { - } - new AclImpl(objectIdentity, null, authzStrategy, mockAuditLogger); - } - - @SuppressWarnings("deprecation") - @Test(expected=IllegalArgumentException.class) - public void constructorsRejectNullAclAuthzStrategy() throws Exception { - try { - new AclImpl(objectIdentity, 1, null, new DefaultPermissionGrantingStrategy(mockAuditLogger), null, null, true, new PrincipalSid("joe")); - fail("It should have thrown IllegalArgumentException"); - } - catch (IllegalArgumentException expected) { - } - new AclImpl(objectIdentity, 1, null, mockAuditLogger); - } - - @Test - public void insertAceRejectsNullParameters() throws Exception { - MutableAcl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null, true, new PrincipalSid( - "joe")); - try { - acl.insertAce(0, null, new GrantedAuthoritySid("ROLE_IGNORED"), true); - fail("It should have thrown IllegalArgumentException"); - } - catch (IllegalArgumentException expected) { - } - try { - acl.insertAce(0, BasePermission.READ, null, true); - fail("It should have thrown IllegalArgumentException"); - } - catch (IllegalArgumentException expected) { - } - } - - @Test - public void insertAceAddsElementAtCorrectIndex() throws Exception { - MutableAcl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null, true, new PrincipalSid("joe")); - MockAclService service = new MockAclService(); - - // Insert one permission - acl.insertAce(0, BasePermission.READ, new GrantedAuthoritySid("ROLE_TEST1"), true); - service.updateAcl(acl); - // Check it was successfully added - assertEquals(1, acl.getEntries().size()); - assertEquals(acl.getEntries().get(0).getAcl(), acl); - assertEquals(acl.getEntries().get(0).getPermission(), BasePermission.READ); - assertEquals(acl.getEntries().get(0).getSid(), new GrantedAuthoritySid("ROLE_TEST1")); - - // Add a second permission - acl.insertAce(1, BasePermission.READ, new GrantedAuthoritySid("ROLE_TEST2"), true); - service.updateAcl(acl); - // Check it was added on the last position - assertEquals(2, acl.getEntries().size()); - assertEquals(acl.getEntries().get(1).getAcl(), acl); - assertEquals(acl.getEntries().get(1).getPermission(), BasePermission.READ); - assertEquals(acl.getEntries().get(1).getSid(), new GrantedAuthoritySid("ROLE_TEST2")); - - // Add a third permission, after the first one - acl.insertAce(1, BasePermission.WRITE, new GrantedAuthoritySid("ROLE_TEST3"), false); - service.updateAcl(acl); - assertEquals(3, acl.getEntries().size()); - // Check the third entry was added between the two existent ones - assertEquals(acl.getEntries().get(0).getPermission(), BasePermission.READ); - assertEquals(acl.getEntries().get(0).getSid(), new GrantedAuthoritySid("ROLE_TEST1")); - assertEquals(acl.getEntries().get(1).getPermission(), BasePermission.WRITE); - assertEquals(acl.getEntries().get(1).getSid(), new GrantedAuthoritySid("ROLE_TEST3")); - assertEquals(acl.getEntries().get(2).getPermission(), BasePermission.READ); - assertEquals(acl.getEntries().get(2).getSid(), new GrantedAuthoritySid("ROLE_TEST2")); - } - - @Test(expected=NotFoundException.class) - public void insertAceFailsForNonExistentElement() throws Exception { - MutableAcl acl = new AclImpl(objectIdentity,1, authzStrategy, pgs, null, null, true, new PrincipalSid( - "joe")); - MockAclService service = new MockAclService(); - - // Insert one permission - acl.insertAce(0, BasePermission.READ, new GrantedAuthoritySid("ROLE_TEST1"), true); - service.updateAcl(acl); - - acl.insertAce(55, BasePermission.READ, new GrantedAuthoritySid("ROLE_TEST2"), true); - } - - @Test - public void deleteAceKeepsInitialOrdering() throws Exception { - MutableAcl acl = new AclImpl(objectIdentity,1, authzStrategy, pgs, null, null, true, new PrincipalSid("joe")); - MockAclService service = new MockAclService(); - - // Add several permissions - acl.insertAce(0, BasePermission.READ, new GrantedAuthoritySid("ROLE_TEST1"), true); - acl.insertAce(1, BasePermission.READ, new GrantedAuthoritySid("ROLE_TEST2"), true); - acl.insertAce(2, BasePermission.READ, new GrantedAuthoritySid("ROLE_TEST3"), true); - service.updateAcl(acl); - - // Delete first permission and check the order of the remaining permissions is kept - acl.deleteAce(0); - assertEquals(2, acl.getEntries().size()); - assertEquals(acl.getEntries().get(0).getSid(), new GrantedAuthoritySid("ROLE_TEST2")); - assertEquals(acl.getEntries().get(1).getSid(), new GrantedAuthoritySid("ROLE_TEST3")); - - // Add one more permission and remove the permission in the middle - acl.insertAce(2, BasePermission.READ, new GrantedAuthoritySid("ROLE_TEST4"), true); - service.updateAcl(acl); - acl.deleteAce(1); - assertEquals(2, acl.getEntries().size()); - assertEquals(acl.getEntries().get(0).getSid(), new GrantedAuthoritySid("ROLE_TEST2")); - assertEquals(acl.getEntries().get(1).getSid(), new GrantedAuthoritySid("ROLE_TEST4")); - - // Remove remaining permissions - acl.deleteAce(1); - acl.deleteAce(0); - assertEquals(0, acl.getEntries().size()); - } - - @Test - public void deleteAceFailsForNonExistentElement() throws Exception { - AclAuthorizationStrategyImpl strategy = new AclAuthorizationStrategyImpl( - new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority("ROLE_AUDITING"), - new SimpleGrantedAuthority("ROLE_GENERAL")); - MutableAcl acl = new AclImpl(objectIdentity, (1), strategy, pgs, null, null, true, new PrincipalSid( - "joe")); - try { - acl.deleteAce(99); - fail("It should have thrown NotFoundException"); - } - catch (NotFoundException expected) { - } - } - - @Test - public void isGrantingRejectsEmptyParameters() throws Exception { - MutableAcl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null, true, new PrincipalSid("joe")); - Sid ben = new PrincipalSid("ben"); - try { - acl.isGranted(new ArrayList(0), Arrays.asList(ben) , false); - fail("It should have thrown IllegalArgumentException"); - } - catch (IllegalArgumentException expected) { - } - try { - acl.isGranted(READ, new ArrayList(0), false); - fail("It should have thrown IllegalArgumentException"); - } - catch (IllegalArgumentException expected) { - } - } - - @Test - public void isGrantingGrantsAccessForAclWithNoParent() throws Exception { - Authentication auth = new TestingAuthenticationToken("ben", "ignored", "ROLE_GENERAL","ROLE_GUEST"); - auth.setAuthenticated(true); - SecurityContextHolder.getContext().setAuthentication(auth); - ObjectIdentity rootOid = new ObjectIdentityImpl(TARGET_CLASS, 100); - - // Create an ACL which owner is not the authenticated principal - MutableAcl rootAcl = new AclImpl(rootOid, 1, authzStrategy, pgs, null, null, false, new PrincipalSid("joe")); - - // Grant some permissions - rootAcl.insertAce(0, BasePermission.READ, new PrincipalSid("ben"), false); - rootAcl.insertAce(1, BasePermission.WRITE, new PrincipalSid("scott"), true); - rootAcl.insertAce(2, BasePermission.WRITE, new PrincipalSid("rod"), false); - rootAcl.insertAce(3, BasePermission.WRITE, new GrantedAuthoritySid("WRITE_ACCESS_ROLE"), true); - - // Check permissions granting - List permissions = Arrays.asList(BasePermission.READ, BasePermission.CREATE); - List sids = Arrays.asList(new PrincipalSid("ben"), new GrantedAuthoritySid("ROLE_GUEST")); - assertFalse(rootAcl.isGranted(permissions, sids, false)); - try { - rootAcl.isGranted(permissions, SCOTT, false); - fail("It should have thrown NotFoundException"); - } - catch (NotFoundException expected) { - } - assertTrue(rootAcl.isGranted(WRITE, SCOTT, false)); - assertFalse(rootAcl.isGranted(WRITE, - Arrays.asList(new PrincipalSid("rod"), new GrantedAuthoritySid("WRITE_ACCESS_ROLE")), false)); - assertTrue(rootAcl.isGranted(WRITE, Arrays.asList(new GrantedAuthoritySid("WRITE_ACCESS_ROLE"), new PrincipalSid("rod")), false)); - try { - // Change the type of the Sid and check the granting process - rootAcl.isGranted(WRITE, Arrays.asList(new GrantedAuthoritySid("rod"), new PrincipalSid("WRITE_ACCESS_ROLE")), false); - fail("It should have thrown NotFoundException"); - } - catch (NotFoundException expected) { - } - } - - @Test - public void isGrantingGrantsAccessForInheritableAcls() throws Exception { - Authentication auth = new TestingAuthenticationToken("ben", "ignored","ROLE_GENERAL"); - auth.setAuthenticated(true); - SecurityContextHolder.getContext().setAuthentication(auth); - ObjectIdentity grandParentOid = new ObjectIdentityImpl(TARGET_CLASS, 100); - ObjectIdentity parentOid1 = new ObjectIdentityImpl(TARGET_CLASS, 101); - ObjectIdentity parentOid2 = new ObjectIdentityImpl(TARGET_CLASS, 102); - ObjectIdentity childOid1 = new ObjectIdentityImpl(TARGET_CLASS, 103); - ObjectIdentity childOid2 = new ObjectIdentityImpl(TARGET_CLASS, 104); - - // Create ACLs - PrincipalSid joe = new PrincipalSid("joe"); - MutableAcl grandParentAcl = new AclImpl(grandParentOid, 1, authzStrategy, pgs, null, null, false, joe); - MutableAcl parentAcl1 = new AclImpl(parentOid1, 2, authzStrategy, pgs, null, null, true, joe); - MutableAcl parentAcl2 = new AclImpl(parentOid2, 3, authzStrategy, pgs, null, null, true, joe); - MutableAcl childAcl1 = new AclImpl(childOid1, 4, authzStrategy, pgs, null, null, true, joe); - MutableAcl childAcl2 = new AclImpl(childOid2, 4, authzStrategy, pgs, null, null, false, joe); - - // Create hierarchies - childAcl2.setParent(childAcl1); - childAcl1.setParent(parentAcl1); - parentAcl2.setParent(grandParentAcl); - parentAcl1.setParent(grandParentAcl); - - // Add some permissions - grandParentAcl.insertAce(0, BasePermission.READ, new GrantedAuthoritySid("ROLE_USER_READ"), true); - grandParentAcl.insertAce(1, BasePermission.WRITE, new PrincipalSid("ben"), true); - grandParentAcl.insertAce(2, BasePermission.DELETE, new PrincipalSid("ben"), false); - grandParentAcl.insertAce(3, BasePermission.DELETE, new PrincipalSid("scott"), true); - parentAcl1.insertAce(0, BasePermission.READ, new PrincipalSid("scott"), true); - parentAcl1.insertAce(1, BasePermission.DELETE, new PrincipalSid("scott"), false); - parentAcl2.insertAce(0, BasePermission.CREATE, new PrincipalSid("ben"), true); - childAcl1.insertAce(0, BasePermission.CREATE, new PrincipalSid("scott"), true); - - // Check granting process for parent1 - assertTrue(parentAcl1.isGranted(READ, SCOTT, false)); - assertTrue(parentAcl1.isGranted(READ, Arrays.asList((Sid)new GrantedAuthoritySid("ROLE_USER_READ")), false)); - assertTrue(parentAcl1.isGranted(WRITE, BEN, false)); - assertFalse(parentAcl1.isGranted(DELETE, BEN, false)); - assertFalse(parentAcl1.isGranted(DELETE, SCOTT, false)); - - // Check granting process for parent2 - assertTrue(parentAcl2.isGranted(CREATE, BEN, false)); - assertTrue(parentAcl2.isGranted(WRITE, BEN, false)); - assertFalse(parentAcl2.isGranted(DELETE, BEN, false)); - - // Check granting process for child1 - assertTrue(childAcl1.isGranted(CREATE, SCOTT, - false)); - assertTrue(childAcl1.isGranted(READ, Arrays.asList((Sid)new GrantedAuthoritySid("ROLE_USER_READ")), false)); - assertFalse(childAcl1.isGranted(DELETE, BEN, false)); - - // Check granting process for child2 (doesn't inherit the permissions from its parent) - try { - assertTrue(childAcl2.isGranted(CREATE, SCOTT, false)); - fail("It should have thrown NotFoundException"); - } - catch (NotFoundException expected) { - assertTrue(true); - } - try { - assertTrue(childAcl2.isGranted(CREATE, Arrays.asList((Sid)new PrincipalSid("joe")), false)); - fail("It should have thrown NotFoundException"); - } - catch (NotFoundException expected) { - assertTrue(true); - } - } - - @Test - public void updatedAceValuesAreCorrectlyReflectedInAcl() throws Exception { - Authentication auth = new TestingAuthenticationToken("ben", "ignored","ROLE_GENERAL"); - auth.setAuthenticated(true); - SecurityContextHolder.getContext().setAuthentication(auth); - MutableAcl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null, false, new PrincipalSid("joe")); - MockAclService service = new MockAclService(); - - acl.insertAce(0, BasePermission.READ, new GrantedAuthoritySid("ROLE_USER_READ"), true); - acl.insertAce(1, BasePermission.WRITE, new GrantedAuthoritySid("ROLE_USER_READ"), true); - acl.insertAce(2, BasePermission.CREATE, new PrincipalSid("ben"), true); - service.updateAcl(acl); - - assertEquals(acl.getEntries().get(0).getPermission(), BasePermission.READ); - assertEquals(acl.getEntries().get(1).getPermission(), BasePermission.WRITE); - assertEquals(acl.getEntries().get(2).getPermission(), BasePermission.CREATE); - - // Change each permission - acl.updateAce(0, BasePermission.CREATE); - acl.updateAce(1, BasePermission.DELETE); - acl.updateAce(2, BasePermission.READ); - - // Check the change was successfully made - assertEquals(acl.getEntries().get(0).getPermission(), BasePermission.CREATE); - assertEquals(acl.getEntries().get(1).getPermission(), BasePermission.DELETE); - assertEquals(acl.getEntries().get(2).getPermission(), BasePermission.READ); - } - - @Test - public void auditableEntryFlagsAreUpdatedCorrectly() throws Exception { - Authentication auth = new TestingAuthenticationToken("ben", "ignored", "ROLE_AUDITING", "ROLE_GENERAL"); - auth.setAuthenticated(true); - SecurityContextHolder.getContext().setAuthentication(auth); - MutableAcl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null, false, new PrincipalSid("joe")); - MockAclService service = new MockAclService(); - - acl.insertAce(0, BasePermission.READ, new GrantedAuthoritySid("ROLE_USER_READ"), true); - acl.insertAce(1, BasePermission.WRITE, new GrantedAuthoritySid("ROLE_USER_READ"), true); - service.updateAcl(acl); - - assertFalse(((AuditableAccessControlEntry) acl.getEntries().get(0)).isAuditFailure()); - assertFalse(((AuditableAccessControlEntry) acl.getEntries().get(1)).isAuditFailure()); - assertFalse(((AuditableAccessControlEntry) acl.getEntries().get(0)).isAuditSuccess()); - assertFalse(((AuditableAccessControlEntry) acl.getEntries().get(1)).isAuditSuccess()); - - // Change each permission - ((AuditableAcl) acl).updateAuditing(0, true, true); - ((AuditableAcl) acl).updateAuditing(1, true, true); - - // Check the change was successfuly made - assertTrue(((AuditableAccessControlEntry) acl.getEntries().get(0)).isAuditFailure()); - assertTrue(((AuditableAccessControlEntry) acl.getEntries().get(1)).isAuditFailure()); - assertTrue(((AuditableAccessControlEntry) acl.getEntries().get(0)).isAuditSuccess()); - assertTrue(((AuditableAccessControlEntry) acl.getEntries().get(1)).isAuditSuccess()); - } - - @Test - public void gettersAndSettersAreConsistent() throws Exception { - Authentication auth = new TestingAuthenticationToken("ben", "ignored", "ROLE_GENERAL"); - auth.setAuthenticated(true); - SecurityContextHolder.getContext().setAuthentication(auth); - ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, (100)); - ObjectIdentity identity2 = new ObjectIdentityImpl(TARGET_CLASS, (101)); - MutableAcl acl = new AclImpl(identity, 1, authzStrategy, pgs, null, null, true, new PrincipalSid("joe")); - MutableAcl parentAcl = new AclImpl(identity2, 2, authzStrategy, pgs, null, null, true, new PrincipalSid("joe")); - MockAclService service = new MockAclService(); - acl.insertAce(0, BasePermission.READ, new GrantedAuthoritySid("ROLE_USER_READ"), true); - acl.insertAce(1, BasePermission.WRITE, new GrantedAuthoritySid("ROLE_USER_READ"), true); - service.updateAcl(acl); - - assertEquals(acl.getId(), 1); - assertEquals(acl.getObjectIdentity(), identity); - assertEquals(acl.getOwner(), new PrincipalSid("joe")); - assertNull(acl.getParentAcl()); - assertTrue(acl.isEntriesInheriting()); - assertEquals(2, acl.getEntries().size()); - - acl.setParent(parentAcl); - assertEquals(acl.getParentAcl(), parentAcl); - - acl.setEntriesInheriting(false); - assertFalse(acl.isEntriesInheriting()); - - acl.setOwner(new PrincipalSid("ben")); - assertEquals(acl.getOwner(), new PrincipalSid("ben")); - } - - @Test - public void isSidLoadedBehavesAsExpected() throws Exception { - List loadedSids = Arrays.asList(new PrincipalSid("ben"), new GrantedAuthoritySid("ROLE_IGNORED")); - MutableAcl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, loadedSids, true, - new PrincipalSid("joe")); - - assertTrue(acl.isSidLoaded(loadedSids)); - assertTrue(acl.isSidLoaded(Arrays.asList(new GrantedAuthoritySid("ROLE_IGNORED"), new PrincipalSid("ben")))); - assertTrue(acl.isSidLoaded(Arrays.asList((Sid)new GrantedAuthoritySid("ROLE_IGNORED")))); - assertTrue(acl.isSidLoaded(BEN)); - assertTrue(acl.isSidLoaded(null)); - assertTrue(acl.isSidLoaded(new ArrayList(0))); - assertTrue(acl.isSidLoaded(Arrays.asList((Sid)new GrantedAuthoritySid("ROLE_IGNORED"), new GrantedAuthoritySid("ROLE_IGNORED")))); - assertFalse(acl.isSidLoaded(Arrays.asList((Sid)new GrantedAuthoritySid("ROLE_GENERAL"), new GrantedAuthoritySid("ROLE_IGNORED")))); - assertFalse(acl.isSidLoaded(Arrays.asList((Sid)new GrantedAuthoritySid("ROLE_IGNORED"), new GrantedAuthoritySid("ROLE_GENERAL")))); - } - - @Test(expected=NotFoundException.class) - public void insertAceRaisesNotFoundExceptionForIndexLessThanZero() throws Exception { - AclImpl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null, true, new PrincipalSid("joe")); - acl.insertAce(-1, mock(Permission.class), mock(Sid.class), true); - } - - @Test(expected=NotFoundException.class) - public void deleteAceRaisesNotFoundExceptionForIndexLessThanZero() throws Exception { - AclImpl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null, true, new PrincipalSid("joe")); - acl.deleteAce(-1); - } - - @Test(expected=NotFoundException.class) - public void insertAceRaisesNotFoundExceptionForIndexGreaterThanSize() throws Exception { - AclImpl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null, true, new PrincipalSid("joe")); - // Insert at zero, OK. - acl.insertAce(0, mock(Permission.class), mock(Sid.class), true); - // Size is now 1 - acl.insertAce(2, mock(Permission.class), mock(Sid.class), true); - } - - // SEC-1151 - @Test(expected=NotFoundException.class) - public void deleteAceRaisesNotFoundExceptionForIndexEqualToSize() throws Exception { - AclImpl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null, true, new PrincipalSid("joe")); - acl.insertAce(0, mock(Permission.class), mock(Sid.class), true); - // Size is now 1 - acl.deleteAce(1); - } - - // SEC-1795 - @Test - public void changingParentIsSuccessful() throws Exception { - AclImpl parentAcl = new AclImpl(objectIdentity, 1L, authzStrategy, mockAuditLogger); - AclImpl childAcl = new AclImpl(objectIdentity, 2L, authzStrategy, mockAuditLogger); - AclImpl changeParentAcl = new AclImpl(objectIdentity, 3L, authzStrategy, mockAuditLogger); - - childAcl.setParent(parentAcl); - childAcl.setParent(changeParentAcl); - } - - //~ Inner Classes ================================================================================================== - - private class MockAclService implements MutableAclService { - public MutableAcl createAcl(ObjectIdentity objectIdentity) throws AlreadyExistsException { - return null; - } - - public void deleteAcl(ObjectIdentity objectIdentity, boolean deleteChildren) throws ChildrenExistException { - } - - /* - * Mock implementation that populates the aces list with fully initialized AccessControlEntries - * @see org.springframework.security.acls.MutableAclService#updateAcl(org.springframework.security.acls.MutableAcl) - */ - @SuppressWarnings("unchecked") - public MutableAcl updateAcl(MutableAcl acl) throws NotFoundException { - List oldAces = acl.getEntries(); - Field acesField = FieldUtils.getField(AclImpl.class, "aces"); - acesField.setAccessible(true); - List newAces; - try { - newAces = (List) acesField.get(acl); - newAces.clear(); - - for (int i = 0; i < oldAces.size(); i++) { - AccessControlEntry ac = oldAces.get(i); - // Just give an ID to all this acl's aces, rest of the fields are just copied - newAces.add(new AccessControlEntryImpl((i + 1), ac.getAcl(), ac.getSid(), ac.getPermission(), ac - .isGranting(), ((AuditableAccessControlEntry) ac).isAuditSuccess(), - ((AuditableAccessControlEntry) ac).isAuditFailure())); - } - } - catch (IllegalAccessException e) { - e.printStackTrace(); - } - - return acl; - } - - public List findChildren(ObjectIdentity parentIdentity) { - return null; - } - - public Acl readAclById(ObjectIdentity object) throws NotFoundException { - return null; - } - - public Acl readAclById(ObjectIdentity object, List sids) throws NotFoundException { - return null; - } - - public Map readAclsById(List objects) throws NotFoundException { - return null; - } - - public Map readAclsById(List objects, List sids) throws NotFoundException { - return null; - } - } + private static final String TARGET_CLASS = "org.springframework.security.acls.TargetObject"; + private static final List READ = Arrays.asList(BasePermission.READ); + private static final List WRITE = Arrays.asList(BasePermission.WRITE); + private static final List CREATE = Arrays.asList(BasePermission.CREATE); + private static final List DELETE = Arrays.asList(BasePermission.DELETE); + private static final List SCOTT = Arrays.asList((Sid) new PrincipalSid("scott")); + private static final List BEN = Arrays.asList((Sid) new PrincipalSid("ben")); + + Authentication auth = new TestingAuthenticationToken("joe", "ignored", + "ROLE_ADMINISTRATOR"); + AclAuthorizationStrategy authzStrategy; + PermissionGrantingStrategy pgs; + AuditLogger mockAuditLogger; + ObjectIdentity objectIdentity = new ObjectIdentityImpl(TARGET_CLASS, 100); + + // ~ Methods + // ======================================================================================================== + + @Before + public void setUp() throws Exception { + SecurityContextHolder.getContext().setAuthentication(auth); + authzStrategy = mock(AclAuthorizationStrategy.class); + mockAuditLogger = mock(AuditLogger.class); + pgs = new DefaultPermissionGrantingStrategy(mockAuditLogger); + auth.setAuthenticated(true); + } + + @After + public void tearDown() throws Exception { + SecurityContextHolder.clearContext(); + } + + @Test(expected = IllegalArgumentException.class) + public void constructorsRejectNullObjectIdentity() throws Exception { + try { + new AclImpl(null, 1, authzStrategy, pgs, null, null, true, new PrincipalSid( + "joe")); + fail("Should have thrown IllegalArgumentException"); + } + catch (IllegalArgumentException expected) { + } + new AclImpl(null, 1, authzStrategy, mockAuditLogger); + } + + @Test(expected = IllegalArgumentException.class) + public void constructorsRejectNullId() throws Exception { + try { + new AclImpl(objectIdentity, null, authzStrategy, pgs, null, null, true, + new PrincipalSid("joe")); + fail("Should have thrown IllegalArgumentException"); + } + catch (IllegalArgumentException expected) { + } + new AclImpl(objectIdentity, null, authzStrategy, mockAuditLogger); + } + + @SuppressWarnings("deprecation") + @Test(expected = IllegalArgumentException.class) + public void constructorsRejectNullAclAuthzStrategy() throws Exception { + try { + new AclImpl(objectIdentity, 1, null, new DefaultPermissionGrantingStrategy( + mockAuditLogger), null, null, true, new PrincipalSid("joe")); + fail("It should have thrown IllegalArgumentException"); + } + catch (IllegalArgumentException expected) { + } + new AclImpl(objectIdentity, 1, null, mockAuditLogger); + } + + @Test + public void insertAceRejectsNullParameters() throws Exception { + MutableAcl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null, + true, new PrincipalSid("joe")); + try { + acl.insertAce(0, null, new GrantedAuthoritySid("ROLE_IGNORED"), true); + fail("It should have thrown IllegalArgumentException"); + } + catch (IllegalArgumentException expected) { + } + try { + acl.insertAce(0, BasePermission.READ, null, true); + fail("It should have thrown IllegalArgumentException"); + } + catch (IllegalArgumentException expected) { + } + } + + @Test + public void insertAceAddsElementAtCorrectIndex() throws Exception { + MutableAcl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null, + true, new PrincipalSid("joe")); + MockAclService service = new MockAclService(); + + // Insert one permission + acl.insertAce(0, BasePermission.READ, new GrantedAuthoritySid("ROLE_TEST1"), true); + service.updateAcl(acl); + // Check it was successfully added + assertEquals(1, acl.getEntries().size()); + assertEquals(acl.getEntries().get(0).getAcl(), acl); + assertEquals(acl.getEntries().get(0).getPermission(), BasePermission.READ); + assertEquals(acl.getEntries().get(0).getSid(), new GrantedAuthoritySid( + "ROLE_TEST1")); + + // Add a second permission + acl.insertAce(1, BasePermission.READ, new GrantedAuthoritySid("ROLE_TEST2"), true); + service.updateAcl(acl); + // Check it was added on the last position + assertEquals(2, acl.getEntries().size()); + assertEquals(acl.getEntries().get(1).getAcl(), acl); + assertEquals(acl.getEntries().get(1).getPermission(), BasePermission.READ); + assertEquals(acl.getEntries().get(1).getSid(), new GrantedAuthoritySid( + "ROLE_TEST2")); + + // Add a third permission, after the first one + acl.insertAce(1, BasePermission.WRITE, new GrantedAuthoritySid("ROLE_TEST3"), + false); + service.updateAcl(acl); + assertEquals(3, acl.getEntries().size()); + // Check the third entry was added between the two existent ones + assertEquals(acl.getEntries().get(0).getPermission(), BasePermission.READ); + assertEquals(acl.getEntries().get(0).getSid(), new GrantedAuthoritySid( + "ROLE_TEST1")); + assertEquals(acl.getEntries().get(1).getPermission(), BasePermission.WRITE); + assertEquals(acl.getEntries().get(1).getSid(), new GrantedAuthoritySid( + "ROLE_TEST3")); + assertEquals(acl.getEntries().get(2).getPermission(), BasePermission.READ); + assertEquals(acl.getEntries().get(2).getSid(), new GrantedAuthoritySid( + "ROLE_TEST2")); + } + + @Test(expected = NotFoundException.class) + public void insertAceFailsForNonExistentElement() throws Exception { + MutableAcl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null, + true, new PrincipalSid("joe")); + MockAclService service = new MockAclService(); + + // Insert one permission + acl.insertAce(0, BasePermission.READ, new GrantedAuthoritySid("ROLE_TEST1"), true); + service.updateAcl(acl); + + acl.insertAce(55, BasePermission.READ, new GrantedAuthoritySid("ROLE_TEST2"), + true); + } + + @Test + public void deleteAceKeepsInitialOrdering() throws Exception { + MutableAcl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null, + true, new PrincipalSid("joe")); + MockAclService service = new MockAclService(); + + // Add several permissions + acl.insertAce(0, BasePermission.READ, new GrantedAuthoritySid("ROLE_TEST1"), true); + acl.insertAce(1, BasePermission.READ, new GrantedAuthoritySid("ROLE_TEST2"), true); + acl.insertAce(2, BasePermission.READ, new GrantedAuthoritySid("ROLE_TEST3"), true); + service.updateAcl(acl); + + // Delete first permission and check the order of the remaining permissions is + // kept + acl.deleteAce(0); + assertEquals(2, acl.getEntries().size()); + assertEquals(acl.getEntries().get(0).getSid(), new GrantedAuthoritySid( + "ROLE_TEST2")); + assertEquals(acl.getEntries().get(1).getSid(), new GrantedAuthoritySid( + "ROLE_TEST3")); + + // Add one more permission and remove the permission in the middle + acl.insertAce(2, BasePermission.READ, new GrantedAuthoritySid("ROLE_TEST4"), true); + service.updateAcl(acl); + acl.deleteAce(1); + assertEquals(2, acl.getEntries().size()); + assertEquals(acl.getEntries().get(0).getSid(), new GrantedAuthoritySid( + "ROLE_TEST2")); + assertEquals(acl.getEntries().get(1).getSid(), new GrantedAuthoritySid( + "ROLE_TEST4")); + + // Remove remaining permissions + acl.deleteAce(1); + acl.deleteAce(0); + assertEquals(0, acl.getEntries().size()); + } + + @Test + public void deleteAceFailsForNonExistentElement() throws Exception { + AclAuthorizationStrategyImpl strategy = new AclAuthorizationStrategyImpl( + new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority( + "ROLE_AUDITING"), new SimpleGrantedAuthority("ROLE_GENERAL")); + MutableAcl acl = new AclImpl(objectIdentity, (1), strategy, pgs, null, null, + true, new PrincipalSid("joe")); + try { + acl.deleteAce(99); + fail("It should have thrown NotFoundException"); + } + catch (NotFoundException expected) { + } + } + + @Test + public void isGrantingRejectsEmptyParameters() throws Exception { + MutableAcl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null, + true, new PrincipalSid("joe")); + Sid ben = new PrincipalSid("ben"); + try { + acl.isGranted(new ArrayList(0), Arrays.asList(ben), false); + fail("It should have thrown IllegalArgumentException"); + } + catch (IllegalArgumentException expected) { + } + try { + acl.isGranted(READ, new ArrayList(0), false); + fail("It should have thrown IllegalArgumentException"); + } + catch (IllegalArgumentException expected) { + } + } + + @Test + public void isGrantingGrantsAccessForAclWithNoParent() throws Exception { + Authentication auth = new TestingAuthenticationToken("ben", "ignored", + "ROLE_GENERAL", "ROLE_GUEST"); + auth.setAuthenticated(true); + SecurityContextHolder.getContext().setAuthentication(auth); + ObjectIdentity rootOid = new ObjectIdentityImpl(TARGET_CLASS, 100); + + // Create an ACL which owner is not the authenticated principal + MutableAcl rootAcl = new AclImpl(rootOid, 1, authzStrategy, pgs, null, null, + false, new PrincipalSid("joe")); + + // Grant some permissions + rootAcl.insertAce(0, BasePermission.READ, new PrincipalSid("ben"), false); + rootAcl.insertAce(1, BasePermission.WRITE, new PrincipalSid("scott"), true); + rootAcl.insertAce(2, BasePermission.WRITE, new PrincipalSid("rod"), false); + rootAcl.insertAce(3, BasePermission.WRITE, new GrantedAuthoritySid( + "WRITE_ACCESS_ROLE"), true); + + // Check permissions granting + List permissions = Arrays.asList(BasePermission.READ, + BasePermission.CREATE); + List sids = Arrays.asList(new PrincipalSid("ben"), new GrantedAuthoritySid( + "ROLE_GUEST")); + assertFalse(rootAcl.isGranted(permissions, sids, false)); + try { + rootAcl.isGranted(permissions, SCOTT, false); + fail("It should have thrown NotFoundException"); + } + catch (NotFoundException expected) { + } + assertTrue(rootAcl.isGranted(WRITE, SCOTT, false)); + assertFalse(rootAcl.isGranted(WRITE, Arrays.asList(new PrincipalSid("rod"), + new GrantedAuthoritySid("WRITE_ACCESS_ROLE")), false)); + assertTrue(rootAcl.isGranted(WRITE, Arrays.asList(new GrantedAuthoritySid( + "WRITE_ACCESS_ROLE"), new PrincipalSid("rod")), false)); + try { + // Change the type of the Sid and check the granting process + rootAcl.isGranted(WRITE, Arrays.asList(new GrantedAuthoritySid("rod"), + new PrincipalSid("WRITE_ACCESS_ROLE")), false); + fail("It should have thrown NotFoundException"); + } + catch (NotFoundException expected) { + } + } + + @Test + public void isGrantingGrantsAccessForInheritableAcls() throws Exception { + Authentication auth = new TestingAuthenticationToken("ben", "ignored", + "ROLE_GENERAL"); + auth.setAuthenticated(true); + SecurityContextHolder.getContext().setAuthentication(auth); + ObjectIdentity grandParentOid = new ObjectIdentityImpl(TARGET_CLASS, 100); + ObjectIdentity parentOid1 = new ObjectIdentityImpl(TARGET_CLASS, 101); + ObjectIdentity parentOid2 = new ObjectIdentityImpl(TARGET_CLASS, 102); + ObjectIdentity childOid1 = new ObjectIdentityImpl(TARGET_CLASS, 103); + ObjectIdentity childOid2 = new ObjectIdentityImpl(TARGET_CLASS, 104); + + // Create ACLs + PrincipalSid joe = new PrincipalSid("joe"); + MutableAcl grandParentAcl = new AclImpl(grandParentOid, 1, authzStrategy, pgs, + null, null, false, joe); + MutableAcl parentAcl1 = new AclImpl(parentOid1, 2, authzStrategy, pgs, null, + null, true, joe); + MutableAcl parentAcl2 = new AclImpl(parentOid2, 3, authzStrategy, pgs, null, + null, true, joe); + MutableAcl childAcl1 = new AclImpl(childOid1, 4, authzStrategy, pgs, null, null, + true, joe); + MutableAcl childAcl2 = new AclImpl(childOid2, 4, authzStrategy, pgs, null, null, + false, joe); + + // Create hierarchies + childAcl2.setParent(childAcl1); + childAcl1.setParent(parentAcl1); + parentAcl2.setParent(grandParentAcl); + parentAcl1.setParent(grandParentAcl); + + // Add some permissions + grandParentAcl.insertAce(0, BasePermission.READ, new GrantedAuthoritySid( + "ROLE_USER_READ"), true); + grandParentAcl.insertAce(1, BasePermission.WRITE, new PrincipalSid("ben"), true); + grandParentAcl + .insertAce(2, BasePermission.DELETE, new PrincipalSid("ben"), false); + grandParentAcl.insertAce(3, BasePermission.DELETE, new PrincipalSid("scott"), + true); + parentAcl1.insertAce(0, BasePermission.READ, new PrincipalSid("scott"), true); + parentAcl1.insertAce(1, BasePermission.DELETE, new PrincipalSid("scott"), false); + parentAcl2.insertAce(0, BasePermission.CREATE, new PrincipalSid("ben"), true); + childAcl1.insertAce(0, BasePermission.CREATE, new PrincipalSid("scott"), true); + + // Check granting process for parent1 + assertTrue(parentAcl1.isGranted(READ, SCOTT, false)); + assertTrue(parentAcl1.isGranted(READ, + Arrays.asList((Sid) new GrantedAuthoritySid("ROLE_USER_READ")), false)); + assertTrue(parentAcl1.isGranted(WRITE, BEN, false)); + assertFalse(parentAcl1.isGranted(DELETE, BEN, false)); + assertFalse(parentAcl1.isGranted(DELETE, SCOTT, false)); + + // Check granting process for parent2 + assertTrue(parentAcl2.isGranted(CREATE, BEN, false)); + assertTrue(parentAcl2.isGranted(WRITE, BEN, false)); + assertFalse(parentAcl2.isGranted(DELETE, BEN, false)); + + // Check granting process for child1 + assertTrue(childAcl1.isGranted(CREATE, SCOTT, false)); + assertTrue(childAcl1.isGranted(READ, + Arrays.asList((Sid) new GrantedAuthoritySid("ROLE_USER_READ")), false)); + assertFalse(childAcl1.isGranted(DELETE, BEN, false)); + + // Check granting process for child2 (doesn't inherit the permissions from its + // parent) + try { + assertTrue(childAcl2.isGranted(CREATE, SCOTT, false)); + fail("It should have thrown NotFoundException"); + } + catch (NotFoundException expected) { + assertTrue(true); + } + try { + assertTrue(childAcl2.isGranted(CREATE, + Arrays.asList((Sid) new PrincipalSid("joe")), false)); + fail("It should have thrown NotFoundException"); + } + catch (NotFoundException expected) { + assertTrue(true); + } + } + + @Test + public void updatedAceValuesAreCorrectlyReflectedInAcl() throws Exception { + Authentication auth = new TestingAuthenticationToken("ben", "ignored", + "ROLE_GENERAL"); + auth.setAuthenticated(true); + SecurityContextHolder.getContext().setAuthentication(auth); + MutableAcl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null, + false, new PrincipalSid("joe")); + MockAclService service = new MockAclService(); + + acl.insertAce(0, BasePermission.READ, new GrantedAuthoritySid("ROLE_USER_READ"), + true); + acl.insertAce(1, BasePermission.WRITE, new GrantedAuthoritySid("ROLE_USER_READ"), + true); + acl.insertAce(2, BasePermission.CREATE, new PrincipalSid("ben"), true); + service.updateAcl(acl); + + assertEquals(acl.getEntries().get(0).getPermission(), BasePermission.READ); + assertEquals(acl.getEntries().get(1).getPermission(), BasePermission.WRITE); + assertEquals(acl.getEntries().get(2).getPermission(), BasePermission.CREATE); + + // Change each permission + acl.updateAce(0, BasePermission.CREATE); + acl.updateAce(1, BasePermission.DELETE); + acl.updateAce(2, BasePermission.READ); + + // Check the change was successfully made + assertEquals(acl.getEntries().get(0).getPermission(), BasePermission.CREATE); + assertEquals(acl.getEntries().get(1).getPermission(), BasePermission.DELETE); + assertEquals(acl.getEntries().get(2).getPermission(), BasePermission.READ); + } + + @Test + public void auditableEntryFlagsAreUpdatedCorrectly() throws Exception { + Authentication auth = new TestingAuthenticationToken("ben", "ignored", + "ROLE_AUDITING", "ROLE_GENERAL"); + auth.setAuthenticated(true); + SecurityContextHolder.getContext().setAuthentication(auth); + MutableAcl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null, + false, new PrincipalSid("joe")); + MockAclService service = new MockAclService(); + + acl.insertAce(0, BasePermission.READ, new GrantedAuthoritySid("ROLE_USER_READ"), + true); + acl.insertAce(1, BasePermission.WRITE, new GrantedAuthoritySid("ROLE_USER_READ"), + true); + service.updateAcl(acl); + + assertFalse(((AuditableAccessControlEntry) acl.getEntries().get(0)) + .isAuditFailure()); + assertFalse(((AuditableAccessControlEntry) acl.getEntries().get(1)) + .isAuditFailure()); + assertFalse(((AuditableAccessControlEntry) acl.getEntries().get(0)) + .isAuditSuccess()); + assertFalse(((AuditableAccessControlEntry) acl.getEntries().get(1)) + .isAuditSuccess()); + + // Change each permission + ((AuditableAcl) acl).updateAuditing(0, true, true); + ((AuditableAcl) acl).updateAuditing(1, true, true); + + // Check the change was successfuly made + assertTrue(((AuditableAccessControlEntry) acl.getEntries().get(0)) + .isAuditFailure()); + assertTrue(((AuditableAccessControlEntry) acl.getEntries().get(1)) + .isAuditFailure()); + assertTrue(((AuditableAccessControlEntry) acl.getEntries().get(0)) + .isAuditSuccess()); + assertTrue(((AuditableAccessControlEntry) acl.getEntries().get(1)) + .isAuditSuccess()); + } + + @Test + public void gettersAndSettersAreConsistent() throws Exception { + Authentication auth = new TestingAuthenticationToken("ben", "ignored", + "ROLE_GENERAL"); + auth.setAuthenticated(true); + SecurityContextHolder.getContext().setAuthentication(auth); + ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, (100)); + ObjectIdentity identity2 = new ObjectIdentityImpl(TARGET_CLASS, (101)); + MutableAcl acl = new AclImpl(identity, 1, authzStrategy, pgs, null, null, true, + new PrincipalSid("joe")); + MutableAcl parentAcl = new AclImpl(identity2, 2, authzStrategy, pgs, null, null, + true, new PrincipalSid("joe")); + MockAclService service = new MockAclService(); + acl.insertAce(0, BasePermission.READ, new GrantedAuthoritySid("ROLE_USER_READ"), + true); + acl.insertAce(1, BasePermission.WRITE, new GrantedAuthoritySid("ROLE_USER_READ"), + true); + service.updateAcl(acl); + + assertEquals(acl.getId(), 1); + assertEquals(acl.getObjectIdentity(), identity); + assertEquals(acl.getOwner(), new PrincipalSid("joe")); + assertNull(acl.getParentAcl()); + assertTrue(acl.isEntriesInheriting()); + assertEquals(2, acl.getEntries().size()); + + acl.setParent(parentAcl); + assertEquals(acl.getParentAcl(), parentAcl); + + acl.setEntriesInheriting(false); + assertFalse(acl.isEntriesInheriting()); + + acl.setOwner(new PrincipalSid("ben")); + assertEquals(acl.getOwner(), new PrincipalSid("ben")); + } + + @Test + public void isSidLoadedBehavesAsExpected() throws Exception { + List loadedSids = Arrays.asList(new PrincipalSid("ben"), + new GrantedAuthoritySid("ROLE_IGNORED")); + MutableAcl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, + loadedSids, true, new PrincipalSid("joe")); + + assertTrue(acl.isSidLoaded(loadedSids)); + assertTrue(acl.isSidLoaded(Arrays.asList(new GrantedAuthoritySid("ROLE_IGNORED"), + new PrincipalSid("ben")))); + assertTrue(acl.isSidLoaded(Arrays.asList((Sid) new GrantedAuthoritySid( + "ROLE_IGNORED")))); + assertTrue(acl.isSidLoaded(BEN)); + assertTrue(acl.isSidLoaded(null)); + assertTrue(acl.isSidLoaded(new ArrayList(0))); + assertTrue(acl.isSidLoaded(Arrays.asList((Sid) new GrantedAuthoritySid( + "ROLE_IGNORED"), new GrantedAuthoritySid("ROLE_IGNORED")))); + assertFalse(acl.isSidLoaded(Arrays.asList((Sid) new GrantedAuthoritySid( + "ROLE_GENERAL"), new GrantedAuthoritySid("ROLE_IGNORED")))); + assertFalse(acl.isSidLoaded(Arrays.asList((Sid) new GrantedAuthoritySid( + "ROLE_IGNORED"), new GrantedAuthoritySid("ROLE_GENERAL")))); + } + + @Test(expected = NotFoundException.class) + public void insertAceRaisesNotFoundExceptionForIndexLessThanZero() throws Exception { + AclImpl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null, + true, new PrincipalSid("joe")); + acl.insertAce(-1, mock(Permission.class), mock(Sid.class), true); + } + + @Test(expected = NotFoundException.class) + public void deleteAceRaisesNotFoundExceptionForIndexLessThanZero() throws Exception { + AclImpl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null, + true, new PrincipalSid("joe")); + acl.deleteAce(-1); + } + + @Test(expected = NotFoundException.class) + public void insertAceRaisesNotFoundExceptionForIndexGreaterThanSize() + throws Exception { + AclImpl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null, + true, new PrincipalSid("joe")); + // Insert at zero, OK. + acl.insertAce(0, mock(Permission.class), mock(Sid.class), true); + // Size is now 1 + acl.insertAce(2, mock(Permission.class), mock(Sid.class), true); + } + + // SEC-1151 + @Test(expected = NotFoundException.class) + public void deleteAceRaisesNotFoundExceptionForIndexEqualToSize() throws Exception { + AclImpl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null, + true, new PrincipalSid("joe")); + acl.insertAce(0, mock(Permission.class), mock(Sid.class), true); + // Size is now 1 + acl.deleteAce(1); + } + + // SEC-1795 + @Test + public void changingParentIsSuccessful() throws Exception { + AclImpl parentAcl = new AclImpl(objectIdentity, 1L, authzStrategy, + mockAuditLogger); + AclImpl childAcl = new AclImpl(objectIdentity, 2L, authzStrategy, mockAuditLogger); + AclImpl changeParentAcl = new AclImpl(objectIdentity, 3L, authzStrategy, + mockAuditLogger); + + childAcl.setParent(parentAcl); + childAcl.setParent(changeParentAcl); + } + + // ~ Inner Classes + // ================================================================================================== + + private class MockAclService implements MutableAclService { + public MutableAcl createAcl(ObjectIdentity objectIdentity) + throws AlreadyExistsException { + return null; + } + + public void deleteAcl(ObjectIdentity objectIdentity, boolean deleteChildren) + throws ChildrenExistException { + } + + /* + * Mock implementation that populates the aces list with fully initialized + * AccessControlEntries + * + * @see + * org.springframework.security.acls.MutableAclService#updateAcl(org.springframework + * .security.acls.MutableAcl) + */ + @SuppressWarnings("unchecked") + public MutableAcl updateAcl(MutableAcl acl) throws NotFoundException { + List oldAces = acl.getEntries(); + Field acesField = FieldUtils.getField(AclImpl.class, "aces"); + acesField.setAccessible(true); + List newAces; + try { + newAces = (List) acesField.get(acl); + newAces.clear(); + + for (int i = 0; i < oldAces.size(); i++) { + AccessControlEntry ac = oldAces.get(i); + // Just give an ID to all this acl's aces, rest of the fields are just + // copied + newAces.add(new AccessControlEntryImpl((i + 1), ac.getAcl(), ac + .getSid(), ac.getPermission(), ac.isGranting(), + ((AuditableAccessControlEntry) ac).isAuditSuccess(), + ((AuditableAccessControlEntry) ac).isAuditFailure())); + } + } + catch (IllegalAccessException e) { + e.printStackTrace(); + } + + return acl; + } + + public List findChildren(ObjectIdentity parentIdentity) { + return null; + } + + public Acl readAclById(ObjectIdentity object) throws NotFoundException { + return null; + } + + public Acl readAclById(ObjectIdentity object, List sids) + throws NotFoundException { + return null; + } + + public Map readAclsById(List objects) + throws NotFoundException { + return null; + } + + public Map readAclsById(List objects, + List sids) throws NotFoundException { + return null; + } + } } diff --git a/acl/src/test/java/org/springframework/security/acls/domain/AclImplementationSecurityCheckTests.java b/acl/src/test/java/org/springframework/security/acls/domain/AclImplementationSecurityCheckTests.java index 4b7b540ac0..b25f391a72 100644 --- a/acl/src/test/java/org/springframework/security/acls/domain/AclImplementationSecurityCheckTests.java +++ b/acl/src/test/java/org/springframework/security/acls/domain/AclImplementationSecurityCheckTests.java @@ -14,245 +14,284 @@ import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.context.SecurityContextHolder; /** - * Test class for {@link AclAuthorizationStrategyImpl} and {@link AclImpl} - * security checks. + * Test class for {@link AclAuthorizationStrategyImpl} and {@link AclImpl} security + * checks. * * @author Andrei Stefan */ public class AclImplementationSecurityCheckTests { - private static final String TARGET_CLASS = "org.springframework.security.acls.TargetObject"; + private static final String TARGET_CLASS = "org.springframework.security.acls.TargetObject"; - //~ Methods ======================================================================================================== + // ~ Methods + // ======================================================================================================== - @Before - public void setUp() throws Exception { - SecurityContextHolder.clearContext(); - } + @Before + public void setUp() throws Exception { + SecurityContextHolder.clearContext(); + } - @After - public void tearDown() throws Exception { - SecurityContextHolder.clearContext(); - } + @After + public void tearDown() throws Exception { + SecurityContextHolder.clearContext(); + } - @Test - public void testSecurityCheckNoACEs() throws Exception { - Authentication auth = new TestingAuthenticationToken("user", "password","ROLE_GENERAL","ROLE_AUDITING","ROLE_OWNERSHIP"); - auth.setAuthenticated(true); - SecurityContextHolder.getContext().setAuthentication(auth); + @Test + public void testSecurityCheckNoACEs() throws Exception { + Authentication auth = new TestingAuthenticationToken("user", "password", + "ROLE_GENERAL", "ROLE_AUDITING", "ROLE_OWNERSHIP"); + auth.setAuthenticated(true); + SecurityContextHolder.getContext().setAuthentication(auth); - ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, new Long(100)); - AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl( - new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority("ROLE_AUDITING"), - new SimpleGrantedAuthority("ROLE_GENERAL")); + ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, new Long(100)); + AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl( + new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority( + "ROLE_AUDITING"), new SimpleGrantedAuthority("ROLE_GENERAL")); - Acl acl = new AclImpl(identity, new Long(1), aclAuthorizationStrategy, new ConsoleAuditLogger()); + Acl acl = new AclImpl(identity, new Long(1), aclAuthorizationStrategy, + new ConsoleAuditLogger()); - aclAuthorizationStrategy.securityCheck(acl, AclAuthorizationStrategy.CHANGE_GENERAL); - aclAuthorizationStrategy.securityCheck(acl, AclAuthorizationStrategy.CHANGE_AUDITING); - aclAuthorizationStrategy.securityCheck(acl, AclAuthorizationStrategy.CHANGE_OWNERSHIP); + aclAuthorizationStrategy.securityCheck(acl, + AclAuthorizationStrategy.CHANGE_GENERAL); + aclAuthorizationStrategy.securityCheck(acl, + AclAuthorizationStrategy.CHANGE_AUDITING); + aclAuthorizationStrategy.securityCheck(acl, + AclAuthorizationStrategy.CHANGE_OWNERSHIP); - // Create another authorization strategy - AclAuthorizationStrategy aclAuthorizationStrategy2 = new AclAuthorizationStrategyImpl( - new SimpleGrantedAuthority("ROLE_ONE"), new SimpleGrantedAuthority("ROLE_TWO"), - new SimpleGrantedAuthority("ROLE_THREE")); - Acl acl2 = new AclImpl(identity, new Long(1), aclAuthorizationStrategy2, new ConsoleAuditLogger()); - // Check access in case the principal has no authorization rights - try { - aclAuthorizationStrategy2.securityCheck(acl2, AclAuthorizationStrategy.CHANGE_GENERAL); - fail("It should have thrown NotFoundException"); - } - catch (NotFoundException expected) { - } - try { - aclAuthorizationStrategy2.securityCheck(acl2, AclAuthorizationStrategy.CHANGE_AUDITING); - fail("It should have thrown NotFoundException"); - } - catch (NotFoundException expected) { - } - try { - aclAuthorizationStrategy2.securityCheck(acl2, AclAuthorizationStrategy.CHANGE_OWNERSHIP); - fail("It should have thrown NotFoundException"); - } - catch (NotFoundException expected) { - } - } + // Create another authorization strategy + AclAuthorizationStrategy aclAuthorizationStrategy2 = new AclAuthorizationStrategyImpl( + new SimpleGrantedAuthority("ROLE_ONE"), new SimpleGrantedAuthority( + "ROLE_TWO"), new SimpleGrantedAuthority("ROLE_THREE")); + Acl acl2 = new AclImpl(identity, new Long(1), aclAuthorizationStrategy2, + new ConsoleAuditLogger()); + // Check access in case the principal has no authorization rights + try { + aclAuthorizationStrategy2.securityCheck(acl2, + AclAuthorizationStrategy.CHANGE_GENERAL); + fail("It should have thrown NotFoundException"); + } + catch (NotFoundException expected) { + } + try { + aclAuthorizationStrategy2.securityCheck(acl2, + AclAuthorizationStrategy.CHANGE_AUDITING); + fail("It should have thrown NotFoundException"); + } + catch (NotFoundException expected) { + } + try { + aclAuthorizationStrategy2.securityCheck(acl2, + AclAuthorizationStrategy.CHANGE_OWNERSHIP); + fail("It should have thrown NotFoundException"); + } + catch (NotFoundException expected) { + } + } - @Test - public void testSecurityCheckWithMultipleACEs() throws Exception { - // Create a simple authentication with ROLE_GENERAL - Authentication auth = new TestingAuthenticationToken("user", "password", "ROLE_GENERAL"); - auth.setAuthenticated(true); - SecurityContextHolder.getContext().setAuthentication(auth); + @Test + public void testSecurityCheckWithMultipleACEs() throws Exception { + // Create a simple authentication with ROLE_GENERAL + Authentication auth = new TestingAuthenticationToken("user", "password", + "ROLE_GENERAL"); + auth.setAuthenticated(true); + SecurityContextHolder.getContext().setAuthentication(auth); - ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, new Long(100)); - // Authorization strategy will require a different role for each access - AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl( - new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority("ROLE_AUDITING"), - new SimpleGrantedAuthority("ROLE_GENERAL")); + ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, new Long(100)); + // Authorization strategy will require a different role for each access + AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl( + new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority( + "ROLE_AUDITING"), new SimpleGrantedAuthority("ROLE_GENERAL")); - // Let's give the principal the ADMINISTRATION permission, without - // granting access - MutableAcl aclFirstDeny = new AclImpl(identity, new Long(1), aclAuthorizationStrategy, new ConsoleAuditLogger()); - aclFirstDeny.insertAce(0, BasePermission.ADMINISTRATION, new PrincipalSid(auth), false); + // Let's give the principal the ADMINISTRATION permission, without + // granting access + MutableAcl aclFirstDeny = new AclImpl(identity, new Long(1), + aclAuthorizationStrategy, new ConsoleAuditLogger()); + aclFirstDeny.insertAce(0, BasePermission.ADMINISTRATION, new PrincipalSid(auth), + false); - // The CHANGE_GENERAL test should pass as the principal has ROLE_GENERAL - aclAuthorizationStrategy.securityCheck(aclFirstDeny, AclAuthorizationStrategy.CHANGE_GENERAL); + // The CHANGE_GENERAL test should pass as the principal has ROLE_GENERAL + aclAuthorizationStrategy.securityCheck(aclFirstDeny, + AclAuthorizationStrategy.CHANGE_GENERAL); - // The CHANGE_AUDITING and CHANGE_OWNERSHIP should fail since the - // principal doesn't have these authorities, - // nor granting access - try { - aclAuthorizationStrategy.securityCheck(aclFirstDeny, AclAuthorizationStrategy.CHANGE_AUDITING); - fail("It should have thrown AccessDeniedException"); - } - catch (AccessDeniedException expected) { - } - try { - aclAuthorizationStrategy.securityCheck(aclFirstDeny, AclAuthorizationStrategy.CHANGE_OWNERSHIP); - fail("It should have thrown AccessDeniedException"); - } - catch (AccessDeniedException expected) { - } + // The CHANGE_AUDITING and CHANGE_OWNERSHIP should fail since the + // principal doesn't have these authorities, + // nor granting access + try { + aclAuthorizationStrategy.securityCheck(aclFirstDeny, + AclAuthorizationStrategy.CHANGE_AUDITING); + fail("It should have thrown AccessDeniedException"); + } + catch (AccessDeniedException expected) { + } + try { + aclAuthorizationStrategy.securityCheck(aclFirstDeny, + AclAuthorizationStrategy.CHANGE_OWNERSHIP); + fail("It should have thrown AccessDeniedException"); + } + catch (AccessDeniedException expected) { + } - // Add granting access to this principal - aclFirstDeny.insertAce(1, BasePermission.ADMINISTRATION, new PrincipalSid(auth), true); - // and try again for CHANGE_AUDITING - the first ACE's granting flag - // (false) will deny this access - try { - aclAuthorizationStrategy.securityCheck(aclFirstDeny, AclAuthorizationStrategy.CHANGE_AUDITING); - fail("It should have thrown AccessDeniedException"); - } - catch (AccessDeniedException expected) { - } + // Add granting access to this principal + aclFirstDeny.insertAce(1, BasePermission.ADMINISTRATION, new PrincipalSid(auth), + true); + // and try again for CHANGE_AUDITING - the first ACE's granting flag + // (false) will deny this access + try { + aclAuthorizationStrategy.securityCheck(aclFirstDeny, + AclAuthorizationStrategy.CHANGE_AUDITING); + fail("It should have thrown AccessDeniedException"); + } + catch (AccessDeniedException expected) { + } - // Create another ACL and give the principal the ADMINISTRATION - // permission, with granting access - MutableAcl aclFirstAllow = new AclImpl(identity, new Long(1), aclAuthorizationStrategy, - new ConsoleAuditLogger()); - aclFirstAllow.insertAce(0, BasePermission.ADMINISTRATION, new PrincipalSid(auth), true); + // Create another ACL and give the principal the ADMINISTRATION + // permission, with granting access + MutableAcl aclFirstAllow = new AclImpl(identity, new Long(1), + aclAuthorizationStrategy, new ConsoleAuditLogger()); + aclFirstAllow.insertAce(0, BasePermission.ADMINISTRATION, new PrincipalSid(auth), + true); - // The CHANGE_AUDITING test should pass as there is one ACE with - // granting access + // The CHANGE_AUDITING test should pass as there is one ACE with + // granting access - aclAuthorizationStrategy.securityCheck(aclFirstAllow, AclAuthorizationStrategy.CHANGE_AUDITING); + aclAuthorizationStrategy.securityCheck(aclFirstAllow, + AclAuthorizationStrategy.CHANGE_AUDITING); - // Add a deny ACE and test again for CHANGE_AUDITING - aclFirstAllow.insertAce(1, BasePermission.ADMINISTRATION, new PrincipalSid(auth), false); - try { - aclAuthorizationStrategy.securityCheck(aclFirstAllow, AclAuthorizationStrategy.CHANGE_AUDITING); - assertTrue(true); - } - catch (AccessDeniedException notExpected) { - fail("It shouldn't have thrown AccessDeniedException"); - } + // Add a deny ACE and test again for CHANGE_AUDITING + aclFirstAllow.insertAce(1, BasePermission.ADMINISTRATION, new PrincipalSid(auth), + false); + try { + aclAuthorizationStrategy.securityCheck(aclFirstAllow, + AclAuthorizationStrategy.CHANGE_AUDITING); + assertTrue(true); + } + catch (AccessDeniedException notExpected) { + fail("It shouldn't have thrown AccessDeniedException"); + } - // Create an ACL with no ACE - MutableAcl aclNoACE = new AclImpl(identity, new Long(1), aclAuthorizationStrategy, new ConsoleAuditLogger()); - try { - aclAuthorizationStrategy.securityCheck(aclNoACE, AclAuthorizationStrategy.CHANGE_AUDITING); - fail("It should have thrown NotFoundException"); - } - catch (NotFoundException expected) { - assertTrue(true); - } - // and still grant access for CHANGE_GENERAL - try { - aclAuthorizationStrategy.securityCheck(aclNoACE, AclAuthorizationStrategy.CHANGE_GENERAL); - assertTrue(true); - } - catch (NotFoundException expected) { - fail("It shouldn't have thrown NotFoundException"); - } - } + // Create an ACL with no ACE + MutableAcl aclNoACE = new AclImpl(identity, new Long(1), + aclAuthorizationStrategy, new ConsoleAuditLogger()); + try { + aclAuthorizationStrategy.securityCheck(aclNoACE, + AclAuthorizationStrategy.CHANGE_AUDITING); + fail("It should have thrown NotFoundException"); + } + catch (NotFoundException expected) { + assertTrue(true); + } + // and still grant access for CHANGE_GENERAL + try { + aclAuthorizationStrategy.securityCheck(aclNoACE, + AclAuthorizationStrategy.CHANGE_GENERAL); + assertTrue(true); + } + catch (NotFoundException expected) { + fail("It shouldn't have thrown NotFoundException"); + } + } - @Test - public void testSecurityCheckWithInheritableACEs() throws Exception { - // Create a simple authentication with ROLE_GENERAL - Authentication auth = new TestingAuthenticationToken("user", "password", "ROLE_GENERAL"); - auth.setAuthenticated(true); - SecurityContextHolder.getContext().setAuthentication(auth); + @Test + public void testSecurityCheckWithInheritableACEs() throws Exception { + // Create a simple authentication with ROLE_GENERAL + Authentication auth = new TestingAuthenticationToken("user", "password", + "ROLE_GENERAL"); + auth.setAuthenticated(true); + SecurityContextHolder.getContext().setAuthentication(auth); - ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, 100); - // Authorization strategy will require a different role for each access - AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl( - new SimpleGrantedAuthority("ROLE_ONE"), new SimpleGrantedAuthority("ROLE_TWO"), - new SimpleGrantedAuthority("ROLE_GENERAL")); + ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, 100); + // Authorization strategy will require a different role for each access + AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl( + new SimpleGrantedAuthority("ROLE_ONE"), new SimpleGrantedAuthority( + "ROLE_TWO"), new SimpleGrantedAuthority("ROLE_GENERAL")); - // Let's give the principal an ADMINISTRATION permission, with granting - // access - MutableAcl parentAcl = new AclImpl(identity, 1, aclAuthorizationStrategy, new ConsoleAuditLogger()); - parentAcl.insertAce(0, BasePermission.ADMINISTRATION, new PrincipalSid(auth), true); - MutableAcl childAcl = new AclImpl(identity, 2, aclAuthorizationStrategy, new ConsoleAuditLogger()); + // Let's give the principal an ADMINISTRATION permission, with granting + // access + MutableAcl parentAcl = new AclImpl(identity, 1, aclAuthorizationStrategy, + new ConsoleAuditLogger()); + parentAcl.insertAce(0, BasePermission.ADMINISTRATION, new PrincipalSid(auth), + true); + MutableAcl childAcl = new AclImpl(identity, 2, aclAuthorizationStrategy, + new ConsoleAuditLogger()); - // Check against the 'child' acl, which doesn't offer any authorization - // rights on CHANGE_OWNERSHIP - try { - aclAuthorizationStrategy.securityCheck(childAcl, AclAuthorizationStrategy.CHANGE_OWNERSHIP); - fail("It should have thrown NotFoundException"); - } - catch (NotFoundException expected) { - assertTrue(true); - } + // Check against the 'child' acl, which doesn't offer any authorization + // rights on CHANGE_OWNERSHIP + try { + aclAuthorizationStrategy.securityCheck(childAcl, + AclAuthorizationStrategy.CHANGE_OWNERSHIP); + fail("It should have thrown NotFoundException"); + } + catch (NotFoundException expected) { + assertTrue(true); + } - // Link the child with its parent and test again against the - // CHANGE_OWNERSHIP right - childAcl.setParent(parentAcl); - childAcl.setEntriesInheriting(true); - try { - aclAuthorizationStrategy.securityCheck(childAcl, AclAuthorizationStrategy.CHANGE_OWNERSHIP); - assertTrue(true); - } - catch (NotFoundException expected) { - fail("It shouldn't have thrown NotFoundException"); - } + // Link the child with its parent and test again against the + // CHANGE_OWNERSHIP right + childAcl.setParent(parentAcl); + childAcl.setEntriesInheriting(true); + try { + aclAuthorizationStrategy.securityCheck(childAcl, + AclAuthorizationStrategy.CHANGE_OWNERSHIP); + assertTrue(true); + } + catch (NotFoundException expected) { + fail("It shouldn't have thrown NotFoundException"); + } - // Create a root parent and link it to the middle parent - MutableAcl rootParentAcl = new AclImpl(identity, 1, aclAuthorizationStrategy, - new ConsoleAuditLogger()); - parentAcl = new AclImpl(identity, 1, aclAuthorizationStrategy, new ConsoleAuditLogger()); - rootParentAcl.insertAce(0, BasePermission.ADMINISTRATION, new PrincipalSid(auth), true); - parentAcl.setEntriesInheriting(true); - parentAcl.setParent(rootParentAcl); - childAcl.setParent(parentAcl); - try { - aclAuthorizationStrategy.securityCheck(childAcl, AclAuthorizationStrategy.CHANGE_OWNERSHIP); - assertTrue(true); - } - catch (NotFoundException expected) { - fail("It shouldn't have thrown NotFoundException"); - } - } + // Create a root parent and link it to the middle parent + MutableAcl rootParentAcl = new AclImpl(identity, 1, aclAuthorizationStrategy, + new ConsoleAuditLogger()); + parentAcl = new AclImpl(identity, 1, aclAuthorizationStrategy, + new ConsoleAuditLogger()); + rootParentAcl.insertAce(0, BasePermission.ADMINISTRATION, new PrincipalSid(auth), + true); + parentAcl.setEntriesInheriting(true); + parentAcl.setParent(rootParentAcl); + childAcl.setParent(parentAcl); + try { + aclAuthorizationStrategy.securityCheck(childAcl, + AclAuthorizationStrategy.CHANGE_OWNERSHIP); + assertTrue(true); + } + catch (NotFoundException expected) { + fail("It shouldn't have thrown NotFoundException"); + } + } - @Test - public void testSecurityCheckPrincipalOwner() throws Exception { - Authentication auth = new TestingAuthenticationToken("user", "password", "ROLE_ONE"); - auth.setAuthenticated(true); - SecurityContextHolder.getContext().setAuthentication(auth); + @Test + public void testSecurityCheckPrincipalOwner() throws Exception { + Authentication auth = new TestingAuthenticationToken("user", "password", + "ROLE_ONE"); + auth.setAuthenticated(true); + SecurityContextHolder.getContext().setAuthentication(auth); - ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, 100); - AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl( - new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority("ROLE_AUDITING"), - new SimpleGrantedAuthority("ROLE_GENERAL")); + ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, 100); + AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl( + new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority( + "ROLE_AUDITING"), new SimpleGrantedAuthority("ROLE_GENERAL")); - Acl acl = new AclImpl(identity, 1, aclAuthorizationStrategy, new DefaultPermissionGrantingStrategy(new ConsoleAuditLogger()), null, null, - false, new PrincipalSid(auth)); - try { - aclAuthorizationStrategy.securityCheck(acl, AclAuthorizationStrategy.CHANGE_GENERAL); - } - catch (AccessDeniedException notExpected) { - fail("It shouldn't have thrown AccessDeniedException"); - } - try { - aclAuthorizationStrategy.securityCheck(acl, AclAuthorizationStrategy.CHANGE_AUDITING); - fail("It shouldn't have thrown AccessDeniedException"); - } - catch (NotFoundException expected) { - } - try { - aclAuthorizationStrategy.securityCheck(acl, AclAuthorizationStrategy.CHANGE_OWNERSHIP); - } - catch (AccessDeniedException notExpected) { - fail("It shouldn't have thrown AccessDeniedException"); - } - } + Acl acl = new AclImpl(identity, 1, aclAuthorizationStrategy, + new DefaultPermissionGrantingStrategy(new ConsoleAuditLogger()), null, + null, false, new PrincipalSid(auth)); + try { + aclAuthorizationStrategy.securityCheck(acl, + AclAuthorizationStrategy.CHANGE_GENERAL); + } + catch (AccessDeniedException notExpected) { + fail("It shouldn't have thrown AccessDeniedException"); + } + try { + aclAuthorizationStrategy.securityCheck(acl, + AclAuthorizationStrategy.CHANGE_AUDITING); + fail("It shouldn't have thrown AccessDeniedException"); + } + catch (NotFoundException expected) { + } + try { + aclAuthorizationStrategy.securityCheck(acl, + AclAuthorizationStrategy.CHANGE_OWNERSHIP); + } + catch (AccessDeniedException notExpected) { + fail("It shouldn't have thrown AccessDeniedException"); + } + } } diff --git a/acl/src/test/java/org/springframework/security/acls/domain/AuditLoggerTests.java b/acl/src/test/java/org/springframework/security/acls/domain/AuditLoggerTests.java index b2abb2ed4b..2a4fb9904e 100644 --- a/acl/src/test/java/org/springframework/security/acls/domain/AuditLoggerTests.java +++ b/acl/src/test/java/org/springframework/security/acls/domain/AuditLoggerTests.java @@ -18,61 +18,63 @@ import org.springframework.security.acls.model.AuditableAccessControlEntry; * @author Andrei Stefan */ public class AuditLoggerTests { - //~ Instance fields ================================================================================================ - private PrintStream console; - private ByteArrayOutputStream bytes = new ByteArrayOutputStream(); - private ConsoleAuditLogger logger; - private AuditableAccessControlEntry ace; + // ~ Instance fields + // ================================================================================================ + private PrintStream console; + private ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + private ConsoleAuditLogger logger; + private AuditableAccessControlEntry ace; - //~ Methods ======================================================================================================== + // ~ Methods + // ======================================================================================================== - @Before - public void setUp() throws Exception { - logger = new ConsoleAuditLogger(); - ace = mock(AuditableAccessControlEntry.class); - console = System.out; - System.setOut(new PrintStream(bytes)); - } + @Before + public void setUp() throws Exception { + logger = new ConsoleAuditLogger(); + ace = mock(AuditableAccessControlEntry.class); + console = System.out; + System.setOut(new PrintStream(bytes)); + } - @After - public void tearDown() throws Exception { - System.setOut(console); - bytes.reset(); - } + @After + public void tearDown() throws Exception { + System.setOut(console); + bytes.reset(); + } - @Test - public void nonAuditableAceIsIgnored() { - AccessControlEntry ace = mock(AccessControlEntry.class); - logger.logIfNeeded(true, ace); - assertEquals(0, bytes.size()); - } + @Test + public void nonAuditableAceIsIgnored() { + AccessControlEntry ace = mock(AccessControlEntry.class); + logger.logIfNeeded(true, ace); + assertEquals(0, bytes.size()); + } - @Test - public void successIsNotLoggedIfAceDoesntRequireSuccessAudit() throws Exception { - when(ace.isAuditSuccess()).thenReturn(false); - logger.logIfNeeded(true, ace); - assertEquals(0, bytes.size()); - } + @Test + public void successIsNotLoggedIfAceDoesntRequireSuccessAudit() throws Exception { + when(ace.isAuditSuccess()).thenReturn(false); + logger.logIfNeeded(true, ace); + assertEquals(0, bytes.size()); + } - @Test - public void successIsLoggedIfAceRequiresSuccessAudit() throws Exception { - when(ace.isAuditSuccess()).thenReturn(true); + @Test + public void successIsLoggedIfAceRequiresSuccessAudit() throws Exception { + when(ace.isAuditSuccess()).thenReturn(true); - logger.logIfNeeded(true, ace); - assertTrue(bytes.toString().startsWith("GRANTED due to ACE")); - } + logger.logIfNeeded(true, ace); + assertTrue(bytes.toString().startsWith("GRANTED due to ACE")); + } - @Test - public void failureIsntLoggedIfAceDoesntRequireFailureAudit() throws Exception { - when(ace.isAuditFailure()).thenReturn(false); - logger.logIfNeeded(false, ace); - assertEquals(0, bytes.size()); - } + @Test + public void failureIsntLoggedIfAceDoesntRequireFailureAudit() throws Exception { + when(ace.isAuditFailure()).thenReturn(false); + logger.logIfNeeded(false, ace); + assertEquals(0, bytes.size()); + } - @Test - public void failureIsLoggedIfAceRequiresFailureAudit() throws Exception { - when(ace.isAuditFailure()).thenReturn(true); - logger.logIfNeeded(false, ace); - assertTrue(bytes.toString().startsWith("DENIED due to ACE")); - } + @Test + public void failureIsLoggedIfAceRequiresFailureAudit() throws Exception { + when(ace.isAuditFailure()).thenReturn(true); + logger.logIfNeeded(false, ace); + assertTrue(bytes.toString().startsWith("DENIED due to ACE")); + } } diff --git a/acl/src/test/java/org/springframework/security/acls/domain/ObjectIdentityImplTests.java b/acl/src/test/java/org/springframework/security/acls/domain/ObjectIdentityImplTests.java index 042fba7bee..17c13afcd3 100644 --- a/acl/src/test/java/org/springframework/security/acls/domain/ObjectIdentityImplTests.java +++ b/acl/src/test/java/org/springframework/security/acls/domain/ObjectIdentityImplTests.java @@ -15,175 +15,179 @@ import org.springframework.security.acls.model.ObjectIdentity; @SuppressWarnings("unused") public class ObjectIdentityImplTests { - private static final String DOMAIN_CLASS = - "org.springframework.security.acls.domain.ObjectIdentityImplTests$MockIdDomainObject"; + private static final String DOMAIN_CLASS = "org.springframework.security.acls.domain.ObjectIdentityImplTests$MockIdDomainObject"; - //~ Methods ======================================================================================================== + // ~ Methods + // ======================================================================================================== - @Test - public void constructorsRespectRequiredFields() throws Exception { - // Check one-argument constructor required field - try { - new ObjectIdentityImpl(null); - fail("It should have thrown IllegalArgumentException"); - } catch (IllegalArgumentException expected) { - } + @Test + public void constructorsRespectRequiredFields() throws Exception { + // Check one-argument constructor required field + try { + new ObjectIdentityImpl(null); + fail("It should have thrown IllegalArgumentException"); + } + catch (IllegalArgumentException expected) { + } - // Check String-Serializable constructor required field - try { - new ObjectIdentityImpl("", Long.valueOf(1)); - fail("It should have thrown IllegalArgumentException"); - } catch (IllegalArgumentException expected) { - } + // Check String-Serializable constructor required field + try { + new ObjectIdentityImpl("", Long.valueOf(1)); + fail("It should have thrown IllegalArgumentException"); + } + catch (IllegalArgumentException expected) { + } - // Check Serializable parameter is not null - try { - new ObjectIdentityImpl(DOMAIN_CLASS, null); - fail("It should have thrown IllegalArgumentException"); - } - catch (IllegalArgumentException expected) { - } + // Check Serializable parameter is not null + try { + new ObjectIdentityImpl(DOMAIN_CLASS, null); + fail("It should have thrown IllegalArgumentException"); + } + catch (IllegalArgumentException expected) { + } - // The correct way of using String-Serializable constructor - try { - new ObjectIdentityImpl(DOMAIN_CLASS, Long.valueOf(1)); - } - catch (IllegalArgumentException notExpected) { - fail("It shouldn't have thrown IllegalArgumentException"); - } + // The correct way of using String-Serializable constructor + try { + new ObjectIdentityImpl(DOMAIN_CLASS, Long.valueOf(1)); + } + catch (IllegalArgumentException notExpected) { + fail("It shouldn't have thrown IllegalArgumentException"); + } - // Check the Class-Serializable constructor - try { - new ObjectIdentityImpl(MockIdDomainObject.class, null); - fail("It should have thrown IllegalArgumentException"); - } - catch (IllegalArgumentException expected) { - } - } + // Check the Class-Serializable constructor + try { + new ObjectIdentityImpl(MockIdDomainObject.class, null); + fail("It should have thrown IllegalArgumentException"); + } + catch (IllegalArgumentException expected) { + } + } - @Test - public void gettersReturnExpectedValues() throws Exception { - ObjectIdentity obj = new ObjectIdentityImpl(DOMAIN_CLASS, Long.valueOf(1)); - assertEquals(Long.valueOf(1), obj.getIdentifier()); - assertEquals(MockIdDomainObject.class.getName(), obj.getType()); - } + @Test + public void gettersReturnExpectedValues() throws Exception { + ObjectIdentity obj = new ObjectIdentityImpl(DOMAIN_CLASS, Long.valueOf(1)); + assertEquals(Long.valueOf(1), obj.getIdentifier()); + assertEquals(MockIdDomainObject.class.getName(), obj.getType()); + } - @Test - public void testGetIdMethodConstraints() throws Exception { - // Check the getId() method is present - try { - new ObjectIdentityImpl("A_STRING_OBJECT"); - fail("It should have thrown IdentityUnavailableException"); - } - catch (IdentityUnavailableException expected) { + @Test + public void testGetIdMethodConstraints() throws Exception { + // Check the getId() method is present + try { + new ObjectIdentityImpl("A_STRING_OBJECT"); + fail("It should have thrown IdentityUnavailableException"); + } + catch (IdentityUnavailableException expected) { - } + } - // getId() should return a non-null value - MockIdDomainObject mockId = new MockIdDomainObject(); - try { - new ObjectIdentityImpl(mockId); - fail("It should have thrown IllegalArgumentException"); - } - catch (IllegalArgumentException expected) { + // getId() should return a non-null value + MockIdDomainObject mockId = new MockIdDomainObject(); + try { + new ObjectIdentityImpl(mockId); + fail("It should have thrown IllegalArgumentException"); + } + catch (IllegalArgumentException expected) { - } + } - // getId() should return a Serializable object - mockId.setId(new MockIdDomainObject()); - try { - new ObjectIdentityImpl(mockId); - fail("It should have thrown IllegalArgumentException"); - } - catch (IllegalArgumentException expected) { - } + // getId() should return a Serializable object + mockId.setId(new MockIdDomainObject()); + try { + new ObjectIdentityImpl(mockId); + fail("It should have thrown IllegalArgumentException"); + } + catch (IllegalArgumentException expected) { + } - // getId() should return a Serializable object - mockId.setId(new Long(100)); - try { - new ObjectIdentityImpl(mockId); - } - catch (IllegalArgumentException expected) { - } - } + // getId() should return a Serializable object + mockId.setId(new Long(100)); + try { + new ObjectIdentityImpl(mockId); + } + catch (IllegalArgumentException expected) { + } + } - @Test(expected=IllegalArgumentException.class) - public void constructorRejectsInvalidTypeParameter() throws Exception { - new ObjectIdentityImpl("", Long.valueOf(1)); - } + @Test(expected = IllegalArgumentException.class) + public void constructorRejectsInvalidTypeParameter() throws Exception { + new ObjectIdentityImpl("", Long.valueOf(1)); + } - @Test - public void testEquals() throws Exception { - ObjectIdentity obj = new ObjectIdentityImpl(DOMAIN_CLASS, Long.valueOf(1)); - MockIdDomainObject mockObj = new MockIdDomainObject(); - mockObj.setId(Long.valueOf(1)); + @Test + public void testEquals() throws Exception { + ObjectIdentity obj = new ObjectIdentityImpl(DOMAIN_CLASS, Long.valueOf(1)); + MockIdDomainObject mockObj = new MockIdDomainObject(); + mockObj.setId(Long.valueOf(1)); - String string = "SOME_STRING"; - assertNotSame(obj, string); - assertFalse(obj.equals(null)); - assertFalse(obj.equals("DIFFERENT_OBJECT_TYPE")); - assertFalse(obj.equals(new ObjectIdentityImpl(DOMAIN_CLASS, Long.valueOf(2)))); - assertFalse(obj.equals(new ObjectIdentityImpl( - "org.springframework.security.acls.domain.ObjectIdentityImplTests$MockOtherIdDomainObject", - Long.valueOf(1)))); - assertEquals(new ObjectIdentityImpl(DOMAIN_CLASS,Long.valueOf(1)), obj); - assertEquals(obj, new ObjectIdentityImpl(mockObj)); - } + String string = "SOME_STRING"; + assertNotSame(obj, string); + assertFalse(obj.equals(null)); + assertFalse(obj.equals("DIFFERENT_OBJECT_TYPE")); + assertFalse(obj.equals(new ObjectIdentityImpl(DOMAIN_CLASS, Long.valueOf(2)))); + assertFalse(obj + .equals(new ObjectIdentityImpl( + "org.springframework.security.acls.domain.ObjectIdentityImplTests$MockOtherIdDomainObject", + Long.valueOf(1)))); + assertEquals(new ObjectIdentityImpl(DOMAIN_CLASS, Long.valueOf(1)), obj); + assertEquals(obj, new ObjectIdentityImpl(mockObj)); + } - @Test - public void hashcodeIsDifferentForDifferentJavaTypes() throws Exception { - ObjectIdentity obj = new ObjectIdentityImpl(Object.class, Long.valueOf(1)); - ObjectIdentity obj2 = new ObjectIdentityImpl(String.class, Long.valueOf(1)); - assertFalse(obj.hashCode() == obj2.hashCode()); - } + @Test + public void hashcodeIsDifferentForDifferentJavaTypes() throws Exception { + ObjectIdentity obj = new ObjectIdentityImpl(Object.class, Long.valueOf(1)); + ObjectIdentity obj2 = new ObjectIdentityImpl(String.class, Long.valueOf(1)); + assertFalse(obj.hashCode() == obj2.hashCode()); + } - @Test - public void longAndIntegerIdsWithSameValueAreEqualAndHaveSameHashcode() { - ObjectIdentity obj = new ObjectIdentityImpl(Object.class, new Long(5)); - ObjectIdentity obj2 = new ObjectIdentityImpl(Object.class, Integer.valueOf(5)); + @Test + public void longAndIntegerIdsWithSameValueAreEqualAndHaveSameHashcode() { + ObjectIdentity obj = new ObjectIdentityImpl(Object.class, new Long(5)); + ObjectIdentity obj2 = new ObjectIdentityImpl(Object.class, Integer.valueOf(5)); - assertEquals(obj, obj2); - assertEquals(obj.hashCode(), obj2.hashCode()); - } + assertEquals(obj, obj2); + assertEquals(obj.hashCode(), obj2.hashCode()); + } - @Test - public void equalStringIdsAreEqualAndHaveSameHashcode() throws Exception { - ObjectIdentity obj = new ObjectIdentityImpl(Object.class, "1000"); - ObjectIdentity obj2 = new ObjectIdentityImpl(Object.class, "1000"); - assertEquals(obj, obj2); - assertEquals(obj.hashCode(), obj2.hashCode()); - } + @Test + public void equalStringIdsAreEqualAndHaveSameHashcode() throws Exception { + ObjectIdentity obj = new ObjectIdentityImpl(Object.class, "1000"); + ObjectIdentity obj2 = new ObjectIdentityImpl(Object.class, "1000"); + assertEquals(obj, obj2); + assertEquals(obj.hashCode(), obj2.hashCode()); + } - @Test - public void stringAndNumericIdsAreNotEqual() throws Exception { - ObjectIdentity obj = new ObjectIdentityImpl(Object.class, "1000"); - ObjectIdentity obj2 = new ObjectIdentityImpl(Object.class, Long.valueOf(1000)); - assertFalse(obj.equals(obj2)); - } + @Test + public void stringAndNumericIdsAreNotEqual() throws Exception { + ObjectIdentity obj = new ObjectIdentityImpl(Object.class, "1000"); + ObjectIdentity obj2 = new ObjectIdentityImpl(Object.class, Long.valueOf(1000)); + assertFalse(obj.equals(obj2)); + } - //~ Inner Classes ================================================================================================== + // ~ Inner Classes + // ================================================================================================== - private class MockIdDomainObject { - private Object id; + private class MockIdDomainObject { + private Object id; - public Object getId() { - return id; - } + public Object getId() { + return id; + } - public void setId(Object id) { - this.id = id; - } - } + public void setId(Object id) { + this.id = id; + } + } - private class MockOtherIdDomainObject { - private Object id; + private class MockOtherIdDomainObject { + private Object id; - public Object getId() { - return id; - } + public Object getId() { + return id; + } - public void setId(Object id) { - this.id = id; - } - } + public void setId(Object id) { + this.id = id; + } + } } diff --git a/acl/src/test/java/org/springframework/security/acls/domain/ObjectIdentityRetrievalStrategyImplTests.java b/acl/src/test/java/org/springframework/security/acls/domain/ObjectIdentityRetrievalStrategyImplTests.java index bf05d10953..c2eba731cc 100644 --- a/acl/src/test/java/org/springframework/security/acls/domain/ObjectIdentityRetrievalStrategyImplTests.java +++ b/acl/src/test/java/org/springframework/security/acls/domain/ObjectIdentityRetrievalStrategyImplTests.java @@ -13,30 +13,32 @@ import junit.framework.TestCase; * @author Andrei Stefan */ public class ObjectIdentityRetrievalStrategyImplTests extends TestCase { - //~ Methods ======================================================================================================== + // ~ Methods + // ======================================================================================================== - public void testObjectIdentityCreation() throws Exception { - MockIdDomainObject domain = new MockIdDomainObject(); - domain.setId(Integer.valueOf(1)); + public void testObjectIdentityCreation() throws Exception { + MockIdDomainObject domain = new MockIdDomainObject(); + domain.setId(Integer.valueOf(1)); - ObjectIdentityRetrievalStrategy retStrategy = new ObjectIdentityRetrievalStrategyImpl(); - ObjectIdentity identity = retStrategy.getObjectIdentity(domain); + ObjectIdentityRetrievalStrategy retStrategy = new ObjectIdentityRetrievalStrategyImpl(); + ObjectIdentity identity = retStrategy.getObjectIdentity(domain); - assertNotNull(identity); - assertEquals(identity, new ObjectIdentityImpl(domain)); - } + assertNotNull(identity); + assertEquals(identity, new ObjectIdentityImpl(domain)); + } - //~ Inner Classes ================================================================================================== - @SuppressWarnings("unused") - private class MockIdDomainObject { - private Object id; + // ~ Inner Classes + // ================================================================================================== + @SuppressWarnings("unused") + private class MockIdDomainObject { + private Object id; - public Object getId() { - return id; - } + public Object getId() { + return id; + } - public void setId(Object id) { - this.id = id; - } - } + public void setId(Object id) { + this.id = id; + } + } } diff --git a/acl/src/test/java/org/springframework/security/acls/domain/PermissionTests.java b/acl/src/test/java/org/springframework/security/acls/domain/PermissionTests.java index c9c383c721..74e957b528 100644 --- a/acl/src/test/java/org/springframework/security/acls/domain/PermissionTests.java +++ b/acl/src/test/java/org/springframework/security/acls/domain/PermissionTests.java @@ -20,7 +20,6 @@ import org.junit.Before; import org.junit.Test; import org.springframework.security.acls.model.Permission; - /** * Tests classes associated with Permission. * @@ -28,73 +27,92 @@ import org.springframework.security.acls.model.Permission; */ public class PermissionTests { - private DefaultPermissionFactory permissionFactory; + private DefaultPermissionFactory permissionFactory; - @Before - public void createPermissionfactory() { - permissionFactory = new DefaultPermissionFactory(); - } + @Before + public void createPermissionfactory() { + permissionFactory = new DefaultPermissionFactory(); + } - @Test - public void basePermissionTest() { - Permission p = permissionFactory.buildFromName("WRITE"); - assertNotNull(p); - } + @Test + public void basePermissionTest() { + Permission p = permissionFactory.buildFromName("WRITE"); + assertNotNull(p); + } - @Test - public void expectedIntegerValues() { - assertEquals(1, BasePermission.READ.getMask()); - assertEquals(16, BasePermission.ADMINISTRATION.getMask()); - assertEquals(7, - new CumulativePermission().set(BasePermission.READ).set(BasePermission.WRITE).set(BasePermission.CREATE) - .getMask()); - assertEquals(17, - new CumulativePermission().set(BasePermission.READ).set(BasePermission.ADMINISTRATION).getMask()); - } + @Test + public void expectedIntegerValues() { + assertEquals(1, BasePermission.READ.getMask()); + assertEquals(16, BasePermission.ADMINISTRATION.getMask()); + assertEquals( + 7, + new CumulativePermission().set(BasePermission.READ) + .set(BasePermission.WRITE).set(BasePermission.CREATE).getMask()); + assertEquals( + 17, + new CumulativePermission().set(BasePermission.READ) + .set(BasePermission.ADMINISTRATION).getMask()); + } - @Test - public void fromInteger() { - Permission permission = permissionFactory.buildFromMask(7); - System.out.println("7 = " + permission.toString()); - permission = permissionFactory.buildFromMask(4); - System.out.println("4 = " + permission.toString()); - } + @Test + public void fromInteger() { + Permission permission = permissionFactory.buildFromMask(7); + System.out.println("7 = " + permission.toString()); + permission = permissionFactory.buildFromMask(4); + System.out.println("4 = " + permission.toString()); + } - @Test - public void stringConversion() { - permissionFactory.registerPublicPermissions(SpecialPermission.class); + @Test + public void stringConversion() { + permissionFactory.registerPublicPermissions(SpecialPermission.class); - System.out.println("R = " + BasePermission.READ.toString()); - assertEquals("BasePermission[...............................R=1]", BasePermission.READ.toString()); + System.out.println("R = " + BasePermission.READ.toString()); + assertEquals("BasePermission[...............................R=1]", + BasePermission.READ.toString()); - System.out.println("A = " + BasePermission.ADMINISTRATION.toString()); - assertEquals("BasePermission[...........................A....=16]", BasePermission.ADMINISTRATION.toString()); + System.out.println("A = " + BasePermission.ADMINISTRATION.toString()); + assertEquals("BasePermission[...........................A....=16]", + BasePermission.ADMINISTRATION.toString()); - System.out.println("R = " + new CumulativePermission().set(BasePermission.READ).toString()); - assertEquals("CumulativePermission[...............................R=1]", - new CumulativePermission().set(BasePermission.READ).toString()); + System.out.println("R = " + + new CumulativePermission().set(BasePermission.READ).toString()); + assertEquals("CumulativePermission[...............................R=1]", + new CumulativePermission().set(BasePermission.READ).toString()); - System.out.println("A = " + new CumulativePermission().set(SpecialPermission.ENTER).set(BasePermission.ADMINISTRATION).toString()); - assertEquals("CumulativePermission[..........................EA....=48]", - new CumulativePermission().set(SpecialPermission.ENTER).set(BasePermission.ADMINISTRATION).toString()); + System.out.println("A = " + + new CumulativePermission().set(SpecialPermission.ENTER) + .set(BasePermission.ADMINISTRATION).toString()); + assertEquals( + "CumulativePermission[..........................EA....=48]", + new CumulativePermission().set(SpecialPermission.ENTER) + .set(BasePermission.ADMINISTRATION).toString()); - System.out.println("RA = " - + new CumulativePermission().set(BasePermission.ADMINISTRATION).set(BasePermission.READ).toString()); - assertEquals("CumulativePermission[...........................A...R=17]", - new CumulativePermission().set(BasePermission.ADMINISTRATION).set(BasePermission.READ).toString()); + System.out.println("RA = " + + new CumulativePermission().set(BasePermission.ADMINISTRATION) + .set(BasePermission.READ).toString()); + assertEquals( + "CumulativePermission[...........................A...R=17]", + new CumulativePermission().set(BasePermission.ADMINISTRATION) + .set(BasePermission.READ).toString()); - System.out.println("R = " - + new CumulativePermission().set(BasePermission.ADMINISTRATION).set(BasePermission.READ) - .clear(BasePermission.ADMINISTRATION).toString()); - assertEquals("CumulativePermission[...............................R=1]", - new CumulativePermission().set(BasePermission.ADMINISTRATION).set(BasePermission.READ) - .clear(BasePermission.ADMINISTRATION).toString()); + System.out.println("R = " + + new CumulativePermission().set(BasePermission.ADMINISTRATION) + .set(BasePermission.READ).clear(BasePermission.ADMINISTRATION) + .toString()); + assertEquals( + "CumulativePermission[...............................R=1]", + new CumulativePermission().set(BasePermission.ADMINISTRATION) + .set(BasePermission.READ).clear(BasePermission.ADMINISTRATION) + .toString()); - System.out.println("0 = " - + new CumulativePermission().set(BasePermission.ADMINISTRATION).set(BasePermission.READ) - .clear(BasePermission.ADMINISTRATION).clear(BasePermission.READ).toString()); - assertEquals("CumulativePermission[................................=0]", - new CumulativePermission().set(BasePermission.ADMINISTRATION).set(BasePermission.READ) - .clear(BasePermission.ADMINISTRATION).clear(BasePermission.READ).toString()); - } + System.out.println("0 = " + + new CumulativePermission().set(BasePermission.ADMINISTRATION) + .set(BasePermission.READ).clear(BasePermission.ADMINISTRATION) + .clear(BasePermission.READ).toString()); + assertEquals( + "CumulativePermission[................................=0]", + new CumulativePermission().set(BasePermission.ADMINISTRATION) + .set(BasePermission.READ).clear(BasePermission.ADMINISTRATION) + .clear(BasePermission.READ).toString()); + } } diff --git a/acl/src/test/java/org/springframework/security/acls/domain/SpecialPermission.java b/acl/src/test/java/org/springframework/security/acls/domain/SpecialPermission.java index 2582e76495..1c16fdab7f 100644 --- a/acl/src/test/java/org/springframework/security/acls/domain/SpecialPermission.java +++ b/acl/src/test/java/org/springframework/security/acls/domain/SpecialPermission.java @@ -16,17 +16,16 @@ package org.springframework.security.acls.domain; import org.springframework.security.acls.model.Permission; - /** * A test permission. * * @author Ben Alex */ public class SpecialPermission extends BasePermission { - public static final Permission ENTER = new SpecialPermission(1 << 5, 'E'); // 32 - public static final Permission LEAVE = new SpecialPermission(1 << 6, 'L'); + public static final Permission ENTER = new SpecialPermission(1 << 5, 'E'); // 32 + public static final Permission LEAVE = new SpecialPermission(1 << 6, 'L'); - protected SpecialPermission(int mask, char code) { - super(mask, code); - } + protected SpecialPermission(int mask, char code) { + super(mask, code); + } } diff --git a/acl/src/test/java/org/springframework/security/acls/jdbc/BasicLookupStrategyTests.java b/acl/src/test/java/org/springframework/security/acls/jdbc/BasicLookupStrategyTests.java index ba7696ec43..b483640ff1 100644 --- a/acl/src/test/java/org/springframework/security/acls/jdbc/BasicLookupStrategyTests.java +++ b/acl/src/test/java/org/springframework/security/acls/jdbc/BasicLookupStrategyTests.java @@ -29,284 +29,335 @@ import java.util.*; */ public class BasicLookupStrategyTests { - private static final Sid BEN_SID = new PrincipalSid("ben"); - private static final String TARGET_CLASS = "org.springframework.security.acls.TargetObject"; + private static final Sid BEN_SID = new PrincipalSid("ben"); + private static final String TARGET_CLASS = "org.springframework.security.acls.TargetObject"; - //~ Instance fields ================================================================================================ + // ~ Instance fields + // ================================================================================================ - private static JdbcTemplate jdbcTemplate; - private BasicLookupStrategy strategy; - private static SingleConnectionDataSource dataSource; - private static CacheManager cacheManager; + private static JdbcTemplate jdbcTemplate; + private BasicLookupStrategy strategy; + private static SingleConnectionDataSource dataSource; + private static CacheManager cacheManager; - //~ Methods ======================================================================================================== - @BeforeClass - public static void initCacheManaer() { - cacheManager = CacheManager.create(); - cacheManager.addCache(new Cache("basiclookuptestcache", 500, false, false, 30, 30)); - } + // ~ Methods + // ======================================================================================================== + @BeforeClass + public static void initCacheManaer() { + cacheManager = CacheManager.create(); + cacheManager + .addCache(new Cache("basiclookuptestcache", 500, false, false, 30, 30)); + } - @BeforeClass - public static void createDatabase() throws Exception { - dataSource = new SingleConnectionDataSource("jdbc:hsqldb:mem:lookupstrategytest", "sa", "", true); - dataSource.setDriverClassName("org.hsqldb.jdbcDriver"); - jdbcTemplate = new JdbcTemplate(dataSource); + @BeforeClass + public static void createDatabase() throws Exception { + dataSource = new SingleConnectionDataSource("jdbc:hsqldb:mem:lookupstrategytest", + "sa", "", true); + dataSource.setDriverClassName("org.hsqldb.jdbcDriver"); + jdbcTemplate = new JdbcTemplate(dataSource); - Resource resource = new ClassPathResource("createAclSchema.sql"); - String sql = new String(FileCopyUtils.copyToByteArray(resource.getInputStream())); - jdbcTemplate.execute(sql); - } + Resource resource = new ClassPathResource("createAclSchema.sql"); + String sql = new String(FileCopyUtils.copyToByteArray(resource.getInputStream())); + jdbcTemplate.execute(sql); + } - @AfterClass - public static void dropDatabase() throws Exception { - dataSource.destroy(); - } + @AfterClass + public static void dropDatabase() throws Exception { + dataSource.destroy(); + } - @AfterClass - public static void shutdownCacheManager() { - cacheManager.removalAll(); - cacheManager.shutdown(); - } + @AfterClass + public static void shutdownCacheManager() { + cacheManager.removalAll(); + cacheManager.shutdown(); + } - @Before - public void populateDatabase() { - String query = "INSERT INTO acl_sid(ID,PRINCIPAL,SID) VALUES (1,1,'ben');" - + "INSERT INTO acl_class(ID,CLASS) VALUES (2,'" + TARGET_CLASS + "');" - + "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (1,2,100,null,1,1);" - + "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (2,2,101,1,1,1);" - + "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (3,2,102,2,1,1);" - + "INSERT INTO acl_entry(ID,ACL_OBJECT_IDENTITY,ACE_ORDER,SID,MASK,GRANTING,AUDIT_SUCCESS,AUDIT_FAILURE) VALUES (1,1,0,1,1,1,0,0);" - + "INSERT INTO acl_entry(ID,ACL_OBJECT_IDENTITY,ACE_ORDER,SID,MASK,GRANTING,AUDIT_SUCCESS,AUDIT_FAILURE) VALUES (2,1,1,1,2,0,0,0);" - + "INSERT INTO acl_entry(ID,ACL_OBJECT_IDENTITY,ACE_ORDER,SID,MASK,GRANTING,AUDIT_SUCCESS,AUDIT_FAILURE) VALUES (3,2,0,1,8,1,0,0);" - + "INSERT INTO acl_entry(ID,ACL_OBJECT_IDENTITY,ACE_ORDER,SID,MASK,GRANTING,AUDIT_SUCCESS,AUDIT_FAILURE) VALUES (4,3,0,1,8,0,0,0);"; - jdbcTemplate.execute(query); - } + @Before + public void populateDatabase() { + String query = "INSERT INTO acl_sid(ID,PRINCIPAL,SID) VALUES (1,1,'ben');" + + "INSERT INTO acl_class(ID,CLASS) VALUES (2,'" + + TARGET_CLASS + + "');" + + "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (1,2,100,null,1,1);" + + "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (2,2,101,1,1,1);" + + "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (3,2,102,2,1,1);" + + "INSERT INTO acl_entry(ID,ACL_OBJECT_IDENTITY,ACE_ORDER,SID,MASK,GRANTING,AUDIT_SUCCESS,AUDIT_FAILURE) VALUES (1,1,0,1,1,1,0,0);" + + "INSERT INTO acl_entry(ID,ACL_OBJECT_IDENTITY,ACE_ORDER,SID,MASK,GRANTING,AUDIT_SUCCESS,AUDIT_FAILURE) VALUES (2,1,1,1,2,0,0,0);" + + "INSERT INTO acl_entry(ID,ACL_OBJECT_IDENTITY,ACE_ORDER,SID,MASK,GRANTING,AUDIT_SUCCESS,AUDIT_FAILURE) VALUES (3,2,0,1,8,1,0,0);" + + "INSERT INTO acl_entry(ID,ACL_OBJECT_IDENTITY,ACE_ORDER,SID,MASK,GRANTING,AUDIT_SUCCESS,AUDIT_FAILURE) VALUES (4,3,0,1,8,0,0,0);"; + jdbcTemplate.execute(query); + } - @Before - public void initializeBeans() { - EhCacheBasedAclCache cache = new EhCacheBasedAclCache(getCache(), new DefaultPermissionGrantingStrategy(new ConsoleAuditLogger()), new AclAuthorizationStrategyImpl(new SimpleGrantedAuthority("ROLE_USER"))); - AclAuthorizationStrategy authorizationStrategy = new AclAuthorizationStrategyImpl(new SimpleGrantedAuthority("ROLE_ADMINISTRATOR")); - strategy = new BasicLookupStrategy(dataSource, cache, authorizationStrategy, - new DefaultPermissionGrantingStrategy(new ConsoleAuditLogger())); - strategy.setPermissionFactory(new DefaultPermissionFactory()); - } + @Before + public void initializeBeans() { + EhCacheBasedAclCache cache = new EhCacheBasedAclCache(getCache(), + new DefaultPermissionGrantingStrategy(new ConsoleAuditLogger()), + new AclAuthorizationStrategyImpl(new SimpleGrantedAuthority("ROLE_USER"))); + AclAuthorizationStrategy authorizationStrategy = new AclAuthorizationStrategyImpl( + new SimpleGrantedAuthority("ROLE_ADMINISTRATOR")); + strategy = new BasicLookupStrategy(dataSource, cache, authorizationStrategy, + new DefaultPermissionGrantingStrategy(new ConsoleAuditLogger())); + strategy.setPermissionFactory(new DefaultPermissionFactory()); + } - @After - public void emptyDatabase() { - String query = "DELETE FROM acl_entry;" + "DELETE FROM acl_object_identity WHERE ID = 7;" - + "DELETE FROM acl_object_identity WHERE ID = 6;" + "DELETE FROM acl_object_identity WHERE ID = 5;" - + "DELETE FROM acl_object_identity WHERE ID = 4;" + "DELETE FROM acl_object_identity WHERE ID = 3;" - + "DELETE FROM acl_object_identity WHERE ID = 2;" + "DELETE FROM acl_object_identity WHERE ID = 1;" - + "DELETE FROM acl_class;" + "DELETE FROM acl_sid;"; - jdbcTemplate.execute(query); - } + @After + public void emptyDatabase() { + String query = "DELETE FROM acl_entry;" + + "DELETE FROM acl_object_identity WHERE ID = 7;" + + "DELETE FROM acl_object_identity WHERE ID = 6;" + + "DELETE FROM acl_object_identity WHERE ID = 5;" + + "DELETE FROM acl_object_identity WHERE ID = 4;" + + "DELETE FROM acl_object_identity WHERE ID = 3;" + + "DELETE FROM acl_object_identity WHERE ID = 2;" + + "DELETE FROM acl_object_identity WHERE ID = 1;" + + "DELETE FROM acl_class;" + "DELETE FROM acl_sid;"; + jdbcTemplate.execute(query); + } - private Ehcache getCache() { - Ehcache cache = cacheManager.getCache("basiclookuptestcache"); - cache.removeAll(); - return cache; - } + private Ehcache getCache() { + Ehcache cache = cacheManager.getCache("basiclookuptestcache"); + cache.removeAll(); + return cache; + } - @Test - public void testAclsRetrievalWithDefaultBatchSize() throws Exception { - ObjectIdentity topParentOid = new ObjectIdentityImpl(TARGET_CLASS, new Long(100)); - ObjectIdentity middleParentOid = new ObjectIdentityImpl(TARGET_CLASS, new Long(101)); - // Deliberately use an integer for the child, to reproduce bug report in SEC-819 - ObjectIdentity childOid = new ObjectIdentityImpl(TARGET_CLASS, Integer.valueOf(102)); + @Test + public void testAclsRetrievalWithDefaultBatchSize() throws Exception { + ObjectIdentity topParentOid = new ObjectIdentityImpl(TARGET_CLASS, new Long(100)); + ObjectIdentity middleParentOid = new ObjectIdentityImpl(TARGET_CLASS, new Long( + 101)); + // Deliberately use an integer for the child, to reproduce bug report in SEC-819 + ObjectIdentity childOid = new ObjectIdentityImpl(TARGET_CLASS, + Integer.valueOf(102)); - Map map = this.strategy.readAclsById(Arrays.asList(topParentOid, middleParentOid, childOid), null); - checkEntries(topParentOid, middleParentOid, childOid, map); - } + Map map = this.strategy.readAclsById( + Arrays.asList(topParentOid, middleParentOid, childOid), null); + checkEntries(topParentOid, middleParentOid, childOid, map); + } - @Test - public void testAclsRetrievalFromCacheOnly() throws Exception { - ObjectIdentity topParentOid = new ObjectIdentityImpl(TARGET_CLASS, Integer.valueOf(100)); - ObjectIdentity middleParentOid = new ObjectIdentityImpl(TARGET_CLASS, new Long(101)); - ObjectIdentity childOid = new ObjectIdentityImpl(TARGET_CLASS, new Long(102)); + @Test + public void testAclsRetrievalFromCacheOnly() throws Exception { + ObjectIdentity topParentOid = new ObjectIdentityImpl(TARGET_CLASS, + Integer.valueOf(100)); + ObjectIdentity middleParentOid = new ObjectIdentityImpl(TARGET_CLASS, new Long( + 101)); + ObjectIdentity childOid = new ObjectIdentityImpl(TARGET_CLASS, new Long(102)); - // Objects were put in cache - strategy.readAclsById(Arrays.asList(topParentOid, middleParentOid, childOid), null); + // Objects were put in cache + strategy.readAclsById(Arrays.asList(topParentOid, middleParentOid, childOid), + null); - // Let's empty the database to force acls retrieval from cache - emptyDatabase(); - Map map = this.strategy.readAclsById(Arrays.asList(topParentOid, middleParentOid, childOid), null); + // Let's empty the database to force acls retrieval from cache + emptyDatabase(); + Map map = this.strategy.readAclsById( + Arrays.asList(topParentOid, middleParentOid, childOid), null); - checkEntries(topParentOid, middleParentOid, childOid, map); - } + checkEntries(topParentOid, middleParentOid, childOid, map); + } - @Test - public void testAclsRetrievalWithCustomBatchSize() throws Exception { - ObjectIdentity topParentOid = new ObjectIdentityImpl(TARGET_CLASS, new Long(100)); - ObjectIdentity middleParentOid = new ObjectIdentityImpl(TARGET_CLASS, Integer.valueOf(101)); - ObjectIdentity childOid = new ObjectIdentityImpl(TARGET_CLASS, new Long(102)); + @Test + public void testAclsRetrievalWithCustomBatchSize() throws Exception { + ObjectIdentity topParentOid = new ObjectIdentityImpl(TARGET_CLASS, new Long(100)); + ObjectIdentity middleParentOid = new ObjectIdentityImpl(TARGET_CLASS, + Integer.valueOf(101)); + ObjectIdentity childOid = new ObjectIdentityImpl(TARGET_CLASS, new Long(102)); - // Set a batch size to allow multiple database queries in order to retrieve all acls - this.strategy.setBatchSize(1); - Map map = this.strategy.readAclsById(Arrays.asList(topParentOid, middleParentOid, childOid), null); - checkEntries(topParentOid, middleParentOid, childOid, map); - } + // Set a batch size to allow multiple database queries in order to retrieve all + // acls + this.strategy.setBatchSize(1); + Map map = this.strategy.readAclsById( + Arrays.asList(topParentOid, middleParentOid, childOid), null); + checkEntries(topParentOid, middleParentOid, childOid, map); + } - private void checkEntries(ObjectIdentity topParentOid, ObjectIdentity middleParentOid, ObjectIdentity childOid, - Map map) throws Exception { - Assert.assertEquals(3, map.size()); + private void checkEntries(ObjectIdentity topParentOid, + ObjectIdentity middleParentOid, ObjectIdentity childOid, + Map map) throws Exception { + Assert.assertEquals(3, map.size()); - MutableAcl topParent = (MutableAcl) map.get(topParentOid); - MutableAcl middleParent = (MutableAcl) map.get(middleParentOid); - MutableAcl child = (MutableAcl) map.get(childOid); + MutableAcl topParent = (MutableAcl) map.get(topParentOid); + MutableAcl middleParent = (MutableAcl) map.get(middleParentOid); + MutableAcl child = (MutableAcl) map.get(childOid); - // Check the retrieved versions has IDs - Assert.assertNotNull(topParent.getId()); - Assert.assertNotNull(middleParent.getId()); - Assert.assertNotNull(child.getId()); + // Check the retrieved versions has IDs + Assert.assertNotNull(topParent.getId()); + Assert.assertNotNull(middleParent.getId()); + Assert.assertNotNull(child.getId()); - // Check their parents were correctly retrieved - Assert.assertNull(topParent.getParentAcl()); - Assert.assertEquals(topParentOid, middleParent.getParentAcl().getObjectIdentity()); - Assert.assertEquals(middleParentOid, child.getParentAcl().getObjectIdentity()); + // Check their parents were correctly retrieved + Assert.assertNull(topParent.getParentAcl()); + Assert.assertEquals(topParentOid, middleParent.getParentAcl().getObjectIdentity()); + Assert.assertEquals(middleParentOid, child.getParentAcl().getObjectIdentity()); - // Check their ACEs were correctly retrieved - Assert.assertEquals(2, topParent.getEntries().size()); - Assert.assertEquals(1, middleParent.getEntries().size()); - Assert.assertEquals(1, child.getEntries().size()); + // Check their ACEs were correctly retrieved + Assert.assertEquals(2, topParent.getEntries().size()); + Assert.assertEquals(1, middleParent.getEntries().size()); + Assert.assertEquals(1, child.getEntries().size()); - // Check object identities were correctly retrieved - Assert.assertEquals(topParentOid, topParent.getObjectIdentity()); - Assert.assertEquals(middleParentOid, middleParent.getObjectIdentity()); - Assert.assertEquals(childOid, child.getObjectIdentity()); + // Check object identities were correctly retrieved + Assert.assertEquals(topParentOid, topParent.getObjectIdentity()); + Assert.assertEquals(middleParentOid, middleParent.getObjectIdentity()); + Assert.assertEquals(childOid, child.getObjectIdentity()); - // Check each entry - Assert.assertTrue(topParent.isEntriesInheriting()); - Assert.assertEquals(topParent.getId(), Long.valueOf(1)); - Assert.assertEquals(topParent.getOwner(), new PrincipalSid("ben")); - Assert.assertEquals(topParent.getEntries().get(0).getId(), Long.valueOf(1)); - Assert.assertEquals(topParent.getEntries().get(0).getPermission(), BasePermission.READ); - Assert.assertEquals(topParent.getEntries().get(0).getSid(), new PrincipalSid("ben")); - Assert.assertFalse(((AuditableAccessControlEntry) topParent.getEntries().get(0)).isAuditFailure()); - Assert.assertFalse(((AuditableAccessControlEntry) topParent.getEntries().get(0)).isAuditSuccess()); - Assert.assertTrue((topParent.getEntries().get(0)).isGranting()); + // Check each entry + Assert.assertTrue(topParent.isEntriesInheriting()); + Assert.assertEquals(topParent.getId(), Long.valueOf(1)); + Assert.assertEquals(topParent.getOwner(), new PrincipalSid("ben")); + Assert.assertEquals(topParent.getEntries().get(0).getId(), Long.valueOf(1)); + Assert.assertEquals(topParent.getEntries().get(0).getPermission(), + BasePermission.READ); + Assert.assertEquals(topParent.getEntries().get(0).getSid(), new PrincipalSid( + "ben")); + Assert.assertFalse(((AuditableAccessControlEntry) topParent.getEntries().get(0)) + .isAuditFailure()); + Assert.assertFalse(((AuditableAccessControlEntry) topParent.getEntries().get(0)) + .isAuditSuccess()); + Assert.assertTrue((topParent.getEntries().get(0)).isGranting()); - Assert.assertEquals(topParent.getEntries().get(1).getId(), Long.valueOf(2)); - Assert.assertEquals(topParent.getEntries().get(1).getPermission(), BasePermission.WRITE); - Assert.assertEquals(topParent.getEntries().get(1).getSid(), new PrincipalSid("ben")); - Assert.assertFalse(((AuditableAccessControlEntry) topParent.getEntries().get(1)).isAuditFailure()); - Assert.assertFalse(((AuditableAccessControlEntry) topParent.getEntries().get(1)).isAuditSuccess()); - Assert.assertFalse(topParent.getEntries().get(1).isGranting()); + Assert.assertEquals(topParent.getEntries().get(1).getId(), Long.valueOf(2)); + Assert.assertEquals(topParent.getEntries().get(1).getPermission(), + BasePermission.WRITE); + Assert.assertEquals(topParent.getEntries().get(1).getSid(), new PrincipalSid( + "ben")); + Assert.assertFalse(((AuditableAccessControlEntry) topParent.getEntries().get(1)) + .isAuditFailure()); + Assert.assertFalse(((AuditableAccessControlEntry) topParent.getEntries().get(1)) + .isAuditSuccess()); + Assert.assertFalse(topParent.getEntries().get(1).isGranting()); - Assert.assertTrue(middleParent.isEntriesInheriting()); - Assert.assertEquals(middleParent.getId(), Long.valueOf(2)); - Assert.assertEquals(middleParent.getOwner(), new PrincipalSid("ben")); - Assert.assertEquals(middleParent.getEntries().get(0).getId(), Long.valueOf(3)); - Assert.assertEquals(middleParent.getEntries().get(0).getPermission(), BasePermission.DELETE); - Assert.assertEquals(middleParent.getEntries().get(0).getSid(), new PrincipalSid("ben")); - Assert.assertFalse(((AuditableAccessControlEntry) middleParent.getEntries().get(0)).isAuditFailure()); - Assert.assertFalse(((AuditableAccessControlEntry) middleParent.getEntries().get(0)).isAuditSuccess()); - Assert.assertTrue(middleParent.getEntries().get(0).isGranting()); + Assert.assertTrue(middleParent.isEntriesInheriting()); + Assert.assertEquals(middleParent.getId(), Long.valueOf(2)); + Assert.assertEquals(middleParent.getOwner(), new PrincipalSid("ben")); + Assert.assertEquals(middleParent.getEntries().get(0).getId(), Long.valueOf(3)); + Assert.assertEquals(middleParent.getEntries().get(0).getPermission(), + BasePermission.DELETE); + Assert.assertEquals(middleParent.getEntries().get(0).getSid(), new PrincipalSid( + "ben")); + Assert.assertFalse(((AuditableAccessControlEntry) middleParent.getEntries() + .get(0)).isAuditFailure()); + Assert.assertFalse(((AuditableAccessControlEntry) middleParent.getEntries() + .get(0)).isAuditSuccess()); + Assert.assertTrue(middleParent.getEntries().get(0).isGranting()); - Assert.assertTrue(child.isEntriesInheriting()); - Assert.assertEquals(child.getId(), Long.valueOf(3)); - Assert.assertEquals(child.getOwner(), new PrincipalSid("ben")); - Assert.assertEquals(child.getEntries().get(0).getId(), Long.valueOf(4)); - Assert.assertEquals(child.getEntries().get(0).getPermission(), BasePermission.DELETE); - Assert.assertEquals(child.getEntries().get(0).getSid(), new PrincipalSid("ben")); - Assert.assertFalse(((AuditableAccessControlEntry) child.getEntries().get(0)).isAuditFailure()); - Assert.assertFalse(((AuditableAccessControlEntry) child.getEntries().get(0)).isAuditSuccess()); - Assert.assertFalse((child.getEntries().get(0)).isGranting()); - } + Assert.assertTrue(child.isEntriesInheriting()); + Assert.assertEquals(child.getId(), Long.valueOf(3)); + Assert.assertEquals(child.getOwner(), new PrincipalSid("ben")); + Assert.assertEquals(child.getEntries().get(0).getId(), Long.valueOf(4)); + Assert.assertEquals(child.getEntries().get(0).getPermission(), + BasePermission.DELETE); + Assert.assertEquals(child.getEntries().get(0).getSid(), new PrincipalSid("ben")); + Assert.assertFalse(((AuditableAccessControlEntry) child.getEntries().get(0)) + .isAuditFailure()); + Assert.assertFalse(((AuditableAccessControlEntry) child.getEntries().get(0)) + .isAuditSuccess()); + Assert.assertFalse((child.getEntries().get(0)).isGranting()); + } - @Test - public void testAllParentsAreRetrievedWhenChildIsLoaded() throws Exception { - String query = "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (4,2,103,1,1,1);"; - jdbcTemplate.execute(query); + @Test + public void testAllParentsAreRetrievedWhenChildIsLoaded() throws Exception { + String query = "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (4,2,103,1,1,1);"; + jdbcTemplate.execute(query); - ObjectIdentity topParentOid = new ObjectIdentityImpl(TARGET_CLASS, Long.valueOf(100)); - ObjectIdentity middleParentOid = new ObjectIdentityImpl(TARGET_CLASS, Long.valueOf(101)); - ObjectIdentity childOid = new ObjectIdentityImpl(TARGET_CLASS, Long.valueOf(102)); - ObjectIdentity middleParent2Oid = new ObjectIdentityImpl(TARGET_CLASS, Long.valueOf(103)); + ObjectIdentity topParentOid = new ObjectIdentityImpl(TARGET_CLASS, + Long.valueOf(100)); + ObjectIdentity middleParentOid = new ObjectIdentityImpl(TARGET_CLASS, + Long.valueOf(101)); + ObjectIdentity childOid = new ObjectIdentityImpl(TARGET_CLASS, Long.valueOf(102)); + ObjectIdentity middleParent2Oid = new ObjectIdentityImpl(TARGET_CLASS, + Long.valueOf(103)); - // Retrieve the child - Map map = this.strategy.readAclsById(Arrays.asList(childOid), null); + // Retrieve the child + Map map = this.strategy.readAclsById( + Arrays.asList(childOid), null); - // Check that the child and all its parents were retrieved - Assert.assertNotNull(map.get(childOid)); - Assert.assertEquals(childOid, map.get(childOid).getObjectIdentity()); - Assert.assertNotNull(map.get(middleParentOid)); - Assert.assertEquals(middleParentOid, map.get(middleParentOid).getObjectIdentity()); - Assert.assertNotNull(map.get(topParentOid)); - Assert.assertEquals(topParentOid, map.get(topParentOid).getObjectIdentity()); + // Check that the child and all its parents were retrieved + Assert.assertNotNull(map.get(childOid)); + Assert.assertEquals(childOid, map.get(childOid).getObjectIdentity()); + Assert.assertNotNull(map.get(middleParentOid)); + Assert.assertEquals(middleParentOid, map.get(middleParentOid).getObjectIdentity()); + Assert.assertNotNull(map.get(topParentOid)); + Assert.assertEquals(topParentOid, map.get(topParentOid).getObjectIdentity()); - // The second parent shouldn't have been retrieved - Assert.assertNull(map.get(middleParent2Oid)); - } + // The second parent shouldn't have been retrieved + Assert.assertNull(map.get(middleParent2Oid)); + } - /** - * Test created from SEC-590. - */ - @Test - public void testReadAllObjectIdentitiesWhenLastElementIsAlreadyCached() throws Exception { - String query = "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (4,2,104,null,1,1);" - + "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (5,2,105,4,1,1);" - + "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (6,2,106,4,1,1);" - + "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (7,2,107,5,1,1);" - + "INSERT INTO acl_entry(ID,ACL_OBJECT_IDENTITY,ACE_ORDER,SID,MASK,GRANTING,AUDIT_SUCCESS,AUDIT_FAILURE) VALUES (5,4,0,1,1,1,0,0)"; - jdbcTemplate.execute(query); + /** + * Test created from SEC-590. + */ + @Test + public void testReadAllObjectIdentitiesWhenLastElementIsAlreadyCached() + throws Exception { + String query = "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (4,2,104,null,1,1);" + + "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (5,2,105,4,1,1);" + + "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (6,2,106,4,1,1);" + + "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (7,2,107,5,1,1);" + + "INSERT INTO acl_entry(ID,ACL_OBJECT_IDENTITY,ACE_ORDER,SID,MASK,GRANTING,AUDIT_SUCCESS,AUDIT_FAILURE) VALUES (5,4,0,1,1,1,0,0)"; + jdbcTemplate.execute(query); - ObjectIdentity grandParentOid = new ObjectIdentityImpl(TARGET_CLASS, new Long(104)); - ObjectIdentity parent1Oid = new ObjectIdentityImpl(TARGET_CLASS, new Long(105)); - ObjectIdentity parent2Oid = new ObjectIdentityImpl(TARGET_CLASS, Integer.valueOf(106)); - ObjectIdentity childOid = new ObjectIdentityImpl(TARGET_CLASS, Integer.valueOf(107)); + ObjectIdentity grandParentOid = new ObjectIdentityImpl(TARGET_CLASS, + new Long(104)); + ObjectIdentity parent1Oid = new ObjectIdentityImpl(TARGET_CLASS, new Long(105)); + ObjectIdentity parent2Oid = new ObjectIdentityImpl(TARGET_CLASS, + Integer.valueOf(106)); + ObjectIdentity childOid = new ObjectIdentityImpl(TARGET_CLASS, + Integer.valueOf(107)); - // First lookup only child, thus populating the cache with grandParent, parent1 and child - List checkPermission = Arrays.asList(BasePermission.READ); - List sids = Arrays.asList(BEN_SID); - List childOids = Arrays.asList(childOid); + // First lookup only child, thus populating the cache with grandParent, parent1 + // and child + List checkPermission = Arrays.asList(BasePermission.READ); + List sids = Arrays.asList(BEN_SID); + List childOids = Arrays.asList(childOid); - strategy.setBatchSize(6); - Map foundAcls = strategy.readAclsById(childOids, sids); + strategy.setBatchSize(6); + Map foundAcls = strategy.readAclsById(childOids, sids); - Acl foundChildAcl = foundAcls.get(childOid); - Assert.assertNotNull(foundChildAcl); - Assert.assertTrue(foundChildAcl.isGranted(checkPermission, sids, false)); + Acl foundChildAcl = foundAcls.get(childOid); + Assert.assertNotNull(foundChildAcl); + Assert.assertTrue(foundChildAcl.isGranted(checkPermission, sids, false)); - // Search for object identities has to be done in the following order: last element have to be one which - // is already in cache and the element before it must not be stored in cache - List allOids = Arrays.asList(grandParentOid, parent1Oid, parent2Oid, childOid); - try { - foundAcls = strategy.readAclsById(allOids, sids); - Assert.assertTrue(true); - } catch (NotFoundException notExpected) { - Assert.fail("It shouldn't have thrown NotFoundException"); - } + // Search for object identities has to be done in the following order: last + // element have to be one which + // is already in cache and the element before it must not be stored in cache + List allOids = Arrays.asList(grandParentOid, parent1Oid, + parent2Oid, childOid); + try { + foundAcls = strategy.readAclsById(allOids, sids); + Assert.assertTrue(true); + } + catch (NotFoundException notExpected) { + Assert.fail("It shouldn't have thrown NotFoundException"); + } - Acl foundParent2Acl = foundAcls.get(parent2Oid); - Assert.assertNotNull(foundParent2Acl); - Assert.assertTrue(foundParent2Acl.isGranted(checkPermission, sids, false)); - } + Acl foundParent2Acl = foundAcls.get(parent2Oid); + Assert.assertNotNull(foundParent2Acl); + Assert.assertTrue(foundParent2Acl.isGranted(checkPermission, sids, false)); + } - @Test(expected=IllegalArgumentException.class) - public void nullOwnerIsNotSupported() { - String query = "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (4,2,104,null,null,1);"; + @Test(expected = IllegalArgumentException.class) + public void nullOwnerIsNotSupported() { + String query = "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (4,2,104,null,null,1);"; - jdbcTemplate.execute(query); + jdbcTemplate.execute(query); - ObjectIdentity oid = new ObjectIdentityImpl(TARGET_CLASS, new Long(104)); + ObjectIdentity oid = new ObjectIdentityImpl(TARGET_CLASS, new Long(104)); - strategy.readAclsById(Arrays.asList(oid), Arrays.asList(BEN_SID)); - } + strategy.readAclsById(Arrays.asList(oid), Arrays.asList(BEN_SID)); + } - @Test - public void testCreatePrincipalSid() { - Sid result = strategy.createSid(true, "sid"); + @Test + public void testCreatePrincipalSid() { + Sid result = strategy.createSid(true, "sid"); - Assert.assertEquals(PrincipalSid.class, result.getClass()); - Assert.assertEquals("sid", ((PrincipalSid)result).getPrincipal()); - } + Assert.assertEquals(PrincipalSid.class, result.getClass()); + Assert.assertEquals("sid", ((PrincipalSid) result).getPrincipal()); + } - @Test - public void testCreateGrantedAuthority() { - Sid result = strategy.createSid(false, "sid"); + @Test + public void testCreateGrantedAuthority() { + Sid result = strategy.createSid(false, "sid"); - Assert.assertEquals(GrantedAuthoritySid.class, result.getClass()); - Assert.assertEquals("sid", ((GrantedAuthoritySid)result).getGrantedAuthority()); - } + Assert.assertEquals(GrantedAuthoritySid.class, result.getClass()); + Assert.assertEquals("sid", ((GrantedAuthoritySid) result).getGrantedAuthority()); + } } diff --git a/acl/src/test/java/org/springframework/security/acls/jdbc/DatabaseSeeder.java b/acl/src/test/java/org/springframework/security/acls/jdbc/DatabaseSeeder.java index 058aee7be9..41f9958b46 100644 --- a/acl/src/test/java/org/springframework/security/acls/jdbc/DatabaseSeeder.java +++ b/acl/src/test/java/org/springframework/security/acls/jdbc/DatabaseSeeder.java @@ -25,21 +25,21 @@ import java.io.IOException; import javax.sql.DataSource; - /** * Seeds the database for {@link JdbcMutableAclServiceTests}. * * @author Ben Alex */ public class DatabaseSeeder { - //~ Constructors =================================================================================================== + // ~ Constructors + // =================================================================================================== - public DatabaseSeeder(DataSource dataSource, Resource resource) throws IOException { - Assert.notNull(dataSource, "dataSource required"); - Assert.notNull(resource, "resource required"); + public DatabaseSeeder(DataSource dataSource, Resource resource) throws IOException { + Assert.notNull(dataSource, "dataSource required"); + Assert.notNull(resource, "resource required"); - JdbcTemplate template = new JdbcTemplate(dataSource); - String sql = new String(FileCopyUtils.copyToByteArray(resource.getInputStream())); - template.execute(sql); - } + JdbcTemplate template = new JdbcTemplate(dataSource); + String sql = new String(FileCopyUtils.copyToByteArray(resource.getInputStream())); + template.execute(sql); + } } diff --git a/acl/src/test/java/org/springframework/security/acls/jdbc/EhCacheBasedAclCacheTests.java b/acl/src/test/java/org/springframework/security/acls/jdbc/EhCacheBasedAclCacheTests.java index 4fe908b61a..baf3d9e99e 100644 --- a/acl/src/test/java/org/springframework/security/acls/jdbc/EhCacheBasedAclCacheTests.java +++ b/acl/src/test/java/org/springframework/security/acls/jdbc/EhCacheBasedAclCacheTests.java @@ -48,223 +48,239 @@ import org.springframework.util.ReflectionUtils; */ @RunWith(MockitoJUnitRunner.class) public class EhCacheBasedAclCacheTests { - private static final String TARGET_CLASS = "org.springframework.security.acls.TargetObject"; + private static final String TARGET_CLASS = "org.springframework.security.acls.TargetObject"; - @Mock - private Ehcache cache; - @Captor - private ArgumentCaptor element; + @Mock + private Ehcache cache; + @Captor + private ArgumentCaptor element; - private EhCacheBasedAclCache myCache; + private EhCacheBasedAclCache myCache; - private MutableAcl acl; + private MutableAcl acl; - @Before - public void setup() { - myCache = new EhCacheBasedAclCache(cache, new DefaultPermissionGrantingStrategy(new ConsoleAuditLogger()), new AclAuthorizationStrategyImpl(new SimpleGrantedAuthority("ROLE_USER"))); + @Before + public void setup() { + myCache = new EhCacheBasedAclCache(cache, new DefaultPermissionGrantingStrategy( + new ConsoleAuditLogger()), new AclAuthorizationStrategyImpl( + new SimpleGrantedAuthority("ROLE_USER"))); - ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, Long.valueOf(100)); - AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl( - new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority("ROLE_AUDITING"), - new SimpleGrantedAuthority("ROLE_GENERAL")); + ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, Long.valueOf(100)); + AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl( + new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority( + "ROLE_AUDITING"), new SimpleGrantedAuthority("ROLE_GENERAL")); - acl = new AclImpl(identity, Long.valueOf(1), aclAuthorizationStrategy, new ConsoleAuditLogger()); - } + acl = new AclImpl(identity, Long.valueOf(1), aclAuthorizationStrategy, + new ConsoleAuditLogger()); + } - @After - public void cleanup() { - SecurityContextHolder.clearContext(); - } + @After + public void cleanup() { + SecurityContextHolder.clearContext(); + } - @Test(expected=IllegalArgumentException.class) - public void constructorRejectsNullParameters() throws Exception { - new EhCacheBasedAclCache(null, new DefaultPermissionGrantingStrategy(new ConsoleAuditLogger()), new AclAuthorizationStrategyImpl(new SimpleGrantedAuthority("ROLE_USER"))); - } + @Test(expected = IllegalArgumentException.class) + public void constructorRejectsNullParameters() throws Exception { + new EhCacheBasedAclCache(null, new DefaultPermissionGrantingStrategy( + new ConsoleAuditLogger()), new AclAuthorizationStrategyImpl( + new SimpleGrantedAuthority("ROLE_USER"))); + } - @Test - public void methodsRejectNullParameters() throws Exception { - try { - Serializable id = null; - myCache.evictFromCache(id); - fail("It should have thrown IllegalArgumentException"); - } - catch (IllegalArgumentException expected) { - assertTrue(true); - } + @Test + public void methodsRejectNullParameters() throws Exception { + try { + Serializable id = null; + myCache.evictFromCache(id); + fail("It should have thrown IllegalArgumentException"); + } + catch (IllegalArgumentException expected) { + assertTrue(true); + } - try { - ObjectIdentity obj = null; - myCache.evictFromCache(obj); - fail("It should have thrown IllegalArgumentException"); - } - catch (IllegalArgumentException expected) { - assertTrue(true); - } + try { + ObjectIdentity obj = null; + myCache.evictFromCache(obj); + fail("It should have thrown IllegalArgumentException"); + } + catch (IllegalArgumentException expected) { + assertTrue(true); + } - try { - Serializable id = null; - myCache.getFromCache(id); - fail("It should have thrown IllegalArgumentException"); - } - catch (IllegalArgumentException expected) { - assertTrue(true); - } + try { + Serializable id = null; + myCache.getFromCache(id); + fail("It should have thrown IllegalArgumentException"); + } + catch (IllegalArgumentException expected) { + assertTrue(true); + } - try { - ObjectIdentity obj = null; - myCache.getFromCache(obj); - fail("It should have thrown IllegalArgumentException"); - } - catch (IllegalArgumentException expected) { - assertTrue(true); - } + try { + ObjectIdentity obj = null; + myCache.getFromCache(obj); + fail("It should have thrown IllegalArgumentException"); + } + catch (IllegalArgumentException expected) { + assertTrue(true); + } - try { - MutableAcl acl = null; - myCache.putInCache(acl); - fail("It should have thrown IllegalArgumentException"); - } - catch (IllegalArgumentException expected) { - assertTrue(true); - } - } + try { + MutableAcl acl = null; + myCache.putInCache(acl); + fail("It should have thrown IllegalArgumentException"); + } + catch (IllegalArgumentException expected) { + assertTrue(true); + } + } - // SEC-527 - @Test - public void testDiskSerializationOfMutableAclObjectInstance() throws Exception { - // Serialization test - File file = File.createTempFile("SEC_TEST", ".object"); - FileOutputStream fos = new FileOutputStream(file); - ObjectOutputStream oos = new ObjectOutputStream(fos); - oos.writeObject(acl); - oos.close(); + // SEC-527 + @Test + public void testDiskSerializationOfMutableAclObjectInstance() throws Exception { + // Serialization test + File file = File.createTempFile("SEC_TEST", ".object"); + FileOutputStream fos = new FileOutputStream(file); + ObjectOutputStream oos = new ObjectOutputStream(fos); + oos.writeObject(acl); + oos.close(); - FileInputStream fis = new FileInputStream(file); - ObjectInputStream ois = new ObjectInputStream(fis); - MutableAcl retrieved = (MutableAcl) ois.readObject(); - ois.close(); + FileInputStream fis = new FileInputStream(file); + ObjectInputStream ois = new ObjectInputStream(fis); + MutableAcl retrieved = (MutableAcl) ois.readObject(); + ois.close(); - assertEquals(acl, retrieved); + assertEquals(acl, retrieved); - Object retrieved1 = FieldUtils.getProtectedFieldValue("aclAuthorizationStrategy", retrieved); - assertEquals(null, retrieved1); + Object retrieved1 = FieldUtils.getProtectedFieldValue("aclAuthorizationStrategy", + retrieved); + assertEquals(null, retrieved1); - Object retrieved2 = FieldUtils.getProtectedFieldValue("permissionGrantingStrategy", retrieved); - assertEquals(null, retrieved2); - } + Object retrieved2 = FieldUtils.getProtectedFieldValue( + "permissionGrantingStrategy", retrieved); + assertEquals(null, retrieved2); + } - @Test - public void clearCache() throws Exception { - myCache.clearCache(); + @Test + public void clearCache() throws Exception { + myCache.clearCache(); - verify(cache).removeAll(); - } + verify(cache).removeAll(); + } - @Test - public void putInCache() throws Exception { - myCache.putInCache(acl); + @Test + public void putInCache() throws Exception { + myCache.putInCache(acl); - verify(cache, times(2)).put(element.capture()); - assertThat(element.getValue().getKey()).isEqualTo(acl.getId()); - assertThat(element.getValue().getObjectValue()).isEqualTo(acl); - assertThat(element.getAllValues().get(0).getKey()).isEqualTo(acl.getObjectIdentity()); - assertThat(element.getAllValues().get(0).getObjectValue()).isEqualTo(acl); - } + verify(cache, times(2)).put(element.capture()); + assertThat(element.getValue().getKey()).isEqualTo(acl.getId()); + assertThat(element.getValue().getObjectValue()).isEqualTo(acl); + assertThat(element.getAllValues().get(0).getKey()).isEqualTo( + acl.getObjectIdentity()); + assertThat(element.getAllValues().get(0).getObjectValue()).isEqualTo(acl); + } - @Test - public void putInCacheAclWithParent() throws Exception { - Authentication auth = new TestingAuthenticationToken("user", "password", "ROLE_GENERAL"); - auth.setAuthenticated(true); - SecurityContextHolder.getContext().setAuthentication(auth); + @Test + public void putInCacheAclWithParent() throws Exception { + Authentication auth = new TestingAuthenticationToken("user", "password", + "ROLE_GENERAL"); + auth.setAuthenticated(true); + SecurityContextHolder.getContext().setAuthentication(auth); - ObjectIdentity identityParent = new ObjectIdentityImpl(TARGET_CLASS, Long.valueOf(2)); - AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl( - new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority("ROLE_AUDITING"), - new SimpleGrantedAuthority("ROLE_GENERAL")); - MutableAcl parentAcl = new AclImpl(identityParent, Long.valueOf(2), aclAuthorizationStrategy, new ConsoleAuditLogger()); - acl.setParent(parentAcl); + ObjectIdentity identityParent = new ObjectIdentityImpl(TARGET_CLASS, + Long.valueOf(2)); + AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl( + new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority( + "ROLE_AUDITING"), new SimpleGrantedAuthority("ROLE_GENERAL")); + MutableAcl parentAcl = new AclImpl(identityParent, Long.valueOf(2), + aclAuthorizationStrategy, new ConsoleAuditLogger()); + acl.setParent(parentAcl); - myCache.putInCache(acl); + myCache.putInCache(acl); - verify(cache, times(4)).put(element.capture()); + verify(cache, times(4)).put(element.capture()); - List allValues = element.getAllValues(); + List allValues = element.getAllValues(); - assertThat(allValues.get(0).getKey()).isEqualTo(parentAcl.getObjectIdentity()); - assertThat(allValues.get(0).getObjectValue()).isEqualTo(parentAcl); + assertThat(allValues.get(0).getKey()).isEqualTo(parentAcl.getObjectIdentity()); + assertThat(allValues.get(0).getObjectValue()).isEqualTo(parentAcl); - assertThat(allValues.get(1).getKey()).isEqualTo(parentAcl.getId()); - assertThat(allValues.get(1).getObjectValue()).isEqualTo(parentAcl); + assertThat(allValues.get(1).getKey()).isEqualTo(parentAcl.getId()); + assertThat(allValues.get(1).getObjectValue()).isEqualTo(parentAcl); + assertThat(allValues.get(2).getKey()).isEqualTo(acl.getObjectIdentity()); + assertThat(allValues.get(2).getObjectValue()).isEqualTo(acl); - assertThat(allValues.get(2).getKey()).isEqualTo(acl.getObjectIdentity()); - assertThat(allValues.get(2).getObjectValue()).isEqualTo(acl); + assertThat(allValues.get(3).getKey()).isEqualTo(acl.getId()); + assertThat(allValues.get(3).getObjectValue()).isEqualTo(acl); + } - assertThat(allValues.get(3).getKey()).isEqualTo(acl.getId()); - assertThat(allValues.get(3).getObjectValue()).isEqualTo(acl); - } + @Test + public void getFromCacheSerializable() throws Exception { + when(cache.get(acl.getId())).thenReturn(new Element(acl.getId(), acl)); - @Test - public void getFromCacheSerializable() throws Exception { - when(cache.get(acl.getId())).thenReturn(new Element(acl.getId(),acl)); + assertThat(myCache.getFromCache(acl.getId())).isEqualTo(acl); + } - assertThat(myCache.getFromCache(acl.getId())).isEqualTo(acl); - } + @Test + public void getFromCacheSerializablePopulatesTransient() throws Exception { + when(cache.get(acl.getId())).thenReturn(new Element(acl.getId(), acl)); - @Test - public void getFromCacheSerializablePopulatesTransient() throws Exception { - when(cache.get(acl.getId())).thenReturn(new Element(acl.getId(),acl)); + myCache.putInCache(acl); - myCache.putInCache(acl); + ReflectionTestUtils.setField(acl, "permissionGrantingStrategy", null); + ReflectionTestUtils.setField(acl, "aclAuthorizationStrategy", null); - ReflectionTestUtils.setField(acl, "permissionGrantingStrategy", null); - ReflectionTestUtils.setField(acl, "aclAuthorizationStrategy", null); + MutableAcl fromCache = myCache.getFromCache(acl.getId()); - MutableAcl fromCache = myCache.getFromCache(acl.getId()); + assertThat(ReflectionTestUtils.getField(fromCache, "aclAuthorizationStrategy")) + .isNotNull(); + assertThat(ReflectionTestUtils.getField(fromCache, "permissionGrantingStrategy")) + .isNotNull(); + } - assertThat(ReflectionTestUtils.getField(fromCache, "aclAuthorizationStrategy")).isNotNull(); - assertThat(ReflectionTestUtils.getField(fromCache, "permissionGrantingStrategy")).isNotNull(); - } + @Test + public void getFromCacheObjectIdentity() throws Exception { + when(cache.get(acl.getId())).thenReturn(new Element(acl.getId(), acl)); - @Test - public void getFromCacheObjectIdentity() throws Exception { - when(cache.get(acl.getId())).thenReturn(new Element(acl.getId(),acl)); + assertThat(myCache.getFromCache(acl.getId())).isEqualTo(acl); + } - assertThat(myCache.getFromCache(acl.getId())).isEqualTo(acl); - } + @Test + public void getFromCacheObjectIdentityPopulatesTransient() throws Exception { + when(cache.get(acl.getObjectIdentity())) + .thenReturn(new Element(acl.getId(), acl)); - @Test - public void getFromCacheObjectIdentityPopulatesTransient() throws Exception { - when(cache.get(acl.getObjectIdentity())).thenReturn(new Element(acl.getId(),acl)); + myCache.putInCache(acl); - myCache.putInCache(acl); + ReflectionTestUtils.setField(acl, "permissionGrantingStrategy", null); + ReflectionTestUtils.setField(acl, "aclAuthorizationStrategy", null); - ReflectionTestUtils.setField(acl, "permissionGrantingStrategy", null); - ReflectionTestUtils.setField(acl, "aclAuthorizationStrategy", null); + MutableAcl fromCache = myCache.getFromCache(acl.getObjectIdentity()); - MutableAcl fromCache = myCache.getFromCache(acl.getObjectIdentity()); + assertThat(ReflectionTestUtils.getField(fromCache, "aclAuthorizationStrategy")) + .isNotNull(); + assertThat(ReflectionTestUtils.getField(fromCache, "permissionGrantingStrategy")) + .isNotNull(); + } - assertThat(ReflectionTestUtils.getField(fromCache, "aclAuthorizationStrategy")).isNotNull(); - assertThat(ReflectionTestUtils.getField(fromCache, "permissionGrantingStrategy")).isNotNull(); - } + @Test + public void evictCacheSerializable() throws Exception { + when(cache.get(acl.getObjectIdentity())) + .thenReturn(new Element(acl.getId(), acl)); - @Test - public void evictCacheSerializable() throws Exception { - when(cache.get(acl.getObjectIdentity())).thenReturn(new Element(acl.getId(),acl)); + myCache.evictFromCache(acl.getObjectIdentity()); - myCache.evictFromCache(acl.getObjectIdentity()); + verify(cache).remove(acl.getId()); + verify(cache).remove(acl.getObjectIdentity()); + } - verify(cache).remove(acl.getId()); - verify(cache).remove(acl.getObjectIdentity()); - } + @Test + public void evictCacheObjectIdentity() throws Exception { + when(cache.get(acl.getId())).thenReturn(new Element(acl.getId(), acl)); - @Test - public void evictCacheObjectIdentity() throws Exception { - when(cache.get(acl.getId())).thenReturn(new Element(acl.getId(),acl)); + myCache.evictFromCache(acl.getId()); - myCache.evictFromCache(acl.getId()); - - verify(cache).remove(acl.getId()); - verify(cache).remove(acl.getObjectIdentity()); - } + verify(cache).remove(acl.getId()); + verify(cache).remove(acl.getObjectIdentity()); + } } diff --git a/acl/src/test/java/org/springframework/security/acls/jdbc/JdbcAclServiceTests.java b/acl/src/test/java/org/springframework/security/acls/jdbc/JdbcAclServiceTests.java index afa5f011a9..f7cd040a56 100644 --- a/acl/src/test/java/org/springframework/security/acls/jdbc/JdbcAclServiceTests.java +++ b/acl/src/test/java/org/springframework/security/acls/jdbc/JdbcAclServiceTests.java @@ -24,27 +24,29 @@ import org.springframework.security.acls.model.Sid; @RunWith(MockitoJUnitRunner.class) public class JdbcAclServiceTests { - @Mock - private DataSource dataSource; + @Mock + private DataSource dataSource; - @Mock - private LookupStrategy lookupStrategy; + @Mock + private LookupStrategy lookupStrategy; - private JdbcAclService aclService; + private JdbcAclService aclService; - @Before - public void setUp() { - aclService = new JdbcAclService(dataSource, lookupStrategy); - } + @Before + public void setUp() { + aclService = new JdbcAclService(dataSource, lookupStrategy); + } - // SEC-1898 - @Test(expected = NotFoundException.class) - public void readAclByIdMissingAcl() { - Map result = new HashMap(); - when(lookupStrategy.readAclsById(anyListOf(ObjectIdentity.class), anyListOf(Sid.class))).thenReturn(result); - ObjectIdentity objectIdentity = new ObjectIdentityImpl(Object.class, 1); - List sids = Arrays. asList(new PrincipalSid("user")); + // SEC-1898 + @Test(expected = NotFoundException.class) + public void readAclByIdMissingAcl() { + Map result = new HashMap(); + when( + lookupStrategy.readAclsById(anyListOf(ObjectIdentity.class), + anyListOf(Sid.class))).thenReturn(result); + ObjectIdentity objectIdentity = new ObjectIdentityImpl(Object.class, 1); + List sids = Arrays. asList(new PrincipalSid("user")); - aclService.readAclById(objectIdentity, sids); - } + aclService.readAclById(objectIdentity, sids); + } } \ No newline at end of file diff --git a/acl/src/test/java/org/springframework/security/acls/jdbc/JdbcMutableAclServiceTests.java b/acl/src/test/java/org/springframework/security/acls/jdbc/JdbcMutableAclServiceTests.java index 16348f3ac3..09d80760b5 100644 --- a/acl/src/test/java/org/springframework/security/acls/jdbc/JdbcMutableAclServiceTests.java +++ b/acl/src/test/java/org/springframework/security/acls/jdbc/JdbcMutableAclServiceTests.java @@ -60,474 +60,518 @@ import org.springframework.transaction.annotation.Transactional; * @author Ben Alex * @author Andrei Stefan */ -@ContextConfiguration(locations={"/jdbcMutableAclServiceTests-context.xml"}) -public class JdbcMutableAclServiceTests extends AbstractTransactionalJUnit4SpringContextTests { - //~ Constant fields ================================================================================================ - - private static final String TARGET_CLASS = TargetObject.class.getName(); - - private final Authentication auth = new TestingAuthenticationToken("ben", "ignored","ROLE_ADMINISTRATOR"); - - public static final String SELECT_ALL_CLASSES = "SELECT * FROM acl_class WHERE class = ?"; - - //~ Instance fields ================================================================================================ - - private final ObjectIdentity topParentOid = new ObjectIdentityImpl(TARGET_CLASS, Long.valueOf(100)); - private final ObjectIdentity middleParentOid = new ObjectIdentityImpl(TARGET_CLASS, Long.valueOf(101)); - private final ObjectIdentity childOid = new ObjectIdentityImpl(TARGET_CLASS, Long.valueOf(102)); - - @Autowired - private JdbcMutableAclService jdbcMutableAclService; - @Autowired - private AclCache aclCache; - @Autowired - private LookupStrategy lookupStrategy; - @Autowired - private DataSource dataSource; - @Autowired - private JdbcTemplate jdbcTemplate; - - //~ Methods ======================================================================================================== - - @BeforeTransaction - public void createTables() throws Exception { - try { - new DatabaseSeeder(dataSource, new ClassPathResource("createAclSchema.sql")); -// new DatabaseSeeder(dataSource, new ClassPathResource("createAclSchemaPostgres.sql")); - } catch (Exception e) { - e.printStackTrace(); - throw e; - } - } - - @AfterTransaction - public void clearContextAndData() throws Exception { - SecurityContextHolder.clearContext(); - jdbcTemplate.execute("drop table acl_entry"); - jdbcTemplate.execute("drop table acl_object_identity"); - jdbcTemplate.execute("drop table acl_class"); - jdbcTemplate.execute("drop table acl_sid"); - aclCache.clearCache(); - } - - @Test - @Transactional - public void testLifecycle() { - SecurityContextHolder.getContext().setAuthentication(auth); - - MutableAcl topParent = jdbcMutableAclService.createAcl(topParentOid); - MutableAcl middleParent = jdbcMutableAclService.createAcl(middleParentOid); - MutableAcl child = jdbcMutableAclService.createAcl(childOid); - - // Specify the inheritance hierarchy - middleParent.setParent(topParent); - child.setParent(middleParent); - - // Now let's add a couple of permissions - topParent.insertAce(0, BasePermission.READ, new PrincipalSid(auth), true); - topParent.insertAce(1, BasePermission.WRITE, new PrincipalSid(auth), false); - middleParent.insertAce(0, BasePermission.DELETE, new PrincipalSid(auth), true); - child.insertAce(0, BasePermission.DELETE, new PrincipalSid(auth), false); - - // Explicitly save the changed ACL - jdbcMutableAclService.updateAcl(topParent); - jdbcMutableAclService.updateAcl(middleParent); - jdbcMutableAclService.updateAcl(child); - - // Let's check if we can read them back correctly - Map map = jdbcMutableAclService.readAclsById(Arrays.asList(topParentOid, middleParentOid, childOid)); - assertEquals(3, map.size()); - - // Replace our current objects with their retrieved versions - topParent = (MutableAcl) map.get(topParentOid); - middleParent = (MutableAcl) map.get(middleParentOid); - child = (MutableAcl) map.get(childOid); - - // Check the retrieved versions has IDs - assertNotNull(topParent.getId()); - assertNotNull(middleParent.getId()); - assertNotNull(child.getId()); - - // Check their parents were correctly persisted - assertNull(topParent.getParentAcl()); - assertEquals(topParentOid, middleParent.getParentAcl().getObjectIdentity()); - assertEquals(middleParentOid, child.getParentAcl().getObjectIdentity()); - - // Check their ACEs were correctly persisted - assertEquals(2, topParent.getEntries().size()); - assertEquals(1, middleParent.getEntries().size()); - assertEquals(1, child.getEntries().size()); - - // Check the retrieved rights are correct - List read = Arrays.asList(BasePermission.READ); - List write = Arrays.asList(BasePermission.WRITE); - List delete = Arrays.asList(BasePermission.DELETE); - List pSid = Arrays.asList((Sid)new PrincipalSid(auth)); - - - assertTrue(topParent.isGranted(read, pSid, false)); - assertFalse(topParent.isGranted(write, pSid, false)); - assertTrue(middleParent.isGranted(delete, pSid, false)); - assertFalse(child.isGranted(delete, pSid, false)); - - try { - child.isGranted(Arrays.asList(BasePermission.ADMINISTRATION), pSid, false); - fail("Should have thrown NotFoundException"); - } catch (NotFoundException expected) { - assertTrue(true); - } - - // Now check the inherited rights (when not explicitly overridden) also look OK - assertTrue(child.isGranted(read, pSid, false)); - assertFalse(child.isGranted(write, pSid, false)); - assertFalse(child.isGranted(delete, pSid, false)); - - // Next change the child so it doesn't inherit permissions from above - child.setEntriesInheriting(false); - jdbcMutableAclService.updateAcl(child); - child = (MutableAcl) jdbcMutableAclService.readAclById(childOid); - assertFalse(child.isEntriesInheriting()); - - // Check the child permissions no longer inherit - assertFalse(child.isGranted(delete, pSid, true)); - - try { - child.isGranted(read, pSid, true); - fail("Should have thrown NotFoundException"); - } catch (NotFoundException expected) { - assertTrue(true); - } - - try { - child.isGranted(write, pSid, true); - fail("Should have thrown NotFoundException"); - } catch (NotFoundException expected) { - assertTrue(true); - } - - // Let's add an identical permission to the child, but it'll appear AFTER the current permission, so has no impact - child.insertAce(1, BasePermission.DELETE, new PrincipalSid(auth), true); - - // Let's also add another permission to the child - child.insertAce(2, BasePermission.CREATE, new PrincipalSid(auth), true); - - // Save the changed child - jdbcMutableAclService.updateAcl(child); - child = (MutableAcl) jdbcMutableAclService.readAclById(childOid); - assertEquals(3, child.getEntries().size()); - - // Output permissions - for (int i = 0; i < child.getEntries().size(); i++) { - System.out.println(child.getEntries().get(i)); - } - - // Check the permissions are as they should be - assertFalse(child.isGranted(delete, pSid, true)); // as earlier permission overrode - assertTrue(child.isGranted(Arrays.asList(BasePermission.CREATE), pSid, true)); - - // Now check the first ACE (index 0) really is DELETE for our Sid and is non-granting - AccessControlEntry entry = child.getEntries().get(0); - assertEquals(BasePermission.DELETE.getMask(), entry.getPermission().getMask()); - assertEquals(new PrincipalSid(auth), entry.getSid()); - assertFalse(entry.isGranting()); - assertNotNull(entry.getId()); - - // Now delete that first ACE - child.deleteAce(0); - - // Save and check it worked - child = jdbcMutableAclService.updateAcl(child); - assertEquals(2, child.getEntries().size()); - assertTrue(child.isGranted(delete, pSid, false)); - - SecurityContextHolder.clearContext(); - } - - /** - * Test method that demonstrates eviction failure from cache - SEC-676 - */ - @Test - @Transactional - public void deleteAclAlsoDeletesChildren() throws Exception { - SecurityContextHolder.getContext().setAuthentication(auth); - - jdbcMutableAclService.createAcl(topParentOid); - MutableAcl middleParent = jdbcMutableAclService.createAcl(middleParentOid); - MutableAcl child = jdbcMutableAclService.createAcl(childOid); - child.setParent(middleParent); - jdbcMutableAclService.updateAcl(middleParent); - jdbcMutableAclService.updateAcl(child); - // Check the childOid really is a child of middleParentOid - Acl childAcl = jdbcMutableAclService.readAclById(childOid); - - assertEquals(middleParentOid, childAcl.getParentAcl().getObjectIdentity()); - - // Delete the mid-parent and test if the child was deleted, as well - jdbcMutableAclService.deleteAcl(middleParentOid, true); - - try { - jdbcMutableAclService.readAclById(middleParentOid); - fail("It should have thrown NotFoundException"); - } - catch (NotFoundException expected) { - assertTrue(true); - } - try { - jdbcMutableAclService.readAclById(childOid); - fail("It should have thrown NotFoundException"); - } - catch (NotFoundException expected) { - assertTrue(true); - } - - Acl acl = jdbcMutableAclService.readAclById(topParentOid); - assertNotNull(acl); - assertEquals(((MutableAcl) acl).getObjectIdentity(), topParentOid); - } - - @Test - public void constructorRejectsNullParameters() throws Exception { - try { - new JdbcMutableAclService(null, lookupStrategy, aclCache); - fail("It should have thrown IllegalArgumentException"); - } - catch (IllegalArgumentException expected) { - } - - try { - new JdbcMutableAclService(dataSource, null, aclCache); - fail("It should have thrown IllegalArgumentException"); - } - catch (IllegalArgumentException expected) { - } - - try { - new JdbcMutableAclService(dataSource, lookupStrategy, null); - fail("It should have thrown IllegalArgumentException"); - } - catch (IllegalArgumentException expected) { - } - } - - @Test - public void createAclRejectsNullParameter() throws Exception { - try { - jdbcMutableAclService.createAcl(null); - fail("It should have thrown IllegalArgumentException"); - } - catch (IllegalArgumentException expected) { - } - } - - @Test - @Transactional - public void createAclForADuplicateDomainObject() throws Exception { - SecurityContextHolder.getContext().setAuthentication(auth); - ObjectIdentity duplicateOid = new ObjectIdentityImpl(TARGET_CLASS, Long.valueOf(100)); - jdbcMutableAclService.createAcl(duplicateOid); - // Try to add the same object second time - try { - jdbcMutableAclService.createAcl(duplicateOid); - fail("It should have thrown AlreadyExistsException"); - } - catch (AlreadyExistsException expected) { - } - } - - @Test - @Transactional - public void deleteAclRejectsNullParameters() throws Exception { - try { - jdbcMutableAclService.deleteAcl(null, true); - fail("It should have thrown IllegalArgumentException"); - } - catch (IllegalArgumentException expected) { - } - } - - @Test - @Transactional - public void deleteAclWithChildrenThrowsException() throws Exception { - SecurityContextHolder.getContext().setAuthentication(auth); - MutableAcl parent = jdbcMutableAclService.createAcl(topParentOid); - MutableAcl child = jdbcMutableAclService.createAcl(middleParentOid); - - // Specify the inheritance hierarchy - child.setParent(parent); - jdbcMutableAclService.updateAcl(child); - - try { - jdbcMutableAclService.setForeignKeysInDatabase(false); // switch on FK checking in the class, not database - jdbcMutableAclService.deleteAcl(topParentOid, false); - fail("It should have thrown ChildrenExistException"); - } - catch (ChildrenExistException expected) { - } finally { - jdbcMutableAclService.setForeignKeysInDatabase(true); // restore to the default - } - } - - @Test - @Transactional - public void deleteAclRemovesRowsFromDatabase() throws Exception { - SecurityContextHolder.getContext().setAuthentication(auth); - MutableAcl child = jdbcMutableAclService.createAcl(childOid); - child.insertAce(0, BasePermission.DELETE, new PrincipalSid(auth), false); - jdbcMutableAclService.updateAcl(child); - - // Remove the child and check all related database rows were removed accordingly - jdbcMutableAclService.deleteAcl(childOid, false); - assertEquals(1, jdbcTemplate.queryForList(SELECT_ALL_CLASSES, new Object[] {TARGET_CLASS} ).size()); - assertEquals(0, jdbcTemplate.queryForList("select * from acl_object_identity").size()); - assertEquals(0, jdbcTemplate.queryForList("select * from acl_entry").size()); - - // Check the cache - assertNull(aclCache.getFromCache(childOid)); - assertNull(aclCache.getFromCache(Long.valueOf(102))); - } - - /** SEC-1107 */ - @Test - @Transactional - public void identityWithIntegerIdIsSupportedByCreateAcl() throws Exception { - SecurityContextHolder.getContext().setAuthentication(auth); - ObjectIdentity oid = new ObjectIdentityImpl(TARGET_CLASS, Integer.valueOf(101)); - jdbcMutableAclService.createAcl(oid); - - assertNotNull(jdbcMutableAclService.readAclById(new ObjectIdentityImpl(TARGET_CLASS, Long.valueOf(101)))); - } - - /** - * SEC-655 - */ - @Test - @Transactional - public void childrenAreClearedFromCacheWhenParentIsUpdated() throws Exception { - Authentication auth = new TestingAuthenticationToken("ben", "ignored","ROLE_ADMINISTRATOR"); - auth.setAuthenticated(true); - SecurityContextHolder.getContext().setAuthentication(auth); - - ObjectIdentity parentOid = new ObjectIdentityImpl(TARGET_CLASS, Long.valueOf(104)); - ObjectIdentity childOid = new ObjectIdentityImpl(TARGET_CLASS, Long.valueOf(105)); - - MutableAcl parent = jdbcMutableAclService.createAcl(parentOid); - MutableAcl child = jdbcMutableAclService.createAcl(childOid); - - child.setParent(parent); - jdbcMutableAclService.updateAcl(child); - - parent = (AclImpl) jdbcMutableAclService.readAclById(parentOid); - parent.insertAce(0, BasePermission.READ, new PrincipalSid("ben"), true); - jdbcMutableAclService.updateAcl(parent); - - parent = (AclImpl) jdbcMutableAclService.readAclById(parentOid); - parent.insertAce(1, BasePermission.READ, new PrincipalSid("scott"), true); - jdbcMutableAclService.updateAcl(parent); - - child = (MutableAcl) jdbcMutableAclService.readAclById(childOid); - parent = (MutableAcl) child.getParentAcl(); - - assertEquals("Fails because child has a stale reference to its parent", 2, parent.getEntries().size()); - assertEquals(1, parent.getEntries().get(0).getPermission().getMask()); - assertEquals(new PrincipalSid("ben"), parent.getEntries().get(0).getSid()); - assertEquals(1, parent.getEntries().get(1).getPermission().getMask()); - assertEquals(new PrincipalSid("scott"), parent.getEntries().get(1).getSid()); - } - - /** - * SEC-655 - */ - @Test - @Transactional - public void childrenAreClearedFromCacheWhenParentisUpdated2() throws Exception { - Authentication auth = new TestingAuthenticationToken("system", "secret","ROLE_IGNORED"); - SecurityContextHolder.getContext().setAuthentication(auth); - ObjectIdentityImpl rootObject = new ObjectIdentityImpl(TARGET_CLASS, Long.valueOf(1)); - - MutableAcl parent = jdbcMutableAclService.createAcl(rootObject); - MutableAcl child = jdbcMutableAclService.createAcl(new ObjectIdentityImpl(TARGET_CLASS, Long.valueOf(2))); - child.setParent(parent); - jdbcMutableAclService.updateAcl(child); - - parent.insertAce(0, BasePermission.ADMINISTRATION, new GrantedAuthoritySid("ROLE_ADMINISTRATOR"), true); - jdbcMutableAclService.updateAcl(parent); - - parent.insertAce(1, BasePermission.DELETE, new PrincipalSid("terry"), true); - jdbcMutableAclService.updateAcl(parent); - - child = (MutableAcl) jdbcMutableAclService.readAclById(new ObjectIdentityImpl(TARGET_CLASS, Long.valueOf(2))); - - parent = (MutableAcl) child.getParentAcl(); - - assertEquals(2, parent.getEntries().size()); - assertEquals(16, parent.getEntries().get(0).getPermission().getMask()); - assertEquals(new GrantedAuthoritySid("ROLE_ADMINISTRATOR"), parent.getEntries().get(0).getSid()); - assertEquals(8, parent.getEntries().get(1).getPermission().getMask()); - assertEquals(new PrincipalSid("terry"), parent.getEntries().get(1).getSid()); - } - - @Test - @Transactional - public void cumulativePermissions() { - Authentication auth = new TestingAuthenticationToken("ben", "ignored", "ROLE_ADMINISTRATOR"); - auth.setAuthenticated(true); - SecurityContextHolder.getContext().setAuthentication(auth); - - ObjectIdentity topParentOid = new ObjectIdentityImpl(TARGET_CLASS, Long.valueOf(110)); - MutableAcl topParent = jdbcMutableAclService.createAcl(topParentOid); - - // Add an ACE permission entry - Permission cm = new CumulativePermission().set(BasePermission.READ).set(BasePermission.ADMINISTRATION); - assertEquals(17, cm.getMask()); - Sid benSid = new PrincipalSid(auth); - topParent.insertAce(0, cm, benSid, true); - assertEquals(1, topParent.getEntries().size()); - - // Explicitly save the changed ACL - topParent = jdbcMutableAclService.updateAcl(topParent); - - // Check the mask was retrieved correctly - assertEquals(17, topParent.getEntries().get(0).getPermission().getMask()); - assertTrue(topParent.isGranted(Arrays.asList(cm), Arrays.asList(benSid), true)); - - SecurityContextHolder.clearContext(); - } - @Test - public void testProcessingCustomSid() { - CustomJdbcMutableAclService customJdbcMutableAclService = spy(new CustomJdbcMutableAclService(dataSource, - lookupStrategy, aclCache)); - CustomSid customSid = new CustomSid("Custom sid"); - when(customJdbcMutableAclService.createOrRetrieveSidPrimaryKey("Custom sid", false, false)).thenReturn(1L); - - Long result = customJdbcMutableAclService.createOrRetrieveSidPrimaryKey(customSid, false); - - assertEquals(result, new Long(1L)); - } - - /** - * This class needed to show how to extend {@link JdbcMutableAclService} for processing - * custom {@link Sid} implementations - */ - private class CustomJdbcMutableAclService extends JdbcMutableAclService { - - private CustomJdbcMutableAclService(DataSource dataSource, LookupStrategy lookupStrategy, AclCache aclCache) { - super(dataSource, lookupStrategy, aclCache); - } - - @Override - protected Long createOrRetrieveSidPrimaryKey(Sid sid, boolean allowCreate) { - String sidName; - boolean isPrincipal = false; - if (sid instanceof CustomSid) { - sidName = ((CustomSid)sid).getSid(); - } else if (sid instanceof GrantedAuthoritySid) { - sidName = ((GrantedAuthoritySid)sid).getGrantedAuthority(); - } else { - sidName = ((PrincipalSid)sid).getPrincipal(); - isPrincipal = true; - } - return createOrRetrieveSidPrimaryKey(sidName, isPrincipal, allowCreate); - } - } +@ContextConfiguration(locations = { "/jdbcMutableAclServiceTests-context.xml" }) +public class JdbcMutableAclServiceTests extends + AbstractTransactionalJUnit4SpringContextTests { + // ~ Constant fields + // ================================================================================================ + + private static final String TARGET_CLASS = TargetObject.class.getName(); + + private final Authentication auth = new TestingAuthenticationToken("ben", "ignored", + "ROLE_ADMINISTRATOR"); + + public static final String SELECT_ALL_CLASSES = "SELECT * FROM acl_class WHERE class = ?"; + + // ~ Instance fields + // ================================================================================================ + + private final ObjectIdentity topParentOid = new ObjectIdentityImpl(TARGET_CLASS, + Long.valueOf(100)); + private final ObjectIdentity middleParentOid = new ObjectIdentityImpl(TARGET_CLASS, + Long.valueOf(101)); + private final ObjectIdentity childOid = new ObjectIdentityImpl(TARGET_CLASS, + Long.valueOf(102)); + + @Autowired + private JdbcMutableAclService jdbcMutableAclService; + @Autowired + private AclCache aclCache; + @Autowired + private LookupStrategy lookupStrategy; + @Autowired + private DataSource dataSource; + @Autowired + private JdbcTemplate jdbcTemplate; + + // ~ Methods + // ======================================================================================================== + + @BeforeTransaction + public void createTables() throws Exception { + try { + new DatabaseSeeder(dataSource, new ClassPathResource("createAclSchema.sql")); + // new DatabaseSeeder(dataSource, new + // ClassPathResource("createAclSchemaPostgres.sql")); + } + catch (Exception e) { + e.printStackTrace(); + throw e; + } + } + + @AfterTransaction + public void clearContextAndData() throws Exception { + SecurityContextHolder.clearContext(); + jdbcTemplate.execute("drop table acl_entry"); + jdbcTemplate.execute("drop table acl_object_identity"); + jdbcTemplate.execute("drop table acl_class"); + jdbcTemplate.execute("drop table acl_sid"); + aclCache.clearCache(); + } + + @Test + @Transactional + public void testLifecycle() { + SecurityContextHolder.getContext().setAuthentication(auth); + + MutableAcl topParent = jdbcMutableAclService.createAcl(topParentOid); + MutableAcl middleParent = jdbcMutableAclService.createAcl(middleParentOid); + MutableAcl child = jdbcMutableAclService.createAcl(childOid); + + // Specify the inheritance hierarchy + middleParent.setParent(topParent); + child.setParent(middleParent); + + // Now let's add a couple of permissions + topParent.insertAce(0, BasePermission.READ, new PrincipalSid(auth), true); + topParent.insertAce(1, BasePermission.WRITE, new PrincipalSid(auth), false); + middleParent.insertAce(0, BasePermission.DELETE, new PrincipalSid(auth), true); + child.insertAce(0, BasePermission.DELETE, new PrincipalSid(auth), false); + + // Explicitly save the changed ACL + jdbcMutableAclService.updateAcl(topParent); + jdbcMutableAclService.updateAcl(middleParent); + jdbcMutableAclService.updateAcl(child); + + // Let's check if we can read them back correctly + Map map = jdbcMutableAclService.readAclsById(Arrays.asList( + topParentOid, middleParentOid, childOid)); + assertEquals(3, map.size()); + + // Replace our current objects with their retrieved versions + topParent = (MutableAcl) map.get(topParentOid); + middleParent = (MutableAcl) map.get(middleParentOid); + child = (MutableAcl) map.get(childOid); + + // Check the retrieved versions has IDs + assertNotNull(topParent.getId()); + assertNotNull(middleParent.getId()); + assertNotNull(child.getId()); + + // Check their parents were correctly persisted + assertNull(topParent.getParentAcl()); + assertEquals(topParentOid, middleParent.getParentAcl().getObjectIdentity()); + assertEquals(middleParentOid, child.getParentAcl().getObjectIdentity()); + + // Check their ACEs were correctly persisted + assertEquals(2, topParent.getEntries().size()); + assertEquals(1, middleParent.getEntries().size()); + assertEquals(1, child.getEntries().size()); + + // Check the retrieved rights are correct + List read = Arrays.asList(BasePermission.READ); + List write = Arrays.asList(BasePermission.WRITE); + List delete = Arrays.asList(BasePermission.DELETE); + List pSid = Arrays.asList((Sid) new PrincipalSid(auth)); + + assertTrue(topParent.isGranted(read, pSid, false)); + assertFalse(topParent.isGranted(write, pSid, false)); + assertTrue(middleParent.isGranted(delete, pSid, false)); + assertFalse(child.isGranted(delete, pSid, false)); + + try { + child.isGranted(Arrays.asList(BasePermission.ADMINISTRATION), pSid, false); + fail("Should have thrown NotFoundException"); + } + catch (NotFoundException expected) { + assertTrue(true); + } + + // Now check the inherited rights (when not explicitly overridden) also look OK + assertTrue(child.isGranted(read, pSid, false)); + assertFalse(child.isGranted(write, pSid, false)); + assertFalse(child.isGranted(delete, pSid, false)); + + // Next change the child so it doesn't inherit permissions from above + child.setEntriesInheriting(false); + jdbcMutableAclService.updateAcl(child); + child = (MutableAcl) jdbcMutableAclService.readAclById(childOid); + assertFalse(child.isEntriesInheriting()); + + // Check the child permissions no longer inherit + assertFalse(child.isGranted(delete, pSid, true)); + + try { + child.isGranted(read, pSid, true); + fail("Should have thrown NotFoundException"); + } + catch (NotFoundException expected) { + assertTrue(true); + } + + try { + child.isGranted(write, pSid, true); + fail("Should have thrown NotFoundException"); + } + catch (NotFoundException expected) { + assertTrue(true); + } + + // Let's add an identical permission to the child, but it'll appear AFTER the + // current permission, so has no impact + child.insertAce(1, BasePermission.DELETE, new PrincipalSid(auth), true); + + // Let's also add another permission to the child + child.insertAce(2, BasePermission.CREATE, new PrincipalSid(auth), true); + + // Save the changed child + jdbcMutableAclService.updateAcl(child); + child = (MutableAcl) jdbcMutableAclService.readAclById(childOid); + assertEquals(3, child.getEntries().size()); + + // Output permissions + for (int i = 0; i < child.getEntries().size(); i++) { + System.out.println(child.getEntries().get(i)); + } + + // Check the permissions are as they should be + assertFalse(child.isGranted(delete, pSid, true)); // as earlier permission + // overrode + assertTrue(child.isGranted(Arrays.asList(BasePermission.CREATE), pSid, true)); + + // Now check the first ACE (index 0) really is DELETE for our Sid and is + // non-granting + AccessControlEntry entry = child.getEntries().get(0); + assertEquals(BasePermission.DELETE.getMask(), entry.getPermission().getMask()); + assertEquals(new PrincipalSid(auth), entry.getSid()); + assertFalse(entry.isGranting()); + assertNotNull(entry.getId()); + + // Now delete that first ACE + child.deleteAce(0); + + // Save and check it worked + child = jdbcMutableAclService.updateAcl(child); + assertEquals(2, child.getEntries().size()); + assertTrue(child.isGranted(delete, pSid, false)); + + SecurityContextHolder.clearContext(); + } + + /** + * Test method that demonstrates eviction failure from cache - SEC-676 + */ + @Test + @Transactional + public void deleteAclAlsoDeletesChildren() throws Exception { + SecurityContextHolder.getContext().setAuthentication(auth); + + jdbcMutableAclService.createAcl(topParentOid); + MutableAcl middleParent = jdbcMutableAclService.createAcl(middleParentOid); + MutableAcl child = jdbcMutableAclService.createAcl(childOid); + child.setParent(middleParent); + jdbcMutableAclService.updateAcl(middleParent); + jdbcMutableAclService.updateAcl(child); + // Check the childOid really is a child of middleParentOid + Acl childAcl = jdbcMutableAclService.readAclById(childOid); + + assertEquals(middleParentOid, childAcl.getParentAcl().getObjectIdentity()); + + // Delete the mid-parent and test if the child was deleted, as well + jdbcMutableAclService.deleteAcl(middleParentOid, true); + + try { + jdbcMutableAclService.readAclById(middleParentOid); + fail("It should have thrown NotFoundException"); + } + catch (NotFoundException expected) { + assertTrue(true); + } + try { + jdbcMutableAclService.readAclById(childOid); + fail("It should have thrown NotFoundException"); + } + catch (NotFoundException expected) { + assertTrue(true); + } + + Acl acl = jdbcMutableAclService.readAclById(topParentOid); + assertNotNull(acl); + assertEquals(((MutableAcl) acl).getObjectIdentity(), topParentOid); + } + + @Test + public void constructorRejectsNullParameters() throws Exception { + try { + new JdbcMutableAclService(null, lookupStrategy, aclCache); + fail("It should have thrown IllegalArgumentException"); + } + catch (IllegalArgumentException expected) { + } + + try { + new JdbcMutableAclService(dataSource, null, aclCache); + fail("It should have thrown IllegalArgumentException"); + } + catch (IllegalArgumentException expected) { + } + + try { + new JdbcMutableAclService(dataSource, lookupStrategy, null); + fail("It should have thrown IllegalArgumentException"); + } + catch (IllegalArgumentException expected) { + } + } + + @Test + public void createAclRejectsNullParameter() throws Exception { + try { + jdbcMutableAclService.createAcl(null); + fail("It should have thrown IllegalArgumentException"); + } + catch (IllegalArgumentException expected) { + } + } + + @Test + @Transactional + public void createAclForADuplicateDomainObject() throws Exception { + SecurityContextHolder.getContext().setAuthentication(auth); + ObjectIdentity duplicateOid = new ObjectIdentityImpl(TARGET_CLASS, + Long.valueOf(100)); + jdbcMutableAclService.createAcl(duplicateOid); + // Try to add the same object second time + try { + jdbcMutableAclService.createAcl(duplicateOid); + fail("It should have thrown AlreadyExistsException"); + } + catch (AlreadyExistsException expected) { + } + } + + @Test + @Transactional + public void deleteAclRejectsNullParameters() throws Exception { + try { + jdbcMutableAclService.deleteAcl(null, true); + fail("It should have thrown IllegalArgumentException"); + } + catch (IllegalArgumentException expected) { + } + } + + @Test + @Transactional + public void deleteAclWithChildrenThrowsException() throws Exception { + SecurityContextHolder.getContext().setAuthentication(auth); + MutableAcl parent = jdbcMutableAclService.createAcl(topParentOid); + MutableAcl child = jdbcMutableAclService.createAcl(middleParentOid); + + // Specify the inheritance hierarchy + child.setParent(parent); + jdbcMutableAclService.updateAcl(child); + + try { + jdbcMutableAclService.setForeignKeysInDatabase(false); // switch on FK + // checking in the + // class, not database + jdbcMutableAclService.deleteAcl(topParentOid, false); + fail("It should have thrown ChildrenExistException"); + } + catch (ChildrenExistException expected) { + } + finally { + jdbcMutableAclService.setForeignKeysInDatabase(true); // restore to the + // default + } + } + + @Test + @Transactional + public void deleteAclRemovesRowsFromDatabase() throws Exception { + SecurityContextHolder.getContext().setAuthentication(auth); + MutableAcl child = jdbcMutableAclService.createAcl(childOid); + child.insertAce(0, BasePermission.DELETE, new PrincipalSid(auth), false); + jdbcMutableAclService.updateAcl(child); + + // Remove the child and check all related database rows were removed accordingly + jdbcMutableAclService.deleteAcl(childOid, false); + assertEquals( + 1, + jdbcTemplate.queryForList(SELECT_ALL_CLASSES, + new Object[] { TARGET_CLASS }).size()); + assertEquals(0, jdbcTemplate.queryForList("select * from acl_object_identity") + .size()); + assertEquals(0, jdbcTemplate.queryForList("select * from acl_entry").size()); + + // Check the cache + assertNull(aclCache.getFromCache(childOid)); + assertNull(aclCache.getFromCache(Long.valueOf(102))); + } + + /** SEC-1107 */ + @Test + @Transactional + public void identityWithIntegerIdIsSupportedByCreateAcl() throws Exception { + SecurityContextHolder.getContext().setAuthentication(auth); + ObjectIdentity oid = new ObjectIdentityImpl(TARGET_CLASS, Integer.valueOf(101)); + jdbcMutableAclService.createAcl(oid); + + assertNotNull(jdbcMutableAclService.readAclById(new ObjectIdentityImpl( + TARGET_CLASS, Long.valueOf(101)))); + } + + /** + * SEC-655 + */ + @Test + @Transactional + public void childrenAreClearedFromCacheWhenParentIsUpdated() throws Exception { + Authentication auth = new TestingAuthenticationToken("ben", "ignored", + "ROLE_ADMINISTRATOR"); + auth.setAuthenticated(true); + SecurityContextHolder.getContext().setAuthentication(auth); + + ObjectIdentity parentOid = new ObjectIdentityImpl(TARGET_CLASS, Long.valueOf(104)); + ObjectIdentity childOid = new ObjectIdentityImpl(TARGET_CLASS, Long.valueOf(105)); + + MutableAcl parent = jdbcMutableAclService.createAcl(parentOid); + MutableAcl child = jdbcMutableAclService.createAcl(childOid); + + child.setParent(parent); + jdbcMutableAclService.updateAcl(child); + + parent = (AclImpl) jdbcMutableAclService.readAclById(parentOid); + parent.insertAce(0, BasePermission.READ, new PrincipalSid("ben"), true); + jdbcMutableAclService.updateAcl(parent); + + parent = (AclImpl) jdbcMutableAclService.readAclById(parentOid); + parent.insertAce(1, BasePermission.READ, new PrincipalSid("scott"), true); + jdbcMutableAclService.updateAcl(parent); + + child = (MutableAcl) jdbcMutableAclService.readAclById(childOid); + parent = (MutableAcl) child.getParentAcl(); + + assertEquals("Fails because child has a stale reference to its parent", 2, parent + .getEntries().size()); + assertEquals(1, parent.getEntries().get(0).getPermission().getMask()); + assertEquals(new PrincipalSid("ben"), parent.getEntries().get(0).getSid()); + assertEquals(1, parent.getEntries().get(1).getPermission().getMask()); + assertEquals(new PrincipalSid("scott"), parent.getEntries().get(1).getSid()); + } + + /** + * SEC-655 + */ + @Test + @Transactional + public void childrenAreClearedFromCacheWhenParentisUpdated2() throws Exception { + Authentication auth = new TestingAuthenticationToken("system", "secret", + "ROLE_IGNORED"); + SecurityContextHolder.getContext().setAuthentication(auth); + ObjectIdentityImpl rootObject = new ObjectIdentityImpl(TARGET_CLASS, + Long.valueOf(1)); + + MutableAcl parent = jdbcMutableAclService.createAcl(rootObject); + MutableAcl child = jdbcMutableAclService.createAcl(new ObjectIdentityImpl( + TARGET_CLASS, Long.valueOf(2))); + child.setParent(parent); + jdbcMutableAclService.updateAcl(child); + + parent.insertAce(0, BasePermission.ADMINISTRATION, new GrantedAuthoritySid( + "ROLE_ADMINISTRATOR"), true); + jdbcMutableAclService.updateAcl(parent); + + parent.insertAce(1, BasePermission.DELETE, new PrincipalSid("terry"), true); + jdbcMutableAclService.updateAcl(parent); + + child = (MutableAcl) jdbcMutableAclService.readAclById(new ObjectIdentityImpl( + TARGET_CLASS, Long.valueOf(2))); + + parent = (MutableAcl) child.getParentAcl(); + + assertEquals(2, parent.getEntries().size()); + assertEquals(16, parent.getEntries().get(0).getPermission().getMask()); + assertEquals(new GrantedAuthoritySid("ROLE_ADMINISTRATOR"), parent.getEntries() + .get(0).getSid()); + assertEquals(8, parent.getEntries().get(1).getPermission().getMask()); + assertEquals(new PrincipalSid("terry"), parent.getEntries().get(1).getSid()); + } + + @Test + @Transactional + public void cumulativePermissions() { + Authentication auth = new TestingAuthenticationToken("ben", "ignored", + "ROLE_ADMINISTRATOR"); + auth.setAuthenticated(true); + SecurityContextHolder.getContext().setAuthentication(auth); + + ObjectIdentity topParentOid = new ObjectIdentityImpl(TARGET_CLASS, + Long.valueOf(110)); + MutableAcl topParent = jdbcMutableAclService.createAcl(topParentOid); + + // Add an ACE permission entry + Permission cm = new CumulativePermission().set(BasePermission.READ).set( + BasePermission.ADMINISTRATION); + assertEquals(17, cm.getMask()); + Sid benSid = new PrincipalSid(auth); + topParent.insertAce(0, cm, benSid, true); + assertEquals(1, topParent.getEntries().size()); + + // Explicitly save the changed ACL + topParent = jdbcMutableAclService.updateAcl(topParent); + + // Check the mask was retrieved correctly + assertEquals(17, topParent.getEntries().get(0).getPermission().getMask()); + assertTrue(topParent.isGranted(Arrays.asList(cm), Arrays.asList(benSid), true)); + + SecurityContextHolder.clearContext(); + } + + @Test + public void testProcessingCustomSid() { + CustomJdbcMutableAclService customJdbcMutableAclService = spy(new CustomJdbcMutableAclService( + dataSource, lookupStrategy, aclCache)); + CustomSid customSid = new CustomSid("Custom sid"); + when( + customJdbcMutableAclService.createOrRetrieveSidPrimaryKey("Custom sid", + false, false)).thenReturn(1L); + + Long result = customJdbcMutableAclService.createOrRetrieveSidPrimaryKey( + customSid, false); + + assertEquals(result, new Long(1L)); + } + + /** + * This class needed to show how to extend {@link JdbcMutableAclService} for + * processing custom {@link Sid} implementations + */ + private class CustomJdbcMutableAclService extends JdbcMutableAclService { + + private CustomJdbcMutableAclService(DataSource dataSource, + LookupStrategy lookupStrategy, AclCache aclCache) { + super(dataSource, lookupStrategy, aclCache); + } + + @Override + protected Long createOrRetrieveSidPrimaryKey(Sid sid, boolean allowCreate) { + String sidName; + boolean isPrincipal = false; + if (sid instanceof CustomSid) { + sidName = ((CustomSid) sid).getSid(); + } + else if (sid instanceof GrantedAuthoritySid) { + sidName = ((GrantedAuthoritySid) sid).getGrantedAuthority(); + } + else { + sidName = ((PrincipalSid) sid).getPrincipal(); + isPrincipal = true; + } + return createOrRetrieveSidPrimaryKey(sidName, isPrincipal, allowCreate); + } + } } diff --git a/acl/src/test/java/org/springframework/security/acls/jdbc/SpringCacheBasedAclCacheTests.java b/acl/src/test/java/org/springframework/security/acls/jdbc/SpringCacheBasedAclCacheTests.java index 5b4338b5bb..9342cdfa6b 100644 --- a/acl/src/test/java/org/springframework/security/acls/jdbc/SpringCacheBasedAclCacheTests.java +++ b/acl/src/test/java/org/springframework/security/acls/jdbc/SpringCacheBasedAclCacheTests.java @@ -26,117 +26,131 @@ import static org.junit.Assert.*; * @author Marten Deinum */ public class SpringCacheBasedAclCacheTests { - private static final String TARGET_CLASS = "org.springframework.security.acls.TargetObject"; + private static final String TARGET_CLASS = "org.springframework.security.acls.TargetObject"; - private static CacheManager cacheManager; + private static CacheManager cacheManager; - @BeforeClass - public static void initCacheManaer() { - cacheManager = new ConcurrentMapCacheManager(); - // Use disk caching immediately (to test for serialization issue reported in SEC-527) - cacheManager.getCache("springcasebasedacltests"); - } + @BeforeClass + public static void initCacheManaer() { + cacheManager = new ConcurrentMapCacheManager(); + // Use disk caching immediately (to test for serialization issue reported in + // SEC-527) + cacheManager.getCache("springcasebasedacltests"); + } - @After - public void clearContext() { - SecurityContextHolder.clearContext(); - } + @After + public void clearContext() { + SecurityContextHolder.clearContext(); + } - private Cache getCache() { - Cache cache = cacheManager.getCache("springcasebasedacltests"); - cache.clear(); - return cache; - } + private Cache getCache() { + Cache cache = cacheManager.getCache("springcasebasedacltests"); + cache.clear(); + return cache; + } - @Test(expected=IllegalArgumentException.class) - public void constructorRejectsNullParameters() throws Exception { - new SpringCacheBasedAclCache(null, null, null); - } + @Test(expected = IllegalArgumentException.class) + public void constructorRejectsNullParameters() throws Exception { + new SpringCacheBasedAclCache(null, null, null); + } - @SuppressWarnings("rawtypes") - @Test - public void cacheOperationsAclWithoutParent() throws Exception { - Cache cache = getCache(); - Map realCache = (Map) cache.getNativeCache(); - ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, Long.valueOf(100)); - AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl( - new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority("ROLE_AUDITING"), - new SimpleGrantedAuthority("ROLE_GENERAL")); - AuditLogger auditLogger = new ConsoleAuditLogger(); + @SuppressWarnings("rawtypes") + @Test + public void cacheOperationsAclWithoutParent() throws Exception { + Cache cache = getCache(); + Map realCache = (Map) cache.getNativeCache(); + ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, Long.valueOf(100)); + AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl( + new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority( + "ROLE_AUDITING"), new SimpleGrantedAuthority("ROLE_GENERAL")); + AuditLogger auditLogger = new ConsoleAuditLogger(); - PermissionGrantingStrategy permissionGrantingStrategy = new DefaultPermissionGrantingStrategy(auditLogger); - SpringCacheBasedAclCache myCache = new SpringCacheBasedAclCache(cache, permissionGrantingStrategy, aclAuthorizationStrategy); - MutableAcl acl = new AclImpl(identity, Long.valueOf(1), aclAuthorizationStrategy, auditLogger); + PermissionGrantingStrategy permissionGrantingStrategy = new DefaultPermissionGrantingStrategy( + auditLogger); + SpringCacheBasedAclCache myCache = new SpringCacheBasedAclCache(cache, + permissionGrantingStrategy, aclAuthorizationStrategy); + MutableAcl acl = new AclImpl(identity, Long.valueOf(1), aclAuthorizationStrategy, + auditLogger); - assertEquals(0, realCache.size()); - myCache.putInCache(acl); + assertEquals(0, realCache.size()); + myCache.putInCache(acl); - // Check we can get from cache the same objects we put in - assertEquals(myCache.getFromCache(Long.valueOf(1)), acl); - assertEquals(myCache.getFromCache(identity), acl); + // Check we can get from cache the same objects we put in + assertEquals(myCache.getFromCache(Long.valueOf(1)), acl); + assertEquals(myCache.getFromCache(identity), acl); - // Put another object in cache - ObjectIdentity identity2 = new ObjectIdentityImpl(TARGET_CLASS, Long.valueOf(101)); - MutableAcl acl2 = new AclImpl(identity2, Long.valueOf(2), aclAuthorizationStrategy, new ConsoleAuditLogger()); + // Put another object in cache + ObjectIdentity identity2 = new ObjectIdentityImpl(TARGET_CLASS, Long.valueOf(101)); + MutableAcl acl2 = new AclImpl(identity2, Long.valueOf(2), + aclAuthorizationStrategy, new ConsoleAuditLogger()); - myCache.putInCache(acl2); + myCache.putInCache(acl2); - // Try to evict an entry that doesn't exist - myCache.evictFromCache(Long.valueOf(3)); - myCache.evictFromCache(new ObjectIdentityImpl(TARGET_CLASS, Long.valueOf(102))); - assertEquals(realCache.size(), 4); + // Try to evict an entry that doesn't exist + myCache.evictFromCache(Long.valueOf(3)); + myCache.evictFromCache(new ObjectIdentityImpl(TARGET_CLASS, Long.valueOf(102))); + assertEquals(realCache.size(), 4); - myCache.evictFromCache(Long.valueOf(1)); - assertEquals(realCache.size(), 2); + myCache.evictFromCache(Long.valueOf(1)); + assertEquals(realCache.size(), 2); - // Check the second object inserted - assertEquals(myCache.getFromCache(Long.valueOf(2)), acl2); - assertEquals(myCache.getFromCache(identity2), acl2); + // Check the second object inserted + assertEquals(myCache.getFromCache(Long.valueOf(2)), acl2); + assertEquals(myCache.getFromCache(identity2), acl2); - myCache.evictFromCache(identity2); - assertEquals(realCache.size(), 0); - } + myCache.evictFromCache(identity2); + assertEquals(realCache.size(), 0); + } - @SuppressWarnings("rawtypes") - @Test - public void cacheOperationsAclWithParent() throws Exception { - Cache cache = getCache(); - Map realCache = (Map) cache.getNativeCache(); + @SuppressWarnings("rawtypes") + @Test + public void cacheOperationsAclWithParent() throws Exception { + Cache cache = getCache(); + Map realCache = (Map) cache.getNativeCache(); - Authentication auth = new TestingAuthenticationToken("user", "password", "ROLE_GENERAL"); - auth.setAuthenticated(true); - SecurityContextHolder.getContext().setAuthentication(auth); + Authentication auth = new TestingAuthenticationToken("user", "password", + "ROLE_GENERAL"); + auth.setAuthenticated(true); + SecurityContextHolder.getContext().setAuthentication(auth); - ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, Long.valueOf(1)); - ObjectIdentity identityParent = new ObjectIdentityImpl(TARGET_CLASS, Long.valueOf(2)); - AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl( - new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority("ROLE_AUDITING"), - new SimpleGrantedAuthority("ROLE_GENERAL")); - AuditLogger auditLogger = new ConsoleAuditLogger(); + ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, Long.valueOf(1)); + ObjectIdentity identityParent = new ObjectIdentityImpl(TARGET_CLASS, + Long.valueOf(2)); + AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl( + new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority( + "ROLE_AUDITING"), new SimpleGrantedAuthority("ROLE_GENERAL")); + AuditLogger auditLogger = new ConsoleAuditLogger(); - PermissionGrantingStrategy permissionGrantingStrategy = new DefaultPermissionGrantingStrategy(auditLogger); - SpringCacheBasedAclCache myCache = new SpringCacheBasedAclCache(cache, permissionGrantingStrategy, aclAuthorizationStrategy); + PermissionGrantingStrategy permissionGrantingStrategy = new DefaultPermissionGrantingStrategy( + auditLogger); + SpringCacheBasedAclCache myCache = new SpringCacheBasedAclCache(cache, + permissionGrantingStrategy, aclAuthorizationStrategy); - MutableAcl acl = new AclImpl(identity, Long.valueOf(1), aclAuthorizationStrategy, auditLogger); - MutableAcl parentAcl = new AclImpl(identityParent, Long.valueOf(2), aclAuthorizationStrategy, auditLogger); + MutableAcl acl = new AclImpl(identity, Long.valueOf(1), aclAuthorizationStrategy, + auditLogger); + MutableAcl parentAcl = new AclImpl(identityParent, Long.valueOf(2), + aclAuthorizationStrategy, auditLogger); - acl.setParent(parentAcl); + acl.setParent(parentAcl); - assertEquals(0, realCache.size()); - myCache.putInCache(acl); - assertEquals(realCache.size(), 4); + assertEquals(0, realCache.size()); + myCache.putInCache(acl); + assertEquals(realCache.size(), 4); - // Check we can get from cache the same objects we put in - AclImpl aclFromCache = (AclImpl) myCache.getFromCache(Long.valueOf(1)); - assertEquals(acl, aclFromCache); - // SEC-951 check transient fields are set on parent - assertNotNull(FieldUtils.getFieldValue(aclFromCache.getParentAcl(), "aclAuthorizationStrategy")); - assertNotNull(FieldUtils.getFieldValue(aclFromCache.getParentAcl(), "permissionGrantingStrategy")); - assertEquals(acl, myCache.getFromCache(identity)); - assertNotNull(FieldUtils.getFieldValue(aclFromCache, "aclAuthorizationStrategy")); - AclImpl parentAclFromCache = (AclImpl) myCache.getFromCache(Long.valueOf(2)); - assertEquals(parentAcl, parentAclFromCache); - assertNotNull(FieldUtils.getFieldValue(parentAclFromCache, "aclAuthorizationStrategy")); - assertEquals(parentAcl, myCache.getFromCache(identityParent)); - } + // Check we can get from cache the same objects we put in + AclImpl aclFromCache = (AclImpl) myCache.getFromCache(Long.valueOf(1)); + assertEquals(acl, aclFromCache); + // SEC-951 check transient fields are set on parent + assertNotNull(FieldUtils.getFieldValue(aclFromCache.getParentAcl(), + "aclAuthorizationStrategy")); + assertNotNull(FieldUtils.getFieldValue(aclFromCache.getParentAcl(), + "permissionGrantingStrategy")); + assertEquals(acl, myCache.getFromCache(identity)); + assertNotNull(FieldUtils.getFieldValue(aclFromCache, "aclAuthorizationStrategy")); + AclImpl parentAclFromCache = (AclImpl) myCache.getFromCache(Long.valueOf(2)); + assertEquals(parentAcl, parentAclFromCache); + assertNotNull(FieldUtils.getFieldValue(parentAclFromCache, + "aclAuthorizationStrategy")); + assertEquals(parentAcl, myCache.getFromCache(identityParent)); + } } diff --git a/acl/src/test/java/org/springframework/security/acls/sid/CustomSid.java b/acl/src/test/java/org/springframework/security/acls/sid/CustomSid.java index 938f0c7d53..905e161a2e 100644 --- a/acl/src/test/java/org/springframework/security/acls/sid/CustomSid.java +++ b/acl/src/test/java/org/springframework/security/acls/sid/CustomSid.java @@ -8,17 +8,17 @@ import org.springframework.security.acls.model.Sid; */ public class CustomSid implements Sid { - private String sid; + private String sid; - public CustomSid(String sid) { - this.sid = sid; - } + public CustomSid(String sid) { + this.sid = sid; + } - public String getSid() { - return sid; - } + public String getSid() { + return sid; + } - public void setSid(String sid) { - this.sid = sid; - } + public void setSid(String sid) { + this.sid = sid; + } } diff --git a/acl/src/test/java/org/springframework/security/acls/sid/SidRetrievalStrategyTests.java b/acl/src/test/java/org/springframework/security/acls/sid/SidRetrievalStrategyTests.java index d4776f0a8d..dcd37e97fa 100644 --- a/acl/src/test/java/org/springframework/security/acls/sid/SidRetrievalStrategyTests.java +++ b/acl/src/test/java/org/springframework/security/acls/sid/SidRetrievalStrategyTests.java @@ -27,41 +27,44 @@ import org.springframework.security.core.authority.AuthorityUtils; */ @SuppressWarnings("unchecked") public class SidRetrievalStrategyTests { - Authentication authentication = new TestingAuthenticationToken("scott", "password", "A", "B", "C"); + Authentication authentication = new TestingAuthenticationToken("scott", "password", + "A", "B", "C"); - //~ Methods ======================================================================================================== + // ~ Methods + // ======================================================================================================== - @Test - public void correctSidsAreRetrieved() throws Exception { - SidRetrievalStrategy retrStrategy = new SidRetrievalStrategyImpl(); - List sids = retrStrategy.getSids(authentication); + @Test + public void correctSidsAreRetrieved() throws Exception { + SidRetrievalStrategy retrStrategy = new SidRetrievalStrategyImpl(); + List sids = retrStrategy.getSids(authentication); - assertNotNull(sids); - assertEquals(4, sids.size()); - assertNotNull(sids.get(0)); - assertTrue(sids.get(0) instanceof PrincipalSid); + assertNotNull(sids); + assertEquals(4, sids.size()); + assertNotNull(sids.get(0)); + assertTrue(sids.get(0) instanceof PrincipalSid); - for (int i = 1; i < sids.size(); i++) { - assertTrue(sids.get(i) instanceof GrantedAuthoritySid); - } + for (int i = 1; i < sids.size(); i++) { + assertTrue(sids.get(i) instanceof GrantedAuthoritySid); + } - assertEquals("scott", ((PrincipalSid) sids.get(0)).getPrincipal()); - assertEquals("A", ((GrantedAuthoritySid) sids.get(1)).getGrantedAuthority()); - assertEquals("B", ((GrantedAuthoritySid) sids.get(2)).getGrantedAuthority()); - assertEquals("C", ((GrantedAuthoritySid) sids.get(3)).getGrantedAuthority()); - } + assertEquals("scott", ((PrincipalSid) sids.get(0)).getPrincipal()); + assertEquals("A", ((GrantedAuthoritySid) sids.get(1)).getGrantedAuthority()); + assertEquals("B", ((GrantedAuthoritySid) sids.get(2)).getGrantedAuthority()); + assertEquals("C", ((GrantedAuthoritySid) sids.get(3)).getGrantedAuthority()); + } - @Test - public void roleHierarchyIsUsedWhenSet() throws Exception { - RoleHierarchy rh = mock(RoleHierarchy.class); - List rhAuthorities = AuthorityUtils.createAuthorityList("D"); - when(rh.getReachableGrantedAuthorities(anyCollection())).thenReturn(rhAuthorities); - SidRetrievalStrategy strat = new SidRetrievalStrategyImpl(rh); + @Test + public void roleHierarchyIsUsedWhenSet() throws Exception { + RoleHierarchy rh = mock(RoleHierarchy.class); + List rhAuthorities = AuthorityUtils.createAuthorityList("D"); + when(rh.getReachableGrantedAuthorities(anyCollection())) + .thenReturn(rhAuthorities); + SidRetrievalStrategy strat = new SidRetrievalStrategyImpl(rh); - List sids = strat.getSids(authentication); - assertEquals(2, sids.size()); - assertNotNull(sids.get(0)); - assertTrue(sids.get(0) instanceof PrincipalSid); - assertEquals("D", ((GrantedAuthoritySid) sids.get(1)).getGrantedAuthority()); - } + List sids = strat.getSids(authentication); + assertEquals(2, sids.size()); + assertNotNull(sids.get(0)); + assertTrue(sids.get(0) instanceof PrincipalSid); + assertEquals("D", ((GrantedAuthoritySid) sids.get(1)).getGrantedAuthority()); + } } diff --git a/acl/src/test/java/org/springframework/security/acls/sid/SidTests.java b/acl/src/test/java/org/springframework/security/acls/sid/SidTests.java index 7872d237c1..d0e7c0d233 100644 --- a/acl/src/test/java/org/springframework/security/acls/sid/SidTests.java +++ b/acl/src/test/java/org/springframework/security/acls/sid/SidTests.java @@ -12,178 +12,193 @@ import org.springframework.security.core.authority.SimpleGrantedAuthority; public class SidTests extends TestCase { - //~ Methods ======================================================================================================== + // ~ Methods + // ======================================================================================================== - public void testPrincipalSidConstructorsRequiredFields() throws Exception { - // Check one String-argument constructor - try { - String string = null; - new PrincipalSid(string); - Assert.fail("It should have thrown IllegalArgumentException"); - } - catch (IllegalArgumentException expected) { - Assert.assertTrue(true); - } + public void testPrincipalSidConstructorsRequiredFields() throws Exception { + // Check one String-argument constructor + try { + String string = null; + new PrincipalSid(string); + Assert.fail("It should have thrown IllegalArgumentException"); + } + catch (IllegalArgumentException expected) { + Assert.assertTrue(true); + } - try { - new PrincipalSid(""); - Assert.fail("It should have thrown IllegalArgumentException"); - } - catch (IllegalArgumentException expected) { - Assert.assertTrue(true); - } + try { + new PrincipalSid(""); + Assert.fail("It should have thrown IllegalArgumentException"); + } + catch (IllegalArgumentException expected) { + Assert.assertTrue(true); + } - try { - new PrincipalSid("johndoe"); - Assert.assertTrue(true); - } - catch (IllegalArgumentException notExpected) { - Assert.fail("It shouldn't have thrown IllegalArgumentException"); - } + try { + new PrincipalSid("johndoe"); + Assert.assertTrue(true); + } + catch (IllegalArgumentException notExpected) { + Assert.fail("It shouldn't have thrown IllegalArgumentException"); + } - // Check one Authentication-argument constructor - try { - Authentication authentication = null; - new PrincipalSid(authentication); - Assert.fail("It should have thrown IllegalArgumentException"); - } - catch (IllegalArgumentException expected) { - Assert.assertTrue(true); - } + // Check one Authentication-argument constructor + try { + Authentication authentication = null; + new PrincipalSid(authentication); + Assert.fail("It should have thrown IllegalArgumentException"); + } + catch (IllegalArgumentException expected) { + Assert.assertTrue(true); + } - try { - Authentication authentication = new TestingAuthenticationToken(null, "password"); - new PrincipalSid(authentication); - Assert.fail("It should have thrown IllegalArgumentException"); - } - catch (IllegalArgumentException expected) { - Assert.assertTrue(true); - } + try { + Authentication authentication = new TestingAuthenticationToken(null, + "password"); + new PrincipalSid(authentication); + Assert.fail("It should have thrown IllegalArgumentException"); + } + catch (IllegalArgumentException expected) { + Assert.assertTrue(true); + } - try { - Authentication authentication = new TestingAuthenticationToken("johndoe", "password"); - new PrincipalSid(authentication); - Assert.assertTrue(true); - } - catch (IllegalArgumentException notExpected) { - Assert.fail("It shouldn't have thrown IllegalArgumentException"); - } - } + try { + Authentication authentication = new TestingAuthenticationToken("johndoe", + "password"); + new PrincipalSid(authentication); + Assert.assertTrue(true); + } + catch (IllegalArgumentException notExpected) { + Assert.fail("It shouldn't have thrown IllegalArgumentException"); + } + } - public void testGrantedAuthoritySidConstructorsRequiredFields() throws Exception { - // Check one String-argument constructor - try { - String string = null; - new GrantedAuthoritySid(string); - Assert.fail("It should have thrown IllegalArgumentException"); - } - catch (IllegalArgumentException expected) { - Assert.assertTrue(true); - } + public void testGrantedAuthoritySidConstructorsRequiredFields() throws Exception { + // Check one String-argument constructor + try { + String string = null; + new GrantedAuthoritySid(string); + Assert.fail("It should have thrown IllegalArgumentException"); + } + catch (IllegalArgumentException expected) { + Assert.assertTrue(true); + } - try { - new GrantedAuthoritySid(""); - Assert.fail("It should have thrown IllegalArgumentException"); - } - catch (IllegalArgumentException expected) { - Assert.assertTrue(true); - } + try { + new GrantedAuthoritySid(""); + Assert.fail("It should have thrown IllegalArgumentException"); + } + catch (IllegalArgumentException expected) { + Assert.assertTrue(true); + } - try { - new GrantedAuthoritySid("ROLE_TEST"); - Assert.assertTrue(true); - } - catch (IllegalArgumentException notExpected) { - Assert.fail("It shouldn't have thrown IllegalArgumentException"); - } + try { + new GrantedAuthoritySid("ROLE_TEST"); + Assert.assertTrue(true); + } + catch (IllegalArgumentException notExpected) { + Assert.fail("It shouldn't have thrown IllegalArgumentException"); + } - // Check one GrantedAuthority-argument constructor - try { - GrantedAuthority ga = null; - new GrantedAuthoritySid(ga); - Assert.fail("It should have thrown IllegalArgumentException"); - } - catch (IllegalArgumentException expected) { - Assert.assertTrue(true); - } + // Check one GrantedAuthority-argument constructor + try { + GrantedAuthority ga = null; + new GrantedAuthoritySid(ga); + Assert.fail("It should have thrown IllegalArgumentException"); + } + catch (IllegalArgumentException expected) { + Assert.assertTrue(true); + } - try { - GrantedAuthority ga = new SimpleGrantedAuthority(null); - new GrantedAuthoritySid(ga); - Assert.fail("It should have thrown IllegalArgumentException"); - } - catch (IllegalArgumentException expected) { - Assert.assertTrue(true); - } + try { + GrantedAuthority ga = new SimpleGrantedAuthority(null); + new GrantedAuthoritySid(ga); + Assert.fail("It should have thrown IllegalArgumentException"); + } + catch (IllegalArgumentException expected) { + Assert.assertTrue(true); + } - try { - GrantedAuthority ga = new SimpleGrantedAuthority("ROLE_TEST"); - new GrantedAuthoritySid(ga); - Assert.assertTrue(true); - } - catch (IllegalArgumentException notExpected) { - Assert.fail("It shouldn't have thrown IllegalArgumentException"); - } - } + try { + GrantedAuthority ga = new SimpleGrantedAuthority("ROLE_TEST"); + new GrantedAuthoritySid(ga); + Assert.assertTrue(true); + } + catch (IllegalArgumentException notExpected) { + Assert.fail("It shouldn't have thrown IllegalArgumentException"); + } + } - public void testPrincipalSidEquals() throws Exception { - Authentication authentication = new TestingAuthenticationToken("johndoe", "password"); - Sid principalSid = new PrincipalSid(authentication); + public void testPrincipalSidEquals() throws Exception { + Authentication authentication = new TestingAuthenticationToken("johndoe", + "password"); + Sid principalSid = new PrincipalSid(authentication); - Assert.assertFalse(principalSid.equals(null)); - Assert.assertFalse(principalSid.equals("DIFFERENT_TYPE_OBJECT")); - Assert.assertTrue(principalSid.equals(principalSid)); - Assert.assertTrue(principalSid.equals(new PrincipalSid(authentication))); - Assert.assertTrue(principalSid.equals(new PrincipalSid(new TestingAuthenticationToken("johndoe", null)))); - Assert.assertFalse(principalSid.equals(new PrincipalSid(new TestingAuthenticationToken("scott", null)))); - Assert.assertTrue(principalSid.equals(new PrincipalSid("johndoe"))); - Assert.assertFalse(principalSid.equals(new PrincipalSid("scott"))); - } + Assert.assertFalse(principalSid.equals(null)); + Assert.assertFalse(principalSid.equals("DIFFERENT_TYPE_OBJECT")); + Assert.assertTrue(principalSid.equals(principalSid)); + Assert.assertTrue(principalSid.equals(new PrincipalSid(authentication))); + Assert.assertTrue(principalSid.equals(new PrincipalSid( + new TestingAuthenticationToken("johndoe", null)))); + Assert.assertFalse(principalSid.equals(new PrincipalSid( + new TestingAuthenticationToken("scott", null)))); + Assert.assertTrue(principalSid.equals(new PrincipalSid("johndoe"))); + Assert.assertFalse(principalSid.equals(new PrincipalSid("scott"))); + } - public void testGrantedAuthoritySidEquals() throws Exception { - GrantedAuthority ga = new SimpleGrantedAuthority("ROLE_TEST"); - Sid gaSid = new GrantedAuthoritySid(ga); + public void testGrantedAuthoritySidEquals() throws Exception { + GrantedAuthority ga = new SimpleGrantedAuthority("ROLE_TEST"); + Sid gaSid = new GrantedAuthoritySid(ga); - Assert.assertFalse(gaSid.equals(null)); - Assert.assertFalse(gaSid.equals("DIFFERENT_TYPE_OBJECT")); - Assert.assertTrue(gaSid.equals(gaSid)); - Assert.assertTrue(gaSid.equals(new GrantedAuthoritySid(ga))); - Assert.assertTrue(gaSid.equals(new GrantedAuthoritySid(new SimpleGrantedAuthority("ROLE_TEST")))); - Assert.assertFalse(gaSid.equals(new GrantedAuthoritySid(new SimpleGrantedAuthority("ROLE_NOT_EQUAL")))); - Assert.assertTrue(gaSid.equals(new GrantedAuthoritySid("ROLE_TEST"))); - Assert.assertFalse(gaSid.equals(new GrantedAuthoritySid("ROLE_NOT_EQUAL"))); - } + Assert.assertFalse(gaSid.equals(null)); + Assert.assertFalse(gaSid.equals("DIFFERENT_TYPE_OBJECT")); + Assert.assertTrue(gaSid.equals(gaSid)); + Assert.assertTrue(gaSid.equals(new GrantedAuthoritySid(ga))); + Assert.assertTrue(gaSid.equals(new GrantedAuthoritySid( + new SimpleGrantedAuthority("ROLE_TEST")))); + Assert.assertFalse(gaSid.equals(new GrantedAuthoritySid( + new SimpleGrantedAuthority("ROLE_NOT_EQUAL")))); + Assert.assertTrue(gaSid.equals(new GrantedAuthoritySid("ROLE_TEST"))); + Assert.assertFalse(gaSid.equals(new GrantedAuthoritySid("ROLE_NOT_EQUAL"))); + } - public void testPrincipalSidHashCode() throws Exception { - Authentication authentication = new TestingAuthenticationToken("johndoe", "password"); - Sid principalSid = new PrincipalSid(authentication); + public void testPrincipalSidHashCode() throws Exception { + Authentication authentication = new TestingAuthenticationToken("johndoe", + "password"); + Sid principalSid = new PrincipalSid(authentication); - Assert.assertTrue(principalSid.hashCode() == "johndoe".hashCode()); - Assert.assertTrue(principalSid.hashCode() == new PrincipalSid("johndoe").hashCode()); - Assert.assertTrue(principalSid.hashCode() != new PrincipalSid("scott").hashCode()); - Assert.assertTrue(principalSid.hashCode() != new PrincipalSid(new TestingAuthenticationToken("scott", "password")).hashCode()); - } + Assert.assertTrue(principalSid.hashCode() == "johndoe".hashCode()); + Assert.assertTrue(principalSid.hashCode() == new PrincipalSid("johndoe") + .hashCode()); + Assert.assertTrue(principalSid.hashCode() != new PrincipalSid("scott").hashCode()); + Assert.assertTrue(principalSid.hashCode() != new PrincipalSid( + new TestingAuthenticationToken("scott", "password")).hashCode()); + } - public void testGrantedAuthoritySidHashCode() throws Exception { - GrantedAuthority ga = new SimpleGrantedAuthority("ROLE_TEST"); - Sid gaSid = new GrantedAuthoritySid(ga); + public void testGrantedAuthoritySidHashCode() throws Exception { + GrantedAuthority ga = new SimpleGrantedAuthority("ROLE_TEST"); + Sid gaSid = new GrantedAuthoritySid(ga); - Assert.assertTrue(gaSid.hashCode() == "ROLE_TEST".hashCode()); - Assert.assertTrue(gaSid.hashCode() == new GrantedAuthoritySid("ROLE_TEST").hashCode()); - Assert.assertTrue(gaSid.hashCode() != new GrantedAuthoritySid("ROLE_TEST_2").hashCode()); - Assert.assertTrue(gaSid.hashCode() != new GrantedAuthoritySid(new SimpleGrantedAuthority("ROLE_TEST_2")).hashCode()); - } + Assert.assertTrue(gaSid.hashCode() == "ROLE_TEST".hashCode()); + Assert.assertTrue(gaSid.hashCode() == new GrantedAuthoritySid("ROLE_TEST") + .hashCode()); + Assert.assertTrue(gaSid.hashCode() != new GrantedAuthoritySid("ROLE_TEST_2") + .hashCode()); + Assert.assertTrue(gaSid.hashCode() != new GrantedAuthoritySid( + new SimpleGrantedAuthority("ROLE_TEST_2")).hashCode()); + } - public void testGetters() throws Exception { - Authentication authentication = new TestingAuthenticationToken("johndoe", "password"); - PrincipalSid principalSid = new PrincipalSid(authentication); - GrantedAuthority ga = new SimpleGrantedAuthority("ROLE_TEST"); - GrantedAuthoritySid gaSid = new GrantedAuthoritySid(ga); + public void testGetters() throws Exception { + Authentication authentication = new TestingAuthenticationToken("johndoe", + "password"); + PrincipalSid principalSid = new PrincipalSid(authentication); + GrantedAuthority ga = new SimpleGrantedAuthority("ROLE_TEST"); + GrantedAuthoritySid gaSid = new GrantedAuthoritySid(ga); - Assert.assertTrue("johndoe".equals(principalSid.getPrincipal())); - Assert.assertFalse("scott".equals(principalSid.getPrincipal())); + Assert.assertTrue("johndoe".equals(principalSid.getPrincipal())); + Assert.assertFalse("scott".equals(principalSid.getPrincipal())); - Assert.assertTrue("ROLE_TEST".equals(gaSid.getGrantedAuthority())); - Assert.assertFalse("ROLE_TEST2".equals(gaSid.getGrantedAuthority())); - } + Assert.assertTrue("ROLE_TEST".equals(gaSid.getGrantedAuthority())); + Assert.assertFalse("ROLE_TEST2".equals(gaSid.getGrantedAuthority())); + } } diff --git a/aspects/src/test/java/org/springframework/security/access/intercept/aspectj/aspect/AnnotationSecurityAspectTests.java b/aspects/src/test/java/org/springframework/security/access/intercept/aspectj/aspect/AnnotationSecurityAspectTests.java index 552e1c48dc..bce258a5f0 100644 --- a/aspects/src/test/java/org/springframework/security/access/intercept/aspectj/aspect/AnnotationSecurityAspectTests.java +++ b/aspects/src/test/java/org/springframework/security/access/intercept/aspectj/aspect/AnnotationSecurityAspectTests.java @@ -40,150 +40,160 @@ import org.springframework.security.core.context.SecurityContextHolder; * @since 3.0.3 */ public class AnnotationSecurityAspectTests { - private AffirmativeBased adm; - private @Mock AuthenticationManager authman; - private TestingAuthenticationToken anne = new TestingAuthenticationToken("anne", "", "ROLE_A"); -// private TestingAuthenticationToken bob = new TestingAuthenticationToken("bob", "", "ROLE_B"); - private AspectJMethodSecurityInterceptor interceptor; - private SecuredImpl secured = new SecuredImpl(); - private SecuredImplSubclass securedSub = new SecuredImplSubclass(); - private PrePostSecured prePostSecured = new PrePostSecured(); + private AffirmativeBased adm; + private @Mock AuthenticationManager authman; + private TestingAuthenticationToken anne = new TestingAuthenticationToken("anne", "", + "ROLE_A"); + // private TestingAuthenticationToken bob = new TestingAuthenticationToken("bob", "", + // "ROLE_B"); + private AspectJMethodSecurityInterceptor interceptor; + private SecuredImpl secured = new SecuredImpl(); + private SecuredImplSubclass securedSub = new SecuredImplSubclass(); + private PrePostSecured prePostSecured = new PrePostSecured(); - @Before - public final void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - interceptor = new AspectJMethodSecurityInterceptor(); - AccessDecisionVoter[] voters = new AccessDecisionVoter[] - {new RoleVoter(), new PreInvocationAuthorizationAdviceVoter(new ExpressionBasedPreInvocationAdvice())}; - adm = new AffirmativeBased(Arrays.>asList(voters)); - interceptor.setAccessDecisionManager(adm); - interceptor.setAuthenticationManager(authman); - interceptor.setSecurityMetadataSource(new SecuredAnnotationSecurityMetadataSource()); - AnnotationSecurityAspect secAspect = AnnotationSecurityAspect.aspectOf(); - secAspect.setSecurityInterceptor(interceptor); - } + @Before + public final void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + interceptor = new AspectJMethodSecurityInterceptor(); + AccessDecisionVoter[] voters = new AccessDecisionVoter[] { + new RoleVoter(), + new PreInvocationAuthorizationAdviceVoter( + new ExpressionBasedPreInvocationAdvice()) }; + adm = new AffirmativeBased( + Arrays.> asList(voters)); + interceptor.setAccessDecisionManager(adm); + interceptor.setAuthenticationManager(authman); + interceptor + .setSecurityMetadataSource(new SecuredAnnotationSecurityMetadataSource()); + AnnotationSecurityAspect secAspect = AnnotationSecurityAspect.aspectOf(); + secAspect.setSecurityInterceptor(interceptor); + } - @After - public void clearContext() { - SecurityContextHolder.clearContext(); - } + @After + public void clearContext() { + SecurityContextHolder.clearContext(); + } - @Test - public void securedInterfaceMethodAllowsAllAccess() throws Exception { - secured.securedMethod(); - } + @Test + public void securedInterfaceMethodAllowsAllAccess() throws Exception { + secured.securedMethod(); + } - @Test(expected=AuthenticationCredentialsNotFoundException.class) - public void securedClassMethodDeniesUnauthenticatedAccess() throws Exception { - secured.securedClassMethod(); - } + @Test(expected = AuthenticationCredentialsNotFoundException.class) + public void securedClassMethodDeniesUnauthenticatedAccess() throws Exception { + secured.securedClassMethod(); + } - @Test - public void securedClassMethodAllowsAccessToRoleA() throws Exception { - SecurityContextHolder.getContext().setAuthentication(anne); - secured.securedClassMethod(); - } + @Test + public void securedClassMethodAllowsAccessToRoleA() throws Exception { + SecurityContextHolder.getContext().setAuthentication(anne); + secured.securedClassMethod(); + } - @Test(expected=AccessDeniedException.class) - public void internalPrivateCallIsIntercepted() { - SecurityContextHolder.getContext().setAuthentication(anne); + @Test(expected = AccessDeniedException.class) + public void internalPrivateCallIsIntercepted() { + SecurityContextHolder.getContext().setAuthentication(anne); - try { - secured.publicCallsPrivate(); - fail("Expected AccessDeniedException"); - } catch (AccessDeniedException expected) { - } - securedSub.publicCallsPrivate(); - } + try { + secured.publicCallsPrivate(); + fail("Expected AccessDeniedException"); + } + catch (AccessDeniedException expected) { + } + securedSub.publicCallsPrivate(); + } - @Test(expected=AccessDeniedException.class) - public void protectedMethodIsIntercepted() throws Exception { - SecurityContextHolder.getContext().setAuthentication(anne); + @Test(expected = AccessDeniedException.class) + public void protectedMethodIsIntercepted() throws Exception { + SecurityContextHolder.getContext().setAuthentication(anne); - secured.protectedMethod(); - } + secured.protectedMethod(); + } - @Test - public void overriddenProtectedMethodIsNotIntercepted() throws Exception { - // AspectJ doesn't inherit annotations - securedSub.protectedMethod(); - } + @Test + public void overriddenProtectedMethodIsNotIntercepted() throws Exception { + // AspectJ doesn't inherit annotations + securedSub.protectedMethod(); + } - // SEC-1262 - @Test(expected=AccessDeniedException.class) - public void denyAllPreAuthorizeDeniesAccess() throws Exception { - configureForElAnnotations(); - SecurityContextHolder.getContext().setAuthentication(anne); - prePostSecured.denyAllMethod(); - } + // SEC-1262 + @Test(expected = AccessDeniedException.class) + public void denyAllPreAuthorizeDeniesAccess() throws Exception { + configureForElAnnotations(); + SecurityContextHolder.getContext().setAuthentication(anne); + prePostSecured.denyAllMethod(); + } - @Test - public void postFilterIsApplied() throws Exception { - configureForElAnnotations(); - SecurityContextHolder.getContext().setAuthentication(anne); - List objects = prePostSecured.postFilterMethod(); - assertEquals(2, objects.size()); - assertTrue(objects.contains("apple")); - assertTrue(objects.contains("aubergine")); - } + @Test + public void postFilterIsApplied() throws Exception { + configureForElAnnotations(); + SecurityContextHolder.getContext().setAuthentication(anne); + List objects = prePostSecured.postFilterMethod(); + assertEquals(2, objects.size()); + assertTrue(objects.contains("apple")); + assertTrue(objects.contains("aubergine")); + } - private void configureForElAnnotations() { - DefaultMethodSecurityExpressionHandler eh = new DefaultMethodSecurityExpressionHandler(); - interceptor.setSecurityMetadataSource(new PrePostAnnotationSecurityMetadataSource( - new ExpressionBasedAnnotationAttributeFactory(eh))); - interceptor.setAccessDecisionManager(adm); - AfterInvocationProviderManager aim = new AfterInvocationProviderManager(); - aim.setProviders(Arrays.asList(new PostInvocationAdviceProvider(new ExpressionBasedPostInvocationAdvice(eh)))); - interceptor.setAfterInvocationManager(aim); - } + private void configureForElAnnotations() { + DefaultMethodSecurityExpressionHandler eh = new DefaultMethodSecurityExpressionHandler(); + interceptor + .setSecurityMetadataSource(new PrePostAnnotationSecurityMetadataSource( + new ExpressionBasedAnnotationAttributeFactory(eh))); + interceptor.setAccessDecisionManager(adm); + AfterInvocationProviderManager aim = new AfterInvocationProviderManager(); + aim.setProviders(Arrays.asList(new PostInvocationAdviceProvider( + new ExpressionBasedPostInvocationAdvice(eh)))); + interceptor.setAfterInvocationManager(aim); + } } interface SecuredInterface { - @Secured("ROLE_X") - void securedMethod(); + @Secured("ROLE_X") + void securedMethod(); } class SecuredImpl implements SecuredInterface { - // Not really secured because AspectJ doesn't inherit annotations from interfaces - public void securedMethod() { - } + // Not really secured because AspectJ doesn't inherit annotations from interfaces + public void securedMethod() { + } - @Secured("ROLE_A") - public void securedClassMethod() { - } + @Secured("ROLE_A") + public void securedClassMethod() { + } - @Secured("ROLE_X") - private void privateMethod() { - } + @Secured("ROLE_X") + private void privateMethod() { + } - @Secured("ROLE_X") - protected void protectedMethod() { - } + @Secured("ROLE_X") + protected void protectedMethod() { + } - @Secured("ROLE_X") - public void publicCallsPrivate() { - privateMethod(); - } + @Secured("ROLE_X") + public void publicCallsPrivate() { + privateMethod(); + } } class SecuredImplSubclass extends SecuredImpl { - protected void protectedMethod() { - } + protected void protectedMethod() { + } - public void publicCallsPrivate() { - super.publicCallsPrivate(); - } + public void publicCallsPrivate() { + super.publicCallsPrivate(); + } } class PrePostSecured { - @PreAuthorize("denyAll") - public void denyAllMethod() { - } + @PreAuthorize("denyAll") + public void denyAllMethod() { + } - @PostFilter("filterObject.startsWith('a')") - public List postFilterMethod() { - ArrayList objects = new ArrayList(); - objects.addAll(Arrays.asList(new String[] {"apple", "banana", "aubergine", "orange"})); - return objects; - } + @PostFilter("filterObject.startsWith('a')") + public List postFilterMethod() { + ArrayList objects = new ArrayList(); + objects.addAll(Arrays.asList(new String[] { "apple", "banana", "aubergine", + "orange" })); + return objects; + } } diff --git a/cas/src/main/java/org/springframework/security/cas/SamlServiceProperties.java b/cas/src/main/java/org/springframework/security/cas/SamlServiceProperties.java index 15ead68d8d..e3e9599201 100644 --- a/cas/src/main/java/org/springframework/security/cas/SamlServiceProperties.java +++ b/cas/src/main/java/org/springframework/security/cas/SamlServiceProperties.java @@ -15,19 +15,20 @@ package org.springframework.security.cas; /** - * Sets the appropriate parameters for CAS's implementation of SAML (which is not guaranteed to be actually SAML compliant). + * Sets the appropriate parameters for CAS's implementation of SAML (which is not + * guaranteed to be actually SAML compliant). * * @author Scott Battaglia * @since 3.0 */ public final class SamlServiceProperties extends ServiceProperties { - public static final String DEFAULT_SAML_ARTIFACT_PARAMETER = "SAMLart"; + public static final String DEFAULT_SAML_ARTIFACT_PARAMETER = "SAMLart"; - public static final String DEFAULT_SAML_SERVICE_PARAMETER = "TARGET"; + public static final String DEFAULT_SAML_SERVICE_PARAMETER = "TARGET"; - public SamlServiceProperties() { - super.setArtifactParameter(DEFAULT_SAML_ARTIFACT_PARAMETER); - super.setServiceParameter(DEFAULT_SAML_SERVICE_PARAMETER); - } + public SamlServiceProperties() { + super.setArtifactParameter(DEFAULT_SAML_ARTIFACT_PARAMETER); + super.setServiceParameter(DEFAULT_SAML_SERVICE_PARAMETER); + } } diff --git a/cas/src/main/java/org/springframework/security/cas/ServiceProperties.java b/cas/src/main/java/org/springframework/security/cas/ServiceProperties.java index 13e706b477..bb0de24393 100644 --- a/cas/src/main/java/org/springframework/security/cas/ServiceProperties.java +++ b/cas/src/main/java/org/springframework/security/cas/ServiceProperties.java @@ -18,118 +18,123 @@ package org.springframework.security.cas; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; - /** * Stores properties related to this CAS service. *

- * Each web application capable of processing CAS tickets is known as a service. - * This class stores the properties that are relevant to the local CAS service, being the application - * that is being secured by Spring Security. + * Each web application capable of processing CAS tickets is known as a service. This + * class stores the properties that are relevant to the local CAS service, being the + * application that is being secured by Spring Security. * * @author Ben Alex */ public class ServiceProperties implements InitializingBean { - public static final String DEFAULT_CAS_ARTIFACT_PARAMETER = "ticket"; + public static final String DEFAULT_CAS_ARTIFACT_PARAMETER = "ticket"; - public static final String DEFAULT_CAS_SERVICE_PARAMETER = "service"; + public static final String DEFAULT_CAS_SERVICE_PARAMETER = "service"; - //~ Instance fields ================================================================================================ + // ~ Instance fields + // ================================================================================================ - private String service; + private String service; - private boolean authenticateAllArtifacts; + private boolean authenticateAllArtifacts; - private boolean sendRenew = false; + private boolean sendRenew = false; - private String artifactParameter = DEFAULT_CAS_ARTIFACT_PARAMETER; + private String artifactParameter = DEFAULT_CAS_ARTIFACT_PARAMETER; - private String serviceParameter = DEFAULT_CAS_SERVICE_PARAMETER; + private String serviceParameter = DEFAULT_CAS_SERVICE_PARAMETER; - //~ Methods ======================================================================================================== + // ~ Methods + // ======================================================================================================== - public void afterPropertiesSet() throws Exception { - Assert.hasLength(this.service, "service cannot be empty."); - Assert.hasLength(this.artifactParameter, "artifactParameter cannot be empty."); - Assert.hasLength(this.serviceParameter, "serviceParameter cannot be empty."); - } + public void afterPropertiesSet() throws Exception { + Assert.hasLength(this.service, "service cannot be empty."); + Assert.hasLength(this.artifactParameter, "artifactParameter cannot be empty."); + Assert.hasLength(this.serviceParameter, "serviceParameter cannot be empty."); + } - /** - * Represents the service the user is authenticating to. - *

- * This service is the callback URL belonging to the local Spring Security System for Spring secured application. - * For example, - *

-     * https://www.mycompany.com/application/login/cas
-     * 
- * - * @return the URL of the service the user is authenticating to - */ - public final String getService() { - return this.service; - } + /** + * Represents the service the user is authenticating to. + *

+ * This service is the callback URL belonging to the local Spring Security System for + * Spring secured application. For example, + * + *

+	 * https://www.mycompany.com/application/login/cas
+	 * 
+ * + * @return the URL of the service the user is authenticating to + */ + public final String getService() { + return this.service; + } - /** - * Indicates whether the renew parameter should be sent to the CAS login URL and CAS - * validation URL. - *

- * If true, it will force CAS to authenticate the user again (even if the - * user has previously authenticated). During ticket validation it will require the ticket was generated as a - * consequence of an explicit login. High security applications would probably set this to true. - * Defaults to false, providing automated single sign on. - * - * @return whether to send the renew parameter to CAS - */ - public final boolean isSendRenew() { - return this.sendRenew; - } + /** + * Indicates whether the renew parameter should be sent to the CAS login + * URL and CAS validation URL. + *

+ * If true, it will force CAS to authenticate the user again (even if the + * user has previously authenticated). During ticket validation it will require the + * ticket was generated as a consequence of an explicit login. High security + * applications would probably set this to true. Defaults to + * false, providing automated single sign on. + * + * @return whether to send the renew parameter to CAS + */ + public final boolean isSendRenew() { + return this.sendRenew; + } - public final void setSendRenew(final boolean sendRenew) { - this.sendRenew = sendRenew; - } + public final void setSendRenew(final boolean sendRenew) { + this.sendRenew = sendRenew; + } - public final void setService(final String service) { - this.service = service; - } + public final void setService(final String service) { + this.service = service; + } - public final String getArtifactParameter() { - return this.artifactParameter; - } + public final String getArtifactParameter() { + return this.artifactParameter; + } - /** - * Configures the Request Parameter to look for when attempting to see if a CAS ticket was sent from the server. - * - * @param artifactParameter the id to use. Default is "ticket". - */ - public final void setArtifactParameter(final String artifactParameter) { - this.artifactParameter = artifactParameter; - } + /** + * Configures the Request Parameter to look for when attempting to see if a CAS ticket + * was sent from the server. + * + * @param artifactParameter the id to use. Default is "ticket". + */ + public final void setArtifactParameter(final String artifactParameter) { + this.artifactParameter = artifactParameter; + } - /** - * Configures the Request parameter to look for when attempting to send a request to CAS. - * - * @return the service parameter to use. Default is "service". - */ - public final String getServiceParameter() { - return serviceParameter; - } + /** + * Configures the Request parameter to look for when attempting to send a request to + * CAS. + * + * @return the service parameter to use. Default is "service". + */ + public final String getServiceParameter() { + return serviceParameter; + } - public final void setServiceParameter(final String serviceParameter) { - this.serviceParameter = serviceParameter; - } + public final void setServiceParameter(final String serviceParameter) { + this.serviceParameter = serviceParameter; + } - public final boolean isAuthenticateAllArtifacts() { - return authenticateAllArtifacts; - } + public final boolean isAuthenticateAllArtifacts() { + return authenticateAllArtifacts; + } - /** - * If true, then any non-null artifact (ticket) should be authenticated. - * Additionally, the service will be determined dynamically in order to - * ensure the service matches the expected value for this artifact. - * - * @param authenticateAllArtifacts - */ - public final void setAuthenticateAllArtifacts(final boolean authenticateAllArtifacts) { - this.authenticateAllArtifacts = authenticateAllArtifacts; - } + /** + * If true, then any non-null artifact (ticket) should be authenticated. Additionally, + * the service will be determined dynamically in order to ensure the service matches + * the expected value for this artifact. + * + * @param authenticateAllArtifacts + */ + public final void setAuthenticateAllArtifacts(final boolean authenticateAllArtifacts) { + this.authenticateAllArtifacts = authenticateAllArtifacts; + } } diff --git a/cas/src/main/java/org/springframework/security/cas/authentication/CasAssertionAuthenticationToken.java b/cas/src/main/java/org/springframework/security/cas/authentication/CasAssertionAuthenticationToken.java index 37eb15c2ba..57b9b41f43 100644 --- a/cas/src/main/java/org/springframework/security/cas/authentication/CasAssertionAuthenticationToken.java +++ b/cas/src/main/java/org/springframework/security/cas/authentication/CasAssertionAuthenticationToken.java @@ -29,28 +29,28 @@ import org.springframework.security.core.SpringSecurityCoreVersion; */ public final class CasAssertionAuthenticationToken extends AbstractAuthenticationToken { - private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; + private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; - private final Assertion assertion; + private final Assertion assertion; - private final String ticket; + private final String ticket; - public CasAssertionAuthenticationToken(final Assertion assertion, final String ticket) { - super(new ArrayList()); + public CasAssertionAuthenticationToken(final Assertion assertion, final String ticket) { + super(new ArrayList()); - this.assertion = assertion; - this.ticket = ticket; - } + this.assertion = assertion; + this.ticket = ticket; + } - public Object getPrincipal() { - return this.assertion.getPrincipal().getName(); - } + public Object getPrincipal() { + return this.assertion.getPrincipal().getName(); + } - public Object getCredentials() { - return this.ticket; - } + public Object getCredentials() { + return this.ticket; + } - public Assertion getAssertion() { - return this.assertion; - } + public Assertion getAssertion() { + return this.assertion; + } } diff --git a/cas/src/main/java/org/springframework/security/cas/authentication/CasAuthenticationProvider.java b/cas/src/main/java/org/springframework/security/cas/authentication/CasAuthenticationProvider.java index b166fc582e..9e498763b8 100644 --- a/cas/src/main/java/org/springframework/security/cas/authentication/CasAuthenticationProvider.java +++ b/cas/src/main/java/org/springframework/security/cas/authentication/CasAuthenticationProvider.java @@ -39,204 +39,236 @@ import org.springframework.security.core.authority.mapping.NullAuthoritiesMapper import org.springframework.security.core.userdetails.*; import org.springframework.util.Assert; - /** - * An {@link AuthenticationProvider} implementation that integrates with JA-SIG Central Authentication Service - * (CAS). + * An {@link AuthenticationProvider} implementation that integrates with JA-SIG Central + * Authentication Service (CAS). *

- * This AuthenticationProvider is capable of validating {@link UsernamePasswordAuthenticationToken} - * requests which contain a principal name equal to either - * {@link CasAuthenticationFilter#CAS_STATEFUL_IDENTIFIER} or {@link CasAuthenticationFilter#CAS_STATELESS_IDENTIFIER}. - * It can also validate a previously created {@link CasAuthenticationToken}. + * This AuthenticationProvider is capable of validating + * {@link UsernamePasswordAuthenticationToken} requests which contain a + * principal name equal to either + * {@link CasAuthenticationFilter#CAS_STATEFUL_IDENTIFIER} or + * {@link CasAuthenticationFilter#CAS_STATELESS_IDENTIFIER}. It can also validate a + * previously created {@link CasAuthenticationToken}. * * @author Ben Alex * @author Scott Battaglia */ -public class CasAuthenticationProvider implements AuthenticationProvider, InitializingBean, MessageSourceAware { - //~ Static fields/initializers ===================================================================================== +public class CasAuthenticationProvider implements AuthenticationProvider, + InitializingBean, MessageSourceAware { + // ~ Static fields/initializers + // ===================================================================================== - private static final Log logger = LogFactory.getLog(CasAuthenticationProvider.class); + private static final Log logger = LogFactory.getLog(CasAuthenticationProvider.class); - //~ Instance fields ================================================================================================ + // ~ Instance fields + // ================================================================================================ - private AuthenticationUserDetailsService authenticationUserDetailsService; + private AuthenticationUserDetailsService authenticationUserDetailsService; - private final UserDetailsChecker userDetailsChecker = new AccountStatusUserDetailsChecker(); - protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor(); - private StatelessTicketCache statelessTicketCache = new NullStatelessTicketCache(); - private String key; - private TicketValidator ticketValidator; - private ServiceProperties serviceProperties; - private GrantedAuthoritiesMapper authoritiesMapper = new NullAuthoritiesMapper(); + private final UserDetailsChecker userDetailsChecker = new AccountStatusUserDetailsChecker(); + protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor(); + private StatelessTicketCache statelessTicketCache = new NullStatelessTicketCache(); + private String key; + private TicketValidator ticketValidator; + private ServiceProperties serviceProperties; + private GrantedAuthoritiesMapper authoritiesMapper = new NullAuthoritiesMapper(); + // ~ Methods + // ======================================================================================================== - //~ Methods ======================================================================================================== + public void afterPropertiesSet() throws Exception { + Assert.notNull(this.authenticationUserDetailsService, + "An authenticationUserDetailsService must be set"); + Assert.notNull(this.ticketValidator, "A ticketValidator must be set"); + Assert.notNull(this.statelessTicketCache, "A statelessTicketCache must be set"); + Assert.hasText( + this.key, + "A Key is required so CasAuthenticationProvider can identify tokens it previously authenticated"); + Assert.notNull(this.messages, "A message source must be set"); + } - public void afterPropertiesSet() throws Exception { - Assert.notNull(this.authenticationUserDetailsService, "An authenticationUserDetailsService must be set"); - Assert.notNull(this.ticketValidator, "A ticketValidator must be set"); - Assert.notNull(this.statelessTicketCache, "A statelessTicketCache must be set"); - Assert.hasText(this.key, "A Key is required so CasAuthenticationProvider can identify tokens it previously authenticated"); - Assert.notNull(this.messages, "A message source must be set"); - } + public Authentication authenticate(Authentication authentication) + throws AuthenticationException { + if (!supports(authentication.getClass())) { + return null; + } - public Authentication authenticate(Authentication authentication) throws AuthenticationException { - if (!supports(authentication.getClass())) { - return null; - } + if (authentication instanceof UsernamePasswordAuthenticationToken + && (!CasAuthenticationFilter.CAS_STATEFUL_IDENTIFIER + .equals(authentication.getPrincipal().toString()) && !CasAuthenticationFilter.CAS_STATELESS_IDENTIFIER + .equals(authentication.getPrincipal().toString()))) { + // UsernamePasswordAuthenticationToken not CAS related + return null; + } - if (authentication instanceof UsernamePasswordAuthenticationToken - && (!CasAuthenticationFilter.CAS_STATEFUL_IDENTIFIER.equals(authentication.getPrincipal().toString()) - && !CasAuthenticationFilter.CAS_STATELESS_IDENTIFIER.equals(authentication.getPrincipal().toString()))) { - // UsernamePasswordAuthenticationToken not CAS related - return null; - } + // If an existing CasAuthenticationToken, just check we created it + if (authentication instanceof CasAuthenticationToken) { + if (this.key.hashCode() == ((CasAuthenticationToken) authentication) + .getKeyHash()) { + return authentication; + } + else { + throw new BadCredentialsException( + messages.getMessage("CasAuthenticationProvider.incorrectKey", + "The presented CasAuthenticationToken does not contain the expected key")); + } + } - // If an existing CasAuthenticationToken, just check we created it - if (authentication instanceof CasAuthenticationToken) { - if (this.key.hashCode() == ((CasAuthenticationToken) authentication).getKeyHash()) { - return authentication; - } else { - throw new BadCredentialsException(messages.getMessage("CasAuthenticationProvider.incorrectKey", - "The presented CasAuthenticationToken does not contain the expected key")); - } - } + // Ensure credentials are presented + if ((authentication.getCredentials() == null) + || "".equals(authentication.getCredentials())) { + throw new BadCredentialsException(messages.getMessage( + "CasAuthenticationProvider.noServiceTicket", + "Failed to provide a CAS service ticket to validate")); + } - // Ensure credentials are presented - if ((authentication.getCredentials() == null) || "".equals(authentication.getCredentials())) { - throw new BadCredentialsException(messages.getMessage("CasAuthenticationProvider.noServiceTicket", - "Failed to provide a CAS service ticket to validate")); - } + boolean stateless = false; - boolean stateless = false; + if (authentication instanceof UsernamePasswordAuthenticationToken + && CasAuthenticationFilter.CAS_STATELESS_IDENTIFIER.equals(authentication + .getPrincipal())) { + stateless = true; + } - if (authentication instanceof UsernamePasswordAuthenticationToken - && CasAuthenticationFilter.CAS_STATELESS_IDENTIFIER.equals(authentication.getPrincipal())) { - stateless = true; - } + CasAuthenticationToken result = null; - CasAuthenticationToken result = null; + if (stateless) { + // Try to obtain from cache + result = statelessTicketCache.getByTicketId(authentication.getCredentials() + .toString()); + } - if (stateless) { - // Try to obtain from cache - result = statelessTicketCache.getByTicketId(authentication.getCredentials().toString()); - } + if (result == null) { + result = this.authenticateNow(authentication); + result.setDetails(authentication.getDetails()); + } - if (result == null) { - result = this.authenticateNow(authentication); - result.setDetails(authentication.getDetails()); - } + if (stateless) { + // Add to cache + statelessTicketCache.putTicketInCache(result); + } - if (stateless) { - // Add to cache - statelessTicketCache.putTicketInCache(result); - } + return result; + } - return result; - } + private CasAuthenticationToken authenticateNow(final Authentication authentication) + throws AuthenticationException { + try { + final Assertion assertion = this.ticketValidator.validate(authentication + .getCredentials().toString(), getServiceUrl(authentication)); + final UserDetails userDetails = loadUserByAssertion(assertion); + userDetailsChecker.check(userDetails); + return new CasAuthenticationToken(this.key, userDetails, + authentication.getCredentials(), + authoritiesMapper.mapAuthorities(userDetails.getAuthorities()), + userDetails, assertion); + } + catch (final TicketValidationException e) { + throw new BadCredentialsException(e.getMessage(), e); + } + } - private CasAuthenticationToken authenticateNow(final Authentication authentication) throws AuthenticationException { - try { - final Assertion assertion = this.ticketValidator.validate(authentication.getCredentials().toString(), getServiceUrl(authentication)); - final UserDetails userDetails = loadUserByAssertion(assertion); - userDetailsChecker.check(userDetails); - return new CasAuthenticationToken(this.key, userDetails, authentication.getCredentials(), - authoritiesMapper.mapAuthorities(userDetails.getAuthorities()), userDetails, assertion); - } catch (final TicketValidationException e) { - throw new BadCredentialsException(e.getMessage(), e); - } - } + /** + * Gets the serviceUrl. If the {@link Authentication#getDetails()} is an instance of + * {@link ServiceAuthenticationDetails}, then + * {@link ServiceAuthenticationDetails#getServiceUrl()} is used. Otherwise, the + * {@link ServiceProperties#getService()} is used. + * + * @param authentication + * @return + */ + private String getServiceUrl(Authentication authentication) { + String serviceUrl; + if (authentication.getDetails() instanceof ServiceAuthenticationDetails) { + serviceUrl = ((ServiceAuthenticationDetails) authentication.getDetails()) + .getServiceUrl(); + } + else if (serviceProperties == null) { + throw new IllegalStateException( + "serviceProperties cannot be null unless Authentication.getDetails() implements ServiceAuthenticationDetails."); + } + else if (serviceProperties.getService() == null) { + throw new IllegalStateException( + "serviceProperties.getService() cannot be null unless Authentication.getDetails() implements ServiceAuthenticationDetails."); + } + else { + serviceUrl = serviceProperties.getService(); + } + if (logger.isDebugEnabled()) { + logger.debug("serviceUrl = " + serviceUrl); + } + return serviceUrl; + } - /** - * Gets the serviceUrl. If the {@link Authentication#getDetails()} is an - * instance of {@link ServiceAuthenticationDetails}, then - * {@link ServiceAuthenticationDetails#getServiceUrl()} is used. Otherwise, - * the {@link ServiceProperties#getService()} is used. - * - * @param authentication - * @return - */ - private String getServiceUrl(Authentication authentication) { - String serviceUrl; - if(authentication.getDetails() instanceof ServiceAuthenticationDetails) { - serviceUrl = ((ServiceAuthenticationDetails)authentication.getDetails()).getServiceUrl(); - }else if(serviceProperties == null){ - throw new IllegalStateException("serviceProperties cannot be null unless Authentication.getDetails() implements ServiceAuthenticationDetails."); - }else if(serviceProperties.getService() == null){ - throw new IllegalStateException("serviceProperties.getService() cannot be null unless Authentication.getDetails() implements ServiceAuthenticationDetails."); - }else { - serviceUrl = serviceProperties.getService(); - } - if(logger.isDebugEnabled()) { - logger.debug("serviceUrl = "+serviceUrl); - } - return serviceUrl; - } + /** + * Template method for retrieving the UserDetails based on the assertion. Default is + * to call configured userDetailsService and pass the username. Deployers can override + * this method and retrieve the user based on any criteria they desire. + * + * @param assertion The CAS Assertion. + * @return the UserDetails. + */ + protected UserDetails loadUserByAssertion(final Assertion assertion) { + final CasAssertionAuthenticationToken token = new CasAssertionAuthenticationToken( + assertion, ""); + return this.authenticationUserDetailsService.loadUserDetails(token); + } - /** - * Template method for retrieving the UserDetails based on the assertion. Default is to call configured userDetailsService and pass the username. Deployers - * can override this method and retrieve the user based on any criteria they desire. - * - * @param assertion The CAS Assertion. - * @return the UserDetails. - */ - protected UserDetails loadUserByAssertion(final Assertion assertion) { - final CasAssertionAuthenticationToken token = new CasAssertionAuthenticationToken(assertion, ""); - return this.authenticationUserDetailsService.loadUserDetails(token); - } + @SuppressWarnings("unchecked") + /** + * Sets the UserDetailsService to use. This is a convenience method to invoke + */ + public void setUserDetailsService(final UserDetailsService userDetailsService) { + this.authenticationUserDetailsService = new UserDetailsByNameServiceWrapper( + userDetailsService); + } - @SuppressWarnings("unchecked") - /** - * Sets the UserDetailsService to use. This is a convenience method to invoke - */ - public void setUserDetailsService(final UserDetailsService userDetailsService) { - this.authenticationUserDetailsService = new UserDetailsByNameServiceWrapper(userDetailsService); - } + public void setAuthenticationUserDetailsService( + final AuthenticationUserDetailsService authenticationUserDetailsService) { + this.authenticationUserDetailsService = authenticationUserDetailsService; + } + public void setServiceProperties(final ServiceProperties serviceProperties) { + this.serviceProperties = serviceProperties; + } - public void setAuthenticationUserDetailsService(final AuthenticationUserDetailsService authenticationUserDetailsService) { - this.authenticationUserDetailsService = authenticationUserDetailsService; - } + protected String getKey() { + return key; + } - public void setServiceProperties(final ServiceProperties serviceProperties) { - this.serviceProperties = serviceProperties; - } + public void setKey(String key) { + this.key = key; + } - protected String getKey() { - return key; - } + public StatelessTicketCache getStatelessTicketCache() { + return statelessTicketCache; + } - public void setKey(String key) { - this.key = key; - } + protected TicketValidator getTicketValidator() { + return ticketValidator; + } - public StatelessTicketCache getStatelessTicketCache() { - return statelessTicketCache; - } + public void setMessageSource(final MessageSource messageSource) { + this.messages = new MessageSourceAccessor(messageSource); + } - protected TicketValidator getTicketValidator() { - return ticketValidator; - } + public void setStatelessTicketCache(final StatelessTicketCache statelessTicketCache) { + this.statelessTicketCache = statelessTicketCache; + } - public void setMessageSource(final MessageSource messageSource) { - this.messages = new MessageSourceAccessor(messageSource); - } + public void setTicketValidator(final TicketValidator ticketValidator) { + this.ticketValidator = ticketValidator; + } - public void setStatelessTicketCache(final StatelessTicketCache statelessTicketCache) { - this.statelessTicketCache = statelessTicketCache; - } + public void setAuthoritiesMapper(GrantedAuthoritiesMapper authoritiesMapper) { + this.authoritiesMapper = authoritiesMapper; + } - public void setTicketValidator(final TicketValidator ticketValidator) { - this.ticketValidator = ticketValidator; - } - - public void setAuthoritiesMapper(GrantedAuthoritiesMapper authoritiesMapper) { - this.authoritiesMapper = authoritiesMapper; - } - - public boolean supports(final Class authentication) { - return (UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication)) || - (CasAuthenticationToken.class.isAssignableFrom(authentication)) || - (CasAssertionAuthenticationToken.class.isAssignableFrom(authentication)); - } + public boolean supports(final Class authentication) { + return (UsernamePasswordAuthenticationToken.class + .isAssignableFrom(authentication)) + || (CasAuthenticationToken.class.isAssignableFrom(authentication)) + || (CasAssertionAuthenticationToken.class + .isAssignableFrom(authentication)); + } } diff --git a/cas/src/main/java/org/springframework/security/cas/authentication/CasAuthenticationToken.java b/cas/src/main/java/org/springframework/security/cas/authentication/CasAuthenticationToken.java index ffa7897809..2aa93587bb 100644 --- a/cas/src/main/java/org/springframework/security/cas/authentication/CasAuthenticationToken.java +++ b/cas/src/main/java/org/springframework/security/cas/authentication/CasAuthenticationToken.java @@ -30,103 +30,114 @@ import org.springframework.security.core.userdetails.UserDetails; * @author Ben Alex * @author Scott Battaglia */ -public class CasAuthenticationToken extends AbstractAuthenticationToken implements Serializable { +public class CasAuthenticationToken extends AbstractAuthenticationToken implements + Serializable { - private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; + private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; - //~ Instance fields ================================================================================================ - private final Object credentials; - private final Object principal; - private final UserDetails userDetails; - private final int keyHash; - private final Assertion assertion; + // ~ Instance fields + // ================================================================================================ + private final Object credentials; + private final Object principal; + private final UserDetails userDetails; + private final int keyHash; + private final Assertion assertion; - //~ Constructors =================================================================================================== + // ~ Constructors + // =================================================================================================== - /** - * Constructor. - * - * @param key to identify if this object made by a given {@link - * CasAuthenticationProvider} - * @param principal typically the UserDetails object (cannot be null) - * @param credentials the service/proxy ticket ID from CAS (cannot be - * null) - * @param authorities the authorities granted to the user (from the {@link - * org.springframework.security.core.userdetails.UserDetailsService}) (cannot be null) - * @param userDetails the user details (from the {@link - * org.springframework.security.core.userdetails.UserDetailsService}) (cannot be null) - * @param assertion the assertion returned from the CAS servers. It contains the principal and how to obtain a - * proxy ticket for the user. - * - * @throws IllegalArgumentException if a null was passed - */ - public CasAuthenticationToken(final String key, final Object principal, final Object credentials, - final Collection authorities, final UserDetails userDetails, final Assertion assertion) { - super(authorities); + /** + * Constructor. + * + * @param key to identify if this object made by a given + * {@link CasAuthenticationProvider} + * @param principal typically the UserDetails object (cannot be null) + * @param credentials the service/proxy ticket ID from CAS (cannot be + * null) + * @param authorities the authorities granted to the user (from the + * {@link org.springframework.security.core.userdetails.UserDetailsService}) (cannot + * be null) + * @param userDetails the user details (from the + * {@link org.springframework.security.core.userdetails.UserDetailsService}) (cannot + * be null) + * @param assertion the assertion returned from the CAS servers. It contains the + * principal and how to obtain a proxy ticket for the user. + * + * @throws IllegalArgumentException if a null was passed + */ + public CasAuthenticationToken(final String key, final Object principal, + final Object credentials, + final Collection authorities, + final UserDetails userDetails, final Assertion assertion) { + super(authorities); - if ((key == null) || ("".equals(key)) || (principal == null) || "".equals(principal) || (credentials == null) - || "".equals(credentials) || (authorities == null) || (userDetails == null) || (assertion == null)) { - throw new IllegalArgumentException("Cannot pass null or empty values to constructor"); - } + if ((key == null) || ("".equals(key)) || (principal == null) + || "".equals(principal) || (credentials == null) + || "".equals(credentials) || (authorities == null) + || (userDetails == null) || (assertion == null)) { + throw new IllegalArgumentException( + "Cannot pass null or empty values to constructor"); + } - this.keyHash = key.hashCode(); - this.principal = principal; - this.credentials = credentials; - this.userDetails = userDetails; - this.assertion = assertion; - setAuthenticated(true); - } + this.keyHash = key.hashCode(); + this.principal = principal; + this.credentials = credentials; + this.userDetails = userDetails; + this.assertion = assertion; + setAuthenticated(true); + } - //~ Methods ======================================================================================================== + // ~ Methods + // ======================================================================================================== - public boolean equals(final Object obj) { - if (!super.equals(obj)) { - return false; - } + public boolean equals(final Object obj) { + if (!super.equals(obj)) { + return false; + } - if (obj instanceof CasAuthenticationToken) { - CasAuthenticationToken test = (CasAuthenticationToken) obj; + if (obj instanceof CasAuthenticationToken) { + CasAuthenticationToken test = (CasAuthenticationToken) obj; - if (!this.assertion.equals(test.getAssertion())) { - return false; - } + if (!this.assertion.equals(test.getAssertion())) { + return false; + } - if (this.getKeyHash() != test.getKeyHash()) { - return false; - } + if (this.getKeyHash() != test.getKeyHash()) { + return false; + } - return true; - } + return true; + } - return false; - } + return false; + } - public Object getCredentials() { - return this.credentials; - } + public Object getCredentials() { + return this.credentials; + } - public int getKeyHash() { - return this.keyHash; - } + public int getKeyHash() { + return this.keyHash; + } - public Object getPrincipal() { - return this.principal; - } + public Object getPrincipal() { + return this.principal; + } - public Assertion getAssertion() { - return this.assertion; - } + public Assertion getAssertion() { + return this.assertion; + } - public UserDetails getUserDetails() { - return userDetails; - } + public UserDetails getUserDetails() { + return userDetails; + } - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append(super.toString()); - sb.append(" Assertion: ").append(this.assertion); - sb.append(" Credentials (Service/Proxy Ticket): ").append(this.credentials); + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append(super.toString()); + sb.append(" Assertion: ").append(this.assertion); + sb.append(" Credentials (Service/Proxy Ticket): ").append(this.credentials); - return (sb.toString()); - } + return (sb.toString()); + } } diff --git a/cas/src/main/java/org/springframework/security/cas/authentication/EhCacheBasedTicketCache.java b/cas/src/main/java/org/springframework/security/cas/authentication/EhCacheBasedTicketCache.java index 0d9cee19e2..8097fd7904 100644 --- a/cas/src/main/java/org/springframework/security/cas/authentication/EhCacheBasedTicketCache.java +++ b/cas/src/main/java/org/springframework/security/cas/authentication/EhCacheBasedTicketCache.java @@ -23,64 +23,68 @@ import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; - /** - * Caches tickets using a Spring IoC defined EHCACHE. + * Caches tickets using a Spring IoC defined EHCACHE. * * @author Ben Alex */ public class EhCacheBasedTicketCache implements StatelessTicketCache, InitializingBean { - //~ Static fields/initializers ===================================================================================== + // ~ Static fields/initializers + // ===================================================================================== - private static final Log logger = LogFactory.getLog(EhCacheBasedTicketCache.class); + private static final Log logger = LogFactory.getLog(EhCacheBasedTicketCache.class); - //~ Instance fields ================================================================================================ + // ~ Instance fields + // ================================================================================================ - private Ehcache cache; + private Ehcache cache; - //~ Methods ======================================================================================================== + // ~ Methods + // ======================================================================================================== - public void afterPropertiesSet() throws Exception { - Assert.notNull(cache, "cache mandatory"); - } + public void afterPropertiesSet() throws Exception { + Assert.notNull(cache, "cache mandatory"); + } - public CasAuthenticationToken getByTicketId(final String serviceTicket) { - final Element element = cache.get(serviceTicket); + public CasAuthenticationToken getByTicketId(final String serviceTicket) { + final Element element = cache.get(serviceTicket); - if (logger.isDebugEnabled()) { - logger.debug("Cache hit: " + (element != null) + "; service ticket: " + serviceTicket); - } + if (logger.isDebugEnabled()) { + logger.debug("Cache hit: " + (element != null) + "; service ticket: " + + serviceTicket); + } - return element == null ? null : (CasAuthenticationToken) element.getValue(); - } + return element == null ? null : (CasAuthenticationToken) element.getValue(); + } - public Ehcache getCache() { - return cache; - } + public Ehcache getCache() { + return cache; + } - public void putTicketInCache(final CasAuthenticationToken token) { - final Element element = new Element(token.getCredentials().toString(), token); + public void putTicketInCache(final CasAuthenticationToken token) { + final Element element = new Element(token.getCredentials().toString(), token); - if (logger.isDebugEnabled()) { - logger.debug("Cache put: " + element.getKey()); - } + if (logger.isDebugEnabled()) { + logger.debug("Cache put: " + element.getKey()); + } - cache.put(element); - } + cache.put(element); + } - public void removeTicketFromCache(final CasAuthenticationToken token) { - if (logger.isDebugEnabled()) { - logger.debug("Cache remove: " + token.getCredentials().toString()); - } + public void removeTicketFromCache(final CasAuthenticationToken token) { + if (logger.isDebugEnabled()) { + logger.debug("Cache remove: " + token.getCredentials().toString()); + } - this.removeTicketFromCache(token.getCredentials().toString()); - } + this.removeTicketFromCache(token.getCredentials().toString()); + } - public void removeTicketFromCache(final String serviceTicket) { - cache.remove(serviceTicket); - } + public void removeTicketFromCache(final String serviceTicket) { + cache.remove(serviceTicket); + } - public void setCache(final Ehcache cache) { - this.cache = cache; - } + public void setCache(final Ehcache cache) { + this.cache = cache; + } } diff --git a/cas/src/main/java/org/springframework/security/cas/authentication/NullStatelessTicketCache.java b/cas/src/main/java/org/springframework/security/cas/authentication/NullStatelessTicketCache.java index 9f63863ef7..a268fc3bfe 100644 --- a/cas/src/main/java/org/springframework/security/cas/authentication/NullStatelessTicketCache.java +++ b/cas/src/main/java/org/springframework/security/cas/authentication/NullStatelessTicketCache.java @@ -14,46 +14,45 @@ */ package org.springframework.security.cas.authentication; - /** - * Implementation of @link {@link StatelessTicketCache} that has no backing cache. Useful + * Implementation of @link {@link StatelessTicketCache} that has no backing cache. Useful * in instances where storing of tickets for stateless session management is not required. *

- * This is the default StatelessTicketCache of the @link {@link CasAuthenticationProvider} to - * eliminate the unnecessary dependency on EhCache that applications have even if they are not using - * the stateless session management. + * This is the default StatelessTicketCache of the @link {@link CasAuthenticationProvider} + * to eliminate the unnecessary dependency on EhCache that applications have even if they + * are not using the stateless session management. * * @author Scott Battaglia * - *@see CasAuthenticationProvider + * @see CasAuthenticationProvider */ public final class NullStatelessTicketCache implements StatelessTicketCache { - /** - * @return null since we are not storing any tickets. - */ - public CasAuthenticationToken getByTicketId(final String serviceTicket) { - return null; - } + /** + * @return null since we are not storing any tickets. + */ + public CasAuthenticationToken getByTicketId(final String serviceTicket) { + return null; + } - /** - * This is a no-op since we are not storing tickets. - */ - public void putTicketInCache(final CasAuthenticationToken token) { - // nothing to do - } + /** + * This is a no-op since we are not storing tickets. + */ + public void putTicketInCache(final CasAuthenticationToken token) { + // nothing to do + } - /** - * This is a no-op since we are not storing tickets. - */ - public void removeTicketFromCache(final CasAuthenticationToken token) { - // nothing to do - } + /** + * This is a no-op since we are not storing tickets. + */ + public void removeTicketFromCache(final CasAuthenticationToken token) { + // nothing to do + } - /** - * This is a no-op since we are not storing tickets. - */ - public void removeTicketFromCache(final String serviceTicket) { - // nothing to do - } + /** + * This is a no-op since we are not storing tickets. + */ + public void removeTicketFromCache(final String serviceTicket) { + // nothing to do + } } diff --git a/cas/src/main/java/org/springframework/security/cas/authentication/SpringCacheBasedTicketCache.java b/cas/src/main/java/org/springframework/security/cas/authentication/SpringCacheBasedTicketCache.java index fb94bd32cc..b0961b3dd2 100644 --- a/cas/src/main/java/org/springframework/security/cas/authentication/SpringCacheBasedTicketCache.java +++ b/cas/src/main/java/org/springframework/security/cas/authentication/SpringCacheBasedTicketCache.java @@ -20,7 +20,6 @@ import org.apache.commons.logging.LogFactory; import org.springframework.cache.Cache; import org.springframework.util.Assert; - /** * Caches tickets using a Spring IoC defined {@link Cache}. * @@ -29,52 +28,59 @@ import org.springframework.util.Assert; * */ public class SpringCacheBasedTicketCache implements StatelessTicketCache { - //~ Static fields/initializers ===================================================================================== + // ~ Static fields/initializers + // ===================================================================================== - private static final Log logger = LogFactory.getLog(SpringCacheBasedTicketCache.class); + private static final Log logger = LogFactory + .getLog(SpringCacheBasedTicketCache.class); - //~ Instance fields ================================================================================================ + // ~ Instance fields + // ================================================================================================ - private final Cache cache; + private final Cache cache; - //~ Constructors =================================================================================================== + // ~ Constructors + // =================================================================================================== - public SpringCacheBasedTicketCache(Cache cache) throws Exception { - Assert.notNull(cache, "cache mandatory"); - this.cache = cache; - } + public SpringCacheBasedTicketCache(Cache cache) throws Exception { + Assert.notNull(cache, "cache mandatory"); + this.cache = cache; + } - //~ Methods ======================================================================================================== + // ~ Methods + // ======================================================================================================== - public CasAuthenticationToken getByTicketId(final String serviceTicket) { - final Cache.ValueWrapper element = serviceTicket != null ? cache.get(serviceTicket) : null; + public CasAuthenticationToken getByTicketId(final String serviceTicket) { + final Cache.ValueWrapper element = serviceTicket != null ? cache + .get(serviceTicket) : null; - if (logger.isDebugEnabled()) { - logger.debug("Cache hit: " + (element != null) + "; service ticket: " + serviceTicket); - } + if (logger.isDebugEnabled()) { + logger.debug("Cache hit: " + (element != null) + "; service ticket: " + + serviceTicket); + } - return element == null ? null : (CasAuthenticationToken) element.get(); - } + return element == null ? null : (CasAuthenticationToken) element.get(); + } - public void putTicketInCache(final CasAuthenticationToken token) { - String key = token.getCredentials().toString(); + public void putTicketInCache(final CasAuthenticationToken token) { + String key = token.getCredentials().toString(); - if (logger.isDebugEnabled()) { - logger.debug("Cache put: " + key); - } + if (logger.isDebugEnabled()) { + logger.debug("Cache put: " + key); + } - cache.put(key, token); - } + cache.put(key, token); + } - public void removeTicketFromCache(final CasAuthenticationToken token) { - if (logger.isDebugEnabled()) { - logger.debug("Cache remove: " + token.getCredentials().toString()); - } + public void removeTicketFromCache(final CasAuthenticationToken token) { + if (logger.isDebugEnabled()) { + logger.debug("Cache remove: " + token.getCredentials().toString()); + } - this.removeTicketFromCache(token.getCredentials().toString()); - } + this.removeTicketFromCache(token.getCredentials().toString()); + } - public void removeTicketFromCache(final String serviceTicket) { - cache.evict(serviceTicket); - } + public void removeTicketFromCache(final String serviceTicket) { + cache.evict(serviceTicket); + } } diff --git a/cas/src/main/java/org/springframework/security/cas/authentication/StatelessTicketCache.java b/cas/src/main/java/org/springframework/security/cas/authentication/StatelessTicketCache.java index 6d9b22ec54..02f2094b08 100644 --- a/cas/src/main/java/org/springframework/security/cas/authentication/StatelessTicketCache.java +++ b/cas/src/main/java/org/springframework/security/cas/authentication/StatelessTicketCache.java @@ -19,97 +19,95 @@ package org.springframework.security.cas.authentication; * Caches CAS service tickets and CAS proxy tickets for stateless connections. * *

- * When a service ticket or proxy ticket is validated against the CAS server, - * it is unable to be used again. Most types of callers are stateful and are - * associated with a given HttpSession. This allows the - * affirmative CAS validation outcome to be stored in the - * HttpSession, meaning the removal of the ticket from the CAS + * When a service ticket or proxy ticket is validated against the CAS server, it is unable + * to be used again. Most types of callers are stateful and are associated with a given + * HttpSession. This allows the affirmative CAS validation outcome to be + * stored in the HttpSession, meaning the removal of the ticket from the CAS * server is not an issue. *

* *

* Stateless callers, such as remoting protocols, cannot take advantage of - * HttpSession. If the stateless caller is located a significant - * network distance from the CAS server, acquiring a fresh service ticket or - * proxy ticket for each invocation would be expensive. + * HttpSession. If the stateless caller is located a significant network + * distance from the CAS server, acquiring a fresh service ticket or proxy ticket for each + * invocation would be expensive. *

* *

- * To avoid this issue with stateless callers, it is expected stateless callers - * will obtain a single service ticket or proxy ticket, and then present this - * same ticket to the Spring Security secured application on each - * occasion. As no HttpSession is available for such callers, the - * affirmative CAS validation outcome cannot be stored in this location. + * To avoid this issue with stateless callers, it is expected stateless callers will + * obtain a single service ticket or proxy ticket, and then present this same ticket to + * the Spring Security secured application on each occasion. As no + * HttpSession is available for such callers, the affirmative CAS validation + * outcome cannot be stored in this location. *

* *

- * The StatelessTicketCache enables the service tickets and proxy - * tickets belonging to stateless callers to be placed in a cache. This - * in-memory cache stores the CasAuthenticationToken, effectively - * providing the same capability as a HttpSession with the ticket - * identifier being the key rather than a session identifier. + * The StatelessTicketCache enables the service tickets and proxy tickets + * belonging to stateless callers to be placed in a cache. This in-memory cache stores the + * CasAuthenticationToken, effectively providing the same capability as a + * HttpSession with the ticket identifier being the key rather than a session + * identifier. *

* *

- * Implementations should provide a reasonable timeout on stored entries, such - * that the stateless caller are not required to unnecessarily acquire fresh - * CAS service tickets or proxy tickets. + * Implementations should provide a reasonable timeout on stored entries, such that the + * stateless caller are not required to unnecessarily acquire fresh CAS service tickets or + * proxy tickets. *

* * @author Ben Alex */ public interface StatelessTicketCache { - //~ Methods ================================================================ + // ~ Methods ================================================================ - /** - * Retrieves the CasAuthenticationToken associated with the - * specified ticket. - * - *

- * If not found, returns a - * nullCasAuthenticationToken. - *

- * - * @return the fully populated authentication token - */ - CasAuthenticationToken getByTicketId(String serviceTicket); + /** + * Retrieves the CasAuthenticationToken associated with the specified + * ticket. + * + *

+ * If not found, returns a nullCasAuthenticationToken. + *

+ * + * @return the fully populated authentication token + */ + CasAuthenticationToken getByTicketId(String serviceTicket); - /** - * Adds the specified CasAuthenticationToken to the cache. - * - *

- * The {@link CasAuthenticationToken#getCredentials()} method is used to - * retrieve the service ticket number. - *

- * - * @param token to be added to the cache - */ - void putTicketInCache(CasAuthenticationToken token); + /** + * Adds the specified CasAuthenticationToken to the cache. + * + *

+ * The {@link CasAuthenticationToken#getCredentials()} method is used to retrieve the + * service ticket number. + *

+ * + * @param token to be added to the cache + */ + void putTicketInCache(CasAuthenticationToken token); - /** - * Removes the specified ticket from the cache, as per {@link - * #removeTicketFromCache(String)}. - * - *

- * Implementations should use {@link - * CasAuthenticationToken#getCredentials()} to obtain the ticket and then - * delegate to to the {@link #removeTicketFromCache(String)} method. - *

- * - * @param token to be removed - */ - void removeTicketFromCache(CasAuthenticationToken token); + /** + * Removes the specified ticket from the cache, as per + * {@link #removeTicketFromCache(String)}. + * + *

+ * Implementations should use {@link CasAuthenticationToken#getCredentials()} to + * obtain the ticket and then delegate to to the + * {@link #removeTicketFromCache(String)} method. + *

+ * + * @param token to be removed + */ + void removeTicketFromCache(CasAuthenticationToken token); - /** - * Removes the specified ticket from the cache, meaning that future calls - * will require a new service ticket. - * - *

- * This is in case applications wish to provide a session termination - * capability for their stateless clients. - *

- * - * @param serviceTicket to be removed - */ - void removeTicketFromCache(String serviceTicket); + /** + * Removes the specified ticket from the cache, meaning that future calls will require + * a new service ticket. + * + *

+ * This is in case applications wish to provide a session termination capability for + * their stateless clients. + *

+ * + * @param serviceTicket to be removed + */ + void removeTicketFromCache(String serviceTicket); } diff --git a/cas/src/main/java/org/springframework/security/cas/userdetails/AbstractCasAssertionUserDetailsService.java b/cas/src/main/java/org/springframework/security/cas/userdetails/AbstractCasAssertionUserDetailsService.java index 0e19ef0e7d..939f21d895 100644 --- a/cas/src/main/java/org/springframework/security/cas/userdetails/AbstractCasAssertionUserDetailsService.java +++ b/cas/src/main/java/org/springframework/security/cas/userdetails/AbstractCasAssertionUserDetailsService.java @@ -20,25 +20,28 @@ import org.springframework.security.core.userdetails.AuthenticationUserDetailsSe import org.springframework.security.core.userdetails.UserDetails; /** - * Abstract class for using the provided CAS assertion to construct a new User object. This generally is most - * useful when combined with a SAML-based response from the CAS Server/client. + * Abstract class for using the provided CAS assertion to construct a new User object. + * This generally is most useful when combined with a SAML-based response from the CAS + * Server/client. * * @author Scott Battaglia * @since 3.0 */ -public abstract class AbstractCasAssertionUserDetailsService - implements AuthenticationUserDetailsService { +public abstract class AbstractCasAssertionUserDetailsService implements + AuthenticationUserDetailsService { - public final UserDetails loadUserDetails(final CasAssertionAuthenticationToken token) { - return loadUserDetails(token.getAssertion()); - } + public final UserDetails loadUserDetails(final CasAssertionAuthenticationToken token) { + return loadUserDetails(token.getAssertion()); + } - /** - * Protected template method for construct a {@link org.springframework.security.core.userdetails.UserDetails} via the supplied CAS - * assertion. - * - * @param assertion the assertion to use to construct the new UserDetails. CANNOT be NULL. - * @return the newly constructed UserDetails. - */ - protected abstract UserDetails loadUserDetails(Assertion assertion); + /** + * Protected template method for construct a + * {@link org.springframework.security.core.userdetails.UserDetails} via the supplied + * CAS assertion. + * + * @param assertion the assertion to use to construct the new UserDetails. CANNOT be + * NULL. + * @return the newly constructed UserDetails. + */ + protected abstract UserDetails loadUserDetails(Assertion assertion); } diff --git a/cas/src/main/java/org/springframework/security/cas/userdetails/GrantedAuthorityFromAssertionAttributesUserDetailsService.java b/cas/src/main/java/org/springframework/security/cas/userdetails/GrantedAuthorityFromAssertionAttributesUserDetailsService.java index 1f11037ba4..b44db23fea 100644 --- a/cas/src/main/java/org/springframework/security/cas/userdetails/GrantedAuthorityFromAssertionAttributesUserDetailsService.java +++ b/cas/src/main/java/org/springframework/security/cas/userdetails/GrantedAuthorityFromAssertionAttributesUserDetailsService.java @@ -25,61 +25,71 @@ import java.util.List; import java.util.ArrayList; /** - * Populates the {@link org.springframework.security.core.GrantedAuthority}s for a user by reading a list of attributes that were returned as - * part of the CAS response. Each attribute is read and each value of the attribute is turned into a GrantedAuthority. If the attribute has no - * value then its not added. + * Populates the {@link org.springframework.security.core.GrantedAuthority}s for a user by + * reading a list of attributes that were returned as part of the CAS response. Each + * attribute is read and each value of the attribute is turned into a GrantedAuthority. If + * the attribute has no value then its not added. * * @author Scott Battaglia * @since 3.0 */ -public final class GrantedAuthorityFromAssertionAttributesUserDetailsService extends AbstractCasAssertionUserDetailsService { +public final class GrantedAuthorityFromAssertionAttributesUserDetailsService extends + AbstractCasAssertionUserDetailsService { - private static final String NON_EXISTENT_PASSWORD_VALUE = "NO_PASSWORD"; + private static final String NON_EXISTENT_PASSWORD_VALUE = "NO_PASSWORD"; - private final String[] attributes; + private final String[] attributes; - private boolean convertToUpperCase = true; + private boolean convertToUpperCase = true; - public GrantedAuthorityFromAssertionAttributesUserDetailsService(final String[] attributes) { - Assert.notNull(attributes, "attributes cannot be null."); - Assert.isTrue(attributes.length > 0, "At least one attribute is required to retrieve roles from."); - this.attributes = attributes; - } + public GrantedAuthorityFromAssertionAttributesUserDetailsService( + final String[] attributes) { + Assert.notNull(attributes, "attributes cannot be null."); + Assert.isTrue(attributes.length > 0, + "At least one attribute is required to retrieve roles from."); + this.attributes = attributes; + } - @SuppressWarnings("unchecked") - @Override - protected UserDetails loadUserDetails(final Assertion assertion) { - final List grantedAuthorities = new ArrayList(); + @SuppressWarnings("unchecked") + @Override + protected UserDetails loadUserDetails(final Assertion assertion) { + final List grantedAuthorities = new ArrayList(); - for (final String attribute : this.attributes) { - final Object value = assertion.getPrincipal().getAttributes().get(attribute); + for (final String attribute : this.attributes) { + final Object value = assertion.getPrincipal().getAttributes().get(attribute); - if (value == null) { - continue; - } + if (value == null) { + continue; + } - if (value instanceof List) { - final List list = (List) value; + if (value instanceof List) { + final List list = (List) value; - for (final Object o : list) { - grantedAuthorities.add(new SimpleGrantedAuthority(this.convertToUpperCase ? o.toString().toUpperCase() : o.toString())); - } + for (final Object o : list) { + grantedAuthorities.add(new SimpleGrantedAuthority( + this.convertToUpperCase ? o.toString().toUpperCase() : o + .toString())); + } - } else { - grantedAuthorities.add(new SimpleGrantedAuthority(this.convertToUpperCase ? value.toString().toUpperCase() : value.toString())); - } + } + else { + grantedAuthorities.add(new SimpleGrantedAuthority( + this.convertToUpperCase ? value.toString().toUpperCase() : value + .toString())); + } - } + } - return new User(assertion.getPrincipal().getName(), NON_EXISTENT_PASSWORD_VALUE, true, true, true, true, grantedAuthorities); - } + return new User(assertion.getPrincipal().getName(), NON_EXISTENT_PASSWORD_VALUE, + true, true, true, true, grantedAuthorities); + } - /** - * Converts the returned attribute values to uppercase values. - * - * @param convertToUpperCase true if it should convert, false otherwise. - */ - public void setConvertToUpperCase(final boolean convertToUpperCase) { - this.convertToUpperCase = convertToUpperCase; - } + /** + * Converts the returned attribute values to uppercase values. + * + * @param convertToUpperCase true if it should convert, false otherwise. + */ + public void setConvertToUpperCase(final boolean convertToUpperCase) { + this.convertToUpperCase = convertToUpperCase; + } } diff --git a/cas/src/main/java/org/springframework/security/cas/web/CasAuthenticationEntryPoint.java b/cas/src/main/java/org/springframework/security/cas/web/CasAuthenticationEntryPoint.java index 1e56f9346d..f4011f8240 100644 --- a/cas/src/main/java/org/springframework/security/cas/web/CasAuthenticationEntryPoint.java +++ b/cas/src/main/java/org/springframework/security/cas/web/CasAuthenticationEntryPoint.java @@ -28,122 +28,140 @@ import org.springframework.security.web.AuthenticationEntryPoint; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; - /** - * Used by the ExceptionTranslationFilter to commence authentication via the JA-SIG Central - * Authentication Service (CAS). + * Used by the ExceptionTranslationFilter to commence authentication via the + * JA-SIG Central Authentication Service (CAS). *

* The user's browser will be redirected to the JA-SIG CAS enterprise-wide login page. - * This page is specified by the loginUrl property. Once login is complete, the CAS login page will - * redirect to the page indicated by the service property. The service is a HTTP URL - * belonging to the current application. The service URL is monitored by the {@link CasAuthenticationFilter}, - * which will validate the CAS login was successful. + * This page is specified by the loginUrl property. Once login is complete, + * the CAS login page will redirect to the page indicated by the service + * property. The service is a HTTP URL belonging to the current application. + * The service URL is monitored by the {@link CasAuthenticationFilter}, which + * will validate the CAS login was successful. * * @author Ben Alex * @author Scott Battaglia */ -public class CasAuthenticationEntryPoint implements AuthenticationEntryPoint, InitializingBean { - //~ Instance fields ================================================================================================ - private ServiceProperties serviceProperties; +public class CasAuthenticationEntryPoint implements AuthenticationEntryPoint, + InitializingBean { + // ~ Instance fields + // ================================================================================================ + private ServiceProperties serviceProperties; - private String loginUrl; + private String loginUrl; - /** - * Determines whether the Service URL should include the session id for the specific user. As of CAS 3.0.5, the - * session id will automatically be stripped. However, older versions of CAS (i.e. CAS 2), do not automatically - * strip the session identifier (this is a bug on the part of the older server implementations), so an option to - * disable the session encoding is provided for backwards compatibility. - * - * By default, encoding is enabled. - */ - private boolean encodeServiceUrlWithSessionId = true; + /** + * Determines whether the Service URL should include the session id for the specific + * user. As of CAS 3.0.5, the session id will automatically be stripped. However, + * older versions of CAS (i.e. CAS 2), do not automatically strip the session + * identifier (this is a bug on the part of the older server implementations), so an + * option to disable the session encoding is provided for backwards compatibility. + * + * By default, encoding is enabled. + */ + private boolean encodeServiceUrlWithSessionId = true; - //~ Methods ======================================================================================================== + // ~ Methods + // ======================================================================================================== - public void afterPropertiesSet() throws Exception { - Assert.hasLength(this.loginUrl, "loginUrl must be specified"); - Assert.notNull(this.serviceProperties, "serviceProperties must be specified"); - Assert.notNull(this.serviceProperties.getService(),"serviceProperties.getService() cannot be null."); - } + public void afterPropertiesSet() throws Exception { + Assert.hasLength(this.loginUrl, "loginUrl must be specified"); + Assert.notNull(this.serviceProperties, "serviceProperties must be specified"); + Assert.notNull(this.serviceProperties.getService(), + "serviceProperties.getService() cannot be null."); + } - public final void commence(final HttpServletRequest servletRequest, final HttpServletResponse response, - final AuthenticationException authenticationException) throws IOException, ServletException { + public final void commence(final HttpServletRequest servletRequest, + final HttpServletResponse response, + final AuthenticationException authenticationException) throws IOException, + ServletException { - final String urlEncodedService = createServiceUrl(servletRequest, response); - final String redirectUrl = createRedirectUrl(urlEncodedService); + final String urlEncodedService = createServiceUrl(servletRequest, response); + final String redirectUrl = createRedirectUrl(urlEncodedService); - preCommence(servletRequest, response); + preCommence(servletRequest, response); - response.sendRedirect(redirectUrl); - } + response.sendRedirect(redirectUrl); + } - /** - * Constructs a new Service Url. The default implementation relies on the CAS client to do the bulk of the work. - * @param request the HttpServletRequest - * @param response the HttpServlet Response - * @return the constructed service url. CANNOT be NULL. - */ - protected String createServiceUrl(final HttpServletRequest request, final HttpServletResponse response) { - return CommonUtils.constructServiceUrl(null, response, this.serviceProperties.getService(), null, this.serviceProperties.getArtifactParameter(), this.encodeServiceUrlWithSessionId); - } + /** + * Constructs a new Service Url. The default implementation relies on the CAS client + * to do the bulk of the work. + * @param request the HttpServletRequest + * @param response the HttpServlet Response + * @return the constructed service url. CANNOT be NULL. + */ + protected String createServiceUrl(final HttpServletRequest request, + final HttpServletResponse response) { + return CommonUtils.constructServiceUrl(null, response, + this.serviceProperties.getService(), null, + this.serviceProperties.getArtifactParameter(), + this.encodeServiceUrlWithSessionId); + } - /** - * Constructs the Url for Redirection to the CAS server. Default implementation relies on the CAS client to do the bulk of the work. - * - * @param serviceUrl the service url that should be included. - * @return the redirect url. CANNOT be NULL. - */ - protected String createRedirectUrl(final String serviceUrl) { - return CommonUtils.constructRedirectUrl(this.loginUrl, this.serviceProperties.getServiceParameter(), serviceUrl, this.serviceProperties.isSendRenew(), false); - } + /** + * Constructs the Url for Redirection to the CAS server. Default implementation relies + * on the CAS client to do the bulk of the work. + * + * @param serviceUrl the service url that should be included. + * @return the redirect url. CANNOT be NULL. + */ + protected String createRedirectUrl(final String serviceUrl) { + return CommonUtils.constructRedirectUrl(this.loginUrl, + this.serviceProperties.getServiceParameter(), serviceUrl, + this.serviceProperties.isSendRenew(), false); + } - /** - * Template method for you to do your own pre-processing before the redirect occurs. - * - * @param request the HttpServletRequest - * @param response the HttpServletResponse - */ - protected void preCommence(final HttpServletRequest request, final HttpServletResponse response) { + /** + * Template method for you to do your own pre-processing before the redirect occurs. + * + * @param request the HttpServletRequest + * @param response the HttpServletResponse + */ + protected void preCommence(final HttpServletRequest request, + final HttpServletResponse response) { - } + } - /** - * The enterprise-wide CAS login URL. Usually something like - * https://www.mycompany.com/cas/login. - * - * @return the enterprise-wide CAS login URL - */ - public final String getLoginUrl() { - return this.loginUrl; - } + /** + * The enterprise-wide CAS login URL. Usually something like + * https://www.mycompany.com/cas/login. + * + * @return the enterprise-wide CAS login URL + */ + public final String getLoginUrl() { + return this.loginUrl; + } - public final ServiceProperties getServiceProperties() { - return this.serviceProperties; - } + public final ServiceProperties getServiceProperties() { + return this.serviceProperties; + } - public final void setLoginUrl(final String loginUrl) { - this.loginUrl = loginUrl; - } + public final void setLoginUrl(final String loginUrl) { + this.loginUrl = loginUrl; + } - public final void setServiceProperties(final ServiceProperties serviceProperties) { - this.serviceProperties = serviceProperties; - } + public final void setServiceProperties(final ServiceProperties serviceProperties) { + this.serviceProperties = serviceProperties; + } - /** - * Sets whether to encode the service url with the session id or not. - * - * @param encodeServiceUrlWithSessionId whether to encode the service url with the session id or not. - */ - public final void setEncodeServiceUrlWithSessionId(final boolean encodeServiceUrlWithSessionId) { - this.encodeServiceUrlWithSessionId = encodeServiceUrlWithSessionId; - } + /** + * Sets whether to encode the service url with the session id or not. + * + * @param encodeServiceUrlWithSessionId whether to encode the service url with the + * session id or not. + */ + public final void setEncodeServiceUrlWithSessionId( + final boolean encodeServiceUrlWithSessionId) { + this.encodeServiceUrlWithSessionId = encodeServiceUrlWithSessionId; + } - /** - * Sets whether to encode the service url with the session id or not. - * @return whether to encode the service url with the session id or not. - * - */ - protected boolean getEncodeServiceUrlWithSessionId() { - return this.encodeServiceUrlWithSessionId; - } + /** + * Sets whether to encode the service url with the session id or not. + * @return whether to encode the service url with the session id or not. + * + */ + protected boolean getEncodeServiceUrlWithSessionId() { + return this.encodeServiceUrlWithSessionId; + } } diff --git a/cas/src/main/java/org/springframework/security/cas/web/CasAuthenticationFilter.java b/cas/src/main/java/org/springframework/security/cas/web/CasAuthenticationFilter.java index e374067e03..f7f094907b 100644 --- a/cas/src/main/java/org/springframework/security/cas/web/CasAuthenticationFilter.java +++ b/cas/src/main/java/org/springframework/security/cas/web/CasAuthenticationFilter.java @@ -43,51 +43,64 @@ import org.springframework.security.web.util.matcher.RequestMatcher; import org.springframework.util.Assert; /** - * Processes a CAS service ticket, obtains proxy granting tickets, and processes proxy tickets. - *

Service Tickets

+ * Processes a CAS service ticket, obtains proxy granting tickets, and processes proxy + * tickets.

Service Tickets

*

- * A service ticket consists of an opaque ticket string. It arrives at this filter by the user's browser successfully - * authenticating using CAS, and then receiving a HTTP redirect to a service. The opaque ticket string is - * presented in the ticket request parameter. + * A service ticket consists of an opaque ticket string. It arrives at this filter by the + * user's browser successfully authenticating using CAS, and then receiving a HTTP + * redirect to a service. The opaque ticket string is presented in the + * ticket request parameter. *

- * This filter monitors the service URL so it can - * receive the service ticket and process it. By default this filter processes the URL /login/cas. - * When processing this URL, the value of {@link ServiceProperties#getService()} is used as the service when validating - * the ticket. This means that it is important that {@link ServiceProperties#getService()} specifies the same value - * as the filterProcessesUrl. + * This filter monitors the service URL so it can receive the service ticket + * and process it. By default this filter processes the URL /login/cas. When + * processing this URL, the value of {@link ServiceProperties#getService()} is used as the + * service when validating the ticket. This means that it is + * important that {@link ServiceProperties#getService()} specifies the same value as the + * filterProcessesUrl. *

- * Processing the service ticket involves creating a UsernamePasswordAuthenticationToken which - * uses {@link #CAS_STATEFUL_IDENTIFIER} for the principal and the opaque ticket string as the - * credentials. + * Processing the service ticket involves creating a + * UsernamePasswordAuthenticationToken which uses + * {@link #CAS_STATEFUL_IDENTIFIER} for the principal and the opaque ticket + * string as the credentials. *

Obtaining Proxy Granting Tickets

*

- * If specified, the filter can also monitor the proxyReceptorUrl. The filter will respond to requests matching - * this url so that the CAS Server can provide a PGT to the filter. Note that in addition to the proxyReceptorUrl a non-null - * proxyGrantingTicketStorage must be provided in order for the filter to respond to proxy receptor requests. By configuring - * a shared {@link ProxyGrantingTicketStorage} between the {@link TicketValidator} and the CasAuthenticationFilter one can have the - * CasAuthenticationFilter handle the proxying requirements for CAS. + * If specified, the filter can also monitor the proxyReceptorUrl. The filter + * will respond to requests matching this url so that the CAS Server can provide a PGT to + * the filter. Note that in addition to the proxyReceptorUrl a non-null + * proxyGrantingTicketStorage must be provided in order for the filter to + * respond to proxy receptor requests. By configuring a shared + * {@link ProxyGrantingTicketStorage} between the {@link TicketValidator} and the + * CasAuthenticationFilter one can have the CasAuthenticationFilter handle the proxying + * requirements for CAS. *

Proxy Tickets

*

- * The filter can process tickets present on any url. This is useful when wanting to process proxy tickets. In order for proxy - * tickets to get processed {@link ServiceProperties#isAuthenticateAllArtifacts()} must return true. Additionally, - * if the request is already authenticated, authentication will not occur. Last, {@link AuthenticationDetailsSource#buildDetails(Object)} - * must return a {@link ServiceAuthenticationDetails}. This can be accomplished using the {@link ServiceAuthenticationDetailsSource}. - * In this case {@link ServiceAuthenticationDetails#getServiceUrl()} will be used for the service url. + * The filter can process tickets present on any url. This is useful when wanting to + * process proxy tickets. In order for proxy tickets to get processed + * {@link ServiceProperties#isAuthenticateAllArtifacts()} must return true. + * Additionally, if the request is already authenticated, authentication will not + * occur. Last, {@link AuthenticationDetailsSource#buildDetails(Object)} must return a + * {@link ServiceAuthenticationDetails}. This can be accomplished using the + * {@link ServiceAuthenticationDetailsSource}. In this case + * {@link ServiceAuthenticationDetails#getServiceUrl()} will be used for the service url. *

- * Processing the proxy ticket involves creating a UsernamePasswordAuthenticationToken which - * uses {@link #CAS_STATELESS_IDENTIFIER} for the principal and the opaque ticket string as the - * credentials. When a proxy ticket is successfully authenticated, the FilterChain continues and the + * Processing the proxy ticket involves creating a + * UsernamePasswordAuthenticationToken which uses + * {@link #CAS_STATELESS_IDENTIFIER} for the principal and the opaque ticket + * string as the credentials. When a proxy ticket is successfully + * authenticated, the FilterChain continues and the * authenticationSuccessHandler is not used. *

Notes about the AuthenticationManager

*

- * The configured AuthenticationManager is expected to provide a provider that can recognise - * UsernamePasswordAuthenticationTokens containing this special principal name, and process - * them accordingly by validation with the CAS server. Additionally, it should be capable of using the result of - * {@link ServiceAuthenticationDetails#getServiceUrl()} as the service when validating the ticket. + * The configured AuthenticationManager is expected to provide a provider + * that can recognise UsernamePasswordAuthenticationTokens containing this + * special principal name, and process them accordingly by validation with + * the CAS server. Additionally, it should be capable of using the result of + * {@link ServiceAuthenticationDetails#getServiceUrl()} as the service when validating the + * ticket. *

Example Configuration

*

- * An example configuration that supports service tickets, obtaining proxy granting tickets, and proxy tickets is - * illustrated below: + * An example configuration that supports service tickets, obtaining proxy granting + * tickets, and proxy tickets is illustrated below: * *

  * <b:bean id="serviceProperties"
@@ -157,236 +170,265 @@ import org.springframework.util.Assert;
  * @author Rob Winch
  */
 public class CasAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
-    //~ Static fields/initializers =====================================================================================
+	// ~ Static fields/initializers
+	// =====================================================================================
 
-    /** Used to identify a CAS request for a stateful user agent, such as a web browser. */
-    public static final String CAS_STATEFUL_IDENTIFIER = "_cas_stateful_";
+	/** Used to identify a CAS request for a stateful user agent, such as a web browser. */
+	public static final String CAS_STATEFUL_IDENTIFIER = "_cas_stateful_";
 
-    /**
-     * Used to identify a CAS request for a stateless user agent, such as a remoting protocol client (e.g.
-     * Hessian, Burlap, SOAP etc). Results in a more aggressive caching strategy being used, as the absence of a
-     * HttpSession will result in a new authentication attempt on every request.
-     */
-    public static final String CAS_STATELESS_IDENTIFIER = "_cas_stateless_";
+	/**
+	 * Used to identify a CAS request for a stateless user agent, such as a remoting
+	 * protocol client (e.g. Hessian, Burlap, SOAP etc). Results in a more aggressive
+	 * caching strategy being used, as the absence of a HttpSession will
+	 * result in a new authentication attempt on every request.
+	 */
+	public static final String CAS_STATELESS_IDENTIFIER = "_cas_stateless_";
 
-    /**
-     * The last portion of the receptor url, i.e. /proxy/receptor
-     */
-    private RequestMatcher proxyReceptorMatcher;
+	/**
+	 * The last portion of the receptor url, i.e. /proxy/receptor
+	 */
+	private RequestMatcher proxyReceptorMatcher;
 
-    /**
-     * The backing storage to store ProxyGrantingTicket requests.
-     */
-    private ProxyGrantingTicketStorage proxyGrantingTicketStorage;
+	/**
+	 * The backing storage to store ProxyGrantingTicket requests.
+	 */
+	private ProxyGrantingTicketStorage proxyGrantingTicketStorage;
 
-    private String artifactParameter = ServiceProperties.DEFAULT_CAS_ARTIFACT_PARAMETER;
+	private String artifactParameter = ServiceProperties.DEFAULT_CAS_ARTIFACT_PARAMETER;
 
-    private boolean authenticateAllArtifacts;
+	private boolean authenticateAllArtifacts;
 
-    private AuthenticationFailureHandler proxyFailureHandler = new SimpleUrlAuthenticationFailureHandler();
+	private AuthenticationFailureHandler proxyFailureHandler = new SimpleUrlAuthenticationFailureHandler();
 
-    //~ Constructors ===================================================================================================
+	// ~ Constructors
+	// ===================================================================================================
 
-    public CasAuthenticationFilter() {
-        super("/login/cas");
-        setAuthenticationFailureHandler(new SimpleUrlAuthenticationFailureHandler());
-    }
+	public CasAuthenticationFilter() {
+		super("/login/cas");
+		setAuthenticationFailureHandler(new SimpleUrlAuthenticationFailureHandler());
+	}
 
-    //~ Methods ========================================================================================================
+	// ~ Methods
+	// ========================================================================================================
 
-    @Override
-    protected final void successfulAuthentication(HttpServletRequest request,
-            HttpServletResponse response, FilterChain chain, Authentication authResult)
-            throws IOException, ServletException {
-        boolean continueFilterChain = proxyTicketRequest(serviceTicketRequest(request, response),request);
-        if(!continueFilterChain) {
-            super.successfulAuthentication(request, response, chain, authResult);
-            return;
-        }
+	@Override
+	protected final void successfulAuthentication(HttpServletRequest request,
+			HttpServletResponse response, FilterChain chain, Authentication authResult)
+			throws IOException, ServletException {
+		boolean continueFilterChain = proxyTicketRequest(
+				serviceTicketRequest(request, response), request);
+		if (!continueFilterChain) {
+			super.successfulAuthentication(request, response, chain, authResult);
+			return;
+		}
 
-        if (logger.isDebugEnabled()) {
-            logger.debug("Authentication success. Updating SecurityContextHolder to contain: " + authResult);
-        }
+		if (logger.isDebugEnabled()) {
+			logger.debug("Authentication success. Updating SecurityContextHolder to contain: "
+					+ authResult);
+		}
 
-        SecurityContextHolder.getContext().setAuthentication(authResult);
+		SecurityContextHolder.getContext().setAuthentication(authResult);
 
-        // Fire event
-        if (this.eventPublisher != null) {
-            eventPublisher.publishEvent(new InteractiveAuthenticationSuccessEvent(authResult, this.getClass()));
-        }
+		// Fire event
+		if (this.eventPublisher != null) {
+			eventPublisher.publishEvent(new InteractiveAuthenticationSuccessEvent(
+					authResult, this.getClass()));
+		}
 
-        chain.doFilter(request, response);
-    }
+		chain.doFilter(request, response);
+	}
 
-    @Override
-    public Authentication attemptAuthentication(final HttpServletRequest request, final HttpServletResponse response)
-            throws AuthenticationException, IOException {
-        // if the request is a proxy request process it and return null to indicate the request has been processed
-        if(proxyReceptorRequest(request)) {
-            logger.debug("Responding to proxy receptor request");
-            CommonUtils.readAndRespondToProxyReceptorRequest(request, response, this.proxyGrantingTicketStorage);
-            return null;
-        }
+	@Override
+	public Authentication attemptAuthentication(final HttpServletRequest request,
+			final HttpServletResponse response) throws AuthenticationException,
+			IOException {
+		// if the request is a proxy request process it and return null to indicate the
+		// request has been processed
+		if (proxyReceptorRequest(request)) {
+			logger.debug("Responding to proxy receptor request");
+			CommonUtils.readAndRespondToProxyReceptorRequest(request, response,
+					this.proxyGrantingTicketStorage);
+			return null;
+		}
 
-        final boolean serviceTicketRequest = serviceTicketRequest(request, response);
-        final String username = serviceTicketRequest ? CAS_STATEFUL_IDENTIFIER : CAS_STATELESS_IDENTIFIER;
-        String password = obtainArtifact(request);
+		final boolean serviceTicketRequest = serviceTicketRequest(request, response);
+		final String username = serviceTicketRequest ? CAS_STATEFUL_IDENTIFIER
+				: CAS_STATELESS_IDENTIFIER;
+		String password = obtainArtifact(request);
 
-        if (password == null) {
-            logger.debug("Failed to obtain an artifact (cas ticket)");
-            password = "";
-        }
+		if (password == null) {
+			logger.debug("Failed to obtain an artifact (cas ticket)");
+			password = "";
+		}
 
-        final UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
+		final UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(
+				username, password);
 
-        authRequest.setDetails(authenticationDetailsSource.buildDetails(request));
+		authRequest.setDetails(authenticationDetailsSource.buildDetails(request));
 
-        return this.getAuthenticationManager().authenticate(authRequest);
-    }
+		return this.getAuthenticationManager().authenticate(authRequest);
+	}
 
-    /**
-     * If present, gets the artifact (CAS ticket) from the {@link HttpServletRequest}.
-     * @param request
-     * @return if present the artifact from the {@link HttpServletRequest}, else null
-     */
-    protected String obtainArtifact(HttpServletRequest request) {
-        return request.getParameter(artifactParameter);
-    }
+	/**
+	 * If present, gets the artifact (CAS ticket) from the {@link HttpServletRequest}.
+	 * @param request
+	 * @return if present the artifact from the {@link HttpServletRequest}, else null
+	 */
+	protected String obtainArtifact(HttpServletRequest request) {
+		return request.getParameter(artifactParameter);
+	}
 
-    /**
-     * Overridden to provide proxying capabilities.
-     */
-    protected boolean requiresAuthentication(final HttpServletRequest request, final HttpServletResponse response) {
-        final boolean serviceTicketRequest = serviceTicketRequest(request, response);
-        final boolean result = serviceTicketRequest || proxyReceptorRequest(request) || (proxyTicketRequest(serviceTicketRequest, request));
-        if(logger.isDebugEnabled()) {
-            logger.debug("requiresAuthentication = "+result);
-        }
-        return result;
-    }
+	/**
+	 * Overridden to provide proxying capabilities.
+	 */
+	protected boolean requiresAuthentication(final HttpServletRequest request,
+			final HttpServletResponse response) {
+		final boolean serviceTicketRequest = serviceTicketRequest(request, response);
+		final boolean result = serviceTicketRequest || proxyReceptorRequest(request)
+				|| (proxyTicketRequest(serviceTicketRequest, request));
+		if (logger.isDebugEnabled()) {
+			logger.debug("requiresAuthentication = " + result);
+		}
+		return result;
+	}
 
-    /**
-     * Sets the {@link AuthenticationFailureHandler} for proxy requests.
-     * @param proxyFailureHandler
-     */
-    public final void setProxyAuthenticationFailureHandler(
-            AuthenticationFailureHandler proxyFailureHandler) {
-        Assert.notNull(proxyFailureHandler,"proxyFailureHandler cannot be null");
-        this.proxyFailureHandler = proxyFailureHandler;
-    }
+	/**
+	 * Sets the {@link AuthenticationFailureHandler} for proxy requests.
+	 * @param proxyFailureHandler
+	 */
+	public final void setProxyAuthenticationFailureHandler(
+			AuthenticationFailureHandler proxyFailureHandler) {
+		Assert.notNull(proxyFailureHandler, "proxyFailureHandler cannot be null");
+		this.proxyFailureHandler = proxyFailureHandler;
+	}
 
-    /**
-     * Wraps the {@link AuthenticationFailureHandler} to distinguish between
-     * handling proxy ticket authentication failures and service ticket
-     * failures.
-     */
-    @Override
-    public final void setAuthenticationFailureHandler(
-            AuthenticationFailureHandler failureHandler) {
-        super.setAuthenticationFailureHandler(new CasAuthenticationFailureHandler(failureHandler));
-    }
+	/**
+	 * Wraps the {@link AuthenticationFailureHandler} to distinguish between handling
+	 * proxy ticket authentication failures and service ticket failures.
+	 */
+	@Override
+	public final void setAuthenticationFailureHandler(
+			AuthenticationFailureHandler failureHandler) {
+		super.setAuthenticationFailureHandler(new CasAuthenticationFailureHandler(
+				failureHandler));
+	}
 
-    public final void setProxyReceptorUrl(final String proxyReceptorUrl) {
-        this.proxyReceptorMatcher = new AntPathRequestMatcher("/**" + proxyReceptorUrl);
-    }
+	public final void setProxyReceptorUrl(final String proxyReceptorUrl) {
+		this.proxyReceptorMatcher = new AntPathRequestMatcher("/**" + proxyReceptorUrl);
+	}
 
-    public final void setProxyGrantingTicketStorage(
-            final ProxyGrantingTicketStorage proxyGrantingTicketStorage) {
-        this.proxyGrantingTicketStorage = proxyGrantingTicketStorage;
-    }
+	public final void setProxyGrantingTicketStorage(
+			final ProxyGrantingTicketStorage proxyGrantingTicketStorage) {
+		this.proxyGrantingTicketStorage = proxyGrantingTicketStorage;
+	}
 
-    public final void setServiceProperties(final ServiceProperties serviceProperties) {
-        this.artifactParameter = serviceProperties.getArtifactParameter();
-        this.authenticateAllArtifacts = serviceProperties.isAuthenticateAllArtifacts();
-    }
+	public final void setServiceProperties(final ServiceProperties serviceProperties) {
+		this.artifactParameter = serviceProperties.getArtifactParameter();
+		this.authenticateAllArtifacts = serviceProperties.isAuthenticateAllArtifacts();
+	}
 
-    /**
-     * Indicates if the request is elgible to process a service ticket. This method exists for readability.
-     * @param request
-     * @param response
-     * @return
-     */
-    private boolean serviceTicketRequest(final HttpServletRequest request, final HttpServletResponse response) {
-        boolean result = super.requiresAuthentication(request, response);
-        if(logger.isDebugEnabled()) {
-            logger.debug("serviceTicketRequest = "+result);
-        }
-        return result;
-    }
+	/**
+	 * Indicates if the request is elgible to process a service ticket. This method exists
+	 * for readability.
+	 * @param request
+	 * @param response
+	 * @return
+	 */
+	private boolean serviceTicketRequest(final HttpServletRequest request,
+			final HttpServletResponse response) {
+		boolean result = super.requiresAuthentication(request, response);
+		if (logger.isDebugEnabled()) {
+			logger.debug("serviceTicketRequest = " + result);
+		}
+		return result;
+	}
 
-    /**
-     * Indicates if the request is elgible to process a proxy ticket.
-     * @param request
-     * @return
-     */
-    private boolean proxyTicketRequest(final boolean serviceTicketRequest, final HttpServletRequest request) {
-        if(serviceTicketRequest) {
-            return false;
-        }
-        final boolean result = authenticateAllArtifacts && obtainArtifact(request) != null && !authenticated();
-        if(logger.isDebugEnabled()) {
-            logger.debug("proxyTicketRequest = "+result);
-        }
-        return result;
-    }
+	/**
+	 * Indicates if the request is elgible to process a proxy ticket.
+	 * @param request
+	 * @return
+	 */
+	private boolean proxyTicketRequest(final boolean serviceTicketRequest,
+			final HttpServletRequest request) {
+		if (serviceTicketRequest) {
+			return false;
+		}
+		final boolean result = authenticateAllArtifacts
+				&& obtainArtifact(request) != null && !authenticated();
+		if (logger.isDebugEnabled()) {
+			logger.debug("proxyTicketRequest = " + result);
+		}
+		return result;
+	}
 
-    /**
-     * Determines if a user is already authenticated.
-     * @return
-     */
-    private boolean authenticated() {
-        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
-        return authentication != null && authentication.isAuthenticated() && !(authentication instanceof AnonymousAuthenticationToken);
-    }
-    /**
-     * Indicates if the request is elgible to be processed as the proxy receptor.
-     * @param request
-     * @return
-     */
-    private boolean proxyReceptorRequest(final HttpServletRequest request) {
-        final boolean result = proxyReceptorConfigured() && proxyReceptorMatcher.matches(request);
-        if(logger.isDebugEnabled()) {
-            logger.debug("proxyReceptorRequest = "+result);
-        }
-        return result;
-    }
+	/**
+	 * Determines if a user is already authenticated.
+	 * @return
+	 */
+	private boolean authenticated() {
+		Authentication authentication = SecurityContextHolder.getContext()
+				.getAuthentication();
+		return authentication != null && authentication.isAuthenticated()
+				&& !(authentication instanceof AnonymousAuthenticationToken);
+	}
 
-    /**
-     * Determines if the {@link CasAuthenticationFilter} is configured to handle the proxy receptor requests.
-     *
-     * @return
-     */
-    private boolean proxyReceptorConfigured() {
-        final boolean result = this.proxyGrantingTicketStorage != null && proxyReceptorMatcher != null;
-        if(logger.isDebugEnabled()) {
-            logger.debug("proxyReceptorConfigured = "+result);
-        }
-        return result;
-    }
+	/**
+	 * Indicates if the request is elgible to be processed as the proxy receptor.
+	 * @param request
+	 * @return
+	 */
+	private boolean proxyReceptorRequest(final HttpServletRequest request) {
+		final boolean result = proxyReceptorConfigured()
+				&& proxyReceptorMatcher.matches(request);
+		if (logger.isDebugEnabled()) {
+			logger.debug("proxyReceptorRequest = " + result);
+		}
+		return result;
+	}
 
-    /**
-     * A wrapper for the AuthenticationFailureHandler that will flex the {@link AuthenticationFailureHandler} that is used. The value
-     * {@link CasAuthenticationFilter#setProxyAuthenticationFailureHandler(AuthenticationFailureHandler) will be used for proxy requests
-     * that fail. The value {@link CasAuthenticationFilter#setAuthenticationFailureHandler(AuthenticationFailureHandler)} will be used for
-     * service tickets that fail.
-     *
-     * @author Rob Winch
-     */
-    private class CasAuthenticationFailureHandler implements AuthenticationFailureHandler {
-        private final AuthenticationFailureHandler serviceTicketFailureHandler;
-        public CasAuthenticationFailureHandler(AuthenticationFailureHandler failureHandler) {
-            Assert.notNull(failureHandler,"failureHandler");
-            this.serviceTicketFailureHandler = failureHandler;
-        }
-        public void onAuthenticationFailure(HttpServletRequest request,
-                HttpServletResponse response,
-                AuthenticationException exception) throws IOException,
-                ServletException {
-            if(serviceTicketRequest(request, response)) {
-                serviceTicketFailureHandler.onAuthenticationFailure(request, response, exception);
-            }else {
-                proxyFailureHandler.onAuthenticationFailure(request, response, exception);
-            }
-        }
-    }
+	/**
+	 * Determines if the {@link CasAuthenticationFilter} is configured to handle the proxy
+	 * receptor requests.
+	 *
+	 * @return
+	 */
+	private boolean proxyReceptorConfigured() {
+		final boolean result = this.proxyGrantingTicketStorage != null
+				&& proxyReceptorMatcher != null;
+		if (logger.isDebugEnabled()) {
+			logger.debug("proxyReceptorConfigured = " + result);
+		}
+		return result;
+	}
+
+	/**
+	 * A wrapper for the AuthenticationFailureHandler that will flex the
+	 * {@link AuthenticationFailureHandler} that is used. The value
+	 * {@link CasAuthenticationFilter#setProxyAuthenticationFailureHandler(AuthenticationFailureHandler)
+	 * will be used for proxy requests that fail. The value
+	 * {@link CasAuthenticationFilter#setAuthenticationFailureHandler(AuthenticationFailureHandler)}
+	 * will be used for service tickets that fail.
+	 *
+	 * @author Rob Winch
+	 */
+	private class CasAuthenticationFailureHandler implements AuthenticationFailureHandler {
+		private final AuthenticationFailureHandler serviceTicketFailureHandler;
+
+		public CasAuthenticationFailureHandler(AuthenticationFailureHandler failureHandler) {
+			Assert.notNull(failureHandler, "failureHandler");
+			this.serviceTicketFailureHandler = failureHandler;
+		}
+
+		public void onAuthenticationFailure(HttpServletRequest request,
+				HttpServletResponse response, AuthenticationException exception)
+				throws IOException, ServletException {
+			if (serviceTicketRequest(request, response)) {
+				serviceTicketFailureHandler.onAuthenticationFailure(request, response,
+						exception);
+			}
+			else {
+				proxyFailureHandler.onAuthenticationFailure(request, response, exception);
+			}
+		}
+	}
 }
\ No newline at end of file
diff --git a/cas/src/main/java/org/springframework/security/cas/web/authentication/DefaultServiceAuthenticationDetails.java b/cas/src/main/java/org/springframework/security/cas/web/authentication/DefaultServiceAuthenticationDetails.java
index 4dcec20df9..bb141f0bea 100644
--- a/cas/src/main/java/org/springframework/security/cas/web/authentication/DefaultServiceAuthenticationDetails.java
+++ b/cas/src/main/java/org/springframework/security/cas/web/authentication/DefaultServiceAuthenticationDetails.java
@@ -26,123 +26,128 @@ import org.springframework.security.web.util.UrlUtils;
 import org.springframework.util.Assert;
 
 /**
- * A default implementation of {@link ServiceAuthenticationDetails} that figures
- * out the value for {@link #getServiceUrl()} by inspecting the current
- * {@link HttpServletRequest} and using the current URL minus the artifact and
- * the corresponding value.
+ * A default implementation of {@link ServiceAuthenticationDetails} that figures out the
+ * value for {@link #getServiceUrl()} by inspecting the current {@link HttpServletRequest}
+ * and using the current URL minus the artifact and the corresponding value.
  *
  * @author Rob Winch
  */
-final class DefaultServiceAuthenticationDetails extends WebAuthenticationDetails implements ServiceAuthenticationDetails {
-    private static final long serialVersionUID = 6192409090610517700L;
+final class DefaultServiceAuthenticationDetails extends WebAuthenticationDetails
+		implements ServiceAuthenticationDetails {
+	private static final long serialVersionUID = 6192409090610517700L;
 
-    //~ Instance fields ================================================================================================
+	// ~ Instance fields
+	// ================================================================================================
 
-    private final String serviceUrl;
+	private final String serviceUrl;
 
-    //~ Constructors ===================================================================================================
+	// ~ Constructors
+	// ===================================================================================================
 
-    /**
-     * Creates a new instance
-     * @param request
-     *            the current {@link HttpServletRequest} to obtain the
-     *            {@link #getServiceUrl()} from.
-     * @param artifactPattern
-     *            the {@link Pattern} that will be used to clean up the query
-     *            string from containing the artifact name and value. This can
-     *            be created using {@link #createArtifactPattern(String)}.
-     */
-    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(casServiceUrl.getProtocol(),
-                casServiceUrl.getHost(), port,
-                request.getRequestURI(), query);
-    }
+	/**
+	 * Creates a new instance
+	 * @param request the current {@link HttpServletRequest} to obtain the
+	 * {@link #getServiceUrl()} from.
+	 * @param artifactPattern the {@link Pattern} that will be used to clean up the query
+	 * string from containing the artifact name and value. This can be created using
+	 * {@link #createArtifactPattern(String)}.
+	 */
+	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(casServiceUrl.getProtocol(),
+				casServiceUrl.getHost(), port, request.getRequestURI(), query);
+	}
 
-    //~ Methods ========================================================================================================
+	// ~ Methods
+	// ========================================================================================================
 
-    /**
-     * Returns the current URL minus the artifact parameter and its value, if present.
-     * @see org.springframework.security.cas.web.authentication.ServiceAuthenticationDetails#getServiceUrl()
-     */
-    public String getServiceUrl() {
-        return serviceUrl;
-    }
+	/**
+	 * Returns the current URL minus the artifact parameter and its value, if present.
+	 * @see org.springframework.security.cas.web.authentication.ServiceAuthenticationDetails#getServiceUrl()
+	 */
+	public String getServiceUrl() {
+		return serviceUrl;
+	}
 
-    @Override
-    public int hashCode() {
-        final int prime = 31;
-        int result = super.hashCode();
-        result = prime * result
-                + serviceUrl.hashCode();
-        return result;
-    }
+	@Override
+	public int hashCode() {
+		final int prime = 31;
+		int result = super.hashCode();
+		result = prime * result + serviceUrl.hashCode();
+		return result;
+	}
 
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (!super.equals(obj) || !(obj instanceof DefaultServiceAuthenticationDetails)) {
-            return false;
-        }
-        ServiceAuthenticationDetails that = (ServiceAuthenticationDetails) obj;
-        return serviceUrl.equals(that.getServiceUrl());
-    }
+	@Override
+	public boolean equals(Object obj) {
+		if (this == obj) {
+			return true;
+		}
+		if (!super.equals(obj) || !(obj instanceof DefaultServiceAuthenticationDetails)) {
+			return false;
+		}
+		ServiceAuthenticationDetails that = (ServiceAuthenticationDetails) obj;
+		return serviceUrl.equals(that.getServiceUrl());
+	}
 
-    @Override
-    public String toString() {
-        StringBuilder result = new StringBuilder();
-        result.append(super.toString());
-        result.append("ServiceUrl: ");
-        result.append(serviceUrl);
-        return result.toString();
-    }
+	@Override
+	public String toString() {
+		StringBuilder result = new StringBuilder();
+		result.append(super.toString());
+		result.append("ServiceUrl: ");
+		result.append(serviceUrl);
+		return result.toString();
+	}
 
-    /**
-     * If present, removes the artifactParameterName and the corresponding value from the query String.
-     * @param request
-     * @return the query String minus the artifactParameterName and the corresponding value.
-     */
-    private String getQueryString(final HttpServletRequest request, final Pattern artifactPattern) {
-        final String query = request.getQueryString();
-        if(query == null) {
-            return null;
-        }
-        final String result = artifactPattern.matcher(query).replaceFirst("");
-        if(result.length() == 0) {
-            return null;
-        }
-        // strip off the trailing & only if the artifact was the first query param
-        return result.startsWith("&") ? result.substring(1) : result;
-    }
+	/**
+	 * If present, removes the artifactParameterName and the corresponding value from the
+	 * query String.
+	 * @param request
+	 * @return the query String minus the artifactParameterName and the corresponding
+	 * value.
+	 */
+	private String getQueryString(final HttpServletRequest request,
+			final Pattern artifactPattern) {
+		final String query = request.getQueryString();
+		if (query == null) {
+			return null;
+		}
+		final String result = artifactPattern.matcher(query).replaceFirst("");
+		if (result.length() == 0) {
+			return null;
+		}
+		// strip off the trailing & only if the artifact was the first query param
+		return result.startsWith("&") ? result.substring(1) : result;
+	}
 
-    /**
-     * Creates a {@link Pattern} that can be passed into the constructor. This
-     * allows the {@link Pattern} to be reused for every instance of
-     * {@link DefaultServiceAuthenticationDetails}.
-     *
-     * @param artifactParameterName
-     * @return
-     */
-    static Pattern createArtifactPattern(String artifactParameterName) {
-        Assert.hasLength(artifactParameterName);
-        return Pattern.compile("&?"+Pattern.quote(artifactParameterName)+"=[^&]*");
-    }
+	/**
+	 * Creates a {@link Pattern} that can be passed into the constructor. This allows the
+	 * {@link Pattern} to be reused for every instance of
+	 * {@link DefaultServiceAuthenticationDetails}.
+	 *
+	 * @param artifactParameterName
+	 * @return
+	 */
+	static Pattern createArtifactPattern(String artifactParameterName) {
+		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/login/cas")
-     * @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;
-    }
+	/**
+	 * 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/login/cas")
+	 * @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;
+	}
 }
\ No newline at end of file
diff --git a/cas/src/main/java/org/springframework/security/cas/web/authentication/ServiceAuthenticationDetails.java b/cas/src/main/java/org/springframework/security/cas/web/authentication/ServiceAuthenticationDetails.java
index b242023c01..631a6776e4 100644
--- a/cas/src/main/java/org/springframework/security/cas/web/authentication/ServiceAuthenticationDetails.java
+++ b/cas/src/main/java/org/springframework/security/cas/web/authentication/ServiceAuthenticationDetails.java
@@ -22,10 +22,9 @@ import org.springframework.security.cas.authentication.CasAuthenticationProvider
 import org.springframework.security.core.Authentication;
 
 /**
- * In order for the {@link CasAuthenticationProvider} to provide the correct
- * service url to authenticate the ticket, the returned value of
- * {@link Authentication#getDetails()} should implement this interface when
- * tickets can be sent to any URL rather than only
+ * In order for the {@link CasAuthenticationProvider} to provide the correct service url
+ * to authenticate the ticket, the returned value of {@link Authentication#getDetails()}
+ * should implement this interface when tickets can be sent to any URL rather than only
  * {@link ServiceProperties#getService()}.
  *
  * @author Rob Winch
@@ -34,10 +33,10 @@ import org.springframework.security.core.Authentication;
  */
 public interface ServiceAuthenticationDetails extends Serializable {
 
-    /**
-     * Gets the absolute service url (i.e. https://example.com/service/).
-     *
-     * @return the service url. Cannot be null.
-     */
-    String getServiceUrl();
+	/**
+	 * Gets the absolute service url (i.e. https://example.com/service/).
+	 *
+	 * @return the service url. Cannot be null.
+	 */
+	String getServiceUrl();
 }
\ No newline at end of file
diff --git a/cas/src/main/java/org/springframework/security/cas/web/authentication/ServiceAuthenticationDetailsSource.java b/cas/src/main/java/org/springframework/security/cas/web/authentication/ServiceAuthenticationDetailsSource.java
index 813dab91fb..b032e58105 100644
--- a/cas/src/main/java/org/springframework/security/cas/web/authentication/ServiceAuthenticationDetailsSource.java
+++ b/cas/src/main/java/org/springframework/security/cas/web/authentication/ServiceAuthenticationDetailsSource.java
@@ -27,58 +27,66 @@ import org.springframework.util.Assert;
 /**
  * The {@code AuthenticationDetailsSource} that is set on the
  * {@code CasAuthenticationFilter} should return a value that implements
- * {@code ServiceAuthenticationDetails} if the application needs to authenticate
- * dynamic service urls. The
- * {@code ServiceAuthenticationDetailsSource#buildDetails(HttpServletRequest)}
- * creates a default {@code ServiceAuthenticationDetails}.
+ * {@code ServiceAuthenticationDetails} if the application needs to authenticate dynamic
+ * service urls. The
+ * {@code ServiceAuthenticationDetailsSource#buildDetails(HttpServletRequest)} creates a
+ * default {@code ServiceAuthenticationDetails}.
  *
  * @author Rob Winch
  */
-public class ServiceAuthenticationDetailsSource implements AuthenticationDetailsSource {
-    //~ Instance fields ================================================================================================
+public class ServiceAuthenticationDetailsSource implements
+		AuthenticationDetailsSource {
+	// ~ Instance fields
+	// ================================================================================================
 
-    private final Pattern artifactPattern;
+	private final Pattern artifactPattern;
 
-    private ServiceProperties serviceProperties;
+	private ServiceProperties serviceProperties;
 
-    //~ Constructors ===================================================================================================
+	// ~ Constructors
+	// ===================================================================================================
 
-    /**
-     * 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 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
-     *
-     * @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);
-    }
+	/**
+	 * 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 ========================================================================================================
+	// ~ Methods
+	// ========================================================================================================
 
-    /**
-     * @param context the {@code HttpServletRequest} object.
-     * @return the {@code ServiceAuthenticationDetails} containing information about the current request
-     */
-    public ServiceAuthenticationDetails buildDetails(HttpServletRequest context) {
-        try {
-            return new DefaultServiceAuthenticationDetails(serviceProperties.getService(),context,artifactPattern);
-        } catch (MalformedURLException e) {
-            throw new RuntimeException(e);
-        }
-    }
+	/**
+	 * @param context the {@code HttpServletRequest} object.
+	 * @return the {@code ServiceAuthenticationDetails} containing information about the
+	 * current request
+	 */
+	public ServiceAuthenticationDetails buildDetails(HttpServletRequest context) {
+		try {
+			return new DefaultServiceAuthenticationDetails(
+					serviceProperties.getService(), context, artifactPattern);
+		}
+		catch (MalformedURLException e) {
+			throw new RuntimeException(e);
+		}
+	}
 }
\ No newline at end of file
diff --git a/cas/src/main/java/org/springframework/security/cas/web/authentication/package-info.java b/cas/src/main/java/org/springframework/security/cas/web/authentication/package-info.java
index 6a26354bf0..1b58e97681 100644
--- a/cas/src/main/java/org/springframework/security/cas/web/authentication/package-info.java
+++ b/cas/src/main/java/org/springframework/security/cas/web/authentication/package-info.java
@@ -3,3 +3,4 @@
  * credentials using CAS.
  */
 package org.springframework.security.cas.web.authentication;
+
diff --git a/cas/src/test/java/org/springframework/security/cas/authentication/AbstractStatelessTicketCacheTests.java b/cas/src/test/java/org/springframework/security/cas/authentication/AbstractStatelessTicketCacheTests.java
index bce82dbd88..f0e8a741ab 100644
--- a/cas/src/test/java/org/springframework/security/cas/authentication/AbstractStatelessTicketCacheTests.java
+++ b/cas/src/test/java/org/springframework/security/cas/authentication/AbstractStatelessTicketCacheTests.java
@@ -17,15 +17,17 @@ import org.springframework.security.core.userdetails.User;
  */
 public abstract class AbstractStatelessTicketCacheTests {
 
-    protected CasAuthenticationToken getToken() {
-        List proxyList = new ArrayList();
-        proxyList.add("https://localhost/newPortal/login/cas");
+	protected CasAuthenticationToken getToken() {
+		List proxyList = new ArrayList();
+		proxyList.add("https://localhost/newPortal/login/cas");
 
-        User user = new User("rod", "password", true, true, true, true, AuthorityUtils.createAuthorityList("ROLE_ONE", "ROLE_TWO"));
-        final Assertion assertion = new AssertionImpl("rod");
+		User user = new User("rod", "password", true, true, true, true,
+				AuthorityUtils.createAuthorityList("ROLE_ONE", "ROLE_TWO"));
+		final Assertion assertion = new AssertionImpl("rod");
 
-        return new CasAuthenticationToken("key", user, "ST-0-ER94xMJmn6pha35CQRoZ",
-                AuthorityUtils.createAuthorityList("ROLE_ONE", "ROLE_TWO"), user, assertion);
-    }
+		return new CasAuthenticationToken("key", user, "ST-0-ER94xMJmn6pha35CQRoZ",
+				AuthorityUtils.createAuthorityList("ROLE_ONE", "ROLE_TWO"), user,
+				assertion);
+	}
 
 }
diff --git a/cas/src/test/java/org/springframework/security/cas/authentication/CasAuthenticationProviderTests.java b/cas/src/test/java/org/springframework/security/cas/authentication/CasAuthenticationProviderTests.java
index 495ded74d8..387515f416 100644
--- a/cas/src/test/java/org/springframework/security/cas/authentication/CasAuthenticationProviderTests.java
+++ b/cas/src/test/java/org/springframework/security/cas/authentication/CasAuthenticationProviderTests.java
@@ -41,7 +41,6 @@ import org.springframework.security.web.authentication.WebAuthenticationDetails;
 
 import java.util.*;
 
-
 /**
  * Tests {@link CasAuthenticationProvider}.
  *
@@ -50,365 +49,380 @@ import java.util.*;
  */
 @SuppressWarnings("unchecked")
 public class CasAuthenticationProviderTests {
-    //~ Methods ========================================================================================================
-
-    private UserDetails makeUserDetails() {
-        return new User("user", "password", true, true, true, true,
-                AuthorityUtils.createAuthorityList("ROLE_ONE", "ROLE_TWO"));
-    }
-
-    private UserDetails makeUserDetailsFromAuthoritiesPopulator() {
-        return new User("user", "password", true, true, true, true,
-                AuthorityUtils.createAuthorityList("ROLE_A", "ROLE_B"));
-    }
-
-    private ServiceProperties makeServiceProperties() {
-        final ServiceProperties serviceProperties = new ServiceProperties();
-        serviceProperties.setSendRenew(false);
-        serviceProperties.setService("http://test.com");
-
-        return serviceProperties;
-    }
-
-    @Test
-    public void statefulAuthenticationIsSuccessful() throws Exception {
-        CasAuthenticationProvider cap = new CasAuthenticationProvider();
-        cap.setAuthenticationUserDetailsService(new MockAuthoritiesPopulator());
-        cap.setKey("qwerty");
-
-        StatelessTicketCache cache = new MockStatelessTicketCache();
-        cap.setStatelessTicketCache(cache);
-        cap.setServiceProperties(makeServiceProperties());
-
-        cap.setTicketValidator(new MockTicketValidator(true));
-        cap.afterPropertiesSet();
-
-        UsernamePasswordAuthenticationToken token =
-            new UsernamePasswordAuthenticationToken(CasAuthenticationFilter.CAS_STATEFUL_IDENTIFIER, "ST-123");
-        token.setDetails("details");
-
-        Authentication result = cap.authenticate(token);
-
-        // Confirm ST-123 was NOT added to the cache
-        assertTrue(cache.getByTicketId("ST-456") == null);
-
-        if (!(result instanceof CasAuthenticationToken)) {
-            fail("Should have returned a CasAuthenticationToken");
-        }
-
-        CasAuthenticationToken casResult = (CasAuthenticationToken) result;
-        assertEquals(makeUserDetailsFromAuthoritiesPopulator(), casResult.getPrincipal());
-        assertEquals("ST-123", casResult.getCredentials());
-        assertTrue(casResult.getAuthorities().contains(new SimpleGrantedAuthority("ROLE_A")));
-        assertTrue(casResult.getAuthorities().contains(new SimpleGrantedAuthority("ROLE_B")));
-        assertEquals(cap.getKey().hashCode(), casResult.getKeyHash());
-        assertEquals("details", casResult.getDetails());
-
-        // Now confirm the CasAuthenticationToken is automatically re-accepted.
-        // To ensure TicketValidator not called again, set it to deliver an exception...
-        cap.setTicketValidator(new MockTicketValidator(false));
-
-        Authentication laterResult = cap.authenticate(result);
-        assertEquals(result, laterResult);
-    }
-
-    @Test
-    public void statelessAuthenticationIsSuccessful() throws Exception {
-        CasAuthenticationProvider cap = new CasAuthenticationProvider();
-        cap.setAuthenticationUserDetailsService(new MockAuthoritiesPopulator());
-        cap.setKey("qwerty");
-
-        StatelessTicketCache cache = new MockStatelessTicketCache();
-        cap.setStatelessTicketCache(cache);
-        cap.setTicketValidator(new MockTicketValidator(true));
-        cap.setServiceProperties(makeServiceProperties());
-        cap.afterPropertiesSet();
-
-        UsernamePasswordAuthenticationToken token =
-            new UsernamePasswordAuthenticationToken(CasAuthenticationFilter.CAS_STATELESS_IDENTIFIER, "ST-456");
-        token.setDetails("details");
-
-        Authentication result = cap.authenticate(token);
-
-        // Confirm ST-456 was added to the cache
-        assertTrue(cache.getByTicketId("ST-456") != null);
-
-        if (!(result instanceof CasAuthenticationToken)) {
-            fail("Should have returned a CasAuthenticationToken");
-        }
-
-        assertEquals(makeUserDetailsFromAuthoritiesPopulator(), result.getPrincipal());
-        assertEquals("ST-456", result.getCredentials());
-        assertEquals("details", result.getDetails());
-
-        // Now try to authenticate again. To ensure TicketValidator not
-        // called again, set it to deliver an exception...
-        cap.setTicketValidator(new MockTicketValidator(false));
-
-        // Previously created UsernamePasswordAuthenticationToken is OK
-        Authentication newResult = cap.authenticate(token);
-        assertEquals(makeUserDetailsFromAuthoritiesPopulator(), newResult.getPrincipal());
-        assertEquals("ST-456", newResult.getCredentials());
-    }
-
-    @Test
-    public void authenticateAllNullService() throws Exception {
-        String serviceUrl = "https://service/context";
-        ServiceAuthenticationDetails details = mock(ServiceAuthenticationDetails.class);
-        when(details.getServiceUrl()).thenReturn(serviceUrl);
-        TicketValidator validator = mock(TicketValidator.class);
-        when(validator.validate(any(String.class),any(String.class))).thenReturn(new AssertionImpl("rod"));
-
-        ServiceProperties serviceProperties = makeServiceProperties();
-        serviceProperties.setAuthenticateAllArtifacts(true);
-
-        CasAuthenticationProvider cap = new CasAuthenticationProvider();
-        cap.setAuthenticationUserDetailsService(new MockAuthoritiesPopulator());
-        cap.setKey("qwerty");
-
-        cap.setTicketValidator(validator);
-        cap.setServiceProperties(serviceProperties);
-        cap.afterPropertiesSet();
-
-        String ticket = "ST-456";
-        UsernamePasswordAuthenticationToken token =
-            new UsernamePasswordAuthenticationToken(CasAuthenticationFilter.CAS_STATELESS_IDENTIFIER, ticket);
-
-        Authentication result = cap.authenticate(token);
-    }
-
-    @Test
-    public void authenticateAllAuthenticationIsSuccessful() throws Exception {
-        String serviceUrl = "https://service/context";
-        ServiceAuthenticationDetails details = mock(ServiceAuthenticationDetails.class);
-        when(details.getServiceUrl()).thenReturn(serviceUrl);
-        TicketValidator validator = mock(TicketValidator.class);
-        when(validator.validate(any(String.class),any(String.class))).thenReturn(new AssertionImpl("rod"));
-
-        ServiceProperties serviceProperties = makeServiceProperties();
-        serviceProperties.setAuthenticateAllArtifacts(true);
-
-        CasAuthenticationProvider cap = new CasAuthenticationProvider();
-        cap.setAuthenticationUserDetailsService(new MockAuthoritiesPopulator());
-        cap.setKey("qwerty");
-
-        cap.setTicketValidator(validator);
-        cap.setServiceProperties(serviceProperties);
-        cap.afterPropertiesSet();
-
-        String ticket = "ST-456";
-        UsernamePasswordAuthenticationToken token =
-            new UsernamePasswordAuthenticationToken(CasAuthenticationFilter.CAS_STATELESS_IDENTIFIER, ticket);
-
-        Authentication result = cap.authenticate(token);
-        verify(validator).validate(ticket, serviceProperties.getService());
-
-        serviceProperties.setAuthenticateAllArtifacts(true);
-        result = cap.authenticate(token);
-        verify(validator,times(2)).validate(ticket, serviceProperties.getService());
-
-        token.setDetails(details);
-        result = cap.authenticate(token);
-        verify(validator).validate(ticket, serviceUrl);
-
-        serviceProperties.setAuthenticateAllArtifacts(false);
-        serviceProperties.setService(null);
-        cap.setServiceProperties(serviceProperties);
-        cap.afterPropertiesSet();
-        result = cap.authenticate(token);
-        verify(validator,times(2)).validate(ticket, serviceUrl);
-
-        token.setDetails(new WebAuthenticationDetails(new MockHttpServletRequest()));
-        try {
-            cap.authenticate(token);
-            fail("Expected Exception");
-        }catch(IllegalStateException success) {}
-
-        cap.setServiceProperties(null);
-        cap.afterPropertiesSet();
-        try {
-            cap.authenticate(token);
-            fail("Expected Exception");
-        }catch(IllegalStateException success) {}
-    }
-
-    @Test(expected = BadCredentialsException.class)
-    public void missingTicketIdIsDetected() throws Exception {
-        CasAuthenticationProvider cap = new CasAuthenticationProvider();
-        cap.setAuthenticationUserDetailsService(new MockAuthoritiesPopulator());
-        cap.setKey("qwerty");
-
-        StatelessTicketCache cache = new MockStatelessTicketCache();
-        cap.setStatelessTicketCache(cache);
-        cap.setTicketValidator(new MockTicketValidator(true));
-        cap.setServiceProperties(makeServiceProperties());
-        cap.afterPropertiesSet();
-
-        UsernamePasswordAuthenticationToken token =
-                new UsernamePasswordAuthenticationToken(CasAuthenticationFilter.CAS_STATEFUL_IDENTIFIER, "");
-
-        cap.authenticate(token);
-    }
-
-    @Test(expected = BadCredentialsException.class)
-    public void invalidKeyIsDetected() throws Exception {
-        final Assertion assertion = new AssertionImpl("test");
-        CasAuthenticationProvider cap = new CasAuthenticationProvider();
-        cap.setAuthenticationUserDetailsService(new MockAuthoritiesPopulator());
-        cap.setKey("qwerty");
-
-        StatelessTicketCache cache = new MockStatelessTicketCache();
-        cap.setStatelessTicketCache(cache);
-        cap.setTicketValidator(new MockTicketValidator(true));
-        cap.setServiceProperties(makeServiceProperties());
-        cap.afterPropertiesSet();
-
-        CasAuthenticationToken token = new CasAuthenticationToken("WRONG_KEY", makeUserDetails(), "credentials",
-                AuthorityUtils.createAuthorityList("XX"), makeUserDetails(), assertion);
-
-        cap.authenticate(token);
-    }
-
-    @Test(expected = IllegalArgumentException.class)
-    public void detectsMissingAuthoritiesPopulator() throws Exception {
-        CasAuthenticationProvider cap = new CasAuthenticationProvider();
-        cap.setKey("qwerty");
-        cap.setStatelessTicketCache(new MockStatelessTicketCache());
-        cap.setTicketValidator(new MockTicketValidator(true));
-        cap.setServiceProperties(makeServiceProperties());
-        cap.afterPropertiesSet();
-    }
-
-    @Test(expected = IllegalArgumentException.class)
-    public void detectsMissingKey() throws Exception {
-        CasAuthenticationProvider cap = new CasAuthenticationProvider();
-        cap.setAuthenticationUserDetailsService(new MockAuthoritiesPopulator());
-        cap.setStatelessTicketCache(new MockStatelessTicketCache());
-        cap.setTicketValidator(new MockTicketValidator(true));
-        cap.setServiceProperties(makeServiceProperties());
-        cap.afterPropertiesSet();
-    }
-
-    @Test(expected = IllegalArgumentException.class)
-    public void detectsMissingStatelessTicketCache() throws Exception {
-        CasAuthenticationProvider cap = new CasAuthenticationProvider();
-        // set this explicitly to null to test failure
-        cap.setStatelessTicketCache(null);
-        cap.setAuthenticationUserDetailsService(new MockAuthoritiesPopulator());
-        cap.setKey("qwerty");
-        cap.setTicketValidator(new MockTicketValidator(true));
-        cap.setServiceProperties(makeServiceProperties());
-        cap.afterPropertiesSet();
-    }
-
-    @Test(expected = IllegalArgumentException.class)
-    public void detectsMissingTicketValidator() throws Exception {
-        CasAuthenticationProvider cap = new CasAuthenticationProvider();
-        cap.setAuthenticationUserDetailsService(new MockAuthoritiesPopulator());
-        cap.setKey("qwerty");
-        cap.setStatelessTicketCache(new MockStatelessTicketCache());
-        cap.setServiceProperties(makeServiceProperties());
-        cap.afterPropertiesSet();
-    }
-
-    @Test
-    public void gettersAndSettersMatch() throws Exception {
-        CasAuthenticationProvider cap = new CasAuthenticationProvider();
-        cap.setAuthenticationUserDetailsService(new MockAuthoritiesPopulator());
-        cap.setKey("qwerty");
-        cap.setStatelessTicketCache(new MockStatelessTicketCache());
-        cap.setTicketValidator(new MockTicketValidator(true));
-        cap.setServiceProperties(makeServiceProperties());
-        cap.afterPropertiesSet();
-
-// TODO disabled because why do we need to expose this?
-//        assertTrue(cap.getUserDetailsService() != null);
-        assertEquals("qwerty", cap.getKey());
-        assertTrue(cap.getStatelessTicketCache() != null);
-        assertTrue(cap.getTicketValidator() != null);
-    }
-
-    @Test
-    public void ignoresClassesItDoesNotSupport() throws Exception {
-        CasAuthenticationProvider cap = new CasAuthenticationProvider();
-        cap.setAuthenticationUserDetailsService(new MockAuthoritiesPopulator());
-        cap.setKey("qwerty");
-        cap.setStatelessTicketCache(new MockStatelessTicketCache());
-        cap.setTicketValidator(new MockTicketValidator(true));
-        cap.setServiceProperties(makeServiceProperties());
-        cap.afterPropertiesSet();
-
-        TestingAuthenticationToken token = new TestingAuthenticationToken("user", "password", "ROLE_A");
-        assertFalse(cap.supports(TestingAuthenticationToken.class));
-
-        // Try it anyway
-        assertEquals(null, cap.authenticate(token));
-    }
-
-    @Test
-    public void ignoresUsernamePasswordAuthenticationTokensWithoutCasIdentifiersAsPrincipal() throws Exception {
-        CasAuthenticationProvider cap = new CasAuthenticationProvider();
-        cap.setAuthenticationUserDetailsService(new MockAuthoritiesPopulator());
-        cap.setKey("qwerty");
-        cap.setStatelessTicketCache(new MockStatelessTicketCache());
-        cap.setTicketValidator(new MockTicketValidator(true));
-        cap.setServiceProperties(makeServiceProperties());
-        cap.afterPropertiesSet();
-
-        UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("some_normal_user",
-                "password", AuthorityUtils.createAuthorityList("ROLE_A"));
-        assertEquals(null, cap.authenticate(token));
-    }
-
-    @Test
-    public void supportsRequiredTokens() {
-        CasAuthenticationProvider cap = new CasAuthenticationProvider();
-        assertTrue(cap.supports(UsernamePasswordAuthenticationToken.class));
-        assertTrue(cap.supports(CasAuthenticationToken.class));
-    }
-
-    //~ Inner Classes ==================================================================================================
-
-    private class MockAuthoritiesPopulator implements AuthenticationUserDetailsService {
-
-        public UserDetails loadUserDetails(final Authentication token) throws UsernameNotFoundException {
-            return makeUserDetailsFromAuthoritiesPopulator();
-        }
-    }
-
-    private class MockStatelessTicketCache implements StatelessTicketCache {
-        private Map cache = new HashMap();
-
-        public CasAuthenticationToken getByTicketId(String serviceTicket) {
-            return cache.get(serviceTicket);
-        }
-
-        public void putTicketInCache(CasAuthenticationToken token) {
-            cache.put(token.getCredentials().toString(), token);
-        }
-
-        public void removeTicketFromCache(CasAuthenticationToken token) {
-            throw new UnsupportedOperationException("mock method not implemented");
-        }
-
-        public void removeTicketFromCache(String serviceTicket) {
-            throw new UnsupportedOperationException("mock method not implemented");
-        }
-    }
-
-    private class MockTicketValidator implements TicketValidator {
-        private boolean returnTicket;
-
-        public MockTicketValidator(boolean returnTicket) {
-            this.returnTicket = returnTicket;
-        }
-
-        public Assertion validate(final String ticket, final String service)
-                throws TicketValidationException {
-            if (returnTicket) {
-                return new AssertionImpl("rod");
-            }
-            throw new BadCredentialsException("As requested from mock");
-        }
-    }
+	// ~ Methods
+	// ========================================================================================================
+
+	private UserDetails makeUserDetails() {
+		return new User("user", "password", true, true, true, true,
+				AuthorityUtils.createAuthorityList("ROLE_ONE", "ROLE_TWO"));
+	}
+
+	private UserDetails makeUserDetailsFromAuthoritiesPopulator() {
+		return new User("user", "password", true, true, true, true,
+				AuthorityUtils.createAuthorityList("ROLE_A", "ROLE_B"));
+	}
+
+	private ServiceProperties makeServiceProperties() {
+		final ServiceProperties serviceProperties = new ServiceProperties();
+		serviceProperties.setSendRenew(false);
+		serviceProperties.setService("http://test.com");
+
+		return serviceProperties;
+	}
+
+	@Test
+	public void statefulAuthenticationIsSuccessful() throws Exception {
+		CasAuthenticationProvider cap = new CasAuthenticationProvider();
+		cap.setAuthenticationUserDetailsService(new MockAuthoritiesPopulator());
+		cap.setKey("qwerty");
+
+		StatelessTicketCache cache = new MockStatelessTicketCache();
+		cap.setStatelessTicketCache(cache);
+		cap.setServiceProperties(makeServiceProperties());
+
+		cap.setTicketValidator(new MockTicketValidator(true));
+		cap.afterPropertiesSet();
+
+		UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(
+				CasAuthenticationFilter.CAS_STATEFUL_IDENTIFIER, "ST-123");
+		token.setDetails("details");
+
+		Authentication result = cap.authenticate(token);
+
+		// Confirm ST-123 was NOT added to the cache
+		assertTrue(cache.getByTicketId("ST-456") == null);
+
+		if (!(result instanceof CasAuthenticationToken)) {
+			fail("Should have returned a CasAuthenticationToken");
+		}
+
+		CasAuthenticationToken casResult = (CasAuthenticationToken) result;
+		assertEquals(makeUserDetailsFromAuthoritiesPopulator(), casResult.getPrincipal());
+		assertEquals("ST-123", casResult.getCredentials());
+		assertTrue(casResult.getAuthorities().contains(
+				new SimpleGrantedAuthority("ROLE_A")));
+		assertTrue(casResult.getAuthorities().contains(
+				new SimpleGrantedAuthority("ROLE_B")));
+		assertEquals(cap.getKey().hashCode(), casResult.getKeyHash());
+		assertEquals("details", casResult.getDetails());
+
+		// Now confirm the CasAuthenticationToken is automatically re-accepted.
+		// To ensure TicketValidator not called again, set it to deliver an exception...
+		cap.setTicketValidator(new MockTicketValidator(false));
+
+		Authentication laterResult = cap.authenticate(result);
+		assertEquals(result, laterResult);
+	}
+
+	@Test
+	public void statelessAuthenticationIsSuccessful() throws Exception {
+		CasAuthenticationProvider cap = new CasAuthenticationProvider();
+		cap.setAuthenticationUserDetailsService(new MockAuthoritiesPopulator());
+		cap.setKey("qwerty");
+
+		StatelessTicketCache cache = new MockStatelessTicketCache();
+		cap.setStatelessTicketCache(cache);
+		cap.setTicketValidator(new MockTicketValidator(true));
+		cap.setServiceProperties(makeServiceProperties());
+		cap.afterPropertiesSet();
+
+		UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(
+				CasAuthenticationFilter.CAS_STATELESS_IDENTIFIER, "ST-456");
+		token.setDetails("details");
+
+		Authentication result = cap.authenticate(token);
+
+		// Confirm ST-456 was added to the cache
+		assertTrue(cache.getByTicketId("ST-456") != null);
+
+		if (!(result instanceof CasAuthenticationToken)) {
+			fail("Should have returned a CasAuthenticationToken");
+		}
+
+		assertEquals(makeUserDetailsFromAuthoritiesPopulator(), result.getPrincipal());
+		assertEquals("ST-456", result.getCredentials());
+		assertEquals("details", result.getDetails());
+
+		// Now try to authenticate again. To ensure TicketValidator not
+		// called again, set it to deliver an exception...
+		cap.setTicketValidator(new MockTicketValidator(false));
+
+		// Previously created UsernamePasswordAuthenticationToken is OK
+		Authentication newResult = cap.authenticate(token);
+		assertEquals(makeUserDetailsFromAuthoritiesPopulator(), newResult.getPrincipal());
+		assertEquals("ST-456", newResult.getCredentials());
+	}
+
+	@Test
+	public void authenticateAllNullService() throws Exception {
+		String serviceUrl = "https://service/context";
+		ServiceAuthenticationDetails details = mock(ServiceAuthenticationDetails.class);
+		when(details.getServiceUrl()).thenReturn(serviceUrl);
+		TicketValidator validator = mock(TicketValidator.class);
+		when(validator.validate(any(String.class), any(String.class))).thenReturn(
+				new AssertionImpl("rod"));
+
+		ServiceProperties serviceProperties = makeServiceProperties();
+		serviceProperties.setAuthenticateAllArtifacts(true);
+
+		CasAuthenticationProvider cap = new CasAuthenticationProvider();
+		cap.setAuthenticationUserDetailsService(new MockAuthoritiesPopulator());
+		cap.setKey("qwerty");
+
+		cap.setTicketValidator(validator);
+		cap.setServiceProperties(serviceProperties);
+		cap.afterPropertiesSet();
+
+		String ticket = "ST-456";
+		UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(
+				CasAuthenticationFilter.CAS_STATELESS_IDENTIFIER, ticket);
+
+		Authentication result = cap.authenticate(token);
+	}
+
+	@Test
+	public void authenticateAllAuthenticationIsSuccessful() throws Exception {
+		String serviceUrl = "https://service/context";
+		ServiceAuthenticationDetails details = mock(ServiceAuthenticationDetails.class);
+		when(details.getServiceUrl()).thenReturn(serviceUrl);
+		TicketValidator validator = mock(TicketValidator.class);
+		when(validator.validate(any(String.class), any(String.class))).thenReturn(
+				new AssertionImpl("rod"));
+
+		ServiceProperties serviceProperties = makeServiceProperties();
+		serviceProperties.setAuthenticateAllArtifacts(true);
+
+		CasAuthenticationProvider cap = new CasAuthenticationProvider();
+		cap.setAuthenticationUserDetailsService(new MockAuthoritiesPopulator());
+		cap.setKey("qwerty");
+
+		cap.setTicketValidator(validator);
+		cap.setServiceProperties(serviceProperties);
+		cap.afterPropertiesSet();
+
+		String ticket = "ST-456";
+		UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(
+				CasAuthenticationFilter.CAS_STATELESS_IDENTIFIER, ticket);
+
+		Authentication result = cap.authenticate(token);
+		verify(validator).validate(ticket, serviceProperties.getService());
+
+		serviceProperties.setAuthenticateAllArtifacts(true);
+		result = cap.authenticate(token);
+		verify(validator, times(2)).validate(ticket, serviceProperties.getService());
+
+		token.setDetails(details);
+		result = cap.authenticate(token);
+		verify(validator).validate(ticket, serviceUrl);
+
+		serviceProperties.setAuthenticateAllArtifacts(false);
+		serviceProperties.setService(null);
+		cap.setServiceProperties(serviceProperties);
+		cap.afterPropertiesSet();
+		result = cap.authenticate(token);
+		verify(validator, times(2)).validate(ticket, serviceUrl);
+
+		token.setDetails(new WebAuthenticationDetails(new MockHttpServletRequest()));
+		try {
+			cap.authenticate(token);
+			fail("Expected Exception");
+		}
+		catch (IllegalStateException success) {
+		}
+
+		cap.setServiceProperties(null);
+		cap.afterPropertiesSet();
+		try {
+			cap.authenticate(token);
+			fail("Expected Exception");
+		}
+		catch (IllegalStateException success) {
+		}
+	}
+
+	@Test(expected = BadCredentialsException.class)
+	public void missingTicketIdIsDetected() throws Exception {
+		CasAuthenticationProvider cap = new CasAuthenticationProvider();
+		cap.setAuthenticationUserDetailsService(new MockAuthoritiesPopulator());
+		cap.setKey("qwerty");
+
+		StatelessTicketCache cache = new MockStatelessTicketCache();
+		cap.setStatelessTicketCache(cache);
+		cap.setTicketValidator(new MockTicketValidator(true));
+		cap.setServiceProperties(makeServiceProperties());
+		cap.afterPropertiesSet();
+
+		UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(
+				CasAuthenticationFilter.CAS_STATEFUL_IDENTIFIER, "");
+
+		cap.authenticate(token);
+	}
+
+	@Test(expected = BadCredentialsException.class)
+	public void invalidKeyIsDetected() throws Exception {
+		final Assertion assertion = new AssertionImpl("test");
+		CasAuthenticationProvider cap = new CasAuthenticationProvider();
+		cap.setAuthenticationUserDetailsService(new MockAuthoritiesPopulator());
+		cap.setKey("qwerty");
+
+		StatelessTicketCache cache = new MockStatelessTicketCache();
+		cap.setStatelessTicketCache(cache);
+		cap.setTicketValidator(new MockTicketValidator(true));
+		cap.setServiceProperties(makeServiceProperties());
+		cap.afterPropertiesSet();
+
+		CasAuthenticationToken token = new CasAuthenticationToken("WRONG_KEY",
+				makeUserDetails(), "credentials",
+				AuthorityUtils.createAuthorityList("XX"), makeUserDetails(), assertion);
+
+		cap.authenticate(token);
+	}
+
+	@Test(expected = IllegalArgumentException.class)
+	public void detectsMissingAuthoritiesPopulator() throws Exception {
+		CasAuthenticationProvider cap = new CasAuthenticationProvider();
+		cap.setKey("qwerty");
+		cap.setStatelessTicketCache(new MockStatelessTicketCache());
+		cap.setTicketValidator(new MockTicketValidator(true));
+		cap.setServiceProperties(makeServiceProperties());
+		cap.afterPropertiesSet();
+	}
+
+	@Test(expected = IllegalArgumentException.class)
+	public void detectsMissingKey() throws Exception {
+		CasAuthenticationProvider cap = new CasAuthenticationProvider();
+		cap.setAuthenticationUserDetailsService(new MockAuthoritiesPopulator());
+		cap.setStatelessTicketCache(new MockStatelessTicketCache());
+		cap.setTicketValidator(new MockTicketValidator(true));
+		cap.setServiceProperties(makeServiceProperties());
+		cap.afterPropertiesSet();
+	}
+
+	@Test(expected = IllegalArgumentException.class)
+	public void detectsMissingStatelessTicketCache() throws Exception {
+		CasAuthenticationProvider cap = new CasAuthenticationProvider();
+		// set this explicitly to null to test failure
+		cap.setStatelessTicketCache(null);
+		cap.setAuthenticationUserDetailsService(new MockAuthoritiesPopulator());
+		cap.setKey("qwerty");
+		cap.setTicketValidator(new MockTicketValidator(true));
+		cap.setServiceProperties(makeServiceProperties());
+		cap.afterPropertiesSet();
+	}
+
+	@Test(expected = IllegalArgumentException.class)
+	public void detectsMissingTicketValidator() throws Exception {
+		CasAuthenticationProvider cap = new CasAuthenticationProvider();
+		cap.setAuthenticationUserDetailsService(new MockAuthoritiesPopulator());
+		cap.setKey("qwerty");
+		cap.setStatelessTicketCache(new MockStatelessTicketCache());
+		cap.setServiceProperties(makeServiceProperties());
+		cap.afterPropertiesSet();
+	}
+
+	@Test
+	public void gettersAndSettersMatch() throws Exception {
+		CasAuthenticationProvider cap = new CasAuthenticationProvider();
+		cap.setAuthenticationUserDetailsService(new MockAuthoritiesPopulator());
+		cap.setKey("qwerty");
+		cap.setStatelessTicketCache(new MockStatelessTicketCache());
+		cap.setTicketValidator(new MockTicketValidator(true));
+		cap.setServiceProperties(makeServiceProperties());
+		cap.afterPropertiesSet();
+
+		// TODO disabled because why do we need to expose this?
+		// assertTrue(cap.getUserDetailsService() != null);
+		assertEquals("qwerty", cap.getKey());
+		assertTrue(cap.getStatelessTicketCache() != null);
+		assertTrue(cap.getTicketValidator() != null);
+	}
+
+	@Test
+	public void ignoresClassesItDoesNotSupport() throws Exception {
+		CasAuthenticationProvider cap = new CasAuthenticationProvider();
+		cap.setAuthenticationUserDetailsService(new MockAuthoritiesPopulator());
+		cap.setKey("qwerty");
+		cap.setStatelessTicketCache(new MockStatelessTicketCache());
+		cap.setTicketValidator(new MockTicketValidator(true));
+		cap.setServiceProperties(makeServiceProperties());
+		cap.afterPropertiesSet();
+
+		TestingAuthenticationToken token = new TestingAuthenticationToken("user",
+				"password", "ROLE_A");
+		assertFalse(cap.supports(TestingAuthenticationToken.class));
+
+		// Try it anyway
+		assertEquals(null, cap.authenticate(token));
+	}
+
+	@Test
+	public void ignoresUsernamePasswordAuthenticationTokensWithoutCasIdentifiersAsPrincipal()
+			throws Exception {
+		CasAuthenticationProvider cap = new CasAuthenticationProvider();
+		cap.setAuthenticationUserDetailsService(new MockAuthoritiesPopulator());
+		cap.setKey("qwerty");
+		cap.setStatelessTicketCache(new MockStatelessTicketCache());
+		cap.setTicketValidator(new MockTicketValidator(true));
+		cap.setServiceProperties(makeServiceProperties());
+		cap.afterPropertiesSet();
+
+		UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(
+				"some_normal_user", "password",
+				AuthorityUtils.createAuthorityList("ROLE_A"));
+		assertEquals(null, cap.authenticate(token));
+	}
+
+	@Test
+	public void supportsRequiredTokens() {
+		CasAuthenticationProvider cap = new CasAuthenticationProvider();
+		assertTrue(cap.supports(UsernamePasswordAuthenticationToken.class));
+		assertTrue(cap.supports(CasAuthenticationToken.class));
+	}
+
+	// ~ Inner Classes
+	// ==================================================================================================
+
+	private class MockAuthoritiesPopulator implements AuthenticationUserDetailsService {
+
+		public UserDetails loadUserDetails(final Authentication token)
+				throws UsernameNotFoundException {
+			return makeUserDetailsFromAuthoritiesPopulator();
+		}
+	}
+
+	private class MockStatelessTicketCache implements StatelessTicketCache {
+		private Map cache = new HashMap();
+
+		public CasAuthenticationToken getByTicketId(String serviceTicket) {
+			return cache.get(serviceTicket);
+		}
+
+		public void putTicketInCache(CasAuthenticationToken token) {
+			cache.put(token.getCredentials().toString(), token);
+		}
+
+		public void removeTicketFromCache(CasAuthenticationToken token) {
+			throw new UnsupportedOperationException("mock method not implemented");
+		}
+
+		public void removeTicketFromCache(String serviceTicket) {
+			throw new UnsupportedOperationException("mock method not implemented");
+		}
+	}
+
+	private class MockTicketValidator implements TicketValidator {
+		private boolean returnTicket;
+
+		public MockTicketValidator(boolean returnTicket) {
+			this.returnTicket = returnTicket;
+		}
+
+		public Assertion validate(final String ticket, final String service)
+				throws TicketValidationException {
+			if (returnTicket) {
+				return new AssertionImpl("rod");
+			}
+			throw new BadCredentialsException("As requested from mock");
+		}
+	}
 }
diff --git a/cas/src/test/java/org/springframework/security/cas/authentication/CasAuthenticationTokenTests.java b/cas/src/test/java/org/springframework/security/cas/authentication/CasAuthenticationTokenTests.java
index 16dc11f1d6..c392d6a7ce 100644
--- a/cas/src/test/java/org/springframework/security/cas/authentication/CasAuthenticationTokenTests.java
+++ b/cas/src/test/java/org/springframework/security/cas/authentication/CasAuthenticationTokenTests.java
@@ -33,156 +33,176 @@ import java.util.*;
  * @author Ben Alex
  */
 public class CasAuthenticationTokenTests extends TestCase {
-    private final List ROLES = AuthorityUtils.createAuthorityList("ROLE_ONE","ROLE_TWO");
+	private final List ROLES = AuthorityUtils.createAuthorityList(
+			"ROLE_ONE", "ROLE_TWO");
 
-    private UserDetails makeUserDetails() {
-        return makeUserDetails("user");
-    }
+	private UserDetails makeUserDetails() {
+		return makeUserDetails("user");
+	}
 
-    private UserDetails makeUserDetails(final String name) {
-        return new User(name, "password", true, true, true, true, ROLES);
-    }
+	private UserDetails makeUserDetails(final String name) {
+		return new User(name, "password", true, true, true, true, ROLES);
+	}
 
-    public final void setUp() throws Exception {
-        super.setUp();
-    }
+	public final void setUp() throws Exception {
+		super.setUp();
+	}
 
-    public void testConstructorRejectsNulls() {
-        final Assertion assertion = new AssertionImpl("test");
-        try {
-            new CasAuthenticationToken(null, makeUserDetails(), "Password", ROLES, makeUserDetails(), assertion);
-            fail("Should have thrown IllegalArgumentException");
-        } catch (IllegalArgumentException expected) {
-        }
+	public void testConstructorRejectsNulls() {
+		final Assertion assertion = new AssertionImpl("test");
+		try {
+			new CasAuthenticationToken(null, makeUserDetails(), "Password", ROLES,
+					makeUserDetails(), assertion);
+			fail("Should have thrown IllegalArgumentException");
+		}
+		catch (IllegalArgumentException expected) {
+		}
 
-        try {
-            new CasAuthenticationToken("key", null, "Password", ROLES, makeUserDetails(), assertion);
-            fail("Should have thrown IllegalArgumentException");
-        } catch (IllegalArgumentException expected) {
-        }
+		try {
+			new CasAuthenticationToken("key", null, "Password", ROLES, makeUserDetails(),
+					assertion);
+			fail("Should have thrown IllegalArgumentException");
+		}
+		catch (IllegalArgumentException expected) {
+		}
 
-        try {
-            new CasAuthenticationToken("key", makeUserDetails(), null, ROLES, makeUserDetails(), assertion);
-            fail("Should have thrown IllegalArgumentException");
-        } catch (IllegalArgumentException expected) {
-        }
+		try {
+			new CasAuthenticationToken("key", makeUserDetails(), null, ROLES,
+					makeUserDetails(), assertion);
+			fail("Should have thrown IllegalArgumentException");
+		}
+		catch (IllegalArgumentException expected) {
+		}
 
-        try {
-            new CasAuthenticationToken("key", makeUserDetails(), "Password", ROLES, makeUserDetails(), null);
-            fail("Should have thrown IllegalArgumentException");
-        } catch (IllegalArgumentException expected) {
-        }
+		try {
+			new CasAuthenticationToken("key", makeUserDetails(), "Password", ROLES,
+					makeUserDetails(), null);
+			fail("Should have thrown IllegalArgumentException");
+		}
+		catch (IllegalArgumentException expected) {
+		}
 
-        try {
-            new CasAuthenticationToken("key", makeUserDetails(), "Password", ROLES, null, assertion);
-            fail("Should have thrown IllegalArgumentException");
-        } catch (IllegalArgumentException expected) {
-        }
+		try {
+			new CasAuthenticationToken("key", makeUserDetails(), "Password", ROLES, null,
+					assertion);
+			fail("Should have thrown IllegalArgumentException");
+		}
+		catch (IllegalArgumentException expected) {
+		}
 
-        try {
-            new CasAuthenticationToken("key", makeUserDetails(), "Password", AuthorityUtils.createAuthorityList("ROLE_1", null), makeUserDetails(), assertion);
-            fail("Should have thrown IllegalArgumentException");
-        } catch (IllegalArgumentException expected) {
-            assertTrue(true);
-        }
-    }
+		try {
+			new CasAuthenticationToken("key", makeUserDetails(), "Password",
+					AuthorityUtils.createAuthorityList("ROLE_1", null),
+					makeUserDetails(), assertion);
+			fail("Should have thrown IllegalArgumentException");
+		}
+		catch (IllegalArgumentException expected) {
+			assertTrue(true);
+		}
+	}
 
-    public void testEqualsWhenEqual() {
-        final Assertion assertion = new AssertionImpl("test");
+	public void testEqualsWhenEqual() {
+		final Assertion assertion = new AssertionImpl("test");
 
-        CasAuthenticationToken token1 = new CasAuthenticationToken("key", makeUserDetails(), "Password", ROLES,
-                makeUserDetails(), assertion);
+		CasAuthenticationToken token1 = new CasAuthenticationToken("key",
+				makeUserDetails(), "Password", ROLES, makeUserDetails(), assertion);
 
-        CasAuthenticationToken token2 = new CasAuthenticationToken("key", makeUserDetails(), "Password", ROLES,
-                makeUserDetails(), assertion);
+		CasAuthenticationToken token2 = new CasAuthenticationToken("key",
+				makeUserDetails(), "Password", ROLES, makeUserDetails(), assertion);
 
-        assertEquals(token1, token2);
-    }
+		assertEquals(token1, token2);
+	}
 
-    public void testGetters() {
-        // Build the proxy list returned in the ticket from CAS
-        final Assertion assertion = new AssertionImpl("test");
-        CasAuthenticationToken token = new CasAuthenticationToken("key", makeUserDetails(), "Password", ROLES,
-                makeUserDetails(), assertion);
-        assertEquals("key".hashCode(), token.getKeyHash());
-        assertEquals(makeUserDetails(), token.getPrincipal());
-        assertEquals("Password", token.getCredentials());
-        assertTrue(token.getAuthorities().contains(new SimpleGrantedAuthority("ROLE_ONE")));
-        assertTrue(token.getAuthorities().contains(new SimpleGrantedAuthority("ROLE_TWO")));
-        assertEquals(assertion, token.getAssertion());
-        assertEquals(makeUserDetails().getUsername(), token.getUserDetails().getUsername());
-    }
+	public void testGetters() {
+		// Build the proxy list returned in the ticket from CAS
+		final Assertion assertion = new AssertionImpl("test");
+		CasAuthenticationToken token = new CasAuthenticationToken("key",
+				makeUserDetails(), "Password", ROLES, makeUserDetails(), assertion);
+		assertEquals("key".hashCode(), token.getKeyHash());
+		assertEquals(makeUserDetails(), token.getPrincipal());
+		assertEquals("Password", token.getCredentials());
+		assertTrue(token.getAuthorities()
+				.contains(new SimpleGrantedAuthority("ROLE_ONE")));
+		assertTrue(token.getAuthorities()
+				.contains(new SimpleGrantedAuthority("ROLE_TWO")));
+		assertEquals(assertion, token.getAssertion());
+		assertEquals(makeUserDetails().getUsername(), token.getUserDetails()
+				.getUsername());
+	}
 
-    public void testNoArgConstructorDoesntExist() {
-        try {
-            CasAuthenticationToken.class.getDeclaredConstructor((Class[]) null);
-            fail("Should have thrown NoSuchMethodException");
-        } catch (NoSuchMethodException expected) {
-            assertTrue(true);
-        }
-    }
+	public void testNoArgConstructorDoesntExist() {
+		try {
+			CasAuthenticationToken.class.getDeclaredConstructor((Class[]) null);
+			fail("Should have thrown NoSuchMethodException");
+		}
+		catch (NoSuchMethodException expected) {
+			assertTrue(true);
+		}
+	}
 
-    public void testNotEqualsDueToAbstractParentEqualsCheck() {
-        final Assertion assertion = new AssertionImpl("test");
+	public void testNotEqualsDueToAbstractParentEqualsCheck() {
+		final Assertion assertion = new AssertionImpl("test");
 
-        CasAuthenticationToken token1 = new CasAuthenticationToken("key", makeUserDetails(), "Password", ROLES,
-                makeUserDetails(), assertion);
+		CasAuthenticationToken token1 = new CasAuthenticationToken("key",
+				makeUserDetails(), "Password", ROLES, makeUserDetails(), assertion);
 
-        CasAuthenticationToken token2 = new CasAuthenticationToken("key", makeUserDetails("OTHER_NAME"), "Password",
-                ROLES, makeUserDetails(), assertion);
+		CasAuthenticationToken token2 = new CasAuthenticationToken("key",
+				makeUserDetails("OTHER_NAME"), "Password", ROLES, makeUserDetails(),
+				assertion);
 
-        assertTrue(!token1.equals(token2));
-    }
+		assertTrue(!token1.equals(token2));
+	}
 
-    public void testNotEqualsDueToDifferentAuthenticationClass() {
-        final Assertion assertion = new AssertionImpl("test");
+	public void testNotEqualsDueToDifferentAuthenticationClass() {
+		final Assertion assertion = new AssertionImpl("test");
 
-        CasAuthenticationToken token1 = new CasAuthenticationToken("key", makeUserDetails(), "Password", ROLES,
-                makeUserDetails(), assertion);
+		CasAuthenticationToken token1 = new CasAuthenticationToken("key",
+				makeUserDetails(), "Password", ROLES, makeUserDetails(), assertion);
 
-        UsernamePasswordAuthenticationToken token2 = new UsernamePasswordAuthenticationToken("Test", "Password", ROLES);
-        assertTrue(!token1.equals(token2));
-    }
+		UsernamePasswordAuthenticationToken token2 = new UsernamePasswordAuthenticationToken(
+				"Test", "Password", ROLES);
+		assertTrue(!token1.equals(token2));
+	}
 
-    public void testNotEqualsDueToKey() {
-        final Assertion assertion = new AssertionImpl("test");
+	public void testNotEqualsDueToKey() {
+		final Assertion assertion = new AssertionImpl("test");
 
-        CasAuthenticationToken token1 = new CasAuthenticationToken("key", makeUserDetails(), "Password", ROLES,
-                makeUserDetails(), assertion);
+		CasAuthenticationToken token1 = new CasAuthenticationToken("key",
+				makeUserDetails(), "Password", ROLES, makeUserDetails(), assertion);
 
-        CasAuthenticationToken token2 = new CasAuthenticationToken("DIFFERENT_KEY", makeUserDetails(), "Password",
-                ROLES, makeUserDetails(), assertion);
+		CasAuthenticationToken token2 = new CasAuthenticationToken("DIFFERENT_KEY",
+				makeUserDetails(), "Password", ROLES, makeUserDetails(), assertion);
 
-        assertTrue(!token1.equals(token2));
-    }
+		assertTrue(!token1.equals(token2));
+	}
 
-    public void testNotEqualsDueToAssertion() {
-        final Assertion assertion = new AssertionImpl("test");
-        final Assertion assertion2 = new AssertionImpl("test");
+	public void testNotEqualsDueToAssertion() {
+		final Assertion assertion = new AssertionImpl("test");
+		final Assertion assertion2 = new AssertionImpl("test");
 
-        CasAuthenticationToken token1 = new CasAuthenticationToken("key", makeUserDetails(), "Password", ROLES,
-                makeUserDetails(), assertion);
+		CasAuthenticationToken token1 = new CasAuthenticationToken("key",
+				makeUserDetails(), "Password", ROLES, makeUserDetails(), assertion);
 
-        CasAuthenticationToken token2 = new CasAuthenticationToken("key", makeUserDetails(), "Password", ROLES,
-                makeUserDetails(), assertion2);
+		CasAuthenticationToken token2 = new CasAuthenticationToken("key",
+				makeUserDetails(), "Password", ROLES, makeUserDetails(), assertion2);
 
-        assertTrue(!token1.equals(token2));
-    }
+		assertTrue(!token1.equals(token2));
+	}
 
-    public void testSetAuthenticated() {
-        final Assertion assertion = new AssertionImpl("test");
-        CasAuthenticationToken token = new CasAuthenticationToken("key", makeUserDetails(), "Password", ROLES,
-                makeUserDetails(), assertion);
-        assertTrue(token.isAuthenticated());
-        token.setAuthenticated(false);
-        assertTrue(!token.isAuthenticated());
-    }
+	public void testSetAuthenticated() {
+		final Assertion assertion = new AssertionImpl("test");
+		CasAuthenticationToken token = new CasAuthenticationToken("key",
+				makeUserDetails(), "Password", ROLES, makeUserDetails(), assertion);
+		assertTrue(token.isAuthenticated());
+		token.setAuthenticated(false);
+		assertTrue(!token.isAuthenticated());
+	}
 
-    public void testToString() {
-        final Assertion assertion = new AssertionImpl("test");
-        CasAuthenticationToken token = new CasAuthenticationToken("key", makeUserDetails(), "Password",ROLES,
-                makeUserDetails(), assertion);
-        String result = token.toString();
-        assertTrue(result.lastIndexOf("Credentials (Service/Proxy Ticket):") != -1);
-    }
+	public void testToString() {
+		final Assertion assertion = new AssertionImpl("test");
+		CasAuthenticationToken token = new CasAuthenticationToken("key",
+				makeUserDetails(), "Password", ROLES, makeUserDetails(), assertion);
+		String result = token.toString();
+		assertTrue(result.lastIndexOf("Credentials (Service/Proxy Ticket):") != -1);
+	}
 }
diff --git a/cas/src/test/java/org/springframework/security/cas/authentication/EhCacheBasedTicketCacheTests.java b/cas/src/test/java/org/springframework/security/cas/authentication/EhCacheBasedTicketCacheTests.java
index 01bf1d9a3f..0d542ae4b1 100644
--- a/cas/src/test/java/org/springframework/security/cas/authentication/EhCacheBasedTicketCacheTests.java
+++ b/cas/src/test/java/org/springframework/security/cas/authentication/EhCacheBasedTicketCacheTests.java
@@ -27,62 +27,63 @@ import org.springframework.security.cas.authentication.EhCacheBasedTicketCache;
 
 import static org.junit.Assert.*;
 
-
 /**
  * Tests {@link EhCacheBasedTicketCache}.
  *
  * @author Ben Alex
  */
 public class EhCacheBasedTicketCacheTests extends AbstractStatelessTicketCacheTests {
-    private static CacheManager cacheManager;
+	private static CacheManager cacheManager;
 
-    //~ Methods ========================================================================================================
-    @BeforeClass
-    public static void initCacheManaer() {
-        cacheManager = CacheManager.create();
-        cacheManager.addCache(new Cache("castickets", 500, false, false, 30, 30));
-    }
+	// ~ Methods
+	// ========================================================================================================
+	@BeforeClass
+	public static void initCacheManaer() {
+		cacheManager = CacheManager.create();
+		cacheManager.addCache(new Cache("castickets", 500, false, false, 30, 30));
+	}
 
-    @AfterClass
-    public static void shutdownCacheManager() {
-        cacheManager.removalAll();
-        cacheManager.shutdown();
-    }
+	@AfterClass
+	public static void shutdownCacheManager() {
+		cacheManager.removalAll();
+		cacheManager.shutdown();
+	}
 
-    @Test
-    public void testCacheOperation() throws Exception {
-        EhCacheBasedTicketCache cache = new EhCacheBasedTicketCache();
-        cache.setCache(cacheManager.getCache("castickets"));
-        cache.afterPropertiesSet();
+	@Test
+	public void testCacheOperation() throws Exception {
+		EhCacheBasedTicketCache cache = new EhCacheBasedTicketCache();
+		cache.setCache(cacheManager.getCache("castickets"));
+		cache.afterPropertiesSet();
 
-        final CasAuthenticationToken token = getToken();
+		final CasAuthenticationToken token = getToken();
 
-        // Check it gets stored in the cache
-        cache.putTicketInCache(token);
-        assertEquals(token, cache.getByTicketId("ST-0-ER94xMJmn6pha35CQRoZ"));
+		// Check it gets stored in the cache
+		cache.putTicketInCache(token);
+		assertEquals(token, cache.getByTicketId("ST-0-ER94xMJmn6pha35CQRoZ"));
 
-        // Check it gets removed from the cache
-        cache.removeTicketFromCache(getToken());
-        assertNull(cache.getByTicketId("ST-0-ER94xMJmn6pha35CQRoZ"));
+		// Check it gets removed from the cache
+		cache.removeTicketFromCache(getToken());
+		assertNull(cache.getByTicketId("ST-0-ER94xMJmn6pha35CQRoZ"));
 
-        // Check it doesn't return values for null or unknown service tickets
-        assertNull(cache.getByTicketId(null));
-        assertNull(cache.getByTicketId("UNKNOWN_SERVICE_TICKET"));
-    }
+		// Check it doesn't return values for null or unknown service tickets
+		assertNull(cache.getByTicketId(null));
+		assertNull(cache.getByTicketId("UNKNOWN_SERVICE_TICKET"));
+	}
 
-    @Test
-    public void testStartupDetectsMissingCache() throws Exception {
-        EhCacheBasedTicketCache cache = new EhCacheBasedTicketCache();
+	@Test
+	public void testStartupDetectsMissingCache() throws Exception {
+		EhCacheBasedTicketCache cache = new EhCacheBasedTicketCache();
 
-        try {
-            cache.afterPropertiesSet();
-            fail("Should have thrown IllegalArgumentException");
-        } catch (IllegalArgumentException expected) {
-            assertTrue(true);
-        }
+		try {
+			cache.afterPropertiesSet();
+			fail("Should have thrown IllegalArgumentException");
+		}
+		catch (IllegalArgumentException expected) {
+			assertTrue(true);
+		}
 
-        Ehcache myCache = cacheManager.getCache("castickets");
-        cache.setCache(myCache);
-        assertEquals(myCache, cache.getCache());
-    }
+		Ehcache myCache = cacheManager.getCache("castickets");
+		cache.setCache(myCache);
+		assertEquals(myCache, cache.getCache());
+	}
 }
diff --git a/cas/src/test/java/org/springframework/security/cas/authentication/NullStatelessTicketCacheTests.java b/cas/src/test/java/org/springframework/security/cas/authentication/NullStatelessTicketCacheTests.java
index abf0e0c72d..fb5fd88115 100644
--- a/cas/src/test/java/org/springframework/security/cas/authentication/NullStatelessTicketCacheTests.java
+++ b/cas/src/test/java/org/springframework/security/cas/authentication/NullStatelessTicketCacheTests.java
@@ -14,7 +14,6 @@
  */
 package org.springframework.security.cas.authentication;
 
-
 import org.junit.Test;
 import org.springframework.security.cas.authentication.CasAuthenticationToken;
 import org.springframework.security.cas.authentication.NullStatelessTicketCache;
@@ -30,18 +29,18 @@ import static org.junit.Assert.*;
  */
 public class NullStatelessTicketCacheTests extends AbstractStatelessTicketCacheTests {
 
-    private StatelessTicketCache cache = new NullStatelessTicketCache();
+	private StatelessTicketCache cache = new NullStatelessTicketCache();
 
-    @Test
-    public void testGetter() {
-        assertNull(cache.getByTicketId(null));
-        assertNull(cache.getByTicketId("test"));
-    }
+	@Test
+	public void testGetter() {
+		assertNull(cache.getByTicketId(null));
+		assertNull(cache.getByTicketId("test"));
+	}
 
-    @Test
-    public void testInsertAndGet() {
-        final CasAuthenticationToken token = getToken();
-        cache.putTicketInCache(token);
-        assertNull(cache.getByTicketId((String) token.getCredentials()));
-    }
+	@Test
+	public void testInsertAndGet() {
+		final CasAuthenticationToken token = getToken();
+		cache.putTicketInCache(token);
+		assertNull(cache.getByTicketId((String) token.getCredentials()));
+	}
 }
diff --git a/cas/src/test/java/org/springframework/security/cas/authentication/SpringCacheBasedTicketCacheTests.java b/cas/src/test/java/org/springframework/security/cas/authentication/SpringCacheBasedTicketCacheTests.java
index c8abf77f94..7072921247 100644
--- a/cas/src/test/java/org/springframework/security/cas/authentication/SpringCacheBasedTicketCacheTests.java
+++ b/cas/src/test/java/org/springframework/security/cas/authentication/SpringCacheBasedTicketCacheTests.java
@@ -22,45 +22,47 @@ import org.springframework.cache.concurrent.ConcurrentMapCacheManager;
 
 import static org.junit.Assert.*;
 
-
 /**
- * Tests {@link org.springframework.security.cas.authentication.SpringCacheBasedTicketCache}.
+ * Tests
+ * {@link org.springframework.security.cas.authentication.SpringCacheBasedTicketCache}.
  *
  * @author Marten Deinum
  * @since 3.2
  */
 public class SpringCacheBasedTicketCacheTests extends AbstractStatelessTicketCacheTests {
-    private static CacheManager cacheManager;
+	private static CacheManager cacheManager;
 
-    //~ Methods ========================================================================================================
+	// ~ Methods
+	// ========================================================================================================
 
-    @BeforeClass
-    public static void initCacheManaer() {
-        cacheManager = new ConcurrentMapCacheManager();
-        cacheManager.getCache("castickets");
-    }
+	@BeforeClass
+	public static void initCacheManaer() {
+		cacheManager = new ConcurrentMapCacheManager();
+		cacheManager.getCache("castickets");
+	}
 
-    @Test
-    public void testCacheOperation() throws Exception {
-        SpringCacheBasedTicketCache cache = new SpringCacheBasedTicketCache(cacheManager.getCache("castickets"));
+	@Test
+	public void testCacheOperation() throws Exception {
+		SpringCacheBasedTicketCache cache = new SpringCacheBasedTicketCache(
+				cacheManager.getCache("castickets"));
 
-        final CasAuthenticationToken token = getToken();
+		final CasAuthenticationToken token = getToken();
 
-        // Check it gets stored in the cache
-        cache.putTicketInCache(token);
-        assertEquals(token, cache.getByTicketId("ST-0-ER94xMJmn6pha35CQRoZ"));
+		// Check it gets stored in the cache
+		cache.putTicketInCache(token);
+		assertEquals(token, cache.getByTicketId("ST-0-ER94xMJmn6pha35CQRoZ"));
 
-        // Check it gets removed from the cache
-        cache.removeTicketFromCache(getToken());
-        assertNull(cache.getByTicketId("ST-0-ER94xMJmn6pha35CQRoZ"));
+		// Check it gets removed from the cache
+		cache.removeTicketFromCache(getToken());
+		assertNull(cache.getByTicketId("ST-0-ER94xMJmn6pha35CQRoZ"));
 
-        // Check it doesn't return values for null or unknown service tickets
-        assertNull(cache.getByTicketId(null));
-        assertNull(cache.getByTicketId("UNKNOWN_SERVICE_TICKET"));
-    }
+		// Check it doesn't return values for null or unknown service tickets
+		assertNull(cache.getByTicketId(null));
+		assertNull(cache.getByTicketId("UNKNOWN_SERVICE_TICKET"));
+	}
 
-    @Test(expected = IllegalArgumentException.class)
-    public void testStartupDetectsMissingCache() throws Exception {
-        new SpringCacheBasedTicketCache(null);
-    }
+	@Test(expected = IllegalArgumentException.class)
+	public void testStartupDetectsMissingCache() throws Exception {
+		new SpringCacheBasedTicketCache(null);
+	}
 }
diff --git a/cas/src/test/java/org/springframework/security/cas/userdetails/GrantedAuthorityFromAssertionAttributesUserDetailsServiceTests.java b/cas/src/test/java/org/springframework/security/cas/userdetails/GrantedAuthorityFromAssertionAttributesUserDetailsServiceTests.java
index 0dcc456a80..33ced63c80 100644
--- a/cas/src/test/java/org/springframework/security/cas/userdetails/GrantedAuthorityFromAssertionAttributesUserDetailsServiceTests.java
+++ b/cas/src/test/java/org/springframework/security/cas/userdetails/GrantedAuthorityFromAssertionAttributesUserDetailsServiceTests.java
@@ -21,29 +21,30 @@ import java.util.Set;
  */
 public class GrantedAuthorityFromAssertionAttributesUserDetailsServiceTests {
 
-    @Test
-    public void correctlyExtractsNamedAttributesFromAssertionAndConvertsThemToAuthorities() {
-        GrantedAuthorityFromAssertionAttributesUserDetailsService uds =
-                new GrantedAuthorityFromAssertionAttributesUserDetailsService(new String[] {"a", "b", "c", "d"});
-        uds.setConvertToUpperCase(false);
-        Assertion assertion = mock(Assertion.class);
-        AttributePrincipal principal = mock(AttributePrincipal.class);
-        Map attributes = new HashMap();
-        attributes.put("a", Arrays.asList("role_a1", "role_a2"));
-        attributes.put("b", "role_b");
-        attributes.put("c", "role_c");
-        attributes.put("d", null);
-        attributes.put("someother", "unused");
-        when(assertion.getPrincipal()).thenReturn(principal);
-        when(principal.getAttributes()).thenReturn(attributes);
-        when(principal.getName()).thenReturn("somebody");
-        CasAssertionAuthenticationToken token = new CasAssertionAuthenticationToken(assertion, "ticket");
-        UserDetails user = uds.loadUserDetails(token);
-        Set roles = AuthorityUtils.authorityListToSet(user.getAuthorities());
-        assertTrue(roles.size() == 4);
-        assertTrue(roles.contains("role_a1"));
-        assertTrue(roles.contains("role_a2"));
-        assertTrue(roles.contains("role_b"));
-        assertTrue(roles.contains("role_c"));
-    }
+	@Test
+	public void correctlyExtractsNamedAttributesFromAssertionAndConvertsThemToAuthorities() {
+		GrantedAuthorityFromAssertionAttributesUserDetailsService uds = new GrantedAuthorityFromAssertionAttributesUserDetailsService(
+				new String[] { "a", "b", "c", "d" });
+		uds.setConvertToUpperCase(false);
+		Assertion assertion = mock(Assertion.class);
+		AttributePrincipal principal = mock(AttributePrincipal.class);
+		Map attributes = new HashMap();
+		attributes.put("a", Arrays.asList("role_a1", "role_a2"));
+		attributes.put("b", "role_b");
+		attributes.put("c", "role_c");
+		attributes.put("d", null);
+		attributes.put("someother", "unused");
+		when(assertion.getPrincipal()).thenReturn(principal);
+		when(principal.getAttributes()).thenReturn(attributes);
+		when(principal.getName()).thenReturn("somebody");
+		CasAssertionAuthenticationToken token = new CasAssertionAuthenticationToken(
+				assertion, "ticket");
+		UserDetails user = uds.loadUserDetails(token);
+		Set roles = AuthorityUtils.authorityListToSet(user.getAuthorities());
+		assertTrue(roles.size() == 4);
+		assertTrue(roles.contains("role_a1"));
+		assertTrue(roles.contains("role_a2"));
+		assertTrue(roles.contains("role_b"));
+		assertTrue(roles.contains("role_c"));
+	}
 }
diff --git a/cas/src/test/java/org/springframework/security/cas/web/CasAuthenticationEntryPointTests.java b/cas/src/test/java/org/springframework/security/cas/web/CasAuthenticationEntryPointTests.java
index 9c0af7b2be..fb27a84abd 100644
--- a/cas/src/test/java/org/springframework/security/cas/web/CasAuthenticationEntryPointTests.java
+++ b/cas/src/test/java/org/springframework/security/cas/web/CasAuthenticationEntryPointTests.java
@@ -24,88 +24,92 @@ import org.springframework.security.cas.web.CasAuthenticationEntryPoint;
 
 import java.net.URLEncoder;
 
-
 /**
  * Tests {@link CasAuthenticationEntryPoint}.
  *
  * @author Ben Alex
  */
 public class CasAuthenticationEntryPointTests extends TestCase {
-    //~ Methods ========================================================================================================
+	// ~ Methods
+	// ========================================================================================================
 
-    public void testDetectsMissingLoginFormUrl() throws Exception {
-        CasAuthenticationEntryPoint ep = new CasAuthenticationEntryPoint();
-        ep.setServiceProperties(new ServiceProperties());
+	public void testDetectsMissingLoginFormUrl() throws Exception {
+		CasAuthenticationEntryPoint ep = new CasAuthenticationEntryPoint();
+		ep.setServiceProperties(new ServiceProperties());
 
-        try {
-            ep.afterPropertiesSet();
-            fail("Should have thrown IllegalArgumentException");
-        } catch (IllegalArgumentException expected) {
-            assertEquals("loginUrl must be specified", expected.getMessage());
-        }
-    }
+		try {
+			ep.afterPropertiesSet();
+			fail("Should have thrown IllegalArgumentException");
+		}
+		catch (IllegalArgumentException expected) {
+			assertEquals("loginUrl must be specified", expected.getMessage());
+		}
+	}
 
-    public void testDetectsMissingServiceProperties() throws Exception {
-        CasAuthenticationEntryPoint ep = new CasAuthenticationEntryPoint();
-        ep.setLoginUrl("https://cas/login");
+	public void testDetectsMissingServiceProperties() throws Exception {
+		CasAuthenticationEntryPoint ep = new CasAuthenticationEntryPoint();
+		ep.setLoginUrl("https://cas/login");
 
-        try {
-            ep.afterPropertiesSet();
-            fail("Should have thrown IllegalArgumentException");
-        } catch (IllegalArgumentException expected) {
-            assertEquals("serviceProperties must be specified", expected.getMessage());
-        }
-    }
+		try {
+			ep.afterPropertiesSet();
+			fail("Should have thrown IllegalArgumentException");
+		}
+		catch (IllegalArgumentException expected) {
+			assertEquals("serviceProperties must be specified", expected.getMessage());
+		}
+	}
 
-    public void testGettersSetters() {
-        CasAuthenticationEntryPoint ep = new CasAuthenticationEntryPoint();
-        ep.setLoginUrl("https://cas/login");
-        assertEquals("https://cas/login", ep.getLoginUrl());
+	public void testGettersSetters() {
+		CasAuthenticationEntryPoint ep = new CasAuthenticationEntryPoint();
+		ep.setLoginUrl("https://cas/login");
+		assertEquals("https://cas/login", ep.getLoginUrl());
 
-        ep.setServiceProperties(new ServiceProperties());
-        assertTrue(ep.getServiceProperties() != null);
-    }
+		ep.setServiceProperties(new ServiceProperties());
+		assertTrue(ep.getServiceProperties() != null);
+	}
 
-    public void testNormalOperationWithRenewFalse() throws Exception {
-        ServiceProperties sp = new ServiceProperties();
-        sp.setSendRenew(false);
-        sp.setService("https://mycompany.com/bigWebApp/login/cas");
+	public void testNormalOperationWithRenewFalse() throws Exception {
+		ServiceProperties sp = new ServiceProperties();
+		sp.setSendRenew(false);
+		sp.setService("https://mycompany.com/bigWebApp/login/cas");
 
-        CasAuthenticationEntryPoint ep = new CasAuthenticationEntryPoint();
-        ep.setLoginUrl("https://cas/login");
-        ep.setServiceProperties(sp);
+		CasAuthenticationEntryPoint ep = new CasAuthenticationEntryPoint();
+		ep.setLoginUrl("https://cas/login");
+		ep.setServiceProperties(sp);
 
-        MockHttpServletRequest request = new MockHttpServletRequest();
-        request.setRequestURI("/some_path");
+		MockHttpServletRequest request = new MockHttpServletRequest();
+		request.setRequestURI("/some_path");
 
-        MockHttpServletResponse response = new MockHttpServletResponse();
+		MockHttpServletResponse response = new MockHttpServletResponse();
 
-        ep.afterPropertiesSet();
-        ep.commence(request, response, null);
+		ep.afterPropertiesSet();
+		ep.commence(request, response, null);
 
-        assertEquals("https://cas/login?service="
-            + URLEncoder.encode("https://mycompany.com/bigWebApp/login/cas", "UTF-8"),
-            response.getRedirectedUrl());
-    }
+		assertEquals(
+				"https://cas/login?service="
+						+ URLEncoder.encode("https://mycompany.com/bigWebApp/login/cas",
+								"UTF-8"), response.getRedirectedUrl());
+	}
 
-    public void testNormalOperationWithRenewTrue() throws Exception {
-        ServiceProperties sp = new ServiceProperties();
-        sp.setSendRenew(true);
-        sp.setService("https://mycompany.com/bigWebApp/login/cas");
+	public void testNormalOperationWithRenewTrue() throws Exception {
+		ServiceProperties sp = new ServiceProperties();
+		sp.setSendRenew(true);
+		sp.setService("https://mycompany.com/bigWebApp/login/cas");
 
-        CasAuthenticationEntryPoint ep = new CasAuthenticationEntryPoint();
-        ep.setLoginUrl("https://cas/login");
-        ep.setServiceProperties(sp);
+		CasAuthenticationEntryPoint ep = new CasAuthenticationEntryPoint();
+		ep.setLoginUrl("https://cas/login");
+		ep.setServiceProperties(sp);
 
-        MockHttpServletRequest request = new MockHttpServletRequest();
-        request.setRequestURI("/some_path");
+		MockHttpServletRequest request = new MockHttpServletRequest();
+		request.setRequestURI("/some_path");
 
-        MockHttpServletResponse response = new MockHttpServletResponse();
+		MockHttpServletResponse response = new MockHttpServletResponse();
 
-        ep.afterPropertiesSet();
-        ep.commence(request, response, null);
-        assertEquals("https://cas/login?service="
-            + URLEncoder.encode("https://mycompany.com/bigWebApp/login/cas", "UTF-8") + "&renew=true",
-            response.getRedirectedUrl());
-    }
+		ep.afterPropertiesSet();
+		ep.commence(request, response, null);
+		assertEquals(
+				"https://cas/login?service="
+						+ URLEncoder.encode("https://mycompany.com/bigWebApp/login/cas",
+								"UTF-8") + "&renew=true", response.getRedirectedUrl());
+	}
 }
diff --git a/cas/src/test/java/org/springframework/security/cas/web/CasAuthenticationFilterTests.java b/cas/src/test/java/org/springframework/security/cas/web/CasAuthenticationFilterTests.java
index 309d8159df..9ce03174f0 100644
--- a/cas/src/test/java/org/springframework/security/cas/web/CasAuthenticationFilterTests.java
+++ b/cas/src/test/java/org/springframework/security/cas/web/CasAuthenticationFilterTests.java
@@ -45,7 +45,6 @@ import org.springframework.security.web.authentication.AuthenticationSuccessHand
 import org.springframework.security.web.authentication.NullRememberMeServices;
 import org.springframework.util.ReflectionUtils;
 
-
 /**
  * Tests {@link CasAuthenticationFilter}.
  *
@@ -53,166 +52,176 @@ import org.springframework.util.ReflectionUtils;
  * @author Rob Winch
  */
 public class CasAuthenticationFilterTests {
-    //~ Methods ========================================================================================================
+	// ~ Methods
+	// ========================================================================================================
 
-    @After
-    public void tearDown() {
-        SecurityContextHolder.clearContext();
-    }
+	@After
+	public void tearDown() {
+		SecurityContextHolder.clearContext();
+	}
 
-    @Test
-    public void testGettersSetters() {
-        CasAuthenticationFilter filter = new CasAuthenticationFilter();
-        filter.setProxyGrantingTicketStorage(mock(ProxyGrantingTicketStorage.class));
-        filter.setProxyReceptorUrl("/someurl");
-        filter.setServiceProperties(new ServiceProperties());
-    }
+	@Test
+	public void testGettersSetters() {
+		CasAuthenticationFilter filter = new CasAuthenticationFilter();
+		filter.setProxyGrantingTicketStorage(mock(ProxyGrantingTicketStorage.class));
+		filter.setProxyReceptorUrl("/someurl");
+		filter.setServiceProperties(new ServiceProperties());
+	}
 
-    @Test
-    public void testNormalOperation() throws Exception {
-        MockHttpServletRequest request = new MockHttpServletRequest();
-        request.setServletPath("/login/cas");
-        request.addParameter("ticket", "ST-0-ER94xMJmn6pha35CQRoZ");
+	@Test
+	public void testNormalOperation() throws Exception {
+		MockHttpServletRequest request = new MockHttpServletRequest();
+		request.setServletPath("/login/cas");
+		request.addParameter("ticket", "ST-0-ER94xMJmn6pha35CQRoZ");
 
-        CasAuthenticationFilter filter = new CasAuthenticationFilter();
-        filter.setAuthenticationManager(new AuthenticationManager() {
-            public Authentication authenticate(Authentication a) {
-                return a;
-            }
-        });
+		CasAuthenticationFilter filter = new CasAuthenticationFilter();
+		filter.setAuthenticationManager(new AuthenticationManager() {
+			public Authentication authenticate(Authentication a) {
+				return a;
+			}
+		});
 
-        assertTrue(filter.requiresAuthentication(request, new MockHttpServletResponse()));
+		assertTrue(filter.requiresAuthentication(request, new MockHttpServletResponse()));
 
-        Authentication result = filter.attemptAuthentication(request, new MockHttpServletResponse());
-        assertTrue(result != null);
-    }
+		Authentication result = filter.attemptAuthentication(request,
+				new MockHttpServletResponse());
+		assertTrue(result != null);
+	}
 
-    @Test(expected=AuthenticationException.class)
-    public void testNullServiceTicketHandledGracefully() throws Exception {
-        CasAuthenticationFilter filter = new CasAuthenticationFilter();
-        filter.setAuthenticationManager(new AuthenticationManager() {
-            public Authentication authenticate(Authentication a) {
-                throw new BadCredentialsException("Rejected");
-            }
-        });
+	@Test(expected = AuthenticationException.class)
+	public void testNullServiceTicketHandledGracefully() throws Exception {
+		CasAuthenticationFilter filter = new CasAuthenticationFilter();
+		filter.setAuthenticationManager(new AuthenticationManager() {
+			public Authentication authenticate(Authentication a) {
+				throw new BadCredentialsException("Rejected");
+			}
+		});
 
-        filter.attemptAuthentication(new MockHttpServletRequest(), new MockHttpServletResponse());
-    }
+		filter.attemptAuthentication(new MockHttpServletRequest(),
+				new MockHttpServletResponse());
+	}
 
-    @Test
-    public void testRequiresAuthenticationFilterProcessUrl() {
-        String url = "/login/cas";
-        CasAuthenticationFilter filter = new CasAuthenticationFilter();
-        filter.setFilterProcessesUrl(url);
-        MockHttpServletRequest request = new MockHttpServletRequest();
-        MockHttpServletResponse response = new MockHttpServletResponse();
+	@Test
+	public void testRequiresAuthenticationFilterProcessUrl() {
+		String url = "/login/cas";
+		CasAuthenticationFilter filter = new CasAuthenticationFilter();
+		filter.setFilterProcessesUrl(url);
+		MockHttpServletRequest request = new MockHttpServletRequest();
+		MockHttpServletResponse response = new MockHttpServletResponse();
 
-        request.setServletPath(url);
-        assertTrue(filter.requiresAuthentication(request, response));
-    }
+		request.setServletPath(url);
+		assertTrue(filter.requiresAuthentication(request, response));
+	}
 
-    @Test
-    public void testRequiresAuthenticationProxyRequest() {
-        CasAuthenticationFilter filter = new CasAuthenticationFilter();
-        MockHttpServletRequest request = new MockHttpServletRequest();
-        MockHttpServletResponse response = new MockHttpServletResponse();
+	@Test
+	public void testRequiresAuthenticationProxyRequest() {
+		CasAuthenticationFilter filter = new CasAuthenticationFilter();
+		MockHttpServletRequest request = new MockHttpServletRequest();
+		MockHttpServletResponse response = new MockHttpServletResponse();
 
-        request.setServletPath("/pgtCallback");
-        assertFalse(filter.requiresAuthentication(request, response));
-        filter.setProxyReceptorUrl(request.getServletPath());
-        assertFalse(filter.requiresAuthentication(request, response));
-        filter.setProxyGrantingTicketStorage(mock(ProxyGrantingTicketStorage.class));
-        assertTrue(filter.requiresAuthentication(request, response));
-        request.setServletPath("/other");
-        assertFalse(filter.requiresAuthentication(request, response));
-    }
+		request.setServletPath("/pgtCallback");
+		assertFalse(filter.requiresAuthentication(request, response));
+		filter.setProxyReceptorUrl(request.getServletPath());
+		assertFalse(filter.requiresAuthentication(request, response));
+		filter.setProxyGrantingTicketStorage(mock(ProxyGrantingTicketStorage.class));
+		assertTrue(filter.requiresAuthentication(request, response));
+		request.setServletPath("/other");
+		assertFalse(filter.requiresAuthentication(request, response));
+	}
 
-    @Test
-    public void testRequiresAuthenticationAuthAll() {
-        ServiceProperties properties = new ServiceProperties();
-        properties.setAuthenticateAllArtifacts(true);
+	@Test
+	public void testRequiresAuthenticationAuthAll() {
+		ServiceProperties properties = new ServiceProperties();
+		properties.setAuthenticateAllArtifacts(true);
 
-        String url = "/login/cas";
-        CasAuthenticationFilter filter = new CasAuthenticationFilter();
-        filter.setFilterProcessesUrl(url);
-        filter.setServiceProperties(properties);
-        MockHttpServletRequest request = new MockHttpServletRequest();
-        MockHttpServletResponse response = new MockHttpServletResponse();
+		String url = "/login/cas";
+		CasAuthenticationFilter filter = new CasAuthenticationFilter();
+		filter.setFilterProcessesUrl(url);
+		filter.setServiceProperties(properties);
+		MockHttpServletRequest request = new MockHttpServletRequest();
+		MockHttpServletResponse response = new MockHttpServletResponse();
 
-        request.setServletPath(url);
-        assertTrue(filter.requiresAuthentication(request, response));
+		request.setServletPath(url);
+		assertTrue(filter.requiresAuthentication(request, response));
 
-        request.setServletPath("/other");
-        assertFalse(filter.requiresAuthentication(request, response));
-        request.setParameter(properties.getArtifactParameter(), "value");
-        assertTrue(filter.requiresAuthentication(request, response));
-        SecurityContextHolder.getContext().setAuthentication(new AnonymousAuthenticationToken("key", "principal", AuthorityUtils.createAuthorityList("ROLE_ANONYMOUS")));
-        assertTrue(filter.requiresAuthentication(request, response));
-        SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken("un", "principal", AuthorityUtils.createAuthorityList("ROLE_ANONYMOUS")));
-        assertTrue(filter.requiresAuthentication(request, response));
-        SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken("un", "principal", "ROLE_ANONYMOUS"));
-        assertFalse(filter.requiresAuthentication(request, response));
-    }
+		request.setServletPath("/other");
+		assertFalse(filter.requiresAuthentication(request, response));
+		request.setParameter(properties.getArtifactParameter(), "value");
+		assertTrue(filter.requiresAuthentication(request, response));
+		SecurityContextHolder.getContext().setAuthentication(
+				new AnonymousAuthenticationToken("key", "principal", AuthorityUtils
+						.createAuthorityList("ROLE_ANONYMOUS")));
+		assertTrue(filter.requiresAuthentication(request, response));
+		SecurityContextHolder.getContext().setAuthentication(
+				new TestingAuthenticationToken("un", "principal", AuthorityUtils
+						.createAuthorityList("ROLE_ANONYMOUS")));
+		assertTrue(filter.requiresAuthentication(request, response));
+		SecurityContextHolder.getContext().setAuthentication(
+				new TestingAuthenticationToken("un", "principal", "ROLE_ANONYMOUS"));
+		assertFalse(filter.requiresAuthentication(request, response));
+	}
 
-    @Test
-    public void testAuthenticateProxyUrl() throws Exception {
-        CasAuthenticationFilter filter = new CasAuthenticationFilter();
-        MockHttpServletRequest request = new MockHttpServletRequest();
-        MockHttpServletResponse response = new MockHttpServletResponse();
+	@Test
+	public void testAuthenticateProxyUrl() throws Exception {
+		CasAuthenticationFilter filter = new CasAuthenticationFilter();
+		MockHttpServletRequest request = new MockHttpServletRequest();
+		MockHttpServletResponse response = new MockHttpServletResponse();
 
-        request.setServletPath("/pgtCallback");
-        filter.setProxyGrantingTicketStorage(mock(ProxyGrantingTicketStorage.class));
-        filter.setProxyReceptorUrl(request.getServletPath());
-        assertNull(filter.attemptAuthentication(request, response));
-    }
+		request.setServletPath("/pgtCallback");
+		filter.setProxyGrantingTicketStorage(mock(ProxyGrantingTicketStorage.class));
+		filter.setProxyReceptorUrl(request.getServletPath());
+		assertNull(filter.attemptAuthentication(request, response));
+	}
 
-    @Test
-    public void testDoFilterAuthenticateAll() throws Exception {
-        AuthenticationSuccessHandler successHandler = mock(AuthenticationSuccessHandler.class);
-        AuthenticationManager manager = mock(AuthenticationManager.class);
-        Authentication authentication = new TestingAuthenticationToken("un", "pwd","ROLE_USER");
-        when(manager.authenticate(any(Authentication.class))).thenReturn(authentication);
-        ServiceProperties serviceProperties = new ServiceProperties();
-        serviceProperties.setAuthenticateAllArtifacts(true);
-        MockHttpServletRequest request = new MockHttpServletRequest();
-        request.setParameter("ticket", "ST-1-123");
-        request.setServletPath("/authenticate");
-        MockHttpServletResponse response = new MockHttpServletResponse();
-        FilterChain chain = mock(FilterChain.class);
+	@Test
+	public void testDoFilterAuthenticateAll() throws Exception {
+		AuthenticationSuccessHandler successHandler = mock(AuthenticationSuccessHandler.class);
+		AuthenticationManager manager = mock(AuthenticationManager.class);
+		Authentication authentication = new TestingAuthenticationToken("un", "pwd",
+				"ROLE_USER");
+		when(manager.authenticate(any(Authentication.class))).thenReturn(authentication);
+		ServiceProperties serviceProperties = new ServiceProperties();
+		serviceProperties.setAuthenticateAllArtifacts(true);
+		MockHttpServletRequest request = new MockHttpServletRequest();
+		request.setParameter("ticket", "ST-1-123");
+		request.setServletPath("/authenticate");
+		MockHttpServletResponse response = new MockHttpServletResponse();
+		FilterChain chain = mock(FilterChain.class);
 
-        CasAuthenticationFilter filter = new CasAuthenticationFilter();
-        filter.setServiceProperties(serviceProperties);
-        filter.setAuthenticationSuccessHandler(successHandler);
-        filter.setProxyGrantingTicketStorage(mock(ProxyGrantingTicketStorage.class));
-        filter.setAuthenticationManager(manager);
-        filter.afterPropertiesSet();
+		CasAuthenticationFilter filter = new CasAuthenticationFilter();
+		filter.setServiceProperties(serviceProperties);
+		filter.setAuthenticationSuccessHandler(successHandler);
+		filter.setProxyGrantingTicketStorage(mock(ProxyGrantingTicketStorage.class));
+		filter.setAuthenticationManager(manager);
+		filter.afterPropertiesSet();
 
-        filter.doFilter(request,response,chain);
-        assertFalse("Authentication should not be null",SecurityContextHolder.getContext().getAuthentication() == null);
-        verify(chain).doFilter(request, response);
-        verifyZeroInteractions(successHandler);
+		filter.doFilter(request, response, chain);
+		assertFalse("Authentication should not be null", SecurityContextHolder
+				.getContext().getAuthentication() == null);
+		verify(chain).doFilter(request, response);
+		verifyZeroInteractions(successHandler);
 
-        // validate for when the filterProcessUrl matches
-        filter.setFilterProcessesUrl(request.getServletPath());
-        SecurityContextHolder.clearContext();
-        filter.doFilter(request,response,chain);
-        verifyNoMoreInteractions(chain);
-        verify(successHandler).onAuthenticationSuccess(request, response, authentication);
-    }
+		// validate for when the filterProcessUrl matches
+		filter.setFilterProcessesUrl(request.getServletPath());
+		SecurityContextHolder.clearContext();
+		filter.doFilter(request, response, chain);
+		verifyNoMoreInteractions(chain);
+		verify(successHandler).onAuthenticationSuccess(request, response, authentication);
+	}
 
-    // SEC-1592
-    @Test
-    public void testChainNotInvokedForProxyReceptor() throws Exception {
-        CasAuthenticationFilter filter = new CasAuthenticationFilter();
-        MockHttpServletRequest request = new MockHttpServletRequest();
-        MockHttpServletResponse response = new MockHttpServletResponse();
-        FilterChain chain = mock(FilterChain.class);
+	// SEC-1592
+	@Test
+	public void testChainNotInvokedForProxyReceptor() throws Exception {
+		CasAuthenticationFilter filter = new CasAuthenticationFilter();
+		MockHttpServletRequest request = new MockHttpServletRequest();
+		MockHttpServletResponse response = new MockHttpServletResponse();
+		FilterChain chain = mock(FilterChain.class);
 
-        request.setServletPath("/pgtCallback");
-        filter.setProxyGrantingTicketStorage(mock(ProxyGrantingTicketStorage.class));
-        filter.setProxyReceptorUrl(request.getServletPath());
+		request.setServletPath("/pgtCallback");
+		filter.setProxyGrantingTicketStorage(mock(ProxyGrantingTicketStorage.class));
+		filter.setProxyReceptorUrl(request.getServletPath());
 
-        filter.doFilter(request,response,chain);
-        verifyZeroInteractions(chain);
-    }
+		filter.doFilter(request, response, chain);
+		verifyZeroInteractions(chain);
+	}
 }
\ No newline at end of file
diff --git a/cas/src/test/java/org/springframework/security/cas/web/ServicePropertiesTests.java b/cas/src/test/java/org/springframework/security/cas/web/ServicePropertiesTests.java
index ec327ff49b..1581725aca 100644
--- a/cas/src/test/java/org/springframework/security/cas/web/ServicePropertiesTests.java
+++ b/cas/src/test/java/org/springframework/security/cas/web/ServicePropertiesTests.java
@@ -27,46 +27,51 @@ import org.springframework.security.cas.ServiceProperties;
  * @author Ben Alex
  */
 public class ServicePropertiesTests {
-    //~ Methods ========================================================================================================
+	// ~ Methods
+	// ========================================================================================================
 
-    @Test(expected=IllegalArgumentException.class)
-    public void detectsMissingService() throws Exception {
-        ServiceProperties sp = new ServiceProperties();
-        sp.afterPropertiesSet();
-    }
+	@Test(expected = IllegalArgumentException.class)
+	public void detectsMissingService() throws Exception {
+		ServiceProperties sp = new ServiceProperties();
+		sp.afterPropertiesSet();
+	}
 
-    @Test
-    public void nullServiceWhenAuthenticateAllTokens() throws Exception {
-        ServiceProperties sp = new ServiceProperties();
-        sp.setAuthenticateAllArtifacts(true);
-        try {
-            sp.afterPropertiesSet();
-            fail("Expected Exception");
-        }catch(IllegalArgumentException success) {}
-        sp.setAuthenticateAllArtifacts(false);
-        try {
-            sp.afterPropertiesSet();
-            fail("Expected Exception");
-        }catch(IllegalArgumentException success) {}
-    }
+	@Test
+	public void nullServiceWhenAuthenticateAllTokens() throws Exception {
+		ServiceProperties sp = new ServiceProperties();
+		sp.setAuthenticateAllArtifacts(true);
+		try {
+			sp.afterPropertiesSet();
+			fail("Expected Exception");
+		}
+		catch (IllegalArgumentException success) {
+		}
+		sp.setAuthenticateAllArtifacts(false);
+		try {
+			sp.afterPropertiesSet();
+			fail("Expected Exception");
+		}
+		catch (IllegalArgumentException success) {
+		}
+	}
 
-    @Test
-    public void testGettersSetters() throws Exception {
-        ServiceProperties[] sps = {new ServiceProperties(), new SamlServiceProperties()};
-        for(ServiceProperties sp : sps) {
-            sp.setSendRenew(false);
-            assertFalse(sp.isSendRenew());
-            sp.setSendRenew(true);
-            assertTrue(sp.isSendRenew());
-            sp.setArtifactParameter("notticket");
-            assertEquals("notticket", sp.getArtifactParameter());
-            sp.setServiceParameter("notservice");
-            assertEquals("notservice", sp.getServiceParameter());
+	@Test
+	public void testGettersSetters() throws Exception {
+		ServiceProperties[] sps = { new ServiceProperties(), new SamlServiceProperties() };
+		for (ServiceProperties sp : sps) {
+			sp.setSendRenew(false);
+			assertFalse(sp.isSendRenew());
+			sp.setSendRenew(true);
+			assertTrue(sp.isSendRenew());
+			sp.setArtifactParameter("notticket");
+			assertEquals("notticket", sp.getArtifactParameter());
+			sp.setServiceParameter("notservice");
+			assertEquals("notservice", sp.getServiceParameter());
 
-            sp.setService("https://mycompany.com/service");
-            assertEquals("https://mycompany.com/service", sp.getService());
+			sp.setService("https://mycompany.com/service");
+			assertEquals("https://mycompany.com/service", sp.getService());
 
-            sp.afterPropertiesSet();
-        }
-    }
+			sp.afterPropertiesSet();
+		}
+	}
 }
diff --git a/cas/src/test/java/org/springframework/security/cas/web/authentication/DefaultServiceAuthenticationDetailsTests.java b/cas/src/test/java/org/springframework/security/cas/web/authentication/DefaultServiceAuthenticationDetailsTests.java
index 2243c50956..432a39806c 100644
--- a/cas/src/test/java/org/springframework/security/cas/web/authentication/DefaultServiceAuthenticationDetailsTests.java
+++ b/cas/src/test/java/org/springframework/security/cas/web/authentication/DefaultServiceAuthenticationDetailsTests.java
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 package org.springframework.security.cas.web.authentication;
+
 import static org.junit.Assert.assertEquals;
 
 import java.util.regex.Pattern;
@@ -39,93 +40,102 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
  * @author Rob Winch
  */
 public class DefaultServiceAuthenticationDetailsTests {
-    private DefaultServiceAuthenticationDetails details;
-    private MockHttpServletRequest request;
-    private Pattern artifactPattern;
-    private String casServiceUrl;
+	private DefaultServiceAuthenticationDetails details;
+	private MockHttpServletRequest request;
+	private Pattern artifactPattern;
+	private String casServiceUrl;
 
-    private ConfigurableApplicationContext context;
+	private ConfigurableApplicationContext context;
 
-    @Before
-    public void setUp() {
-        casServiceUrl = "https://localhost:8443/j_spring_security_cas";
-        request = new MockHttpServletRequest();
-        request.setScheme("https");
-        request.setServerName("localhost");
-        request.setServerPort(8443);
-        request.setRequestURI("/cas-sample/secure/");
-        artifactPattern = DefaultServiceAuthenticationDetails.createArtifactPattern(ServiceProperties.DEFAULT_CAS_ARTIFACT_PARAMETER);
+	@Before
+	public void setUp() {
+		casServiceUrl = "https://localhost:8443/j_spring_security_cas";
+		request = new MockHttpServletRequest();
+		request.setScheme("https");
+		request.setServerName("localhost");
+		request.setServerPort(8443);
+		request.setRequestURI("/cas-sample/secure/");
+		artifactPattern = DefaultServiceAuthenticationDetails
+				.createArtifactPattern(ServiceProperties.DEFAULT_CAS_ARTIFACT_PARAMETER);
 
-    }
+	}
 
-    @After
-    public void cleanup() {
-        if(context != null) {
-            context.close();
-        }
-    }
+	@After
+	public void cleanup() {
+		if (context != null) {
+			context.close();
+		}
+	}
 
-    @Test
-    public void getServiceUrlNullQuery() throws Exception {
-        details = new DefaultServiceAuthenticationDetails(casServiceUrl, request,artifactPattern);
-        assertEquals(UrlUtils.buildFullRequestUrl(request), details.getServiceUrl());
-    }
+	@Test
+	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(casServiceUrl,request,artifactPattern);
-        String serviceUrl = details.getServiceUrl();
-        request.setQueryString(null);
-        assertEquals(UrlUtils.buildFullRequestUrl(request),serviceUrl);
-    }
+	@Test
+	public void getServiceUrlTicketOnlyParam() throws Exception {
+		request.setQueryString("ticket=123");
+		details = new DefaultServiceAuthenticationDetails(casServiceUrl, request,
+				artifactPattern);
+		String serviceUrl = details.getServiceUrl();
+		request.setQueryString(null);
+		assertEquals(UrlUtils.buildFullRequestUrl(request), serviceUrl);
+	}
 
-    @Test
-    public void getServiceUrlTicketFirstMultiParam() throws Exception {
-        request.setQueryString("ticket=123&other=value");
-        details = new DefaultServiceAuthenticationDetails(casServiceUrl, request,artifactPattern);
-        String serviceUrl = details.getServiceUrl();
-        request.setQueryString("other=value");
-        assertEquals(UrlUtils.buildFullRequestUrl(request),serviceUrl);
-    }
+	@Test
+	public void getServiceUrlTicketFirstMultiParam() throws Exception {
+		request.setQueryString("ticket=123&other=value");
+		details = new DefaultServiceAuthenticationDetails(casServiceUrl, request,
+				artifactPattern);
+		String serviceUrl = details.getServiceUrl();
+		request.setQueryString("other=value");
+		assertEquals(UrlUtils.buildFullRequestUrl(request), serviceUrl);
+	}
 
-    @Test
-    public void getServiceUrlTicketLastMultiParam() throws Exception {
-        request.setQueryString("other=value&ticket=123");
-        details = new DefaultServiceAuthenticationDetails(casServiceUrl,request,artifactPattern);
-        String serviceUrl = details.getServiceUrl();
-        request.setQueryString("other=value");
-        assertEquals(UrlUtils.buildFullRequestUrl(request),serviceUrl);
-    }
+	@Test
+	public void getServiceUrlTicketLastMultiParam() throws Exception {
+		request.setQueryString("other=value&ticket=123");
+		details = new DefaultServiceAuthenticationDetails(casServiceUrl, request,
+				artifactPattern);
+		String serviceUrl = details.getServiceUrl();
+		request.setQueryString("other=value");
+		assertEquals(UrlUtils.buildFullRequestUrl(request), serviceUrl);
+	}
 
-    @Test
-    public void getServiceUrlTicketMiddleMultiParam() throws Exception {
-        request.setQueryString("other=value&ticket=123&last=this");
-        details = new DefaultServiceAuthenticationDetails(casServiceUrl,request,artifactPattern);
-        String serviceUrl = details.getServiceUrl();
-        request.setQueryString("other=value&last=this");
-        assertEquals(UrlUtils.buildFullRequestUrl(request),serviceUrl);
-    }
+	@Test
+	public void getServiceUrlTicketMiddleMultiParam() throws Exception {
+		request.setQueryString("other=value&ticket=123&last=this");
+		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 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 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());
-    }
+	@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);
-    }
+	private ServiceAuthenticationDetails loadServiceAuthenticationDetails(
+			String resourceName) {
+		context = new GenericXmlApplicationContext(getClass(), resourceName);
+		ServiceAuthenticationDetailsSource source = context
+				.getBean(ServiceAuthenticationDetailsSource.class);
+		return source.buildDetails(request);
+	}
 }
diff --git a/config/src/integration-test/java/org/springframework/security/config/annotation/authentication/ldap/NamespaceLdapAuthenticationProviderTestsConfigs.java b/config/src/integration-test/java/org/springframework/security/config/annotation/authentication/ldap/NamespaceLdapAuthenticationProviderTestsConfigs.java
index 809c6cc4a3..a351745fe0 100644
--- a/config/src/integration-test/java/org/springframework/security/config/annotation/authentication/ldap/NamespaceLdapAuthenticationProviderTestsConfigs.java
+++ b/config/src/integration-test/java/org/springframework/security/config/annotation/authentication/ldap/NamespaceLdapAuthenticationProviderTestsConfigs.java
@@ -15,7 +15,6 @@
  */
 package org.springframework.security.config.annotation.authentication.ldap;
 
-import org.springframework.context.annotation.Configuration;
 import org.springframework.security.authentication.encoding.PlaintextPasswordEncoder;
 import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
 import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
@@ -28,18 +27,22 @@ import org.springframework.security.ldap.userdetails.PersonContextMapper;
  *
  */
 public class NamespaceLdapAuthenticationProviderTestsConfigs {
-    @EnableWebSecurity
-    static class LdapAuthenticationProviderConfig extends WebSecurityConfigurerAdapter {
+	@EnableWebSecurity
+	static class LdapAuthenticationProviderConfig extends WebSecurityConfigurerAdapter {
+		filter-security-metadata-source
         protected void configure(AuthenticationManagerBuilder auth) throws Exception {
             auth
                 .ldapAuthentication()
                     .groupSearchBase("ou=groups")
                     .userDnPatterns("uid={0},ou=people"); // ldap-server@user-dn-pattern
         }
-    }
+        // @formatter:on
+	}
 
-    @EnableWebSecurity
-    static class CustomLdapAuthenticationProviderConfig extends WebSecurityConfigurerAdapter {
+	@EnableWebSecurity
+	static class CustomLdapAuthenticationProviderConfig extends
+			WebSecurityConfigurerAdapter {
+		filter-security-metadata-source
         protected void configure(AuthenticationManagerBuilder auth) throws Exception {
             auth
                 .ldapAuthentication()
@@ -61,21 +64,26 @@ public class NamespaceLdapAuthenticationProviderTestsConfigs {
                         // .url("ldap://localhost:33389/dc-springframework,dc=org") this overrides root and port and is used for external
                         ;
         }
-    }
+        // @formatter:on
+	}
 
-    @EnableWebSecurity
-    static class CustomAuthoritiesPopulatorConfig extends WebSecurityConfigurerAdapter {
-        static LdapAuthoritiesPopulator LAP;
+	@EnableWebSecurity
+	static class CustomAuthoritiesPopulatorConfig extends WebSecurityConfigurerAdapter {
+		static LdapAuthoritiesPopulator LAP;
+
+		filter-security-metadata-source
         protected void configure(AuthenticationManagerBuilder auth) throws Exception {
             auth
                 .ldapAuthentication()
                     .userSearchFilter("(uid={0})")
                     .ldapAuthoritiesPopulator(LAP);
         }
-    }
+        // @formatter:on
+	}
 
-    @EnableWebSecurity
-    static class PasswordCompareLdapConfig extends WebSecurityConfigurerAdapter {
+	@EnableWebSecurity
+	static class PasswordCompareLdapConfig extends WebSecurityConfigurerAdapter {
+		filter-security-metadata-source
         protected void configure(AuthenticationManagerBuilder auth) throws Exception {
             auth
                 .ldapAuthentication()
@@ -85,5 +93,6 @@ public class NamespaceLdapAuthenticationProviderTestsConfigs {
                         .passwordEncoder(new PlaintextPasswordEncoder()) // ldap-authentication-provider/password-compare/password-encoder@ref
                         .passwordAttribute("userPassword"); // ldap-authentication-provider/password-compare@password-attribute
         }
-    }
+        // @formatter:on
+	}
 }
diff --git a/config/src/integration-test/java/org/springframework/security/config/ldap/LdapServerBeanDefinitionParserTests.java b/config/src/integration-test/java/org/springframework/security/config/ldap/LdapServerBeanDefinitionParserTests.java
index 52b9f216c4..520cba7d22 100644
--- a/config/src/integration-test/java/org/springframework/security/config/ldap/LdapServerBeanDefinitionParserTests.java
+++ b/config/src/integration-test/java/org/springframework/security/config/ldap/LdapServerBeanDefinitionParserTests.java
@@ -31,72 +31,83 @@ import org.springframework.test.util.ReflectionTestUtils;
  * @author Rob Winch
  */
 public class LdapServerBeanDefinitionParserTests {
-    InMemoryXmlApplicationContext appCtx;
+	InMemoryXmlApplicationContext appCtx;
 
-    @After
-    public void closeAppContext() {
-        if (appCtx != null) {
-            appCtx.close();
-            appCtx = null;
-        }
-    }
+	@After
+	public void closeAppContext() {
+		if (appCtx != null) {
+			appCtx.close();
+			appCtx = null;
+		}
+	}
 
-    @Test
-    public void embeddedServerCreationContainsExpectedContextSourceAndData() {
-        appCtx = new InMemoryXmlApplicationContext("");
+	@Test
+	public void embeddedServerCreationContainsExpectedContextSourceAndData() {
+		appCtx = new InMemoryXmlApplicationContext(
+				"");
 
-        DefaultSpringSecurityContextSource contextSource = (DefaultSpringSecurityContextSource) appCtx.getBean(BeanIds.CONTEXT_SOURCE);
+		DefaultSpringSecurityContextSource contextSource = (DefaultSpringSecurityContextSource) appCtx
+				.getBean(BeanIds.CONTEXT_SOURCE);
 
-        // Check data is loaded
-        LdapTemplate template = new LdapTemplate(contextSource);
-        template.lookup("uid=ben,ou=people");
-    }
+		// Check data is loaded
+		LdapTemplate template = new LdapTemplate(contextSource);
+		template.lookup("uid=ben,ou=people");
+	}
 
-    @Test
-    public void useOfUrlAttributeCreatesCorrectContextSource() throws Exception {
-        int port = getDefaultPort();
-        // Create second "server" with a url pointing at embedded one
-        appCtx = new InMemoryXmlApplicationContext("" +
-                "");
+	@Test
+	public void useOfUrlAttributeCreatesCorrectContextSource() throws Exception {
+		int port = getDefaultPort();
+		// Create second "server" with a url pointing at embedded one
+		appCtx = new InMemoryXmlApplicationContext(
+				""
+						+ "");
 
-        // Check the default context source is still there.
-        appCtx.getBean(BeanIds.CONTEXT_SOURCE);
+		// Check the default context source is still there.
+		appCtx.getBean(BeanIds.CONTEXT_SOURCE);
 
-        DefaultSpringSecurityContextSource contextSource = (DefaultSpringSecurityContextSource) appCtx.getBean("blah");
+		DefaultSpringSecurityContextSource contextSource = (DefaultSpringSecurityContextSource) appCtx
+				.getBean("blah");
 
-        // Check data is loaded as before
-        LdapTemplate template = new LdapTemplate(contextSource);
-        template.lookup("uid=ben,ou=people");
-    }
+		// Check data is loaded as before
+		LdapTemplate template = new LdapTemplate(contextSource);
+		template.lookup("uid=ben,ou=people");
+	}
 
-    @Test
-    public void loadingSpecificLdifFileIsSuccessful() {
-        appCtx = new InMemoryXmlApplicationContext(
-                "");
-        DefaultSpringSecurityContextSource contextSource = (DefaultSpringSecurityContextSource) appCtx.getBean(BeanIds.CONTEXT_SOURCE);
+	@Test
+	public void loadingSpecificLdifFileIsSuccessful() {
+		appCtx = new InMemoryXmlApplicationContext(
+				"");
+		DefaultSpringSecurityContextSource contextSource = (DefaultSpringSecurityContextSource) appCtx
+				.getBean(BeanIds.CONTEXT_SOURCE);
 
-        LdapTemplate template = new LdapTemplate(contextSource);
-        template.lookup("uid=pg,ou=gorillas");
-    }
+		LdapTemplate template = new LdapTemplate(contextSource);
+		template.lookup("uid=pg,ou=gorillas");
+	}
 
-    @Test
-    public void defaultLdifFileIsSuccessful() {
-        appCtx = new InMemoryXmlApplicationContext(
-                "");
-        ApacheDSContainer dsContainer = appCtx.getBean(ApacheDSContainer.class);
+	@Test
+	public void defaultLdifFileIsSuccessful() {
+		appCtx = new InMemoryXmlApplicationContext("");
+		ApacheDSContainer dsContainer = appCtx.getBean(ApacheDSContainer.class);
 
-        assertEquals("classpath*:*.ldif", ReflectionTestUtils.getField(dsContainer, "ldifResources"));
-    }
+		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) {}
-        }
-    }
+	private int getDefaultPort() throws IOException {
+		ServerSocket server = null;
+		try {
+			server = new ServerSocket(0);
+			return server.getLocalPort();
+		}
+		finally {
+			try {
+				server.close();
+			}
+			catch (IOException e) {
+			}
+		}
+	}
 }
diff --git a/config/src/integration-test/java/org/springframework/security/config/ldap/LdapUserServiceBeanDefinitionParserTests.java b/config/src/integration-test/java/org/springframework/security/config/ldap/LdapUserServiceBeanDefinitionParserTests.java
index d862ca4e9d..45af75f4d8 100644
--- a/config/src/integration-test/java/org/springframework/security/config/ldap/LdapUserServiceBeanDefinitionParserTests.java
+++ b/config/src/integration-test/java/org/springframework/security/config/ldap/LdapUserServiceBeanDefinitionParserTests.java
@@ -38,135 +38,133 @@ import java.util.*;
  * @author Rob Winch
  */
 public class LdapUserServiceBeanDefinitionParserTests {
-    private InMemoryXmlApplicationContext appCtx;
+	private InMemoryXmlApplicationContext appCtx;
 
-    @After
-    public void closeAppContext() {
-        if (appCtx != null) {
-            appCtx.close();
-            appCtx = null;
-        }
-    }
+	@After
+	public void closeAppContext() {
+		if (appCtx != null) {
+			appCtx.close();
+			appCtx = null;
+		}
+	}
 
-    @Test
-    public void beanClassNamesAreCorrect() throws Exception {
-        assertEquals(LDAP_SEARCH_CLASS, FilterBasedLdapUserSearch.class.getName());
-        assertEquals(PERSON_MAPPER_CLASS, PersonContextMapper.class.getName());
-        assertEquals(INET_ORG_PERSON_MAPPER_CLASS, InetOrgPersonContextMapper.class.getName());
-        assertEquals(LDAP_USER_MAPPER_CLASS, LdapUserDetailsMapper.class.getName());
-        assertEquals(LDAP_AUTHORITIES_POPULATOR_CLASS, DefaultLdapAuthoritiesPopulator.class.getName());
-        assertEquals(LdapUserDetailsService.class.getName(), new LdapUserServiceBeanDefinitionParser().getBeanClassName(mock(Element.class)));
-    }
+	@Test
+	public void beanClassNamesAreCorrect() throws Exception {
+		assertEquals(LDAP_SEARCH_CLASS, FilterBasedLdapUserSearch.class.getName());
+		assertEquals(PERSON_MAPPER_CLASS, PersonContextMapper.class.getName());
+		assertEquals(INET_ORG_PERSON_MAPPER_CLASS,
+				InetOrgPersonContextMapper.class.getName());
+		assertEquals(LDAP_USER_MAPPER_CLASS, LdapUserDetailsMapper.class.getName());
+		assertEquals(LDAP_AUTHORITIES_POPULATOR_CLASS,
+				DefaultLdapAuthoritiesPopulator.class.getName());
+		assertEquals(LdapUserDetailsService.class.getName(),
+				new LdapUserServiceBeanDefinitionParser()
+						.getBeanClassName(mock(Element.class)));
+	}
 
-    @Test
-    public void minimalConfigurationIsParsedOk() throws Exception {
-        setContext("");
-    }
+	@Test
+	public void minimalConfigurationIsParsedOk() throws Exception {
+		setContext("");
+	}
 
-    @Test
-    public void userServiceReturnsExpectedData() throws Exception {
-        setContext("");
+	@Test
+	public void userServiceReturnsExpectedData() throws Exception {
+		setContext("");
 
-        UserDetailsService uds = (UserDetailsService) appCtx.getBean("ldapUDS");
-        UserDetails ben = uds.loadUserByUsername("ben");
+		UserDetailsService uds = (UserDetailsService) appCtx.getBean("ldapUDS");
+		UserDetails ben = uds.loadUserByUsername("ben");
 
-        Set authorities = AuthorityUtils.authorityListToSet(ben.getAuthorities());
-        assertEquals(3, authorities.size());
-        assertTrue(authorities.contains("ROLE_DEVELOPERS"));
-    }
+		Set authorities = AuthorityUtils.authorityListToSet(ben.getAuthorities());
+		assertEquals(3, authorities.size());
+		assertTrue(authorities.contains("ROLE_DEVELOPERS"));
+	}
 
-    @Test
-    public void differentUserSearchBaseWorksAsExpected() throws Exception {
-        setContext("");
+	@Test
+	public void differentUserSearchBaseWorksAsExpected() throws Exception {
+		setContext("");
 
-        UserDetailsService uds = (UserDetailsService) appCtx.getBean("ldapUDS");
-        UserDetails joe = uds.loadUserByUsername("Joe Smeth");
+		UserDetailsService uds = (UserDetailsService) appCtx.getBean("ldapUDS");
+		UserDetails joe = uds.loadUserByUsername("Joe Smeth");
 
-        assertEquals("Joe Smeth", joe.getUsername());
-    }
+		assertEquals("Joe Smeth", joe.getUsername());
+	}
 
-    @Test
-    public void rolePrefixIsSupported() throws Exception {
-        setContext(
-                "" +
-                "");
+	@Test
+	public void rolePrefixIsSupported() throws Exception {
+		setContext(""
+				+ "");
 
-        UserDetailsService uds = (UserDetailsService) appCtx.getBean("ldapUDS");
-        UserDetails ben = uds.loadUserByUsername("ben");
-        assertTrue(AuthorityUtils.authorityListToSet(ben.getAuthorities()).contains("PREFIX_DEVELOPERS"));
+		UserDetailsService uds = (UserDetailsService) appCtx.getBean("ldapUDS");
+		UserDetails ben = uds.loadUserByUsername("ben");
+		assertTrue(AuthorityUtils.authorityListToSet(ben.getAuthorities()).contains(
+				"PREFIX_DEVELOPERS"));
 
-        uds = (UserDetailsService) appCtx.getBean("ldapUDSNoPrefix");
-        ben = uds.loadUserByUsername("ben");
-        assertTrue(AuthorityUtils.authorityListToSet(ben.getAuthorities()).contains("DEVELOPERS"));
-    }
+		uds = (UserDetailsService) appCtx.getBean("ldapUDSNoPrefix");
+		ben = uds.loadUserByUsername("ben");
+		assertTrue(AuthorityUtils.authorityListToSet(ben.getAuthorities()).contains(
+				"DEVELOPERS"));
+	}
 
+	@Test
+	public void differentGroupRoleAttributeWorksAsExpected() throws Exception {
+		setContext("");
 
+		UserDetailsService uds = (UserDetailsService) appCtx.getBean("ldapUDS");
+		UserDetails ben = uds.loadUserByUsername("ben");
 
-    @Test
-    public void differentGroupRoleAttributeWorksAsExpected() throws Exception {
-        setContext("");
+		Set authorities = AuthorityUtils.authorityListToSet(ben.getAuthorities());
+		assertEquals(3, authorities.size());
+		assertTrue(authorities.contains("ROLE_DEVELOPER"));
 
-        UserDetailsService uds = (UserDetailsService) appCtx.getBean("ldapUDS");
-        UserDetails ben = uds.loadUserByUsername("ben");
+	}
 
-        Set authorities = AuthorityUtils.authorityListToSet(ben.getAuthorities());
-        assertEquals(3, authorities.size());
-        assertTrue(authorities.contains("ROLE_DEVELOPER"));
+	@Test
+	public void isSupportedByAuthenticationProviderElement() {
+		setContext(""
+				+ ""
+				+ "  "
+				+ "    "
+				+ "  " + "");
+	}
 
-    }
+	@Test
+	public void personContextMapperIsSupported() {
+		setContext(""
+				+ "");
+		UserDetailsService uds = (UserDetailsService) appCtx.getBean("ldapUDS");
+		UserDetails ben = uds.loadUserByUsername("ben");
+		assertTrue(ben instanceof Person);
+	}
 
-    @Test
-    public void isSupportedByAuthenticationProviderElement() {
-        setContext(
-                "" +
-                "" +
-                "  " +
-                "    " +
-                "  " +
-                "");
-    }
+	@Test
+	public void inetOrgContextMapperIsSupported() {
+		setContext(""
+				+ "");
+		UserDetailsService uds = (UserDetailsService) appCtx.getBean("ldapUDS");
+		UserDetails ben = uds.loadUserByUsername("ben");
+		assertTrue(ben instanceof InetOrgPerson);
+	}
 
-    @Test
-    public void personContextMapperIsSupported() {
-        setContext(
-                "" +
-                "");
-        UserDetailsService uds = (UserDetailsService) appCtx.getBean("ldapUDS");
-        UserDetails ben = uds.loadUserByUsername("ben");
-        assertTrue(ben instanceof Person);
-    }
+	@Test
+	public void externalContextMapperIsSupported() {
+		setContext(""
+				+ ""
+				+ "");
 
-    @Test
-    public void inetOrgContextMapperIsSupported() {
-        setContext(
-                "" +
-                "");
-        UserDetailsService uds = (UserDetailsService) appCtx.getBean("ldapUDS");
-        UserDetails ben = uds.loadUserByUsername("ben");
-        assertTrue(ben instanceof InetOrgPerson);
-    }
+		UserDetailsService uds = (UserDetailsService) appCtx.getBean("ldapUDS");
+		UserDetails ben = uds.loadUserByUsername("ben");
+		assertTrue(ben instanceof InetOrgPerson);
+	}
 
-    @Test
-    public void externalContextMapperIsSupported() {
-        setContext(
-                "" +
-                "" +
-                "");
-
-        UserDetailsService uds = (UserDetailsService) appCtx.getBean("ldapUDS");
-        UserDetails ben = uds.loadUserByUsername("ben");
-        assertTrue(ben instanceof InetOrgPerson);
-    }
-
-
-    private void setContext(String context) {
-        appCtx = new InMemoryXmlApplicationContext(context);
-    }
+	private void setContext(String context) {
+		appCtx = new InMemoryXmlApplicationContext(context);
+	}
 }
diff --git a/config/src/main/java/org/springframework/security/config/BeanIds.java b/config/src/main/java/org/springframework/security/config/BeanIds.java
index 996011af3b..c8d318e565 100644
--- a/config/src/main/java/org/springframework/security/config/BeanIds.java
+++ b/config/src/main/java/org/springframework/security/config/BeanIds.java
@@ -1,7 +1,8 @@
 package org.springframework.security.config;
 
 /**
- * Contains globally used default Bean IDs for beans created by the namespace support in Spring Security 2.
+ * Contains globally used default Bean IDs for beans created by the namespace support in
+ * Spring Security 2.
  * 

* These are intended for internal use. * @@ -9,27 +10,35 @@ package org.springframework.security.config; * @author Luke Taylor */ public abstract class BeanIds { - private static final String PREFIX = "org.springframework.security."; + private static final String PREFIX = "org.springframework.security."; - /** The "global" AuthenticationManager instance, registered by the <authentication-manager> element */ - public static final String AUTHENTICATION_MANAGER = PREFIX + "authenticationManager"; + /** + * The "global" AuthenticationManager instance, registered by the + * <authentication-manager> element + */ + public static final String AUTHENTICATION_MANAGER = PREFIX + "authenticationManager"; - /** External alias for FilterChainProxy bean, for use in web.xml files */ - public static final String SPRING_SECURITY_FILTER_CHAIN = "springSecurityFilterChain"; + /** External alias for FilterChainProxy bean, for use in web.xml files */ + public static final String SPRING_SECURITY_FILTER_CHAIN = "springSecurityFilterChain"; - public static final String CONTEXT_SOURCE_SETTING_POST_PROCESSOR = PREFIX + "contextSettingPostProcessor"; + public static final String CONTEXT_SOURCE_SETTING_POST_PROCESSOR = PREFIX + + "contextSettingPostProcessor"; - public static final String USER_DETAILS_SERVICE = PREFIX + "userDetailsService"; - public static final String USER_DETAILS_SERVICE_FACTORY = PREFIX + "userDetailsServiceFactory"; + public static final String USER_DETAILS_SERVICE = PREFIX + "userDetailsService"; + public static final String USER_DETAILS_SERVICE_FACTORY = PREFIX + + "userDetailsServiceFactory"; - public static final String METHOD_ACCESS_MANAGER = PREFIX + "defaultMethodAccessManager"; + public static final String METHOD_ACCESS_MANAGER = PREFIX + + "defaultMethodAccessManager"; - public static final String FILTER_CHAIN_PROXY = PREFIX + "filterChainProxy"; - public static final String FILTER_CHAINS = PREFIX + "filterChains"; + public static final String FILTER_CHAIN_PROXY = PREFIX + "filterChainProxy"; + public static final String FILTER_CHAINS = PREFIX + "filterChains"; - public static final String METHOD_SECURITY_METADATA_SOURCE_ADVISOR = PREFIX + "methodSecurityMetadataSourceAdvisor"; - public static final String EMBEDDED_APACHE_DS = PREFIX + "apacheDirectoryServerContainer"; - public static final String CONTEXT_SOURCE = PREFIX + "securityContextSource"; + public static final String METHOD_SECURITY_METADATA_SOURCE_ADVISOR = PREFIX + + "methodSecurityMetadataSourceAdvisor"; + public static final String EMBEDDED_APACHE_DS = PREFIX + + "apacheDirectoryServerContainer"; + public static final String CONTEXT_SOURCE = PREFIX + "securityContextSource"; - public static final String DEBUG_FILTER = PREFIX + "debugFilter"; + public static final String DEBUG_FILTER = PREFIX + "debugFilter"; } diff --git a/config/src/main/java/org/springframework/security/config/DebugBeanDefinitionParser.java b/config/src/main/java/org/springframework/security/config/DebugBeanDefinitionParser.java index 8173770281..16cf1e5438 100644 --- a/config/src/main/java/org/springframework/security/config/DebugBeanDefinitionParser.java +++ b/config/src/main/java/org/springframework/security/config/DebugBeanDefinitionParser.java @@ -11,10 +11,11 @@ import org.w3c.dom.Element; * @author Luke Taylor */ public class DebugBeanDefinitionParser implements BeanDefinitionParser { - public BeanDefinition parse(Element element, ParserContext parserContext) { - RootBeanDefinition debugPP = new RootBeanDefinition(SecurityDebugBeanFactoryPostProcessor.class); - parserContext.getReaderContext().registerWithGeneratedName(debugPP); + public BeanDefinition parse(Element element, ParserContext parserContext) { + RootBeanDefinition debugPP = new RootBeanDefinition( + SecurityDebugBeanFactoryPostProcessor.class); + parserContext.getReaderContext().registerWithGeneratedName(debugPP); - return null; - } + return null; + } } diff --git a/config/src/main/java/org/springframework/security/config/Elements.java b/config/src/main/java/org/springframework/security/config/Elements.java index 99bd1511b1..8b30c42d21 100644 --- a/config/src/main/java/org/springframework/security/config/Elements.java +++ b/config/src/main/java/org/springframework/security/config/Elements.java @@ -7,54 +7,54 @@ package org.springframework.security.config; */ public abstract class Elements { - public static final String ACCESS_DENIED_HANDLER = "access-denied-handler"; - public static final String AUTHENTICATION_MANAGER = "authentication-manager"; - public static final String AFTER_INVOCATION_PROVIDER = "after-invocation-provider"; - public static final String USER_SERVICE = "user-service"; - public static final String JDBC_USER_SERVICE = "jdbc-user-service"; - public static final String FILTER_CHAIN_MAP = "filter-chain-map"; - public static final String INTERCEPT_METHODS = "intercept-methods"; - public static final String INTERCEPT_URL = "intercept-url"; - public static final String AUTHENTICATION_PROVIDER = "authentication-provider"; - public static final String HTTP = "http"; - public static final String LDAP_PROVIDER = "ldap-authentication-provider"; - public static final String LDAP_SERVER = "ldap-server"; - public static final String LDAP_USER_SERVICE = "ldap-user-service"; - public static final String PROTECT_POINTCUT = "protect-pointcut"; - public static final String EXPRESSION_HANDLER = "expression-handler"; - public static final String INVOCATION_HANDLING = "pre-post-annotation-handling"; - public static final String INVOCATION_ATTRIBUTE_FACTORY = "invocation-attribute-factory"; - public static final String PRE_INVOCATION_ADVICE = "pre-invocation-advice"; - public static final String POST_INVOCATION_ADVICE = "post-invocation-advice"; - public static final String PROTECT = "protect"; - public static final String SESSION_MANAGEMENT = "session-management"; - public static final String CONCURRENT_SESSIONS = "concurrency-control"; - public static final String LOGOUT = "logout"; - public static final String FORM_LOGIN = "form-login"; - public static final String OPENID_LOGIN = "openid-login"; - public static final String OPENID_ATTRIBUTE_EXCHANGE = "attribute-exchange"; - public static final String OPENID_ATTRIBUTE = "openid-attribute"; - public static final String BASIC_AUTH = "http-basic"; - public static final String REMEMBER_ME = "remember-me"; - public static final String ANONYMOUS = "anonymous"; - public static final String FILTER_CHAIN = "filter-chain"; - public static final String GLOBAL_METHOD_SECURITY = "global-method-security"; - public static final String PASSWORD_ENCODER = "password-encoder"; - public static final String SALT_SOURCE = "salt-source"; - public static final String PORT_MAPPINGS = "port-mappings"; - public static final String PORT_MAPPING = "port-mapping"; - public static final String CUSTOM_FILTER = "custom-filter"; - public static final String REQUEST_CACHE = "request-cache"; - public static final String X509 = "x509"; - public static final String JEE = "jee"; - public static final String FILTER_SECURITY_METADATA_SOURCE = "filter-security-metadata-source"; - public static final String METHOD_SECURITY_METADATA_SOURCE = "method-security-metadata-source"; - public static final String LDAP_PASSWORD_COMPARE = "password-compare"; - public static final String DEBUG = "debug"; - public static final String HTTP_FIREWALL = "http-firewall"; - public static final String HEADERS = "headers"; - public static final String CSRF = "csrf"; + public static final String ACCESS_DENIED_HANDLER = "access-denied-handler"; + public static final String AUTHENTICATION_MANAGER = "authentication-manager"; + public static final String AFTER_INVOCATION_PROVIDER = "after-invocation-provider"; + public static final String USER_SERVICE = "user-service"; + public static final String JDBC_USER_SERVICE = "jdbc-user-service"; + public static final String FILTER_CHAIN_MAP = "filter-chain-map"; + public static final String INTERCEPT_METHODS = "intercept-methods"; + public static final String INTERCEPT_URL = "intercept-url"; + public static final String AUTHENTICATION_PROVIDER = "authentication-provider"; + public static final String HTTP = "http"; + public static final String LDAP_PROVIDER = "ldap-authentication-provider"; + public static final String LDAP_SERVER = "ldap-server"; + public static final String LDAP_USER_SERVICE = "ldap-user-service"; + public static final String PROTECT_POINTCUT = "protect-pointcut"; + public static final String EXPRESSION_HANDLER = "expression-handler"; + public static final String INVOCATION_HANDLING = "pre-post-annotation-handling"; + public static final String INVOCATION_ATTRIBUTE_FACTORY = "invocation-attribute-factory"; + public static final String PRE_INVOCATION_ADVICE = "pre-invocation-advice"; + public static final String POST_INVOCATION_ADVICE = "post-invocation-advice"; + public static final String PROTECT = "protect"; + public static final String SESSION_MANAGEMENT = "session-management"; + public static final String CONCURRENT_SESSIONS = "concurrency-control"; + public static final String LOGOUT = "logout"; + public static final String FORM_LOGIN = "form-login"; + public static final String OPENID_LOGIN = "openid-login"; + public static final String OPENID_ATTRIBUTE_EXCHANGE = "attribute-exchange"; + public static final String OPENID_ATTRIBUTE = "openid-attribute"; + public static final String BASIC_AUTH = "http-basic"; + public static final String REMEMBER_ME = "remember-me"; + public static final String ANONYMOUS = "anonymous"; + public static final String FILTER_CHAIN = "filter-chain"; + public static final String GLOBAL_METHOD_SECURITY = "global-method-security"; + public static final String PASSWORD_ENCODER = "password-encoder"; + public static final String SALT_SOURCE = "salt-source"; + public static final String PORT_MAPPINGS = "port-mappings"; + public static final String PORT_MAPPING = "port-mapping"; + public static final String CUSTOM_FILTER = "custom-filter"; + public static final String REQUEST_CACHE = "request-cache"; + public static final String X509 = "x509"; + public static final String JEE = "jee"; + public static final String FILTER_SECURITY_METADATA_SOURCE = "filter-security-metadata-source"; + public static final String METHOD_SECURITY_METADATA_SOURCE = "method-security-metadata-source"; + public static final String LDAP_PASSWORD_COMPARE = "password-compare"; + public static final String DEBUG = "debug"; + public static final String HTTP_FIREWALL = "http-firewall"; + public static final String HEADERS = "headers"; + public static final String CSRF = "csrf"; - public static final String WEBSOCKET_MESSAGE_BROKER = "websocket-message-broker"; - public static final String INTERCEPT_MESSAGE = "intercept-message"; + public static final String WEBSOCKET_MESSAGE_BROKER = "websocket-message-broker"; + public static final String INTERCEPT_MESSAGE = "intercept-message"; } diff --git a/config/src/main/java/org/springframework/security/config/SecurityNamespaceHandler.java b/config/src/main/java/org/springframework/security/config/SecurityNamespaceHandler.java index da3a5c8105..65e83e26bc 100644 --- a/config/src/main/java/org/springframework/security/config/SecurityNamespaceHandler.java +++ b/config/src/main/java/org/springframework/security/config/SecurityNamespaceHandler.java @@ -48,7 +48,8 @@ import org.w3c.dom.Element; import org.w3c.dom.Node; /** - * Parses elements from the "security" namespace (http://www.springframework.org/schema/security). + * Parses elements from the "security" namespace + * (http://www.springframework.org/schema/security). * * @author Luke Taylor * @author Ben Alex @@ -56,154 +57,174 @@ import org.w3c.dom.Node; * @since 2.0 */ public final class SecurityNamespaceHandler implements NamespaceHandler { - private static final String FILTER_CHAIN_PROXY_CLASSNAME = "org.springframework.security.web.FilterChainProxy"; - private static final String MESSAGE_CLASSNAME = "org.springframework.messaging.Message"; - private final Log logger = LogFactory.getLog(getClass()); - private final Map parsers = new HashMap(); - private final BeanDefinitionDecorator interceptMethodsBDD = new InterceptMethodsBeanDefinitionDecorator(); - private BeanDefinitionDecorator filterChainMapBDD; + private static final String FILTER_CHAIN_PROXY_CLASSNAME = "org.springframework.security.web.FilterChainProxy"; + private static final String MESSAGE_CLASSNAME = "org.springframework.messaging.Message"; + private final Log logger = LogFactory.getLog(getClass()); + private final Map parsers = new HashMap(); + private final BeanDefinitionDecorator interceptMethodsBDD = new InterceptMethodsBeanDefinitionDecorator(); + private BeanDefinitionDecorator filterChainMapBDD; - public SecurityNamespaceHandler() { - String coreVersion = SpringSecurityCoreVersion.getVersion(); + public SecurityNamespaceHandler() { + String coreVersion = SpringSecurityCoreVersion.getVersion(); - Package pkg = SpringSecurityCoreVersion.class.getPackage(); + Package pkg = SpringSecurityCoreVersion.class.getPackage(); - if (pkg == null || coreVersion == null) { - logger.info("Couldn't determine package version information."); - return; - } + if (pkg == null || coreVersion == null) { + logger.info("Couldn't determine package version information."); + return; + } - String version = pkg.getImplementationVersion(); - logger.info("Spring Security 'config' module version is " + version); + String version = pkg.getImplementationVersion(); + logger.info("Spring Security 'config' module version is " + version); - if (version.compareTo(coreVersion) != 0) { - logger.error("You are running with different versions of the Spring Security 'core' and 'config' modules"); - } - } + if (version.compareTo(coreVersion) != 0) { + logger.error("You are running with different versions of the Spring Security 'core' and 'config' modules"); + } + } - public BeanDefinition parse(Element element, ParserContext pc) { - if (!namespaceMatchesVersion(element)) { - pc.getReaderContext().fatal("You cannot use a spring-security-2.0.xsd or spring-security-3.0.xsd or spring-security-3.1.xsd schema " + - "with Spring Security 3.2. Please update your schema declarations to the 3.2 schema.", element); - } - String name = pc.getDelegate().getLocalName(element); - BeanDefinitionParser parser = parsers.get(name); + public BeanDefinition parse(Element element, ParserContext pc) { + if (!namespaceMatchesVersion(element)) { + pc.getReaderContext() + .fatal("You cannot use a spring-security-2.0.xsd or spring-security-3.0.xsd or spring-security-3.1.xsd schema " + + "with Spring Security 3.2. Please update your schema declarations to the 3.2 schema.", + element); + } + String name = pc.getDelegate().getLocalName(element); + BeanDefinitionParser parser = parsers.get(name); - if (parser == null) { - // SEC-1455. Load parsers when required, not just on init(). - loadParsers(); - } + if (parser == null) { + // SEC-1455. Load parsers when required, not just on init(). + loadParsers(); + } - if (parser == null) { - if (Elements.HTTP.equals(name) || Elements.FILTER_SECURITY_METADATA_SOURCE.equals(name) || - Elements.FILTER_CHAIN_MAP.equals(name) || Elements.FILTER_CHAIN.equals(name)) { - reportMissingWebClasses(name, pc, element); - } else { - reportUnsupportedNodeType(name, pc, element); - } + if (parser == null) { + if (Elements.HTTP.equals(name) + || Elements.FILTER_SECURITY_METADATA_SOURCE.equals(name) + || Elements.FILTER_CHAIN_MAP.equals(name) + || Elements.FILTER_CHAIN.equals(name)) { + reportMissingWebClasses(name, pc, element); + } + else { + reportUnsupportedNodeType(name, pc, element); + } - return null; - } + return null; + } - return parser.parse(element, pc); - } + return parser.parse(element, pc); + } - public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder definition, ParserContext pc) { - String name = pc.getDelegate().getLocalName(node); + public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder definition, + ParserContext pc) { + String name = pc.getDelegate().getLocalName(node); - // We only handle elements - if (node instanceof Element) { - if (Elements.INTERCEPT_METHODS.equals(name)) { - return interceptMethodsBDD.decorate(node, definition, pc); - } + // We only handle elements + if (node instanceof Element) { + if (Elements.INTERCEPT_METHODS.equals(name)) { + return interceptMethodsBDD.decorate(node, definition, pc); + } - if (Elements.FILTER_CHAIN_MAP.equals(name)) { - if (filterChainMapBDD == null) { - loadParsers(); - } - if (filterChainMapBDD == null) { - reportMissingWebClasses(name, pc, node); - } - return filterChainMapBDD.decorate(node, definition, pc); - } - } + if (Elements.FILTER_CHAIN_MAP.equals(name)) { + if (filterChainMapBDD == null) { + loadParsers(); + } + if (filterChainMapBDD == null) { + reportMissingWebClasses(name, pc, node); + } + return filterChainMapBDD.decorate(node, definition, pc); + } + } - reportUnsupportedNodeType(name, pc, node); + reportUnsupportedNodeType(name, pc, node); - return null; - } + return null; + } - private void reportUnsupportedNodeType(String name, ParserContext pc, Node node) { - pc.getReaderContext().fatal("Security namespace does not support decoration of " + - (node instanceof Element ? "element" : "attribute") + " [" + name + "]", node); - } + private void reportUnsupportedNodeType(String name, ParserContext pc, Node node) { + pc.getReaderContext().fatal( + "Security namespace does not support decoration of " + + (node instanceof Element ? "element" : "attribute") + " [" + + name + "]", node); + } - private void reportMissingWebClasses(String nodeName, ParserContext pc, Node node) { - String errorMessage = "The classes from the spring-security-web jar " - + "(or one of its dependencies) are not available. You need these to use <" + nodeName + ">"; - try { - ClassUtils.forName(FILTER_CHAIN_PROXY_CLASSNAME, getClass().getClassLoader()); - // no details available - pc.getReaderContext().fatal(errorMessage, node); - } catch (Throwable cause) { - // provide details on why it could not be loaded - pc.getReaderContext().fatal(errorMessage, node, cause); - } - } + private void reportMissingWebClasses(String nodeName, ParserContext pc, Node node) { + String errorMessage = "The classes from the spring-security-web jar " + + "(or one of its dependencies) are not available. You need these to use <" + + nodeName + ">"; + try { + ClassUtils.forName(FILTER_CHAIN_PROXY_CLASSNAME, getClass().getClassLoader()); + // no details available + pc.getReaderContext().fatal(errorMessage, node); + } + catch (Throwable cause) { + // provide details on why it could not be loaded + pc.getReaderContext().fatal(errorMessage, node, cause); + } + } - public void init() { - loadParsers(); - } + public void init() { + loadParsers(); + } - @SuppressWarnings("deprecation") - private void loadParsers() { - // Parsers - parsers.put(Elements.LDAP_PROVIDER, new LdapProviderBeanDefinitionParser()); - parsers.put(Elements.LDAP_SERVER, new LdapServerBeanDefinitionParser()); - parsers.put(Elements.LDAP_USER_SERVICE, new LdapUserServiceBeanDefinitionParser()); - parsers.put(Elements.USER_SERVICE, new UserServiceBeanDefinitionParser()); - parsers.put(Elements.JDBC_USER_SERVICE, new JdbcUserServiceBeanDefinitionParser()); - parsers.put(Elements.AUTHENTICATION_PROVIDER, new AuthenticationProviderBeanDefinitionParser()); - parsers.put(Elements.GLOBAL_METHOD_SECURITY, new GlobalMethodSecurityBeanDefinitionParser()); - parsers.put(Elements.AUTHENTICATION_MANAGER, new AuthenticationManagerBeanDefinitionParser()); - parsers.put(Elements.METHOD_SECURITY_METADATA_SOURCE, new MethodSecurityMetadataSourceBeanDefinitionParser()); + @SuppressWarnings("deprecation") + private void loadParsers() { + // Parsers + parsers.put(Elements.LDAP_PROVIDER, new LdapProviderBeanDefinitionParser()); + parsers.put(Elements.LDAP_SERVER, new LdapServerBeanDefinitionParser()); + parsers.put(Elements.LDAP_USER_SERVICE, new LdapUserServiceBeanDefinitionParser()); + parsers.put(Elements.USER_SERVICE, new UserServiceBeanDefinitionParser()); + parsers.put(Elements.JDBC_USER_SERVICE, new JdbcUserServiceBeanDefinitionParser()); + parsers.put(Elements.AUTHENTICATION_PROVIDER, + new AuthenticationProviderBeanDefinitionParser()); + parsers.put(Elements.GLOBAL_METHOD_SECURITY, + new GlobalMethodSecurityBeanDefinitionParser()); + parsers.put(Elements.AUTHENTICATION_MANAGER, + new AuthenticationManagerBeanDefinitionParser()); + parsers.put(Elements.METHOD_SECURITY_METADATA_SOURCE, + new MethodSecurityMetadataSourceBeanDefinitionParser()); - // Only load the web-namespace parsers if the web classes are available - if(ClassUtils.isPresent(FILTER_CHAIN_PROXY_CLASSNAME, getClass().getClassLoader())) { - parsers.put(Elements.DEBUG, new DebugBeanDefinitionParser()); - parsers.put(Elements.HTTP, new HttpSecurityBeanDefinitionParser()); - parsers.put(Elements.HTTP_FIREWALL, new HttpFirewallBeanDefinitionParser()); - parsers.put(Elements.FILTER_SECURITY_METADATA_SOURCE, new FilterInvocationSecurityMetadataSourceParser()); - parsers.put(Elements.FILTER_CHAIN, new FilterChainBeanDefinitionParser()); - filterChainMapBDD = new FilterChainMapBeanDefinitionDecorator(); - } + // Only load the web-namespace parsers if the web classes are available + if (ClassUtils.isPresent(FILTER_CHAIN_PROXY_CLASSNAME, getClass() + .getClassLoader())) { + parsers.put(Elements.DEBUG, new DebugBeanDefinitionParser()); + parsers.put(Elements.HTTP, new HttpSecurityBeanDefinitionParser()); + parsers.put(Elements.HTTP_FIREWALL, new HttpFirewallBeanDefinitionParser()); + parsers.put(Elements.FILTER_SECURITY_METADATA_SOURCE, + new FilterInvocationSecurityMetadataSourceParser()); + parsers.put(Elements.FILTER_CHAIN, new FilterChainBeanDefinitionParser()); + filterChainMapBDD = new FilterChainMapBeanDefinitionDecorator(); + } - if(ClassUtils.isPresent(MESSAGE_CLASSNAME, getClass().getClassLoader())) { - parsers.put(Elements.WEBSOCKET_MESSAGE_BROKER, new WebSocketMessageBrokerSecurityBeanDefinitionParser()); - } - } + if (ClassUtils.isPresent(MESSAGE_CLASSNAME, getClass().getClassLoader())) { + parsers.put(Elements.WEBSOCKET_MESSAGE_BROKER, + new WebSocketMessageBrokerSecurityBeanDefinitionParser()); + } + } - /** - * Check that the schema location declared in the source file being parsed matches the Spring Security version. - * The old 2.0 schema is not compatible with the 3.1 parser, so it is an error to explicitly use - * 2.0. - *

- * There are also differences between 3.0 and 3.1 which are sufficient that we report using 3.0 as an error too. - * It might be an error to declare spring-security.xsd as an alias, but you are only going to find that out - * when one of the sub parsers breaks. - * - * @param element the element that is to be parsed next - * @return true if we find a schema declaration that matches - */ - private boolean namespaceMatchesVersion(Element element) { - return matchesVersionInternal(element) && matchesVersionInternal(element.getOwnerDocument().getDocumentElement()); - } + /** + * Check that the schema location declared in the source file being parsed matches the + * Spring Security version. The old 2.0 schema is not compatible with the 3.1 parser, + * so it is an error to explicitly use 2.0. + *

+ * There are also differences between 3.0 and 3.1 which are sufficient that we report + * using 3.0 as an error too. It might be an error to declare spring-security.xsd as + * an alias, but you are only going to find that out when one of the sub parsers + * breaks. + * + * @param element the element that is to be parsed next + * @return true if we find a schema declaration that matches + */ + private boolean namespaceMatchesVersion(Element element) { + return matchesVersionInternal(element) + && matchesVersionInternal(element.getOwnerDocument().getDocumentElement()); + } - private boolean matchesVersionInternal(Element element) { - String schemaLocation = element.getAttributeNS("http://www.w3.org/2001/XMLSchema-instance", "schemaLocation"); - return schemaLocation.matches("(?m).*spring-security-4\\.0.*.xsd.*") - || schemaLocation.matches("(?m).*spring-security.xsd.*") - || !schemaLocation.matches("(?m).*spring-security.*"); - } + private boolean matchesVersionInternal(Element element) { + String schemaLocation = element.getAttributeNS( + "http://www.w3.org/2001/XMLSchema-instance", "schemaLocation"); + return schemaLocation.matches("(?m).*spring-security-4\\.0.*.xsd.*") + || schemaLocation.matches("(?m).*spring-security.xsd.*") + || !schemaLocation.matches("(?m).*spring-security.*"); + } } diff --git a/config/src/main/java/org/springframework/security/config/annotation/AbstractConfiguredSecurityBuilder.java b/config/src/main/java/org/springframework/security/config/annotation/AbstractConfiguredSecurityBuilder.java index 2102c74701..3926787e89 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/AbstractConfiguredSecurityBuilder.java +++ b/config/src/main/java/org/springframework/security/config/annotation/AbstractConfiguredSecurityBuilder.java @@ -30,428 +30,427 @@ import org.springframework.util.Assert; import org.springframework.web.filter.DelegatingFilterProxy; /** - *

A base {@link SecurityBuilder} that allows {@link SecurityConfigurer} to be - * applied to it. This makes modifying the {@link SecurityBuilder} a strategy - * that can be customized and broken up into a number of - * {@link SecurityConfigurer} objects that have more specific goals than that - * of the {@link SecurityBuilder}.

+ *

+ * A base {@link SecurityBuilder} that allows {@link SecurityConfigurer} to be applied to + * it. This makes modifying the {@link SecurityBuilder} a strategy that can be customized + * and broken up into a number of {@link SecurityConfigurer} objects that have more + * specific goals than that of the {@link SecurityBuilder}. + *

* - *

For example, a {@link SecurityBuilder} may build an - * {@link DelegatingFilterProxy}, but a {@link SecurityConfigurer} might - * populate the {@link SecurityBuilder} with the filters necessary for session - * management, form based login, authorization, etc.

+ *

+ * For example, a {@link SecurityBuilder} may build an {@link DelegatingFilterProxy}, but + * a {@link SecurityConfigurer} might populate the {@link SecurityBuilder} with the + * filters necessary for session management, form based login, authorization, etc. + *

* * @see WebSecurity * * @author Rob Winch * - * @param - * The object that this builder returns - * @param - * The type of this builder (that is returned by the base class) + * @param The object that this builder returns + * @param The type of this builder (that is returned by the base class) */ -public abstract class AbstractConfiguredSecurityBuilder> extends AbstractSecurityBuilder { - private final Log logger = LogFactory.getLog(getClass()); +public abstract class AbstractConfiguredSecurityBuilder> + extends AbstractSecurityBuilder { + private final Log logger = LogFactory.getLog(getClass()); - private final LinkedHashMap>, List>> configurers = - new LinkedHashMap>, List>>(); + private final LinkedHashMap>, List>> configurers = new LinkedHashMap>, List>>(); - private final Map,Object> sharedObjects = new HashMap,Object>(); + private final Map, Object> sharedObjects = new HashMap, Object>(); - private final boolean allowConfigurersOfSameType; + private final boolean allowConfigurersOfSameType; - private BuildState buildState = BuildState.UNBUILT; + private BuildState buildState = BuildState.UNBUILT; - private ObjectPostProcessor objectPostProcessor; + private ObjectPostProcessor objectPostProcessor; - /*** - * Creates a new instance with the provided {@link ObjectPostProcessor}. - * This post processor must support Object since there are many types of - * objects that may be post processed. - * - * @param objectPostProcessor the {@link ObjectPostProcessor} to use - */ - protected AbstractConfiguredSecurityBuilder(ObjectPostProcessor objectPostProcessor) { - this(objectPostProcessor,false); - } + /*** + * Creates a new instance with the provided {@link ObjectPostProcessor}. This post + * processor must support Object since there are many types of objects that may be + * post processed. + * + * @param objectPostProcessor the {@link ObjectPostProcessor} to use + */ + protected AbstractConfiguredSecurityBuilder( + ObjectPostProcessor objectPostProcessor) { + this(objectPostProcessor, false); + } - /*** - * Creates a new instance with the provided {@link ObjectPostProcessor}. - * This post processor must support Object since there are many types of - * objects that may be post processed. - * - * @param objectPostProcessor the {@link ObjectPostProcessor} to use - * @param allowConfigurersOfSameType if true, will not override other {@link SecurityConfigurer}'s when performing apply - */ - protected AbstractConfiguredSecurityBuilder(ObjectPostProcessor objectPostProcessor, boolean allowConfigurersOfSameType) { - Assert.notNull(objectPostProcessor, "objectPostProcessor cannot be null"); - this.objectPostProcessor = objectPostProcessor; - this.allowConfigurersOfSameType = allowConfigurersOfSameType; - } + /*** + * Creates a new instance with the provided {@link ObjectPostProcessor}. This post + * processor must support Object since there are many types of objects that may be + * post processed. + * + * @param objectPostProcessor the {@link ObjectPostProcessor} to use + * @param allowConfigurersOfSameType if true, will not override other + * {@link SecurityConfigurer}'s when performing apply + */ + protected AbstractConfiguredSecurityBuilder( + ObjectPostProcessor objectPostProcessor, + boolean allowConfigurersOfSameType) { + Assert.notNull(objectPostProcessor, "objectPostProcessor cannot be null"); + this.objectPostProcessor = objectPostProcessor; + this.allowConfigurersOfSameType = allowConfigurersOfSameType; + } + /** + * Similar to {@link #build()} and {@link #getObject()} but checks the state to + * determine if {@link #build()} needs to be called first. + * + * @return the result of {@link #build()} or {@link #getObject()}. If an error occurs + * while building, returns null. + */ + public O getOrBuild() { + if (isUnbuilt()) { + try { + return build(); + } + catch (Exception e) { + logger.debug("Failed to perform build. Returning null", e); + return null; + } + } + else { + return getObject(); + } + } - /** - * Similar to {@link #build()} and {@link #getObject()} but checks the state - * to determine if {@link #build()} needs to be called first. - * - * @return the result of {@link #build()} or {@link #getObject()}. If an - * error occurs while building, returns null. - */ - public O getOrBuild() { - if(isUnbuilt()) { - try { - return build(); - } catch(Exception e) { - logger.debug("Failed to perform build. Returning null", e); - return null; - } - } else { - return getObject(); - } - } + /** + * Applies a {@link SecurityConfigurerAdapter} to this {@link SecurityBuilder} and + * invokes {@link SecurityConfigurerAdapter#setBuilder(SecurityBuilder)}. + * + * @param configurer + * @return + * @throws Exception + */ + @SuppressWarnings("unchecked") + public > C apply(C configurer) + throws Exception { + add(configurer); + configurer.addObjectPostProcessor(objectPostProcessor); + configurer.setBuilder((B) this); + return configurer; + } - /** - * Applies a {@link SecurityConfigurerAdapter} to this - * {@link SecurityBuilder} and invokes - * {@link SecurityConfigurerAdapter#setBuilder(SecurityBuilder)}. - * - * @param configurer - * @return - * @throws Exception - */ - @SuppressWarnings("unchecked") - public > C apply(C configurer) - throws Exception { - add(configurer); - configurer.addObjectPostProcessor(objectPostProcessor); - configurer.setBuilder((B) this); - return configurer; - } + /** + * Applies a {@link SecurityConfigurer} to this {@link SecurityBuilder} overriding any + * {@link SecurityConfigurer} of the exact same class. Note that object hierarchies + * are not considered. + * + * @param configurer + * @return + * @throws Exception + */ + public > C apply(C configurer) throws Exception { + add(configurer); + return configurer; + } - /** - * Applies a {@link SecurityConfigurer} to this {@link SecurityBuilder} - * overriding any {@link SecurityConfigurer} of the exact same class. Note - * that object hierarchies are not considered. - * - * @param configurer - * @return - * @throws Exception - */ - public > C apply(C configurer) - throws Exception { - add(configurer); - return configurer; - } + /** + * Sets an object that is shared by multiple {@link SecurityConfigurer}. + * + * @param sharedType the Class to key the shared object by. + * @param object the Object to store + */ + @SuppressWarnings("unchecked") + public void setSharedObject(Class sharedType, C object) { + this.sharedObjects.put((Class) sharedType, object); + } - /** - * Sets an object that is shared by multiple {@link SecurityConfigurer}. - * - * @param sharedType the Class to key the shared object by. - * @param object the Object to store - */ - @SuppressWarnings("unchecked") - public void setSharedObject(Class sharedType, C object) { - this.sharedObjects.put((Class) sharedType, object); - } + /** + * Gets a shared Object. Note that object heirarchies are not considered. + * + * @param sharedType the type of the shared Object + * @return the shared Object or null if it is not found + */ + @SuppressWarnings("unchecked") + public C getSharedObject(Class sharedType) { + return (C) this.sharedObjects.get(sharedType); + } - /** - * Gets a shared Object. Note that object heirarchies are not considered. - * - * @param sharedType the type of the shared Object - * @return the shared Object or null if it is not found - */ - @SuppressWarnings("unchecked") - public C getSharedObject(Class sharedType) { - return (C) this.sharedObjects.get(sharedType); - } + /** + * Gets the shared objects + * @return + */ + public Map, Object> getSharedObjects() { + return Collections.unmodifiableMap(this.sharedObjects); + } - /** - * Gets the shared objects - * @return - */ - public Map,Object> getSharedObjects() { - return Collections.unmodifiableMap(this.sharedObjects); - } + /** + * Adds {@link SecurityConfigurer} ensuring that it is allowed and invoking + * {@link SecurityConfigurer#init(SecurityBuilder)} immediately if necessary. + * + * @param configurer the {@link SecurityConfigurer} to add + * @throws Exception if an error occurs + */ + @SuppressWarnings("unchecked") + private > void add(C configurer) throws Exception { + Assert.notNull(configurer, "configurer cannot be null"); - /** - * Adds {@link SecurityConfigurer} ensuring that it is allowed and - * invoking {@link SecurityConfigurer#init(SecurityBuilder)} immediately - * if necessary. - * - * @param configurer the {@link SecurityConfigurer} to add - * @throws Exception if an error occurs - */ - @SuppressWarnings("unchecked") - private > void add(C configurer) throws Exception { - Assert.notNull(configurer, "configurer cannot be null"); + Class> clazz = (Class>) configurer + .getClass(); + synchronized (configurers) { + if (buildState.isConfigured()) { + throw new IllegalStateException("Cannot apply " + configurer + + " to already built object"); + } + List> configs = allowConfigurersOfSameType ? this.configurers + .get(clazz) : null; + if (configs == null) { + configs = new ArrayList>(1); + } + configs.add(configurer); + this.configurers.put(clazz, configs); + if (buildState.isInitializing()) { + configurer.init((B) this); + } + } + } - Class> clazz = (Class>) configurer - .getClass(); - synchronized(configurers) { - if(buildState.isConfigured()) { - throw new IllegalStateException("Cannot apply "+configurer+" to already built object"); - } - List> configs = allowConfigurersOfSameType ? this.configurers.get(clazz) : null; - if(configs == null) { - configs = new ArrayList>(1); - } - configs.add(configurer); - this.configurers.put(clazz, configs); - if(buildState.isInitializing()) { - configurer.init((B)this); - } - } - } + /** + * Gets all the {@link SecurityConfigurer} instances by its class name or an empty + * List if not found. Note that object hierarchies are not considered. + * + * @param clazz the {@link SecurityConfigurer} class to look for + * @return + */ + @SuppressWarnings("unchecked") + public > List getConfigurers(Class clazz) { + List configs = (List) this.configurers.get(clazz); + if (configs == null) { + return new ArrayList(); + } + return new ArrayList(configs); + } - /** - * Gets all the {@link SecurityConfigurer} instances by its class name or an - * empty List if not found. Note that object hierarchies are not considered. - * - * @param clazz the {@link SecurityConfigurer} class to look for - * @return - */ - @SuppressWarnings("unchecked") - public > List getConfigurers( - Class clazz) { - List configs = (List) this.configurers.get(clazz); - if(configs == null) { - return new ArrayList(); - } - return new ArrayList(configs); - } + /** + * Removes all the {@link SecurityConfigurer} instances by its class name or an empty + * List if not found. Note that object hierarchies are not considered. + * + * @param clazz the {@link SecurityConfigurer} class to look for + * @return + */ + @SuppressWarnings("unchecked") + public > List removeConfigurers(Class clazz) { + List configs = (List) this.configurers.remove(clazz); + if (configs == null) { + return new ArrayList(); + } + return new ArrayList(configs); + } - /** - * Removes all the {@link SecurityConfigurer} instances by its class name or an - * empty List if not found. Note that object hierarchies are not considered. - * - * @param clazz the {@link SecurityConfigurer} class to look for - * @return - */ - @SuppressWarnings("unchecked") - public > List removeConfigurers( - Class clazz) { - List configs = (List) this.configurers.remove(clazz); - if(configs == null) { - return new ArrayList(); - } - return new ArrayList(configs); - } + /** + * Gets the {@link SecurityConfigurer} by its class name or null if not + * found. Note that object hierarchies are not considered. + * + * @param clazz + * @return + */ + @SuppressWarnings("unchecked") + public > C getConfigurer(Class clazz) { + List> configs = this.configurers.get(clazz); + if (configs == null) { + return null; + } + if (configs.size() != 1) { + throw new IllegalStateException("Only one configurer expected for type " + + clazz + ", but got " + configs); + } + return (C) configs.get(0); + } - /** - * Gets the {@link SecurityConfigurer} by its class name or - * null if not found. Note that object hierarchies are not - * considered. - * - * @param clazz - * @return - */ - @SuppressWarnings("unchecked") - public > C getConfigurer( - Class clazz) { - List> configs = this.configurers.get(clazz); - if(configs == null) { - return null; - } - if(configs.size() != 1) { - throw new IllegalStateException("Only one configurer expected for type " + clazz + ", but got " + configs); - } - return (C) configs.get(0); - } + /** + * Removes and returns the {@link SecurityConfigurer} by its class name or + * null if not found. Note that object hierarchies are not considered. + * + * @param clazz + * @return + */ + @SuppressWarnings("unchecked") + public > C removeConfigurer(Class clazz) { + List> configs = this.configurers.remove(clazz); + if (configs == null) { + return null; + } + if (configs.size() != 1) { + throw new IllegalStateException("Only one configurer expected for type " + + clazz + ", but got " + configs); + } + return (C) configs.get(0); + } - /** - * Removes and returns the {@link SecurityConfigurer} by its class name or - * null if not found. Note that object hierarchies are not - * considered. - * - * @param clazz - * @return - */ - @SuppressWarnings("unchecked") - public > C removeConfigurer(Class clazz) { - List> configs = this.configurers.remove(clazz); - if(configs == null) { - return null; - } - if(configs.size() != 1) { - throw new IllegalStateException("Only one configurer expected for type " + clazz + ", but got " + configs); - } - return (C) configs.get(0); - } + /** + * Specifies the {@link ObjectPostProcessor} to use. + * @param objectPostProcessor the {@link ObjectPostProcessor} to use. Cannot be null + * @return the {@link SecurityBuilder} for further customizations + */ + @SuppressWarnings("unchecked") + public O objectPostProcessor(ObjectPostProcessor objectPostProcessor) { + Assert.notNull(objectPostProcessor, "objectPostProcessor cannot be null"); + this.objectPostProcessor = objectPostProcessor; + return (O) this; + } - /** - * Specifies the {@link ObjectPostProcessor} to use. - * @param objectPostProcessor the {@link ObjectPostProcessor} to use. Cannot be null - * @return the {@link SecurityBuilder} for further customizations - */ - @SuppressWarnings("unchecked") - public O objectPostProcessor(ObjectPostProcessor objectPostProcessor) { - Assert.notNull(objectPostProcessor,"objectPostProcessor cannot be null"); - this.objectPostProcessor = objectPostProcessor; - return (O) this; - } + /** + * Performs post processing of an object. The default is to delegate to the + * {@link ObjectPostProcessor}. + * + * @param object the Object to post process + * @return the possibly modified Object to use + */ + protected

P postProcess(P object) { + return (P) this.objectPostProcessor.postProcess(object); + } - /** - * Performs post processing of an object. The default is to delegate to the - * {@link ObjectPostProcessor}. - * - * @param object the Object to post process - * @return the possibly modified Object to use - */ - protected

P postProcess(P object) { - return (P) this.objectPostProcessor.postProcess(object); - } + /** + * Executes the build using the {@link SecurityConfigurer}'s that have been applied + * using the following steps: + * + *

    + *
  • Invokes {@link #beforeInit()} for any subclass to hook into
  • + *
  • Invokes {@link SecurityConfigurer#init(SecurityBuilder)} for any + * {@link SecurityConfigurer} that was applied to this builder.
  • + *
  • Invokes {@link #beforeConfigure()} for any subclass to hook into
  • + *
  • Invokes {@link #performBuild()} which actually builds the Object
  • + *
+ */ + @Override + protected final O doBuild() throws Exception { + synchronized (configurers) { + buildState = BuildState.INITIALIZING; - /** - * Executes the build using the {@link SecurityConfigurer}'s that have been applied using the following steps: - * - *
    - *
  • Invokes {@link #beforeInit()} for any subclass to hook into
  • - *
  • Invokes {@link SecurityConfigurer#init(SecurityBuilder)} for any {@link SecurityConfigurer} that was applied to this builder.
  • - *
  • Invokes {@link #beforeConfigure()} for any subclass to hook into
  • - *
  • Invokes {@link #performBuild()} which actually builds the Object
  • - *
- */ - @Override - protected final O doBuild() throws Exception { - synchronized(configurers) { - buildState = BuildState.INITIALIZING; + beforeInit(); + init(); - beforeInit(); - init(); + buildState = BuildState.CONFIGURING; - buildState = BuildState.CONFIGURING; + beforeConfigure(); + configure(); - beforeConfigure(); - configure(); + buildState = BuildState.BUILDING; - buildState = BuildState.BUILDING; + O result = performBuild(); - O result = performBuild(); + buildState = BuildState.BUILT; - buildState = BuildState.BUILT; + return result; + } + } - return result; - } - } + /** + * Invoked prior to invoking each {@link SecurityConfigurer#init(SecurityBuilder)} + * method. Subclasses may override this method to hook into the lifecycle without + * using a {@link SecurityConfigurer}. + */ + protected void beforeInit() throws Exception { + } - /** - * Invoked prior to invoking each - * {@link SecurityConfigurer#init(SecurityBuilder)} method. Subclasses may - * override this method to hook into the lifecycle without using a - * {@link SecurityConfigurer}. - */ - protected void beforeInit() throws Exception { - } + /** + * Invoked prior to invoking each + * {@link SecurityConfigurer#configure(SecurityBuilder)} method. Subclasses may + * override this method to hook into the lifecycle without using a + * {@link SecurityConfigurer}. + */ + protected void beforeConfigure() throws Exception { + } - /** - * Invoked prior to invoking each - * {@link SecurityConfigurer#configure(SecurityBuilder)} method. - * Subclasses may override this method to hook into the lifecycle without - * using a {@link SecurityConfigurer}. - */ - protected void beforeConfigure() throws Exception { - } + /** + * Subclasses must implement this method to build the object that is being returned. + * + * @return + */ + protected abstract O performBuild() throws Exception; - /** - * Subclasses must implement this method to build the object that is being returned. - * - * @return - */ - protected abstract O performBuild() throws Exception; + @SuppressWarnings("unchecked") + private void init() throws Exception { + Collection> configurers = getConfigurers(); - @SuppressWarnings("unchecked") - private void init() throws Exception { - Collection> configurers = getConfigurers(); + for (SecurityConfigurer configurer : configurers) { + configurer.init((B) this); + } + } - for(SecurityConfigurer configurer : configurers ) { - configurer.init((B) this); - } - } + @SuppressWarnings("unchecked") + private void configure() throws Exception { + Collection> configurers = getConfigurers(); - @SuppressWarnings("unchecked") - private void configure() throws Exception { - Collection> configurers = getConfigurers(); + for (SecurityConfigurer configurer : configurers) { + configurer.configure((B) this); + } + } - for(SecurityConfigurer configurer : configurers ) { - configurer.configure((B) this); - } - } + private Collection> getConfigurers() { + List> result = new ArrayList>(); + for (List> configs : this.configurers.values()) { + result.addAll(configs); + } + return result; + } - private Collection> getConfigurers() { - List> result = new ArrayList>(); - for(List> configs : this.configurers.values()) { - result.addAll(configs); - } - return result; - } + /** + * Determines if the object is unbuilt. + * @return true, if unbuilt else false + */ + private boolean isUnbuilt() { + synchronized (configurers) { + return buildState == BuildState.UNBUILT; + } + } - /** - * Determines if the object is unbuilt. - * @return true, if unbuilt else false - */ - private boolean isUnbuilt() { - synchronized(configurers) { - return buildState == BuildState.UNBUILT; - } - } + /** + * The build state for the application + * + * @author Rob Winch + * @since 3.2 + */ + private static enum BuildState { + /** + * This is the state before the {@link Builder#build()} is invoked + */ + UNBUILT(0), - /** - * The build state for the application - * - * @author Rob Winch - * @since 3.2 - */ - private static enum BuildState { - /** - * This is the state before the {@link Builder#build()} is invoked - */ - UNBUILT(0), + /** + * The state from when {@link Builder#build()} is first invoked until all the + * {@link SecurityConfigurer#init(SecurityBuilder)} methods have been invoked. + */ + INITIALIZING(1), - /** - * The state from when {@link Builder#build()} is first invoked until - * all the {@link SecurityConfigurer#init(SecurityBuilder)} methods - * have been invoked. - */ - INITIALIZING(1), + /** + * The state from after all {@link SecurityConfigurer#init(SecurityBuilder)} have + * been invoked until after all the + * {@link SecurityConfigurer#configure(SecurityBuilder)} methods have been + * invoked. + */ + CONFIGURING(2), - /** - * The state from after all - * {@link SecurityConfigurer#init(SecurityBuilder)} have been invoked - * until after all the - * {@link SecurityConfigurer#configure(SecurityBuilder)} methods have - * been invoked. - */ - CONFIGURING(2), + /** + * From the point after all the + * {@link SecurityConfigurer#configure(SecurityBuilder)} have completed to just + * after {@link AbstractConfiguredSecurityBuilder#performBuild()}. + */ + BUILDING(3), - /** - * From the point after all the - * {@link SecurityConfigurer#configure(SecurityBuilder)} have - * completed to just after - * {@link AbstractConfiguredSecurityBuilder#performBuild()}. - */ - BUILDING(3), + /** + * After the object has been completely built. + */ + BUILT(4); - /** - * After the object has been completely built. - */ - BUILT(4); + private final int order; - private final int order; + BuildState(int order) { + this.order = order; + } - BuildState(int order) { - this.order = order; - } + public boolean isInitializing() { + return INITIALIZING.order == order; + } - public boolean isInitializing() { - return INITIALIZING.order == order; - } - - /** - * Determines if the state is CONFIGURING or later - * @return - */ - public boolean isConfigured() { - return order >= CONFIGURING.order; - } - } + /** + * Determines if the state is CONFIGURING or later + * @return + */ + public boolean isConfigured() { + return order >= CONFIGURING.order; + } + } } \ No newline at end of file diff --git a/config/src/main/java/org/springframework/security/config/annotation/AbstractSecurityBuilder.java b/config/src/main/java/org/springframework/security/config/annotation/AbstractSecurityBuilder.java index 7cc666dad4..892297e93d 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/AbstractSecurityBuilder.java +++ b/config/src/main/java/org/springframework/security/config/annotation/AbstractSecurityBuilder.java @@ -18,8 +18,8 @@ package org.springframework.security.config.annotation; import java.util.concurrent.atomic.AtomicBoolean; /** - * A base {@link SecurityBuilder} that ensures the object being built is only - * built one time. + * A base {@link SecurityBuilder} that ensures the object being built is only built one + * time. * * @param the type of Object that is being built * @@ -27,40 +27,42 @@ import java.util.concurrent.atomic.AtomicBoolean; * */ public abstract class AbstractSecurityBuilder implements SecurityBuilder { - private AtomicBoolean building = new AtomicBoolean(); + private AtomicBoolean building = new AtomicBoolean(); - private O object; + private O object; - /* (non-Javadoc) - * @see org.springframework.security.config.annotation.SecurityBuilder#build() - */ - public final O build() throws Exception { - if(building.compareAndSet(false, true)) { - object = doBuild(); - return object; - } - throw new AlreadyBuiltException("This object has already been built"); - } + /* + * (non-Javadoc) + * + * @see org.springframework.security.config.annotation.SecurityBuilder#build() + */ + public final O build() throws Exception { + if (building.compareAndSet(false, true)) { + object = doBuild(); + return object; + } + throw new AlreadyBuiltException("This object has already been built"); + } - /** - * Gets the object that was built. If it has not been built yet an Exception - * is thrown. - * - * @return the Object that was built - */ - public final O getObject() { - if(!building.get()) { - throw new IllegalStateException("This object has not been built"); - } - return object; - } + /** + * Gets the object that was built. If it has not been built yet an Exception is + * thrown. + * + * @return the Object that was built + */ + public final O getObject() { + if (!building.get()) { + throw new IllegalStateException("This object has not been built"); + } + return object; + } - /** - * Subclasses should implement this to perform the build. - * - * @return the object that should be returned by {@link #build()}. - * - * @throws Exception if an error occurs - */ - protected abstract O doBuild() throws Exception; + /** + * Subclasses should implement this to perform the build. + * + * @return the object that should be returned by {@link #build()}. + * + * @throws Exception if an error occurs + */ + protected abstract O doBuild() throws Exception; } diff --git a/config/src/main/java/org/springframework/security/config/annotation/AlreadyBuiltException.java b/config/src/main/java/org/springframework/security/config/annotation/AlreadyBuiltException.java index dd18467527..76637e1a3a 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/AlreadyBuiltException.java +++ b/config/src/main/java/org/springframework/security/config/annotation/AlreadyBuiltException.java @@ -23,9 +23,9 @@ package org.springframework.security.config.annotation; */ public class AlreadyBuiltException extends IllegalStateException { - public AlreadyBuiltException(String message) { - super(message); - } + public AlreadyBuiltException(String message) { + super(message); + } - private static final long serialVersionUID = -5891004752785553015L; + private static final long serialVersionUID = -5891004752785553015L; } diff --git a/config/src/main/java/org/springframework/security/config/annotation/ObjectPostProcessor.java b/config/src/main/java/org/springframework/security/config/annotation/ObjectPostProcessor.java index 02189fcac7..b3bece82da 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/ObjectPostProcessor.java +++ b/config/src/main/java/org/springframework/security/config/annotation/ObjectPostProcessor.java @@ -20,9 +20,9 @@ import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.InitializingBean; /** - * Allows initialization of Objects. Typically this is used to call the - * {@link Aware} methods, {@link InitializingBean#afterPropertiesSet()}, and - * ensure that {@link DisposableBean#destroy()} has been invoked. + * Allows initialization of Objects. Typically this is used to call the {@link Aware} + * methods, {@link InitializingBean#afterPropertiesSet()}, and ensure that + * {@link DisposableBean#destroy()} has been invoked. * * @param the bound of the types of Objects this {@link ObjectPostProcessor} supports. * @@ -31,12 +31,12 @@ import org.springframework.beans.factory.InitializingBean; */ public interface ObjectPostProcessor { - /** - * Initialize the object possibly returning a modified instance that should - * be used instead. - * - * @param object the object to initialize - * @return the initialized version of the object - */ - O postProcess(O object); + /** + * Initialize the object possibly returning a modified instance that should be used + * instead. + * + * @param object the object to initialize + * @return the initialized version of the object + */ + O postProcess(O object); } \ No newline at end of file diff --git a/config/src/main/java/org/springframework/security/config/annotation/SecurityBuilder.java b/config/src/main/java/org/springframework/security/config/annotation/SecurityBuilder.java index 277ef29e49..2a97d5a33f 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/SecurityBuilder.java +++ b/config/src/main/java/org/springframework/security/config/annotation/SecurityBuilder.java @@ -25,11 +25,11 @@ package org.springframework.security.config.annotation; */ public interface SecurityBuilder { - /** - * Builds the object and returns it or null. - * - * @return the Object to be built or null if the implementation allows it. - * @throws Exception if an error occurred when building the Object - */ - O build() throws Exception; + /** + * Builds the object and returns it or null. + * + * @return the Object to be built or null if the implementation allows it. + * @throws Exception if an error occurred when building the Object + */ + O build() throws Exception; } diff --git a/config/src/main/java/org/springframework/security/config/annotation/SecurityConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/SecurityConfigurer.java index 365b9ba953..f1ab7f3f18 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/SecurityConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/SecurityConfigurer.java @@ -16,40 +16,37 @@ package org.springframework.security.config.annotation; /** - * Allows for configuring a {@link SecurityBuilder}. All - * {@link SecurityConfigurer} first have their {@link #init(SecurityBuilder)} - * method invoked. After all {@link #init(SecurityBuilder)} methods have been - * invoked, each {@link #configure(SecurityBuilder)} method is invoked. + * Allows for configuring a {@link SecurityBuilder}. All {@link SecurityConfigurer} first + * have their {@link #init(SecurityBuilder)} method invoked. After all + * {@link #init(SecurityBuilder)} methods have been invoked, each + * {@link #configure(SecurityBuilder)} method is invoked. * * @see AbstractConfiguredSecurityBuilder * * @author Rob Winch * - * @param - * The object being built by the {@link SecurityBuilder} B - * @param - * The {@link SecurityBuilder} that builds objects of type O. This is - * also the {@link SecurityBuilder} that is being configured. + * @param The object being built by the {@link SecurityBuilder} B + * @param The {@link SecurityBuilder} that builds objects of type O. This is also the + * {@link SecurityBuilder} that is being configured. */ public interface SecurityConfigurer> { - /** - * Initialize the {@link SecurityBuilder}. Here only shared state should be - * created and modified, but not properties on the {@link SecurityBuilder} - * used for building the object. This ensures that the - * {@link #configure(SecurityBuilder)} method uses the correct shared - * objects when building. - * - * @param builder - * @throws Exception - */ - void init(B builder) throws Exception; + /** + * Initialize the {@link SecurityBuilder}. Here only shared state should be created + * and modified, but not properties on the {@link SecurityBuilder} used for building + * the object. This ensures that the {@link #configure(SecurityBuilder)} method uses + * the correct shared objects when building. + * + * @param builder + * @throws Exception + */ + void init(B builder) throws Exception; - /** - * Configure the {@link SecurityBuilder} by setting the necessary properties - * on the {@link SecurityBuilder}. - * - * @param builder - * @throws Exception - */ - void configure(B builder) throws Exception; + /** + * Configure the {@link SecurityBuilder} by setting the necessary properties on the + * {@link SecurityBuilder}. + * + * @param builder + * @throws Exception + */ + void configure(B builder) throws Exception; } diff --git a/config/src/main/java/org/springframework/security/config/annotation/SecurityConfigurerAdapter.java b/config/src/main/java/org/springframework/security/config/annotation/SecurityConfigurerAdapter.java index 610b66927e..5aaf2e25de 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/SecurityConfigurerAdapter.java +++ b/config/src/main/java/org/springframework/security/config/annotation/SecurityConfigurerAdapter.java @@ -21,112 +21,116 @@ import java.util.List; import org.springframework.core.GenericTypeResolver; /** - * A base class for {@link SecurityConfigurer} that allows subclasses to only - * implement the methods they are interested in. It also provides a mechanism - * for using the {@link SecurityConfigurer} and when done gaining access to the - * {@link SecurityBuilder} that is being configured. + * A base class for {@link SecurityConfigurer} that allows subclasses to only implement + * the methods they are interested in. It also provides a mechanism for using the + * {@link SecurityConfigurer} and when done gaining access to the {@link SecurityBuilder} + * that is being configured. * * @author Rob Winch * - * @param - * The Object being built by B - * @param - * The Builder that is building O and is configured by {@link SecurityConfigurerAdapter} + * @param The Object being built by B + * @param The Builder that is building O and is configured by + * {@link SecurityConfigurerAdapter} */ -public abstract class SecurityConfigurerAdapter> implements SecurityConfigurer { - private B securityBuilder; +public abstract class SecurityConfigurerAdapter> + implements SecurityConfigurer { + private B securityBuilder; - private CompositeObjectPostProcessor objectPostProcessor = new CompositeObjectPostProcessor(); + private CompositeObjectPostProcessor objectPostProcessor = new CompositeObjectPostProcessor(); - public void init(B builder) throws Exception {} + public void init(B builder) throws Exception { + } - public void configure(B builder) throws Exception {} + public void configure(B builder) throws Exception { + } - /** - * Return the {@link SecurityBuilder} when done using the - * {@link SecurityConfigurer}. This is useful for method chaining. - * - * @return - */ - public B and() { - return getBuilder(); - } + /** + * Return the {@link SecurityBuilder} when done using the {@link SecurityConfigurer}. + * This is useful for method chaining. + * + * @return + */ + public B and() { + return getBuilder(); + } - /** - * Gets the {@link SecurityBuilder}. Cannot be null. - * - * @return the {@link SecurityBuilder} - * @throw {@link IllegalStateException} if {@link SecurityBuilder} is null - */ - protected final B getBuilder() { - if(securityBuilder == null) { - throw new IllegalStateException("securityBuilder cannot be null"); - } - return securityBuilder; - } + /** + * Gets the {@link SecurityBuilder}. Cannot be null. + * + * @return the {@link SecurityBuilder} + * @throw {@link IllegalStateException} if {@link SecurityBuilder} is null + */ + protected final B getBuilder() { + if (securityBuilder == null) { + throw new IllegalStateException("securityBuilder cannot be null"); + } + return securityBuilder; + } - /** - * Performs post processing of an object. The default is to delegate to the - * {@link ObjectPostProcessor}. - * - * @param object the Object to post process - * @return the possibly modified Object to use - */ - @SuppressWarnings("unchecked") - protected T postProcess(T object) { - return (T) this.objectPostProcessor.postProcess(object); - } + /** + * Performs post processing of an object. The default is to delegate to the + * {@link ObjectPostProcessor}. + * + * @param object the Object to post process + * @return the possibly modified Object to use + */ + @SuppressWarnings("unchecked") + protected T postProcess(T object) { + return (T) this.objectPostProcessor.postProcess(object); + } - /** - * Adds an {@link ObjectPostProcessor} to be used for this - * {@link SecurityConfigurerAdapter}. The default implementation does - * nothing to the object. - * - * @param objectPostProcessor the {@link ObjectPostProcessor} to use - */ - public void addObjectPostProcessor(ObjectPostProcessor objectPostProcessor) { - this.objectPostProcessor.addObjectPostProcessor(objectPostProcessor); - } + /** + * Adds an {@link ObjectPostProcessor} to be used for this + * {@link SecurityConfigurerAdapter}. The default implementation does nothing to the + * object. + * + * @param objectPostProcessor the {@link ObjectPostProcessor} to use + */ + public void addObjectPostProcessor(ObjectPostProcessor objectPostProcessor) { + this.objectPostProcessor.addObjectPostProcessor(objectPostProcessor); + } - /** - * Sets the {@link SecurityBuilder} to be used. This is automatically set - * when using - * {@link AbstractConfiguredSecurityBuilder#apply(SecurityConfigurerAdapter)} - * - * @param builder the {@link SecurityBuilder} to set - */ - public void setBuilder(B builder) { - this.securityBuilder = builder; - } + /** + * Sets the {@link SecurityBuilder} to be used. This is automatically set when using + * {@link AbstractConfiguredSecurityBuilder#apply(SecurityConfigurerAdapter)} + * + * @param builder the {@link SecurityBuilder} to set + */ + public void setBuilder(B builder) { + this.securityBuilder = builder; + } - /** - * An {@link ObjectPostProcessor} that delegates work to numerous - * {@link ObjectPostProcessor} implementations. - * - * @author Rob Winch - */ - private static final class CompositeObjectPostProcessor implements ObjectPostProcessor { - private List> postProcessors = new ArrayList>(); + /** + * An {@link ObjectPostProcessor} that delegates work to numerous + * {@link ObjectPostProcessor} implementations. + * + * @author Rob Winch + */ + private static final class CompositeObjectPostProcessor implements + ObjectPostProcessor { + private List> postProcessors = new ArrayList>(); - @SuppressWarnings({ "rawtypes", "unchecked" }) - public Object postProcess(Object object) { - for(ObjectPostProcessor opp : postProcessors) { - Class oppClass = opp.getClass(); - Class oppType = GenericTypeResolver.resolveTypeArgument(oppClass,ObjectPostProcessor.class); - if(oppType == null || oppType.isAssignableFrom(object.getClass())) { - object = opp.postProcess(object); - } - } - return object; - } + @SuppressWarnings({ "rawtypes", "unchecked" }) + public Object postProcess(Object object) { + for (ObjectPostProcessor opp : postProcessors) { + Class oppClass = opp.getClass(); + Class oppType = GenericTypeResolver.resolveTypeArgument(oppClass, + ObjectPostProcessor.class); + if (oppType == null || oppType.isAssignableFrom(object.getClass())) { + object = opp.postProcess(object); + } + } + return object; + } - /** - * Adds an {@link ObjectPostProcessor} to use - * @param objectPostProcessor the {@link ObjectPostProcessor} to add - * @return true if the {@link ObjectPostProcessor} was added, else false - */ - private boolean addObjectPostProcessor(ObjectPostProcessor objectPostProcessor) { - return this.postProcessors.add(objectPostProcessor); - } - } + /** + * Adds an {@link ObjectPostProcessor} to use + * @param objectPostProcessor the {@link ObjectPostProcessor} to add + * @return true if the {@link ObjectPostProcessor} was added, else false + */ + private boolean addObjectPostProcessor( + ObjectPostProcessor objectPostProcessor) { + return this.postProcessors.add(objectPostProcessor); + } + } } diff --git a/config/src/main/java/org/springframework/security/config/annotation/authentication/ProviderManagerBuilder.java b/config/src/main/java/org/springframework/security/config/annotation/authentication/ProviderManagerBuilder.java index bf8c10012b..7db4b5edde 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/authentication/ProviderManagerBuilder.java +++ b/config/src/main/java/org/springframework/security/config/annotation/authentication/ProviderManagerBuilder.java @@ -27,18 +27,18 @@ import org.springframework.security.config.annotation.SecurityBuilder; * * @param the type of the {@link SecurityBuilder} */ -public interface ProviderManagerBuilder> extends SecurityBuilder { +public interface ProviderManagerBuilder> extends + SecurityBuilder { - /** - * Add authentication based upon the custom {@link AuthenticationProvider} - * that is passed in. Since the {@link AuthenticationProvider} - * implementation is unknown, all customizations must be done externally and - * the {@link ProviderManagerBuilder} is returned immediately. - * - * @return a {@link ProviderManagerBuilder} to allow further authentication - * to be provided to the {@link ProviderManagerBuilder} - * @throws Exception - * if an error occurs when adding the {@link AuthenticationProvider} - */ - B authenticationProvider(AuthenticationProvider authenticationProvider); + /** + * Add authentication based upon the custom {@link AuthenticationProvider} that is + * passed in. Since the {@link AuthenticationProvider} implementation is unknown, all + * customizations must be done externally and the {@link ProviderManagerBuilder} is + * returned immediately. + * + * @return a {@link ProviderManagerBuilder} to allow further authentication to be + * provided to the {@link ProviderManagerBuilder} + * @throws Exception if an error occurs when adding the {@link AuthenticationProvider} + */ + B authenticationProvider(AuthenticationProvider authenticationProvider); } diff --git a/config/src/main/java/org/springframework/security/config/annotation/authentication/builders/AuthenticationManagerBuilder.java b/config/src/main/java/org/springframework/security/config/annotation/authentication/builders/AuthenticationManagerBuilder.java index 1f5ee74b77..98139ffc61 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/authentication/builders/AuthenticationManagerBuilder.java +++ b/config/src/main/java/org/springframework/security/config/annotation/authentication/builders/AuthenticationManagerBuilder.java @@ -39,260 +39,255 @@ import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.util.Assert; /** - * {@link SecurityBuilder} used to create an {@link AuthenticationManager}. - * Allows for easily building in memory authentication, LDAP authentication, - * JDBC based authentication, adding {@link UserDetailsService}, and adding + * {@link SecurityBuilder} used to create an {@link AuthenticationManager}. Allows for + * easily building in memory authentication, LDAP authentication, JDBC based + * authentication, adding {@link UserDetailsService}, and adding * {@link AuthenticationProvider}'s. * * @author Rob Winch * @since 3.2 */ -public class AuthenticationManagerBuilder extends AbstractConfiguredSecurityBuilder implements ProviderManagerBuilder { - private final Log logger = LogFactory.getLog(getClass()); +public class AuthenticationManagerBuilder + extends + AbstractConfiguredSecurityBuilder + implements ProviderManagerBuilder { + private final Log logger = LogFactory.getLog(getClass()); - private AuthenticationManager parentAuthenticationManager; - private List authenticationProviders = new ArrayList(); - private UserDetailsService defaultUserDetailsService; - private Boolean eraseCredentials; - private AuthenticationEventPublisher eventPublisher; + private AuthenticationManager parentAuthenticationManager; + private List authenticationProviders = new ArrayList(); + private UserDetailsService defaultUserDetailsService; + private Boolean eraseCredentials; + private AuthenticationEventPublisher eventPublisher; - /** - * Creates a new instance - * @param the {@link ObjectPostProcessor} instance to use. - */ - public AuthenticationManagerBuilder(ObjectPostProcessor objectPostProcessor) { - super(objectPostProcessor,true); - } + /** + * Creates a new instance + * @param the {@link ObjectPostProcessor} instance to use. + */ + public AuthenticationManagerBuilder(ObjectPostProcessor objectPostProcessor) { + super(objectPostProcessor, true); + } - /** - * Allows providing a parent {@link AuthenticationManager} that will be - * tried if this {@link AuthenticationManager} was unable to attempt to - * authenticate the provided {@link Authentication}. - * - * @param authenticationManager - * the {@link AuthenticationManager} that should be used if the - * current {@link AuthenticationManager} was unable to attempt to - * authenticate the provided {@link Authentication}. - * @return the {@link AuthenticationManagerBuilder} for further adding types - * of authentication - */ - public AuthenticationManagerBuilder parentAuthenticationManager( - AuthenticationManager authenticationManager) { - if(authenticationManager instanceof ProviderManager) { - eraseCredentials(((ProviderManager) authenticationManager).isEraseCredentialsAfterAuthentication()); - } - this.parentAuthenticationManager = authenticationManager; - return this; - } + /** + * Allows providing a parent {@link AuthenticationManager} that will be tried if this + * {@link AuthenticationManager} was unable to attempt to authenticate the provided + * {@link Authentication}. + * + * @param authenticationManager the {@link AuthenticationManager} that should be used + * if the current {@link AuthenticationManager} was unable to attempt to authenticate + * the provided {@link Authentication}. + * @return the {@link AuthenticationManagerBuilder} for further adding types of + * authentication + */ + public AuthenticationManagerBuilder parentAuthenticationManager( + AuthenticationManager authenticationManager) { + if (authenticationManager instanceof ProviderManager) { + eraseCredentials(((ProviderManager) authenticationManager) + .isEraseCredentialsAfterAuthentication()); + } + this.parentAuthenticationManager = authenticationManager; + return this; + } - /** - * Sets the {@link AuthenticationEventPublisher} - * - * @param eventPublisher - * the {@link AuthenticationEventPublisher} to use - * @return the {@link AuthenticationManagerBuilder} for further - * customizations - */ - public AuthenticationManagerBuilder authenticationEventPublisher(AuthenticationEventPublisher eventPublisher) { - Assert.notNull(eventPublisher, "AuthenticationEventPublisher cannot be null"); - this.eventPublisher = eventPublisher; - return this; - } + /** + * Sets the {@link AuthenticationEventPublisher} + * + * @param eventPublisher the {@link AuthenticationEventPublisher} to use + * @return the {@link AuthenticationManagerBuilder} for further customizations + */ + public AuthenticationManagerBuilder authenticationEventPublisher( + AuthenticationEventPublisher eventPublisher) { + Assert.notNull(eventPublisher, "AuthenticationEventPublisher cannot be null"); + this.eventPublisher = eventPublisher; + return this; + } - /** - * - * - * @param eraseCredentials - * true if {@link AuthenticationManager} should clear the - * credentials from the {@link Authentication} object after - * authenticating - * @return the {@link AuthenticationManagerBuilder} for further customizations - */ - public AuthenticationManagerBuilder eraseCredentials(boolean eraseCredentials) { - this.eraseCredentials = eraseCredentials; - return this; - } + /** + * + * + * @param eraseCredentials true if {@link AuthenticationManager} should clear the + * credentials from the {@link Authentication} object after authenticating + * @return the {@link AuthenticationManagerBuilder} for further customizations + */ + public AuthenticationManagerBuilder eraseCredentials(boolean eraseCredentials) { + this.eraseCredentials = eraseCredentials; + return this; + } + /** + * Add in memory authentication to the {@link AuthenticationManagerBuilder} and return + * a {@link InMemoryUserDetailsManagerConfigurer} to allow customization of the in + * memory authentication. + * + *

+ * This method also ensure that a {@link UserDetailsService} is available for the + * {@link #getDefaultUserDetailsService()} method. Note that additional + * {@link UserDetailsService}'s may override this {@link UserDetailsService} as the + * default. + *

+ * + * @return a {@link InMemoryUserDetailsManagerConfigurer} to allow customization of + * the in memory authentication + * @throws Exception if an error occurs when adding the in memory authentication + */ + public InMemoryUserDetailsManagerConfigurer inMemoryAuthentication() + throws Exception { + return apply(new InMemoryUserDetailsManagerConfigurer()); + } - /** - * Add in memory authentication to the {@link AuthenticationManagerBuilder} - * and return a {@link InMemoryUserDetailsManagerConfigurer} to - * allow customization of the in memory authentication. - * - *

- * This method also ensure that a {@link UserDetailsService} is available - * for the {@link #getDefaultUserDetailsService()} method. Note that - * additional {@link UserDetailsService}'s may override this - * {@link UserDetailsService} as the default. - *

- * - * @return a {@link InMemoryUserDetailsManagerConfigurer} to allow - * customization of the in memory authentication - * @throws Exception - * if an error occurs when adding the in memory authentication - */ - public InMemoryUserDetailsManagerConfigurer inMemoryAuthentication() - throws Exception { - return apply(new InMemoryUserDetailsManagerConfigurer()); - } + /** + * Add JDBC authentication to the {@link AuthenticationManagerBuilder} and return a + * {@link JdbcUserDetailsManagerConfigurer} to allow customization of the JDBC + * authentication. + * + *

+ * When using with a persistent data store, it is best to add users external of + * configuration using something like Flyway or Liquibase to create the schema and adding + * users to ensure these steps are only done once and that the optimal SQL is used. + *

+ * + *

+ * This method also ensure that a {@link UserDetailsService} is available for the + * {@link #getDefaultUserDetailsService()} method. Note that additional + * {@link UserDetailsService}'s may override this {@link UserDetailsService} as the + * default. See the User Schema section of the reference for the default schema. + *

+ * + * @return a {@link JdbcUserDetailsManagerConfigurer} to allow customization of the + * JDBC authentication + * @throws Exception if an error occurs when adding the JDBC authentication + */ + public JdbcUserDetailsManagerConfigurer jdbcAuthentication() + throws Exception { + return apply(new JdbcUserDetailsManagerConfigurer()); + } - /** - * Add JDBC authentication to the {@link AuthenticationManagerBuilder} and - * return a {@link JdbcUserDetailsManagerConfigurer} to allow customization - * of the JDBC authentication. - * - *

- * When using with a persistent data store, it is best to add users external - * of configuration using something like Flyway or Liquibase to create the schema and - * adding users to ensure these steps are only done once and that the - * optimal SQL is used. - *

- * - *

- * This method also ensure that a {@link UserDetailsService} is available - * for the {@link #getDefaultUserDetailsService()} method. Note that - * additional {@link UserDetailsService}'s may override this - * {@link UserDetailsService} as the default. See the User Schema section of the reference for the default schema. - *

- * - * @return a {@link JdbcUserDetailsManagerConfigurer} to allow customization - * of the JDBC authentication - * @throws Exception - * if an error occurs when adding the JDBC authentication - */ - public JdbcUserDetailsManagerConfigurer jdbcAuthentication() - throws Exception { - return apply(new JdbcUserDetailsManagerConfigurer()); - } + /** + * Add authentication based upon the custom {@link UserDetailsService} that is passed + * in. It then returns a {@link DaoAuthenticationConfigurer} to allow customization of + * the authentication. + * + *

+ * This method also ensure that the {@link UserDetailsService} is available for the + * {@link #getDefaultUserDetailsService()} method. Note that additional + * {@link UserDetailsService}'s may override this {@link UserDetailsService} as the + * default. + *

+ * + * @return a {@link DaoAuthenticationConfigurer} to allow customization of the DAO + * authentication + * @throws Exception if an error occurs when adding the {@link UserDetailsService} + * based authentication + */ + public DaoAuthenticationConfigurer userDetailsService( + T userDetailsService) throws Exception { + this.defaultUserDetailsService = userDetailsService; + return apply(new DaoAuthenticationConfigurer( + userDetailsService)); + } - /** - * Add authentication based upon the custom {@link UserDetailsService} that - * is passed in. It then returns a {@link DaoAuthenticationConfigurer} to - * allow customization of the authentication. - * - *

- * This method also ensure that the {@link UserDetailsService} is available - * for the {@link #getDefaultUserDetailsService()} method. Note that - * additional {@link UserDetailsService}'s may override this - * {@link UserDetailsService} as the default. - *

- * - * @return a {@link DaoAuthenticationConfigurer} to allow customization - * of the DAO authentication - * @throws Exception - * if an error occurs when adding the {@link UserDetailsService} - * based authentication - */ - public DaoAuthenticationConfigurer userDetailsService( - T userDetailsService) throws Exception { - this.defaultUserDetailsService = userDetailsService; - return apply(new DaoAuthenticationConfigurer(userDetailsService)); - } + /** + * Add LDAP authentication to the {@link AuthenticationManagerBuilder} and return a + * {@link LdapAuthenticationProviderConfigurer} to allow customization of the LDAP + * authentication. + * + *

+ * This method does NOT ensure that a {@link UserDetailsService} is available + * for the {@link #getDefaultUserDetailsService()} method. + *

+ * + * @return a {@link LdapAuthenticationProviderConfigurer} to allow customization of + * the LDAP authentication + * @throws Exception if an error occurs when adding the LDAP authentication + */ + public LdapAuthenticationProviderConfigurer ldapAuthentication() + throws Exception { + return apply(new LdapAuthenticationProviderConfigurer()); + } - /** - * Add LDAP authentication to the {@link AuthenticationManagerBuilder} and - * return a {@link LdapAuthenticationProviderConfigurer} to allow - * customization of the LDAP authentication. - * - *

- * This method does NOT ensure that a {@link UserDetailsService} is - * available for the {@link #getDefaultUserDetailsService()} method. - *

- * - * @return a {@link LdapAuthenticationProviderConfigurer} to allow - * customization of the LDAP authentication - * @throws Exception - * if an error occurs when adding the LDAP authentication - */ - public LdapAuthenticationProviderConfigurer ldapAuthentication() - throws Exception { - return apply(new LdapAuthenticationProviderConfigurer()); - } + /** + * Add authentication based upon the custom {@link AuthenticationProvider} that is + * passed in. Since the {@link AuthenticationProvider} implementation is unknown, all + * customizations must be done externally and the {@link AuthenticationManagerBuilder} + * is returned immediately. + * + *

+ * This method does NOT ensure that the {@link UserDetailsService} is available + * for the {@link #getDefaultUserDetailsService()} method. + *

+ * + * @return a {@link AuthenticationManagerBuilder} to allow further authentication to + * be provided to the {@link AuthenticationManagerBuilder} + * @throws Exception if an error occurs when adding the {@link AuthenticationProvider} + */ + public AuthenticationManagerBuilder authenticationProvider( + AuthenticationProvider authenticationProvider) { + this.authenticationProviders.add(authenticationProvider); + return this; + } - /** - * Add authentication based upon the custom {@link AuthenticationProvider} - * that is passed in. Since the {@link AuthenticationProvider} - * implementation is unknown, all customizations must be done externally and - * the {@link AuthenticationManagerBuilder} is returned immediately. - * - *

- * This method does NOT ensure that the {@link UserDetailsService} is - * available for the {@link #getDefaultUserDetailsService()} method. - *

- * - * @return a {@link AuthenticationManagerBuilder} to allow further authentication - * to be provided to the {@link AuthenticationManagerBuilder} - * @throws Exception - * if an error occurs when adding the {@link AuthenticationProvider} - */ - public AuthenticationManagerBuilder authenticationProvider( - AuthenticationProvider authenticationProvider) { - this.authenticationProviders.add(authenticationProvider); - return this; - } + @Override + protected ProviderManager performBuild() throws Exception { + if (!isConfigured()) { + logger.debug("No authenticationProviders and no parentAuthenticationManager defined. Returning null."); + return null; + } + ProviderManager providerManager = new ProviderManager(authenticationProviders, + parentAuthenticationManager); + if (eraseCredentials != null) { + providerManager.setEraseCredentialsAfterAuthentication(eraseCredentials); + } + if (eventPublisher != null) { + providerManager.setAuthenticationEventPublisher(eventPublisher); + } + providerManager = postProcess(providerManager); + return providerManager; + } - @Override - protected ProviderManager performBuild() throws Exception { - if(!isConfigured()) { - logger.debug("No authenticationProviders and no parentAuthenticationManager defined. Returning null."); - return null; - } - ProviderManager providerManager = new ProviderManager(authenticationProviders, parentAuthenticationManager); - if(eraseCredentials != null) { - providerManager.setEraseCredentialsAfterAuthentication(eraseCredentials); - } - if(eventPublisher != null) { - providerManager.setAuthenticationEventPublisher(eventPublisher); - } - providerManager = postProcess(providerManager); - return providerManager; - } + /** + * Determines if the {@link AuthenticationManagerBuilder} is configured to build a non + * null {@link AuthenticationManager}. This means that either a non-null parent is + * specified or at least one {@link AuthenticationProvider} has been specified. + * + *

+ * When using {@link SecurityConfigurer} instances, the + * {@link AuthenticationManagerBuilder} will not be configured until the + * {@link SecurityConfigurer#configure(SecurityBuilder)} methods. This means a + * {@link SecurityConfigurer} that is last could check this method and provide a + * default configuration in the {@link SecurityConfigurer#configure(SecurityBuilder)} + * method. + * + * @return + */ + public boolean isConfigured() { + return !authenticationProviders.isEmpty() || parentAuthenticationManager != null; + } - /** - * Determines if the {@link AuthenticationManagerBuilder} is configured to - * build a non null {@link AuthenticationManager}. This means that either a - * non-null parent is specified or at least one - * {@link AuthenticationProvider} has been specified. - * - *

- * When using {@link SecurityConfigurer} instances, the - * {@link AuthenticationManagerBuilder} will not be configured until the - * {@link SecurityConfigurer#configure(SecurityBuilder)} methods. This means - * a {@link SecurityConfigurer} that is last could check this method and - * provide a default configuration in the - * {@link SecurityConfigurer#configure(SecurityBuilder)} method. - * - * @return - */ - public boolean isConfigured() { - return !authenticationProviders.isEmpty() || parentAuthenticationManager != null; - } + /** + * Gets the default {@link UserDetailsService} for the + * {@link AuthenticationManagerBuilder}. The result may be null in some circumstances. + * + * @return the default {@link UserDetailsService} for the + * {@link AuthenticationManagerBuilder} + */ + public UserDetailsService getDefaultUserDetailsService() { + return this.defaultUserDetailsService; + } - /** - * Gets the default {@link UserDetailsService} for the - * {@link AuthenticationManagerBuilder}. The result may be null in some - * circumstances. - * - * @return the default {@link UserDetailsService} for the - * {@link AuthenticationManagerBuilder} - */ - public UserDetailsService getDefaultUserDetailsService() { - return this.defaultUserDetailsService; - } - - /** - * Captures the {@link UserDetailsService} from any {@link UserDetailsAwareConfigurer}. - * - * @param configurer the {@link UserDetailsAwareConfigurer} to capture the {@link UserDetailsService} from. - * @return the {@link UserDetailsAwareConfigurer} for further customizations - * @throws Exception if an error occurs - */ - private > C apply(C configurer) throws Exception { - this.defaultUserDetailsService = configurer.getUserDetailsService(); - return (C) super.apply(configurer); - } + /** + * Captures the {@link UserDetailsService} from any {@link UserDetailsAwareConfigurer} + * . + * + * @param configurer the {@link UserDetailsAwareConfigurer} to capture the + * {@link UserDetailsService} from. + * @return the {@link UserDetailsAwareConfigurer} for further customizations + * @throws Exception if an error occurs + */ + private > C apply( + C configurer) throws Exception { + this.defaultUserDetailsService = configurer.getUserDetailsService(); + return (C) super.apply(configurer); + } } \ No newline at end of file diff --git a/config/src/main/java/org/springframework/security/config/annotation/authentication/configuration/AuthenticationConfiguration.java b/config/src/main/java/org/springframework/security/config/annotation/authentication/configuration/AuthenticationConfiguration.java index 58c4e0eac6..c82469ee67 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/authentication/configuration/AuthenticationConfiguration.java +++ b/config/src/main/java/org/springframework/security/config/annotation/authentication/configuration/AuthenticationConfiguration.java @@ -45,97 +45,106 @@ import org.springframework.util.Assert; */ @Configuration public class AuthenticationConfiguration { - private ApplicationContext applicationContext; + private ApplicationContext applicationContext; - private AuthenticationManager authenticationManager; + private AuthenticationManager authenticationManager; - private boolean authenticationManagerInitialized; + private boolean authenticationManagerInitialized; - private List globalAuthConfigures = Collections.emptyList(); + private List globalAuthConfigures = Collections + .emptyList(); - private ObjectPostProcessor objectPostProcessor; + private ObjectPostProcessor objectPostProcessor; - @Bean - public AuthenticationManagerBuilder authenticationManagerBuilder(ObjectPostProcessor objectPostProcessor) { - return new AuthenticationManagerBuilder(objectPostProcessor); - } + @Bean + public AuthenticationManagerBuilder authenticationManagerBuilder( + ObjectPostProcessor objectPostProcessor) { + return new AuthenticationManagerBuilder(objectPostProcessor); + } - @Bean - public static GlobalAuthenticationConfigurerAdapter enableGlobalAuthenticationAutowiredConfigurer(ApplicationContext context) { - return new EnableGlobalAuthenticationAutowiredConfigurer(context); - } + @Bean + public static GlobalAuthenticationConfigurerAdapter enableGlobalAuthenticationAutowiredConfigurer( + ApplicationContext context) { + return new EnableGlobalAuthenticationAutowiredConfigurer(context); + } - public AuthenticationManager getAuthenticationManager() throws Exception { - if(authenticationManagerInitialized) { - return authenticationManager; - } + public AuthenticationManager getAuthenticationManager() throws Exception { + if (authenticationManagerInitialized) { + return authenticationManager; + } - AuthenticationManagerBuilder authBuilder = authenticationManagerBuilder(objectPostProcessor); - for(GlobalAuthenticationConfigurerAdapter config : globalAuthConfigures) { - authBuilder.apply(config); - } + AuthenticationManagerBuilder authBuilder = authenticationManagerBuilder(objectPostProcessor); + for (GlobalAuthenticationConfigurerAdapter config : globalAuthConfigures) { + authBuilder.apply(config); + } - authenticationManager = authBuilder.build(); + authenticationManager = authBuilder.build(); - if(authenticationManager == null) { - authenticationManager = getAuthenticationMangerBean(); - } + if (authenticationManager == null) { + authenticationManager = getAuthenticationMangerBean(); + } - this.authenticationManagerInitialized = true; - return authenticationManager; - } + this.authenticationManagerInitialized = true; + return authenticationManager; + } - @Autowired(required = false) - public void setGlobalAuthenticationConfigurers(List configurers) throws Exception { - Collections.sort(configurers, AnnotationAwareOrderComparator.INSTANCE); - this.globalAuthConfigures = configurers; - } + @Autowired(required = false) + public void setGlobalAuthenticationConfigurers( + List configurers) throws Exception { + Collections.sort(configurers, AnnotationAwareOrderComparator.INSTANCE); + this.globalAuthConfigures = configurers; + } - @Autowired - public void setApplicationContext(ApplicationContext applicationContext) { - this.applicationContext = applicationContext; - } + @Autowired + public void setApplicationContext(ApplicationContext applicationContext) { + this.applicationContext = applicationContext; + } - @Autowired - public void setObjectPostProcessor(ObjectPostProcessor objectPostProcessor) { - this.objectPostProcessor = objectPostProcessor; - } + @Autowired + public void setObjectPostProcessor(ObjectPostProcessor objectPostProcessor) { + this.objectPostProcessor = objectPostProcessor; + } + @SuppressWarnings("unchecked") + private T lazyBean(Class interfaceName) { + LazyInitTargetSource lazyTargetSource = new LazyInitTargetSource(); + String[] beanNamesForType = BeanFactoryUtils.beanNamesForTypeIncludingAncestors( + applicationContext, interfaceName); + if (beanNamesForType.length == 0) { + return null; + } + Assert.isTrue(beanNamesForType.length == 1, + "Expecting to only find a single bean for type " + interfaceName + + ", but found " + Arrays.asList(beanNamesForType)); + lazyTargetSource.setTargetBeanName(beanNamesForType[0]); + lazyTargetSource.setBeanFactory(applicationContext); + ProxyFactoryBean proxyFactory = new ProxyFactoryBean(); + proxyFactory = objectPostProcessor.postProcess(proxyFactory); + proxyFactory.setTargetSource(lazyTargetSource); + return (T) proxyFactory.getObject(); + } - @SuppressWarnings("unchecked") - private T lazyBean(Class interfaceName) { - LazyInitTargetSource lazyTargetSource = new LazyInitTargetSource(); - String[] beanNamesForType = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(applicationContext, interfaceName); - if(beanNamesForType.length == 0) { - return null; - } - Assert.isTrue(beanNamesForType.length == 1 , "Expecting to only find a single bean for type " + interfaceName + ", but found " + Arrays.asList(beanNamesForType)); - lazyTargetSource.setTargetBeanName(beanNamesForType[0]); - lazyTargetSource.setBeanFactory(applicationContext); - ProxyFactoryBean proxyFactory = new ProxyFactoryBean(); - proxyFactory = objectPostProcessor.postProcess(proxyFactory); - proxyFactory.setTargetSource(lazyTargetSource); - return (T) proxyFactory.getObject(); - } + private AuthenticationManager getAuthenticationMangerBean() { + return lazyBean(AuthenticationManager.class); + } - private AuthenticationManager getAuthenticationMangerBean() { - return lazyBean(AuthenticationManager.class); - } + private static class EnableGlobalAuthenticationAutowiredConfigurer extends + GlobalAuthenticationConfigurerAdapter { + private final ApplicationContext context; + private static final Log logger = LogFactory + .getLog(EnableGlobalAuthenticationAutowiredConfigurer.class); - private static class EnableGlobalAuthenticationAutowiredConfigurer extends GlobalAuthenticationConfigurerAdapter { - private final ApplicationContext context; - private static final Log logger = LogFactory.getLog(EnableGlobalAuthenticationAutowiredConfigurer.class); + public EnableGlobalAuthenticationAutowiredConfigurer(ApplicationContext context) { + this.context = context; + } - public EnableGlobalAuthenticationAutowiredConfigurer(ApplicationContext context) { - this.context = context; - } - - @Override - public void init(AuthenticationManagerBuilder auth) { - Map beansWithAnnotation = context.getBeansWithAnnotation(EnableGlobalAuthentication.class); - if(logger.isDebugEnabled()) { - logger.debug("Eagerly initializing " + beansWithAnnotation); - } - } - } + @Override + public void init(AuthenticationManagerBuilder auth) { + Map beansWithAnnotation = context + .getBeansWithAnnotation(EnableGlobalAuthentication.class); + if (logger.isDebugEnabled()) { + logger.debug("Eagerly initializing " + beansWithAnnotation); + } + } + } } \ No newline at end of file diff --git a/config/src/main/java/org/springframework/security/config/annotation/authentication/configuration/EnableGlobalAuthentication.java b/config/src/main/java/org/springframework/security/config/annotation/authentication/configuration/EnableGlobalAuthentication.java index 0412e56d48..95a693b7b1 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/authentication/configuration/EnableGlobalAuthentication.java +++ b/config/src/main/java/org/springframework/security/config/annotation/authentication/configuration/EnableGlobalAuthentication.java @@ -27,56 +27,52 @@ import org.springframework.security.config.annotation.web.configuration.EnableWe import org.springframework.security.config.annotation.web.servlet.configuration.EnableWebMvcSecurity; /** - * The {@link EnableGlobalAuthentication} annotation signals that the annotated - * class can be used to configure a global instance of - * {@link AuthenticationManagerBuilder}. For example: + * The {@link EnableGlobalAuthentication} annotation signals that the annotated class can + * be used to configure a global instance of {@link AuthenticationManagerBuilder}. For + * example: * *
  * @Configuration
  * @EnableGlobalAuthentication
  * public class MyGlobalAuthenticationConfiguration {
- *
- *     @Autowired
- *     public void configureGlobal(AuthenticationManagerBuilder auth) {
- *        auth
- *            .inMemoryAuthentication()
- *                .withUser("user").password("password").roles("USER").and()
- *                .withUser("admin").password("password").roles("USER", "ADMIN");
- *     }
+ * 
+ * 	@Autowired
+ * 	public void configureGlobal(AuthenticationManagerBuilder auth) {
+ * 		auth.inMemoryAuthentication().withUser("user").password("password").roles("USER")
+ * 				.and().withUser("admin").password("password").roles("USER", "ADMIN");
+ * 	}
  * }
  * 
* - * Annotations that are annotated with {@link EnableGlobalAuthentication} also - * signal that the annotated class can be used to configure a global instance of + * Annotations that are annotated with {@link EnableGlobalAuthentication} also signal that + * the annotated class can be used to configure a global instance of * {@link AuthenticationManagerBuilder}. For example: * *
  * @Configuration
  * @EnableWebSecurity
  * public class MyWebSecurityConfiguration extends WebSecurityConfigurerAdapter {
- *
- *    @Autowired
- *    public void configureGlobal(AuthenticationManagerBuilder auth) {
- *        auth
- *            .inMemoryAuthentication()
- *                .withUser("user").password("password").roles("USER").and()
- *                .withUser("admin").password("password").roles("USER", "ADMIN");
- *    }
- *
- *    // Possibly overridden methods ...
+ * 
+ * 	@Autowired
+ * 	public void configureGlobal(AuthenticationManagerBuilder auth) {
+ * 		auth.inMemoryAuthentication().withUser("user").password("password").roles("USER")
+ * 				.and().withUser("admin").password("password").roles("USER", "ADMIN");
+ * 	}
+ * 
+ * 	// Possibly overridden methods ...
  * }
  * 
* * The following annotations are annotated with {@link EnableGlobalAuthentication} * *
    - *
  • {@link EnableWebSecurity}
  • - *
  • {@link EnableWebMvcSecurity}
  • - *
  • {@link EnableGlobalMethodSecurity}
  • + *
  • {@link EnableWebSecurity}
  • + *
  • {@link EnableWebMvcSecurity}
  • + *
  • {@link EnableGlobalMethodSecurity}
  • *
* - * Configuring {@link AuthenticationManagerBuilder} in a class without the {@link EnableGlobalAuthentication} annotation has - * unpredictable results. + * Configuring {@link AuthenticationManagerBuilder} in a class without the + * {@link EnableGlobalAuthentication} annotation has unpredictable results. * * @see EnableWebMvcSecurity * @see EnableWebSecurity @@ -85,9 +81,10 @@ import org.springframework.security.config.annotation.web.servlet.configuration. * @author Rob Winch * */ -@Retention(value=java.lang.annotation.RetentionPolicy.RUNTIME) -@Target(value={java.lang.annotation.ElementType.TYPE}) +@Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME) +@Target(value = { java.lang.annotation.ElementType.TYPE }) @Documented @Import(AuthenticationConfiguration.class) @Configuration -public @interface EnableGlobalAuthentication {} +public @interface EnableGlobalAuthentication { +} diff --git a/config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/GlobalAuthenticationConfigurerAdapter.java b/config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/GlobalAuthenticationConfigurerAdapter.java index 2bc1e13cd2..2957b19641 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/GlobalAuthenticationConfigurerAdapter.java +++ b/config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/GlobalAuthenticationConfigurerAdapter.java @@ -22,18 +22,21 @@ import org.springframework.security.config.annotation.authentication.builders.Au import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; /** - * A {@link SecurityConfigurer} that can be exposed as a bean to configure the - * global {@link AuthenticationManagerBuilder}. Beans of this type are - * automatically used by {@link AuthenticationConfiguration} to configure the - * global {@link AuthenticationManagerBuilder}. + * A {@link SecurityConfigurer} that can be exposed as a bean to configure the global + * {@link AuthenticationManagerBuilder}. Beans of this type are automatically used by + * {@link AuthenticationConfiguration} to configure the global + * {@link AuthenticationManagerBuilder}. * * @since 3.2.1 * @author Rob Winch */ @Order(100) -public abstract class GlobalAuthenticationConfigurerAdapter implements SecurityConfigurer { +public abstract class GlobalAuthenticationConfigurerAdapter implements + SecurityConfigurer { - public void init(AuthenticationManagerBuilder auth) throws Exception {} + public void init(AuthenticationManagerBuilder auth) throws Exception { + } - public void configure(AuthenticationManagerBuilder auth) throws Exception {} + public void configure(AuthenticationManagerBuilder auth) throws Exception { + } } \ No newline at end of file diff --git a/config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/ldap/LdapAuthenticationProviderConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/ldap/LdapAuthenticationProviderConfigurer.java index 045d9c97c1..eb7d555fc5 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/ldap/LdapAuthenticationProviderConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/ldap/LdapAuthenticationProviderConfigurer.java @@ -53,509 +53,532 @@ import java.net.ServerSocket; * @author Rob Winch * @since 3.2 */ -public class LdapAuthenticationProviderConfigurer> extends SecurityConfigurerAdapter { - private String groupRoleAttribute = "cn"; - private String groupSearchBase = ""; - private String groupSearchFilter = "(uniqueMember={0})"; - private String rolePrefix = "ROLE_"; - private String userSearchBase = ""; // only for search - private String userSearchFilter = null;//"uid={0}"; // only for search - private String[] userDnPatterns; - private BaseLdapPathContextSource contextSource; - private ContextSourceBuilder contextSourceBuilder = new ContextSourceBuilder(); - private UserDetailsContextMapper userDetailsContextMapper; - private Object passwordEncoder; - private String passwordAttribute; - private LdapAuthoritiesPopulator ldapAuthoritiesPopulator; +public class LdapAuthenticationProviderConfigurer> + extends SecurityConfigurerAdapter { + private String groupRoleAttribute = "cn"; + private String groupSearchBase = ""; + private String groupSearchFilter = "(uniqueMember={0})"; + private String rolePrefix = "ROLE_"; + private String userSearchBase = ""; // only for search + private String userSearchFilter = null;// "uid={0}"; // only for search + private String[] userDnPatterns; + private BaseLdapPathContextSource contextSource; + private ContextSourceBuilder contextSourceBuilder = new ContextSourceBuilder(); + private UserDetailsContextMapper userDetailsContextMapper; + private Object passwordEncoder; + private String passwordAttribute; + private LdapAuthoritiesPopulator ldapAuthoritiesPopulator; - private LdapAuthenticationProvider build() throws Exception { - BaseLdapPathContextSource contextSource = getContextSource(); - LdapAuthenticator ldapAuthenticator = createLdapAuthenticator(contextSource); + private LdapAuthenticationProvider build() throws Exception { + BaseLdapPathContextSource contextSource = getContextSource(); + LdapAuthenticator ldapAuthenticator = createLdapAuthenticator(contextSource); - LdapAuthoritiesPopulator authoritiesPopulator = getLdapAuthoritiesPopulator(); + LdapAuthoritiesPopulator authoritiesPopulator = getLdapAuthoritiesPopulator(); - LdapAuthenticationProvider ldapAuthenticationProvider = new LdapAuthenticationProvider( - ldapAuthenticator, authoritiesPopulator); - SimpleAuthorityMapper simpleAuthorityMapper = new SimpleAuthorityMapper(); - simpleAuthorityMapper.setPrefix(rolePrefix); - simpleAuthorityMapper.afterPropertiesSet(); - ldapAuthenticationProvider.setAuthoritiesMapper(simpleAuthorityMapper); - if(userDetailsContextMapper != null) { - ldapAuthenticationProvider.setUserDetailsContextMapper(userDetailsContextMapper); - } - return ldapAuthenticationProvider; - } + LdapAuthenticationProvider ldapAuthenticationProvider = new LdapAuthenticationProvider( + ldapAuthenticator, authoritiesPopulator); + SimpleAuthorityMapper simpleAuthorityMapper = new SimpleAuthorityMapper(); + simpleAuthorityMapper.setPrefix(rolePrefix); + simpleAuthorityMapper.afterPropertiesSet(); + ldapAuthenticationProvider.setAuthoritiesMapper(simpleAuthorityMapper); + if (userDetailsContextMapper != null) { + ldapAuthenticationProvider + .setUserDetailsContextMapper(userDetailsContextMapper); + } + return ldapAuthenticationProvider; + } - /** - * Specifies the {@link LdapAuthoritiesPopulator}. - * - * @param ldapAuthoritiesPopulator the {@link LdapAuthoritiesPopulator} the default is {@link DefaultLdapAuthoritiesPopulator} - * @return the {@link LdapAuthenticationProviderConfigurer} for further customizations - */ - public LdapAuthenticationProviderConfigurer ldapAuthoritiesPopulator(LdapAuthoritiesPopulator ldapAuthoritiesPopulator) { - this.ldapAuthoritiesPopulator = ldapAuthoritiesPopulator; - return this; - } + /** + * Specifies the {@link LdapAuthoritiesPopulator}. + * + * @param ldapAuthoritiesPopulator the {@link LdapAuthoritiesPopulator} the default is + * {@link DefaultLdapAuthoritiesPopulator} + * @return the {@link LdapAuthenticationProviderConfigurer} for further customizations + */ + public LdapAuthenticationProviderConfigurer ldapAuthoritiesPopulator( + LdapAuthoritiesPopulator ldapAuthoritiesPopulator) { + this.ldapAuthoritiesPopulator = ldapAuthoritiesPopulator; + return this; + } - /** - * Adds an {@link ObjectPostProcessor} for this class. - * - * @param objectPostProcessor - * @return the {@link ChannelSecurityConfigurer} for further customizations - */ - public LdapAuthenticationProviderConfigurer withObjectPostProcessor(ObjectPostProcessor objectPostProcessor) { - addObjectPostProcessor(objectPostProcessor); - return this; - } + /** + * Adds an {@link ObjectPostProcessor} for this class. + * + * @param objectPostProcessor + * @return the {@link ChannelSecurityConfigurer} for further customizations + */ + public LdapAuthenticationProviderConfigurer withObjectPostProcessor( + ObjectPostProcessor objectPostProcessor) { + addObjectPostProcessor(objectPostProcessor); + return this; + } - /** - * Gets the {@link LdapAuthoritiesPopulator} and defaults to {@link DefaultLdapAuthoritiesPopulator} - * - * @return the {@link LdapAuthoritiesPopulator} - */ - private LdapAuthoritiesPopulator getLdapAuthoritiesPopulator() { - if(ldapAuthoritiesPopulator != null) { - return ldapAuthoritiesPopulator; - } + /** + * Gets the {@link LdapAuthoritiesPopulator} and defaults to + * {@link DefaultLdapAuthoritiesPopulator} + * + * @return the {@link LdapAuthoritiesPopulator} + */ + private LdapAuthoritiesPopulator getLdapAuthoritiesPopulator() { + if (ldapAuthoritiesPopulator != null) { + return ldapAuthoritiesPopulator; + } - DefaultLdapAuthoritiesPopulator defaultAuthoritiesPopulator = new DefaultLdapAuthoritiesPopulator( - contextSource, groupSearchBase); - defaultAuthoritiesPopulator.setGroupRoleAttribute(groupRoleAttribute); - defaultAuthoritiesPopulator.setGroupSearchFilter(groupSearchFilter); + DefaultLdapAuthoritiesPopulator defaultAuthoritiesPopulator = new DefaultLdapAuthoritiesPopulator( + contextSource, groupSearchBase); + defaultAuthoritiesPopulator.setGroupRoleAttribute(groupRoleAttribute); + defaultAuthoritiesPopulator.setGroupSearchFilter(groupSearchFilter); - this.ldapAuthoritiesPopulator = defaultAuthoritiesPopulator; - return defaultAuthoritiesPopulator; - } + this.ldapAuthoritiesPopulator = defaultAuthoritiesPopulator; + return defaultAuthoritiesPopulator; + } - /** - * Creates the {@link LdapAuthenticator} to use - * - * @param contextSource the {@link BaseLdapPathContextSource} to use - * @return the {@link LdapAuthenticator} to use - */ - private LdapAuthenticator createLdapAuthenticator(BaseLdapPathContextSource contextSource) { - AbstractLdapAuthenticator ldapAuthenticator = passwordEncoder == null ? createBindAuthenticator(contextSource) : createPasswordCompareAuthenticator(contextSource); - LdapUserSearch userSearch = createUserSearch(); - if(userSearch != null) { - ldapAuthenticator.setUserSearch(userSearch); - } - if(userDnPatterns != null && userDnPatterns.length > 0) { - ldapAuthenticator.setUserDnPatterns(userDnPatterns); - } - return postProcess(ldapAuthenticator); - } + /** + * Creates the {@link LdapAuthenticator} to use + * + * @param contextSource the {@link BaseLdapPathContextSource} to use + * @return the {@link LdapAuthenticator} to use + */ + private LdapAuthenticator createLdapAuthenticator( + BaseLdapPathContextSource contextSource) { + AbstractLdapAuthenticator ldapAuthenticator = passwordEncoder == null ? createBindAuthenticator(contextSource) + : createPasswordCompareAuthenticator(contextSource); + LdapUserSearch userSearch = createUserSearch(); + if (userSearch != null) { + ldapAuthenticator.setUserSearch(userSearch); + } + if (userDnPatterns != null && userDnPatterns.length > 0) { + ldapAuthenticator.setUserDnPatterns(userDnPatterns); + } + return postProcess(ldapAuthenticator); + } - /** - * Creates {@link PasswordComparisonAuthenticator} - * - * @param contextSource the {@link BaseLdapPathContextSource} to use - * @return - */ - private PasswordComparisonAuthenticator createPasswordCompareAuthenticator(BaseLdapPathContextSource contextSource) { - PasswordComparisonAuthenticator ldapAuthenticator = new PasswordComparisonAuthenticator(contextSource); - if(passwordAttribute != null) { - ldapAuthenticator.setPasswordAttributeName(passwordAttribute); - } - ldapAuthenticator.setPasswordEncoder(passwordEncoder); - return ldapAuthenticator; - } + /** + * Creates {@link PasswordComparisonAuthenticator} + * + * @param contextSource the {@link BaseLdapPathContextSource} to use + * @return + */ + private PasswordComparisonAuthenticator createPasswordCompareAuthenticator( + BaseLdapPathContextSource contextSource) { + PasswordComparisonAuthenticator ldapAuthenticator = new PasswordComparisonAuthenticator( + contextSource); + if (passwordAttribute != null) { + ldapAuthenticator.setPasswordAttributeName(passwordAttribute); + } + ldapAuthenticator.setPasswordEncoder(passwordEncoder); + return ldapAuthenticator; + } - /** - * Creates a {@link BindAuthenticator} - * - * @param contextSource the {@link BaseLdapPathContextSource} to use - * @return the {@link BindAuthenticator} to use - */ - private BindAuthenticator createBindAuthenticator( - BaseLdapPathContextSource contextSource) { - return new BindAuthenticator(contextSource); - } + /** + * Creates a {@link BindAuthenticator} + * + * @param contextSource the {@link BaseLdapPathContextSource} to use + * @return the {@link BindAuthenticator} to use + */ + private BindAuthenticator createBindAuthenticator( + BaseLdapPathContextSource contextSource) { + return new BindAuthenticator(contextSource); + } - private LdapUserSearch createUserSearch() { - if(userSearchFilter == null) { - return null; - } - return new FilterBasedLdapUserSearch(userSearchBase, userSearchFilter, contextSource); - } + private LdapUserSearch createUserSearch() { + if (userSearchFilter == null) { + return null; + } + return new FilterBasedLdapUserSearch(userSearchBase, userSearchFilter, + contextSource); + } - /** - * Specifies the {@link BaseLdapPathContextSource} to be used. If not - * specified, an embedded LDAP server will be created using - * {@link #contextSource()}. - * - * @param contextSource - * the {@link BaseLdapPathContextSource} to use - * @return the {@link LdapAuthenticationProviderConfigurer} for further - * customizations - * @see #contextSource() - */ - public LdapAuthenticationProviderConfigurer contextSource(BaseLdapPathContextSource contextSource) { - this.contextSource = contextSource; - return this; - } + /** + * Specifies the {@link BaseLdapPathContextSource} to be used. If not specified, an + * embedded LDAP server will be created using {@link #contextSource()}. + * + * @param contextSource the {@link BaseLdapPathContextSource} to use + * @return the {@link LdapAuthenticationProviderConfigurer} for further customizations + * @see #contextSource() + */ + public LdapAuthenticationProviderConfigurer contextSource( + BaseLdapPathContextSource contextSource) { + this.contextSource = contextSource; + return this; + } - /** - * Allows easily configuring of a {@link BaseLdapPathContextSource} with - * defaults pointing to an embedded LDAP server that is created. - * - * @return the {@link ContextSourceBuilder} for further customizations - */ - public ContextSourceBuilder contextSource() { - return contextSourceBuilder; - } + /** + * Allows easily configuring of a {@link BaseLdapPathContextSource} with defaults + * pointing to an embedded LDAP server that is created. + * + * @return the {@link ContextSourceBuilder} for further customizations + */ + public ContextSourceBuilder contextSource() { + return contextSourceBuilder; + } - /** - * Specifies the {@link PasswordEncoder} to be used when authenticating with - * password comparison. - * - * @param passwordEncoder the {@link PasswordEncoder} to use - * @return the {@link LdapAuthenticationProviderConfigurer} for further customization - * @deprecated Use {@link #passwordEncoder(org.springframework.security.crypto.password.PasswordEncoder)} instead - */ - public LdapAuthenticationProviderConfigurer passwordEncoder(PasswordEncoder passwordEncoder) { - this.passwordEncoder = passwordEncoder; - return this; - } + /** + * Specifies the {@link PasswordEncoder} to be used when authenticating with password + * comparison. + * + * @param passwordEncoder the {@link PasswordEncoder} to use + * @return the {@link LdapAuthenticationProviderConfigurer} for further customization + * @deprecated Use + * {@link #passwordEncoder(org.springframework.security.crypto.password.PasswordEncoder)} + * instead + */ + public LdapAuthenticationProviderConfigurer passwordEncoder( + PasswordEncoder passwordEncoder) { + this.passwordEncoder = passwordEncoder; + return this; + } - /** - * Specifies the {@link org.springframework.security.crypto.password.PasswordEncoder} to be used when authenticating with - * password comparison. - * - * @param passwordEncoder the {@link org.springframework.security.crypto.password.PasswordEncoder} to use - * @return the {@link LdapAuthenticationProviderConfigurer} for further customization - */ - public LdapAuthenticationProviderConfigurer passwordEncoder(final org.springframework.security.crypto.password.PasswordEncoder passwordEncoder) { - Assert.notNull(passwordEncoder, "passwordEncoder must not be null."); - this.passwordEncoder = passwordEncoder; - return this; - } + /** + * Specifies the {@link org.springframework.security.crypto.password.PasswordEncoder} + * to be used when authenticating with password comparison. + * + * @param passwordEncoder the + * {@link org.springframework.security.crypto.password.PasswordEncoder} to use + * @return the {@link LdapAuthenticationProviderConfigurer} for further customization + */ + public LdapAuthenticationProviderConfigurer passwordEncoder( + final org.springframework.security.crypto.password.PasswordEncoder passwordEncoder) { + Assert.notNull(passwordEncoder, "passwordEncoder must not be null."); + this.passwordEncoder = passwordEncoder; + return this; + } - /** - * If your users are at a fixed location in the directory (i.e. you can work - * out the DN directly from the username without doing a directory search), - * you can use this attribute to map directly to the DN. It maps directly to - * the userDnPatterns property of AbstractLdapAuthenticator. The value is a - * specific pattern used to build the user's DN, for example - * "uid={0},ou=people". The key "{0}" must be present and will be - * substituted with the username. - * - * @param userDnPatterns the LDAP patterns for finding the usernames - * @return the {@link LdapAuthenticationProviderConfigurer} for further customizations - */ - public LdapAuthenticationProviderConfigurer userDnPatterns(String...userDnPatterns) { - this.userDnPatterns = userDnPatterns; - return this; - } + /** + * If your users are at a fixed location in the directory (i.e. you can work out the + * DN directly from the username without doing a directory search), you can use this + * attribute to map directly to the DN. It maps directly to the userDnPatterns + * property of AbstractLdapAuthenticator. The value is a specific pattern used to + * build the user's DN, for example "uid={0},ou=people". The key "{0}" must be present + * and will be substituted with the username. + * + * @param userDnPatterns the LDAP patterns for finding the usernames + * @return the {@link LdapAuthenticationProviderConfigurer} for further customizations + */ + public LdapAuthenticationProviderConfigurer userDnPatterns( + String... userDnPatterns) { + this.userDnPatterns = userDnPatterns; + return this; + } - /** - * Allows explicit customization of the loaded user object by specifying a - * UserDetailsContextMapper bean which will be called with the context - * information from the user's directory entry. - * - * @param userDetailsContextMapper the {@link UserDetailsContextMapper} to use - * @return the {@link LdapAuthenticationProviderConfigurer} for further - * customizations - * - * @see PersonContextMapper - * @see InetOrgPersonContextMapper - * @see LdapUserDetailsMapper - */ - public LdapAuthenticationProviderConfigurer userDetailsContextMapper(UserDetailsContextMapper userDetailsContextMapper) { - this.userDetailsContextMapper = userDetailsContextMapper; - return this; - } + /** + * Allows explicit customization of the loaded user object by specifying a + * UserDetailsContextMapper bean which will be called with the context information + * from the user's directory entry. + * + * @param userDetailsContextMapper the {@link UserDetailsContextMapper} to use + * @return the {@link LdapAuthenticationProviderConfigurer} for further customizations + * + * @see PersonContextMapper + * @see InetOrgPersonContextMapper + * @see LdapUserDetailsMapper + */ + public LdapAuthenticationProviderConfigurer userDetailsContextMapper( + UserDetailsContextMapper userDetailsContextMapper) { + this.userDetailsContextMapper = userDetailsContextMapper; + return this; + } - /** - * Specifies the attribute name which contains the role name. Default is "cn". - * @param groupRoleAttribute the attribute name that maps a group to a role. - * @return - */ - public LdapAuthenticationProviderConfigurer groupRoleAttribute(String groupRoleAttribute) { - this.groupRoleAttribute = groupRoleAttribute; - return this; - } + /** + * Specifies the attribute name which contains the role name. Default is "cn". + * @param groupRoleAttribute the attribute name that maps a group to a role. + * @return + */ + public LdapAuthenticationProviderConfigurer groupRoleAttribute( + String groupRoleAttribute) { + this.groupRoleAttribute = groupRoleAttribute; + return this; + } - /** - * The search base for group membership searches. Defaults to "". - * @param groupSearchBase - * @return the {@link LdapAuthenticationProviderConfigurer} for further customizations - */ - public LdapAuthenticationProviderConfigurer groupSearchBase(String groupSearchBase) { - this.groupSearchBase = groupSearchBase; - return this; - } + /** + * The search base for group membership searches. Defaults to "". + * @param groupSearchBase + * @return the {@link LdapAuthenticationProviderConfigurer} for further customizations + */ + public LdapAuthenticationProviderConfigurer groupSearchBase(String groupSearchBase) { + this.groupSearchBase = groupSearchBase; + return this; + } - /** - * The LDAP filter to search for groups. Defaults to "(uniqueMember={0})". - * The substituted parameter is the DN of the user. - * - * @param groupSearchFilter the LDAP filter to search for groups - * @return the {@link LdapAuthenticationProviderConfigurer} for further customizations - */ - public LdapAuthenticationProviderConfigurer groupSearchFilter(String groupSearchFilter) { - this.groupSearchFilter = groupSearchFilter; - return this; - } + /** + * The LDAP filter to search for groups. Defaults to "(uniqueMember={0})". The + * substituted parameter is the DN of the user. + * + * @param groupSearchFilter the LDAP filter to search for groups + * @return the {@link LdapAuthenticationProviderConfigurer} for further customizations + */ + public LdapAuthenticationProviderConfigurer groupSearchFilter( + String groupSearchFilter) { + this.groupSearchFilter = groupSearchFilter; + return this; + } - /** - * A non-empty string prefix that will be added as a prefix to the existing - * roles. The default is "ROLE_". - * - * @param rolePrefix the prefix to be added to the roles that are loaded. - * @return the {@link LdapAuthenticationProviderConfigurer} for further customizations - * @see SimpleAuthorityMapper#setPrefix(String) - */ - public LdapAuthenticationProviderConfigurer rolePrefix(String rolePrefix) { - this.rolePrefix = rolePrefix; - return this; - } - /** - * Search base for user searches. Defaults to "". Only used with {@link #userSearchFilter(String)}. - * - * @param userSearchBase search base for user searches - * @return the {@link LdapAuthenticationProviderConfigurer} for further customizations - */ - public LdapAuthenticationProviderConfigurer userSearchBase(String userSearchBase) { - this.userSearchBase = userSearchBase; - return this; - } + /** + * A non-empty string prefix that will be added as a prefix to the existing roles. The + * default is "ROLE_". + * + * @param rolePrefix the prefix to be added to the roles that are loaded. + * @return the {@link LdapAuthenticationProviderConfigurer} for further customizations + * @see SimpleAuthorityMapper#setPrefix(String) + */ + public LdapAuthenticationProviderConfigurer rolePrefix(String rolePrefix) { + this.rolePrefix = rolePrefix; + return this; + } - /** - * The LDAP filter used to search for users (optional). For example - * "(uid={0})". The substituted parameter is the user's login name. - * - * @param userSearchFilter - * the LDAP filter used to search for users - * @return the {@link LdapAuthenticationProviderConfigurer} for further - * customizations - */ - public LdapAuthenticationProviderConfigurer userSearchFilter(String userSearchFilter) { - this.userSearchFilter = userSearchFilter; - return this; - } + /** + * Search base for user searches. Defaults to "". Only used with + * {@link #userSearchFilter(String)}. + * + * @param userSearchBase search base for user searches + * @return the {@link LdapAuthenticationProviderConfigurer} for further customizations + */ + public LdapAuthenticationProviderConfigurer userSearchBase(String userSearchBase) { + this.userSearchBase = userSearchBase; + return this; + } - @Override - public void configure(B builder) throws Exception { - LdapAuthenticationProvider provider = postProcess(build()); - builder.authenticationProvider(provider); - } + /** + * The LDAP filter used to search for users (optional). For example "(uid={0})". The + * substituted parameter is the user's login name. + * + * @param userSearchFilter the LDAP filter used to search for users + * @return the {@link LdapAuthenticationProviderConfigurer} for further customizations + */ + public LdapAuthenticationProviderConfigurer userSearchFilter( + String userSearchFilter) { + this.userSearchFilter = userSearchFilter; + return this; + } - /** - * Sets up Password based comparison - * - * @author Rob Winch - */ - public final class PasswordCompareConfigurer { + @Override + public void configure(B builder) throws Exception { + LdapAuthenticationProvider provider = postProcess(build()); + builder.authenticationProvider(provider); + } - /** - * Allows specifying the {@link PasswordEncoder} to use. The default is {@link PlaintextPasswordEncoder}. - * @param passwordEncoder the {@link PasswordEncoder} to use - * @return the {@link PasswordEncoder} to use - */ - public PasswordCompareConfigurer passwordEncoder(PasswordEncoder passwordEncoder) { - LdapAuthenticationProviderConfigurer.this.passwordEncoder = passwordEncoder; - return this; - } + /** + * Sets up Password based comparison + * + * @author Rob Winch + */ + public final class PasswordCompareConfigurer { - /** - * The attribute in the directory which contains the user password. Defaults to "userPassword". - * - * @param passwordAttribute the attribute in the directory which contains the user password - * @return the {@link PasswordCompareConfigurer} for further customizations - */ - public PasswordCompareConfigurer passwordAttribute(String passwordAttribute) { - LdapAuthenticationProviderConfigurer.this.passwordAttribute = passwordAttribute; - return this; - } + /** + * Allows specifying the {@link PasswordEncoder} to use. The default is + * {@link PlaintextPasswordEncoder}. + * @param passwordEncoder the {@link PasswordEncoder} to use + * @return the {@link PasswordEncoder} to use + */ + public PasswordCompareConfigurer passwordEncoder(PasswordEncoder passwordEncoder) { + LdapAuthenticationProviderConfigurer.this.passwordEncoder = passwordEncoder; + return this; + } - /** - * Allows obtaining a reference to the - * {@link LdapAuthenticationProviderConfigurer} for further - * customizations - * - * @return attribute in the directory which contains the user password - */ - public LdapAuthenticationProviderConfigurer and() { - return LdapAuthenticationProviderConfigurer.this; - } + /** + * The attribute in the directory which contains the user password. Defaults to + * "userPassword". + * + * @param passwordAttribute the attribute in the directory which contains the user + * password + * @return the {@link PasswordCompareConfigurer} for further customizations + */ + public PasswordCompareConfigurer passwordAttribute(String passwordAttribute) { + LdapAuthenticationProviderConfigurer.this.passwordAttribute = passwordAttribute; + return this; + } - private PasswordCompareConfigurer() {} - } + /** + * Allows obtaining a reference to the + * {@link LdapAuthenticationProviderConfigurer} for further customizations + * + * @return attribute in the directory which contains the user password + */ + public LdapAuthenticationProviderConfigurer and() { + return LdapAuthenticationProviderConfigurer.this; + } - /** - * Allows building a {@link BaseLdapPathContextSource} and optionally - * creating an embedded LDAP instance. - * - * @author Rob Winch - * @since 3.2 - */ - public final class ContextSourceBuilder { - private String ldif = "classpath*:*.ldif"; - private String managerPassword; - private String managerDn; - private Integer port; - private static final int DEFAULT_PORT = 33389; - private String root = "dc=springframework,dc=org"; - private String url; + private PasswordCompareConfigurer() { + } + } - /** - * Specifies an ldif to load at startup for an embedded LDAP server. - * This only loads if using an embedded instance. The default is - * "classpath*:*.ldif". - * - * @param ldif - * the ldif to load at startup for an embedded LDAP server. - * @return the {@link ContextSourceBuilder} for further customization - */ - public ContextSourceBuilder ldif(String ldif) { - this.ldif = ldif; - return this; - } + /** + * Allows building a {@link BaseLdapPathContextSource} and optionally creating an + * embedded LDAP instance. + * + * @author Rob Winch + * @since 3.2 + */ + public final class ContextSourceBuilder { + private String ldif = "classpath*:*.ldif"; + private String managerPassword; + private String managerDn; + private Integer port; + private static final int DEFAULT_PORT = 33389; + private String root = "dc=springframework,dc=org"; + private String url; - /** - * Username (DN) of the "manager" user identity (i.e. - * "uid=admin,ou=system") which will be used to authenticate to a - * (non-embedded) LDAP server. If omitted, anonymous access will be - * used. - * - * @param managerDn - * the username (DN) of the "manager" user identity used to - * authenticate to a LDAP server. - * @return the {@link ContextSourceBuilder} for further customization - */ - public ContextSourceBuilder managerDn(String managerDn) { - this.managerDn = managerDn; - return this; - } + /** + * Specifies an ldif to load at startup for an embedded LDAP server. This only + * loads if using an embedded instance. The default is "classpath*:*.ldif". + * + * @param ldif the ldif to load at startup for an embedded LDAP server. + * @return the {@link ContextSourceBuilder} for further customization + */ + public ContextSourceBuilder ldif(String ldif) { + this.ldif = ldif; + return this; + } - /** - * The password for the manager DN. This is required if the manager-dn is specified. - * @param managerPassword password for the manager DN - * @return the {@link ContextSourceBuilder} for further customization - */ - public ContextSourceBuilder managerPassword(String managerPassword) { - this.managerPassword = managerPassword; - return this; - } + /** + * Username (DN) of the "manager" user identity (i.e. "uid=admin,ou=system") which + * will be used to authenticate to a (non-embedded) LDAP server. If omitted, + * anonymous access will be used. + * + * @param managerDn the username (DN) of the "manager" user identity used to + * authenticate to a LDAP server. + * @return the {@link ContextSourceBuilder} for further customization + */ + public ContextSourceBuilder managerDn(String managerDn) { + this.managerDn = managerDn; + return this; + } - /** - * The port to connect to LDAP to (the default is 33389 or random available port if unavailable). - * @param port the port to connect to - * @return the {@link ContextSourceBuilder} for further customization - */ - public ContextSourceBuilder port(int port) { - this.port = port; - return this; - } + /** + * The password for the manager DN. This is required if the manager-dn is + * specified. + * @param managerPassword password for the manager DN + * @return the {@link ContextSourceBuilder} for further customization + */ + public ContextSourceBuilder managerPassword(String managerPassword) { + this.managerPassword = managerPassword; + return this; + } - /** - * Optional root suffix for the embedded LDAP server. Default is - * "dc=springframework,dc=org" - * - * @param root - * root suffix for the embedded LDAP server - * @return the {@link ContextSourceBuilder} for further customization - */ - public ContextSourceBuilder root(String root) { - this.root = root; - return this; - } + /** + * The port to connect to LDAP to (the default is 33389 or random available port + * if unavailable). + * @param port the port to connect to + * @return the {@link ContextSourceBuilder} for further customization + */ + public ContextSourceBuilder port(int port) { + this.port = port; + return this; + } - /** - * Specifies the ldap server URL when not using the embedded LDAP - * server. For example, "ldaps://ldap.example.com:33389/dc=myco,dc=org". - * - * @param url - * the ldap server URL - * @return the {@link ContextSourceBuilder} for further customization - */ - public ContextSourceBuilder url(String url) { - this.url = url; - return this; - } + /** + * Optional root suffix for the embedded LDAP server. Default is + * "dc=springframework,dc=org" + * + * @param root root suffix for the embedded LDAP server + * @return the {@link ContextSourceBuilder} for further customization + */ + public ContextSourceBuilder root(String root) { + this.root = root; + return this; + } - /** - * Gets the {@link LdapAuthenticationProviderConfigurer} for further - * customizations - * - * @return the {@link LdapAuthenticationProviderConfigurer} for further - * customizations - */ - public LdapAuthenticationProviderConfigurer and() { - return LdapAuthenticationProviderConfigurer.this; - } + /** + * Specifies the ldap server URL when not using the embedded LDAP server. For + * example, "ldaps://ldap.example.com:33389/dc=myco,dc=org". + * + * @param url the ldap server URL + * @return the {@link ContextSourceBuilder} for further customization + */ + public ContextSourceBuilder url(String url) { + this.url = url; + return this; + } - private DefaultSpringSecurityContextSource build() throws Exception { - DefaultSpringSecurityContextSource contextSource = new DefaultSpringSecurityContextSource(getProviderUrl()); - if(managerDn != null) { - contextSource.setUserDn(managerDn); - if(managerPassword == null) { - throw new IllegalStateException("managerPassword is required if managerDn is supplied"); - } - contextSource.setPassword(managerPassword); - } - contextSource = postProcess(contextSource); - if(url != null) { - return contextSource; - } - ApacheDSContainer apacheDsContainer = new ApacheDSContainer(root, ldif); - apacheDsContainer.setPort(getPort()); - postProcess(apacheDsContainer); - return contextSource; - } + /** + * Gets the {@link LdapAuthenticationProviderConfigurer} for further + * customizations + * + * @return the {@link LdapAuthenticationProviderConfigurer} for further + * customizations + */ + public LdapAuthenticationProviderConfigurer and() { + return LdapAuthenticationProviderConfigurer.this; + } - private int getPort() { - if(port == null) { - port = getDefaultPort(); - } - return port; - } + private DefaultSpringSecurityContextSource build() throws Exception { + DefaultSpringSecurityContextSource contextSource = new DefaultSpringSecurityContextSource( + getProviderUrl()); + if (managerDn != null) { + contextSource.setUserDn(managerDn); + if (managerPassword == null) { + throw new IllegalStateException( + "managerPassword is required if managerDn is supplied"); + } + contextSource.setPassword(managerPassword); + } + contextSource = postProcess(contextSource); + if (url != null) { + return contextSource; + } + ApacheDSContainer apacheDsContainer = new ApacheDSContainer(root, ldif); + apacheDsContainer.setPort(getPort()); + postProcess(apacheDsContainer); + return contextSource; + } - private int getDefaultPort() { - ServerSocket serverSocket = null; - try { - try { - serverSocket = new ServerSocket(DEFAULT_PORT); - } catch (IOException e) { - try { - serverSocket = new ServerSocket(0); - } catch(IOException e2) { - return DEFAULT_PORT; - } - } - return serverSocket.getLocalPort(); - } finally { - if(serverSocket != null) { - try { - serverSocket.close(); - } catch (IOException e) {} - } - } - } + private int getPort() { + if (port == null) { + port = getDefaultPort(); + } + return port; + } - private String getProviderUrl() { - if(url == null) { - return "ldap://127.0.0.1:" + getPort() + "/" + root; - } - return url; - } + private int getDefaultPort() { + ServerSocket serverSocket = null; + try { + try { + serverSocket = new ServerSocket(DEFAULT_PORT); + } + catch (IOException e) { + try { + serverSocket = new ServerSocket(0); + } + catch (IOException e2) { + return DEFAULT_PORT; + } + } + return serverSocket.getLocalPort(); + } + finally { + if (serverSocket != null) { + try { + serverSocket.close(); + } + catch (IOException e) { + } + } + } + } - private ContextSourceBuilder() {} - } + private String getProviderUrl() { + if (url == null) { + return "ldap://127.0.0.1:" + getPort() + "/" + root; + } + return url; + } - private BaseLdapPathContextSource getContextSource() throws Exception { - if(contextSource == null) { - contextSource = contextSourceBuilder.build(); - } - return contextSource; - } + private ContextSourceBuilder() { + } + } - /** - * @return - */ - public PasswordCompareConfigurer passwordCompare() { - return new PasswordCompareConfigurer() - .passwordAttribute("password") - .passwordEncoder(new PlaintextPasswordEncoder()); - } + private BaseLdapPathContextSource getContextSource() throws Exception { + if (contextSource == null) { + contextSource = contextSourceBuilder.build(); + } + return contextSource; + } + + /** + * @return + */ + public PasswordCompareConfigurer passwordCompare() { + return new PasswordCompareConfigurer().passwordAttribute("password") + .passwordEncoder(new PlaintextPasswordEncoder()); + } } \ No newline at end of file diff --git a/config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/provisioning/InMemoryUserDetailsManagerConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/provisioning/InMemoryUserDetailsManagerConfigurer.java index f35804a27d..2aa384e206 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/provisioning/InMemoryUserDetailsManagerConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/provisioning/InMemoryUserDetailsManagerConfigurer.java @@ -22,21 +22,23 @@ import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.provisioning.InMemoryUserDetailsManager; /** - * Configures an {@link org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder} to - * have in memory authentication. It also allows easily adding users to the in memory authentication. + * Configures an + * {@link org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder} + * to have in memory authentication. It also allows easily adding users to the in memory + * authentication. * * @param the type of the {@link SecurityBuilder} that is being configured * * @author Rob Winch * @since 3.2 */ -public class InMemoryUserDetailsManagerConfigurer> extends - UserDetailsManagerConfigurer> { +public class InMemoryUserDetailsManagerConfigurer> + extends UserDetailsManagerConfigurer> { - /** - * Creates a new instance - */ - public InMemoryUserDetailsManagerConfigurer() { - super(new InMemoryUserDetailsManager(new ArrayList())); - } + /** + * Creates a new instance + */ + public InMemoryUserDetailsManagerConfigurer() { + super(new InMemoryUserDetailsManager(new ArrayList())); + } } diff --git a/config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/provisioning/JdbcUserDetailsManagerConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/provisioning/JdbcUserDetailsManagerConfigurer.java index 181317fb96..b47fc8e082 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/provisioning/JdbcUserDetailsManagerConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/provisioning/JdbcUserDetailsManagerConfigurer.java @@ -30,12 +30,14 @@ import org.springframework.security.core.userdetails.UserCache; import org.springframework.security.provisioning.JdbcUserDetailsManager; /** - * Configures an {@link org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder} to - * have JDBC authentication. It also allows easily adding users to the database used for authentication and setting up - * the schema. + * Configures an + * {@link org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder} + * to have JDBC authentication. It also allows easily adding users to the database used + * for authentication and setting up the schema. * *

- * The only required method is the {@link #dataSource(javax.sql.DataSource)} all other methods have reasonable defaults. + * The only required method is the {@link #dataSource(javax.sql.DataSource)} all other + * methods have reasonable defaults. *

* * @param the type of the {@link ProviderManagerBuilder} that is being configured @@ -43,150 +45,161 @@ import org.springframework.security.provisioning.JdbcUserDetailsManager; * @author Rob Winch * @since 3.2 */ -public class JdbcUserDetailsManagerConfigurer> extends - UserDetailsManagerConfigurer> { +public class JdbcUserDetailsManagerConfigurer> + extends UserDetailsManagerConfigurer> { - private DataSource dataSource; + private DataSource dataSource; - private List initScripts = new ArrayList(); + private List initScripts = new ArrayList(); - public JdbcUserDetailsManagerConfigurer(JdbcUserDetailsManager manager) { - super(manager); - } + public JdbcUserDetailsManagerConfigurer(JdbcUserDetailsManager manager) { + super(manager); + } - public JdbcUserDetailsManagerConfigurer() { - this(new JdbcUserDetailsManager()); - } + public JdbcUserDetailsManagerConfigurer() { + this(new JdbcUserDetailsManager()); + } + /** + * Populates the {@link DataSource} to be used. This is the only required attribute. + * + * @param dataSource the {@link DataSource} to be used. Cannot be null. + * @return + * @throws Exception + */ + public JdbcUserDetailsManagerConfigurer dataSource(DataSource dataSource) + throws Exception { + this.dataSource = dataSource; + getUserDetailsService().setDataSource(dataSource); + return this; + } - /** - * Populates the {@link DataSource} to be used. This is the only required attribute. - * - * @param dataSource the {@link DataSource} to be used. Cannot be null. - * @return - * @throws Exception - */ - public JdbcUserDetailsManagerConfigurer dataSource(DataSource dataSource) throws Exception { - this.dataSource = dataSource; - getUserDetailsService().setDataSource(dataSource); - return this; - } + /** + * Sets the query to be used for finding a user by their username. For example: + * + * + * select username,password,enabled from users where username = ? + * + * @param query The query to use for selecting the username, password, and if the user + * is enabled by username. Must contain a single parameter for the username. + * @return The {@link JdbcUserDetailsManagerRegistry} used for additional + * customizations + * @throws Exception + */ + public JdbcUserDetailsManagerConfigurer usersByUsernameQuery(String query) + throws Exception { + getUserDetailsService().setUsersByUsernameQuery(query); + return this; + } - /** - * Sets the query to be used for finding a user by their username. For example: - * - * - * select username,password,enabled from users where username = ? - * - * @param query The query to use for selecting the username, password, and if the user is enabled by username. - * Must contain a single parameter for the username. - * @return The {@link JdbcUserDetailsManagerRegistry} used for additional customizations - * @throws Exception - */ - public JdbcUserDetailsManagerConfigurer usersByUsernameQuery(String query) throws Exception { - getUserDetailsService().setUsersByUsernameQuery(query); - return this; - } + /** + * Sets the query to be used for finding a user's authorities by their username. For + * example: + * + * + * select username,authority from authorities where username = ? + * + * + * @param query The query to use for selecting the username, authority by username. + * Must contain a single parameter for the username. + * @return The {@link JdbcUserDetailsManagerRegistry} used for additional + * customizations + * @throws Exception + */ + public JdbcUserDetailsManagerConfigurer authoritiesByUsernameQuery(String query) + throws Exception { + getUserDetailsService().setAuthoritiesByUsernameQuery(query); + return this; + } - /** - * Sets the query to be used for finding a user's authorities by their username. For example: - * - * - * select username,authority from authorities where username = ? - * - * - * @param query The query to use for selecting the username, authority by username. - * Must contain a single parameter for the username. - * @return The {@link JdbcUserDetailsManagerRegistry} used for additional customizations - * @throws Exception - */ - public JdbcUserDetailsManagerConfigurer authoritiesByUsernameQuery(String query) throws Exception { - getUserDetailsService().setAuthoritiesByUsernameQuery(query); - return this; - } + /** + * An SQL statement to query user's group authorities given a username. For example: + * + * + * select + * g.id, g.group_name, ga.authority + * from + * groups g, group_members gm, group_authorities ga + * where + * gm.username = ? and g.id = ga.group_id and g.id = gm.group_id + * + * + * @param query The query to use for selecting the authorities by group. Must contain + * a single parameter for the username. + * @return The {@link JdbcUserDetailsManagerRegistry} used for additional + * customizations + * @throws Exception + */ + public JdbcUserDetailsManagerConfigurer groupAuthoritiesByUsername(String query) + throws Exception { + JdbcUserDetailsManager userDetailsService = getUserDetailsService(); + userDetailsService.setEnableGroups(true); + userDetailsService.setGroupAuthoritiesByUsernameQuery(query); + return this; + } - /** - * An SQL statement to query user's group authorities given a username. For example: - * - * - * select - * g.id, g.group_name, ga.authority - * from - * groups g, group_members gm, group_authorities ga - * where - * gm.username = ? and g.id = ga.group_id and g.id = gm.group_id - * - * - * @param query The query to use for selecting the authorities by group. - * Must contain a single parameter for the username. - * @return The {@link JdbcUserDetailsManagerRegistry} used for additional customizations - * @throws Exception - */ - public JdbcUserDetailsManagerConfigurer groupAuthoritiesByUsername(String query) throws Exception { - JdbcUserDetailsManager userDetailsService = getUserDetailsService(); - userDetailsService.setEnableGroups(true); - userDetailsService.setGroupAuthoritiesByUsernameQuery(query); - return this; - } + /** + * A non-empty string prefix that will be added to role strings loaded from persistent + * storage (default is ""). + * + * @param rolePrefix + * @return + * @throws Exception + */ + public JdbcUserDetailsManagerConfigurer rolePrefix(String rolePrefix) + throws Exception { + getUserDetailsService().setRolePrefix(rolePrefix); + return this; + } - /** - * A non-empty string prefix that will be added to role strings loaded from persistent storage (default is ""). - * - * @param rolePrefix - * @return - * @throws Exception - */ - public JdbcUserDetailsManagerConfigurer rolePrefix(String rolePrefix) throws Exception { - getUserDetailsService().setRolePrefix(rolePrefix); - return this; - } + /** + * Defines the {@link UserCache} to use + * + * @param userCache the {@link UserCache} to use + * @return the {@link JdbcUserDetailsManagerConfigurer} for further customizations + * @throws Exception + */ + public JdbcUserDetailsManagerConfigurer userCache(UserCache userCache) + throws Exception { + getUserDetailsService().setUserCache(userCache); + return this; + } + @Override + protected void initUserDetailsService() throws Exception { + if (!initScripts.isEmpty()) { + getDataSourceInit().afterPropertiesSet(); + } + super.initUserDetailsService(); + } - /** - * Defines the {@link UserCache} to use - * - * @param userCache the {@link UserCache} to use - * @return the {@link JdbcUserDetailsManagerConfigurer} for further customizations - * @throws Exception - */ - public JdbcUserDetailsManagerConfigurer userCache(UserCache userCache) throws Exception { - getUserDetailsService().setUserCache(userCache); - return this; - } + @Override + public JdbcUserDetailsManager getUserDetailsService() { + return (JdbcUserDetailsManager) super.getUserDetailsService(); + } - @Override - protected void initUserDetailsService() throws Exception { - if(!initScripts.isEmpty()) { - getDataSourceInit().afterPropertiesSet(); - } - super.initUserDetailsService(); - } + /** + * Populates the default schema that allows users and authorities to be stored. + * + * @return The {@link JdbcUserDetailsManagerRegistry} used for additional + * customizations + */ + public JdbcUserDetailsManagerConfigurer withDefaultSchema() { + this.initScripts.add(new ClassPathResource( + "org/springframework/security/core/userdetails/jdbc/users.ddl")); + return this; + } - @Override - public JdbcUserDetailsManager getUserDetailsService() { - return (JdbcUserDetailsManager) super.getUserDetailsService(); - } + protected DatabasePopulator getDatabasePopulator() { + ResourceDatabasePopulator dbp = new ResourceDatabasePopulator(); + dbp.setScripts(initScripts.toArray(new Resource[initScripts.size()])); + return dbp; + } - /** - * Populates the default schema that allows users and authorities to be stored. - * - * @return The {@link JdbcUserDetailsManagerRegistry} used for additional customizations - */ - public JdbcUserDetailsManagerConfigurer withDefaultSchema() { - this.initScripts.add(new ClassPathResource("org/springframework/security/core/userdetails/jdbc/users.ddl")); - return this; - } - - protected DatabasePopulator getDatabasePopulator() { - ResourceDatabasePopulator dbp = new ResourceDatabasePopulator(); - dbp.setScripts(initScripts.toArray(new Resource[initScripts.size()])); - return dbp; - } - - private DataSourceInitializer getDataSourceInit() { - DataSourceInitializer dsi = new DataSourceInitializer(); - dsi.setDatabasePopulator(getDatabasePopulator()); - dsi.setDataSource(dataSource); - return dsi; - } + private DataSourceInitializer getDataSourceInit() { + DataSourceInitializer dsi = new DataSourceInitializer(); + dsi.setDatabasePopulator(getDatabasePopulator()); + dsi.setDataSource(dataSource); + return dsi; + } } diff --git a/config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/provisioning/UserDetailsManagerConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/provisioning/UserDetailsManagerConfigurer.java index 88be60e62d..92c02291de 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/provisioning/UserDetailsManagerConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/provisioning/UserDetailsManagerConfigurer.java @@ -32,8 +32,8 @@ import org.springframework.util.Assert; /** * Base class for populating an - * {@link org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder} with a - * {@link UserDetailsManager}. + * {@link org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder} + * with a {@link UserDetailsManager}. * * @param the type of the {@link SecurityBuilder} that is being configured * @param the type of {@link UserDetailsManagerConfigurer} @@ -41,223 +41,231 @@ import org.springframework.util.Assert; * @author Rob Winch * @since 3.2 */ -public class UserDetailsManagerConfigurer, C extends UserDetailsManagerConfigurer> extends - UserDetailsServiceConfigurer { +public class UserDetailsManagerConfigurer, C extends UserDetailsManagerConfigurer> + extends UserDetailsServiceConfigurer { - private final List userBuilders = new ArrayList(); + private final List userBuilders = new ArrayList(); - protected UserDetailsManagerConfigurer(UserDetailsManager userDetailsManager) { - super(userDetailsManager); - } + protected UserDetailsManagerConfigurer(UserDetailsManager userDetailsManager) { + super(userDetailsManager); + } - /** - * Populates the users that have been added. - * - * @throws Exception - */ - @Override - protected void initUserDetailsService() throws Exception { - for(UserDetailsBuilder userBuilder : userBuilders) { - getUserDetailsService().createUser(userBuilder.build()); - } - } + /** + * Populates the users that have been added. + * + * @throws Exception + */ + @Override + protected void initUserDetailsService() throws Exception { + for (UserDetailsBuilder userBuilder : userBuilders) { + getUserDetailsService().createUser(userBuilder.build()); + } + } - /** - * Allows adding a user to the {@link UserDetailsManager} that is being created. This method can be invoked - * multiple times to add multiple users. - * - * @param username the username for the user being added. Cannot be null. - * @return - */ - @SuppressWarnings("unchecked") - public final UserDetailsBuilder withUser(String username) { - UserDetailsBuilder userBuilder = new UserDetailsBuilder((C)this); - userBuilder.username(username); - this.userBuilders.add(userBuilder); - return userBuilder; - } + /** + * Allows adding a user to the {@link UserDetailsManager} that is being created. This + * method can be invoked multiple times to add multiple users. + * + * @param username the username for the user being added. Cannot be null. + * @return + */ + @SuppressWarnings("unchecked") + public final UserDetailsBuilder withUser(String username) { + UserDetailsBuilder userBuilder = new UserDetailsBuilder((C) this); + userBuilder.username(username); + this.userBuilders.add(userBuilder); + return userBuilder; + } - /** - * Builds the user to be added. At minimum the username, password, and authorities should provided. The remaining - * attributes have reasonable defaults. - * - * @param the type of {@link UserDetailsManagerConfigurer} to return for chaining methods. - */ - public class UserDetailsBuilder { - private String username; - private String password; - private List authorities; - private boolean accountExpired; - private boolean accountLocked; - private boolean credentialsExpired; - private boolean disabled; - private final C builder; + /** + * Builds the user to be added. At minimum the username, password, and authorities + * should provided. The remaining attributes have reasonable defaults. + * + * @param the type of {@link UserDetailsManagerConfigurer} to return for chaining + * methods. + */ + public class UserDetailsBuilder { + private String username; + private String password; + private List authorities; + private boolean accountExpired; + private boolean accountLocked; + private boolean credentialsExpired; + private boolean disabled; + private final C builder; - /** - * Creates a new instance - * @param builder the builder to return - */ - private UserDetailsBuilder(C builder) { - this.builder = builder; - } + /** + * Creates a new instance + * @param builder the builder to return + */ + private UserDetailsBuilder(C builder) { + this.builder = builder; + } - /** - * Returns the {@link UserDetailsManagerRegistry} for method chaining (i.e. to add another user) - * - * @return the {@link UserDetailsManagerRegistry} for method chaining (i.e. to add another user) - */ - public C and() { - return builder; - } + /** + * Returns the {@link UserDetailsManagerRegistry} for method chaining (i.e. to add + * another user) + * + * @return the {@link UserDetailsManagerRegistry} for method chaining (i.e. to add + * another user) + */ + public C and() { + return builder; + } - /** - * Populates the username. This attribute is required. - * - * @param username the username. Cannot be null. - * @return the {@link UserDetailsBuilder} for method chaining (i.e. to populate additional attributes for this - * user) - */ - private UserDetailsBuilder username(String username) { - Assert.notNull(username, "username cannot be null"); - this.username = username; - return this; - } + /** + * Populates the username. This attribute is required. + * + * @param username the username. Cannot be null. + * @return the {@link UserDetailsBuilder} for method chaining (i.e. to populate + * additional attributes for this user) + */ + private UserDetailsBuilder username(String username) { + Assert.notNull(username, "username cannot be null"); + this.username = username; + return this; + } - /** - * Populates the password. This attribute is required. - * - * @param password the password. Cannot be null. - * @return the {@link UserDetailsBuilder} for method chaining (i.e. to populate additional attributes for this - * user) - */ - public UserDetailsBuilder password(String password) { - Assert.notNull(password, "password cannot be null"); - this.password = password; - return this; - } + /** + * Populates the password. This attribute is required. + * + * @param password the password. Cannot be null. + * @return the {@link UserDetailsBuilder} for method chaining (i.e. to populate + * additional attributes for this user) + */ + public UserDetailsBuilder password(String password) { + Assert.notNull(password, "password cannot be null"); + this.password = password; + return this; + } - /** - * Populates the roles. This method is a shortcut for calling {@link #authorities(String...)}, but automatically - * prefixes each entry with "ROLE_". This means the following: - * - * - * builder.roles("USER","ADMIN"); - * - * - * is equivalent to - * - * - * builder.authorities("ROLE_USER","ROLE_ADMIN"); - * - * - *

This attribute is required, but can also be populated with {@link #authorities(String...)}.

- * - * @param roles the roles for this user (i.e. USER, ADMIN, etc). Cannot be null, contain null values or start - * with "ROLE_" - * @return the {@link UserDetailsBuilder} for method chaining (i.e. to populate additional attributes for this - * user) - */ - public UserDetailsBuilder roles(String... roles) { - List authorities = new ArrayList(roles.length); - for(String role : roles) { - Assert.isTrue(!role.startsWith("ROLE_"), role + " cannot start with ROLE_ (it is automatically added)"); - authorities.add(new SimpleGrantedAuthority("ROLE_"+role)); - } - return authorities(authorities); - } + /** + * Populates the roles. This method is a shortcut for calling + * {@link #authorities(String...)}, but automatically prefixes each entry with + * "ROLE_". This means the following: + * + * + * builder.roles("USER","ADMIN"); + * + * + * is equivalent to + * + * + * builder.authorities("ROLE_USER","ROLE_ADMIN"); + * + * + *

+ * This attribute is required, but can also be populated with + * {@link #authorities(String...)}. + *

+ * + * @param roles the roles for this user (i.e. USER, ADMIN, etc). Cannot be null, + * contain null values or start with "ROLE_" + * @return the {@link UserDetailsBuilder} for method chaining (i.e. to populate + * additional attributes for this user) + */ + public UserDetailsBuilder roles(String... roles) { + List authorities = new ArrayList( + roles.length); + for (String role : roles) { + Assert.isTrue(!role.startsWith("ROLE_"), role + + " cannot start with ROLE_ (it is automatically added)"); + authorities.add(new SimpleGrantedAuthority("ROLE_" + role)); + } + return authorities(authorities); + } - /** - * Populates the authorities. This attribute is required. - * - * @param authorities the authorities for this user. Cannot be null, or contain null - * values - * @return the {@link UserDetailsBuilder} for method chaining (i.e. to populate additional attributes for this - * user) - * @see #roles(String...) - */ - public UserDetailsBuilder authorities(GrantedAuthority...authorities) { - return authorities(Arrays.asList(authorities)); - } + /** + * Populates the authorities. This attribute is required. + * + * @param authorities the authorities for this user. Cannot be null, or contain + * null values + * @return the {@link UserDetailsBuilder} for method chaining (i.e. to populate + * additional attributes for this user) + * @see #roles(String...) + */ + public UserDetailsBuilder authorities(GrantedAuthority... authorities) { + return authorities(Arrays.asList(authorities)); + } - /** - * Populates the authorities. This attribute is required. - * - * @param authorities the authorities for this user. Cannot be null, or contain null - * values - * @return the {@link UserDetailsBuilder} for method chaining (i.e. to populate additional attributes for this - * user) - * @see #roles(String...) - */ - public UserDetailsBuilder authorities(List authorities) { - this.authorities = new ArrayList(authorities); - return this; - } + /** + * Populates the authorities. This attribute is required. + * + * @param authorities the authorities for this user. Cannot be null, or contain + * null values + * @return the {@link UserDetailsBuilder} for method chaining (i.e. to populate + * additional attributes for this user) + * @see #roles(String...) + */ + public UserDetailsBuilder authorities(List authorities) { + this.authorities = new ArrayList(authorities); + return this; + } - /** - * Populates the authorities. This attribute is required. - * - * @param authorities the authorities for this user (i.e. ROLE_USER, ROLE_ADMIN, etc). Cannot be null, or contain null - * values - * @return the {@link UserDetailsBuilder} for method chaining (i.e. to populate additional attributes for this - * user) - * @see #roles(String...) - */ - public UserDetailsBuilder authorities(String... authorities) { - return authorities(AuthorityUtils.createAuthorityList(authorities)); - } + /** + * Populates the authorities. This attribute is required. + * + * @param authorities the authorities for this user (i.e. ROLE_USER, ROLE_ADMIN, + * etc). Cannot be null, or contain null values + * @return the {@link UserDetailsBuilder} for method chaining (i.e. to populate + * additional attributes for this user) + * @see #roles(String...) + */ + public UserDetailsBuilder authorities(String... authorities) { + return authorities(AuthorityUtils.createAuthorityList(authorities)); + } - /** - * Defines if the account is expired or not. Default is false. - * - * @param accountExpired true if the account is expired, false otherwise - * @return the {@link UserDetailsBuilder} for method chaining (i.e. to populate additional attributes for this - * user) - */ - public UserDetailsBuilder accountExpired(boolean accountExpired) { - this.accountExpired = accountExpired; - return this; - } + /** + * Defines if the account is expired or not. Default is false. + * + * @param accountExpired true if the account is expired, false otherwise + * @return the {@link UserDetailsBuilder} for method chaining (i.e. to populate + * additional attributes for this user) + */ + public UserDetailsBuilder accountExpired(boolean accountExpired) { + this.accountExpired = accountExpired; + return this; + } - /** - * Defines if the account is locked or not. Default is false. - * - * @param accountLocked true if the account is locked, false otherwise - * @return the {@link UserDetailsBuilder} for method chaining (i.e. to populate additional attributes for this - * user) - */ - public UserDetailsBuilder accountLocked(boolean accountLocked) { - this.accountLocked = accountLocked; - return this; - } + /** + * Defines if the account is locked or not. Default is false. + * + * @param accountLocked true if the account is locked, false otherwise + * @return the {@link UserDetailsBuilder} for method chaining (i.e. to populate + * additional attributes for this user) + */ + public UserDetailsBuilder accountLocked(boolean accountLocked) { + this.accountLocked = accountLocked; + return this; + } - /** - * Defines if the credentials are expired or not. Default is false. - * - * @param credentialsExpired true if the credentials are expired, false otherwise - * @return the {@link UserDetailsBuilder} for method chaining (i.e. to populate additional attributes for this - * user) - */ - public UserDetailsBuilder credentialsExpired(boolean credentialsExpired) { - this.credentialsExpired = credentialsExpired; - return this; - } + /** + * Defines if the credentials are expired or not. Default is false. + * + * @param credentialsExpired true if the credentials are expired, false otherwise + * @return the {@link UserDetailsBuilder} for method chaining (i.e. to populate + * additional attributes for this user) + */ + public UserDetailsBuilder credentialsExpired(boolean credentialsExpired) { + this.credentialsExpired = credentialsExpired; + return this; + } + /** + * Defines if the account is disabled or not. Default is false. + * + * @param disabled true if the account is disabled, false otherwise + * @return the {@link UserDetailsBuilder} for method chaining (i.e. to populate + * additional attributes for this user) + */ + public UserDetailsBuilder disabled(boolean disabled) { + this.disabled = disabled; + return this; + } - /** - * Defines if the account is disabled or not. Default is false. - * - * @param disabled true if the account is disabled, false otherwise - * @return the {@link UserDetailsBuilder} for method chaining (i.e. to populate additional attributes for this - * user) - */ - public UserDetailsBuilder disabled(boolean disabled) { - this.disabled = disabled; - return this; - } - - private UserDetails build() { - return new User(username, password, !disabled, !accountExpired, - !credentialsExpired, !accountLocked, authorities); - } - } + private UserDetails build() { + return new User(username, password, !disabled, !accountExpired, + !credentialsExpired, !accountLocked, authorities); + } + } } diff --git a/config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/userdetails/AbstractDaoAuthenticationConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/userdetails/AbstractDaoAuthenticationConfigurer.java index cc30dd96a2..218042465c 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/userdetails/AbstractDaoAuthenticationConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/userdetails/AbstractDaoAuthenticationConfigurer.java @@ -34,75 +34,77 @@ import org.springframework.security.crypto.password.PasswordEncoder; * @param The type of {@link UserDetailsService} that is being used * */ -abstract class AbstractDaoAuthenticationConfigurer, C extends AbstractDaoAuthenticationConfigurer,U extends UserDetailsService> extends UserDetailsAwareConfigurer { - private DaoAuthenticationProvider provider = new DaoAuthenticationProvider(); - private final U userDetailsService; +abstract class AbstractDaoAuthenticationConfigurer, C extends AbstractDaoAuthenticationConfigurer, U extends UserDetailsService> + extends UserDetailsAwareConfigurer { + private DaoAuthenticationProvider provider = new DaoAuthenticationProvider(); + private final U userDetailsService; - /** - * Creates a new instance - * - * @param userDetailsService - */ - protected AbstractDaoAuthenticationConfigurer(U userDetailsService) { - this.userDetailsService = userDetailsService; - provider.setUserDetailsService(userDetailsService); - } + /** + * Creates a new instance + * + * @param userDetailsService + */ + protected AbstractDaoAuthenticationConfigurer(U userDetailsService) { + this.userDetailsService = userDetailsService; + provider.setUserDetailsService(userDetailsService); + } - /** - * Adds an {@link ObjectPostProcessor} for this class. - * - * @param objectPostProcessor - * @return the {@link AbstractDaoAuthenticationConfigurer} for further customizations - */ - @SuppressWarnings("unchecked") - public C withObjectPostProcessor(ObjectPostProcessor objectPostProcessor) { - addObjectPostProcessor(objectPostProcessor); - return (C) this; - } + /** + * Adds an {@link ObjectPostProcessor} for this class. + * + * @param objectPostProcessor + * @return the {@link AbstractDaoAuthenticationConfigurer} for further customizations + */ + @SuppressWarnings("unchecked") + public C withObjectPostProcessor(ObjectPostProcessor objectPostProcessor) { + addObjectPostProcessor(objectPostProcessor); + return (C) this; + } - /** - * Allows specifying the {@link PasswordEncoder} to use with the {@link DaoAuthenticationProvider}. The default is - * is to use plain text. - * - * @param passwordEncoder The {@link PasswordEncoder} to use. - * @return - */ - @SuppressWarnings("unchecked") - public C passwordEncoder(PasswordEncoder passwordEncoder) { - provider.setPasswordEncoder(passwordEncoder); - return (C) this; - } + /** + * Allows specifying the {@link PasswordEncoder} to use with the + * {@link DaoAuthenticationProvider}. The default is is to use plain text. + * + * @param passwordEncoder The {@link PasswordEncoder} to use. + * @return + */ + @SuppressWarnings("unchecked") + public C passwordEncoder(PasswordEncoder passwordEncoder) { + provider.setPasswordEncoder(passwordEncoder); + return (C) this; + } - /** - * Allows specifying the - * {@link org.springframework.security.authentication.encoding.PasswordEncoder} - * to use with the {@link DaoAuthenticationProvider}. The default is is to - * use plain text. - * - * @param passwordEncoder - * The - * {@link org.springframework.security.authentication.encoding.PasswordEncoder} - * to use. - * @return the {@link SecurityConfigurer} for further customizations - */ - @SuppressWarnings("unchecked") - public C passwordEncoder(org.springframework.security.authentication.encoding.PasswordEncoder passwordEncoder) { - provider.setPasswordEncoder(passwordEncoder); - return (C) this; - } + /** + * Allows specifying the + * {@link org.springframework.security.authentication.encoding.PasswordEncoder} to use + * with the {@link DaoAuthenticationProvider}. The default is is to use plain text. + * + * @param passwordEncoder The + * {@link org.springframework.security.authentication.encoding.PasswordEncoder} to + * use. + * @return the {@link SecurityConfigurer} for further customizations + */ + @SuppressWarnings("unchecked") + public C passwordEncoder( + org.springframework.security.authentication.encoding.PasswordEncoder passwordEncoder) { + provider.setPasswordEncoder(passwordEncoder); + return (C) this; + } - @Override - public void configure(B builder) throws Exception { - provider = postProcess(provider); - builder.authenticationProvider(provider); - } + @Override + public void configure(B builder) throws Exception { + provider = postProcess(provider); + builder.authenticationProvider(provider); + } - /** - * Gets the {@link UserDetailsService} that is used with the {@link DaoAuthenticationProvider} - * - * @return the {@link UserDetailsService} that is used with the {@link DaoAuthenticationProvider} - */ - public U getUserDetailsService() { - return userDetailsService; - } + /** + * Gets the {@link UserDetailsService} that is used with the + * {@link DaoAuthenticationProvider} + * + * @return the {@link UserDetailsService} that is used with the + * {@link DaoAuthenticationProvider} + */ + public U getUserDetailsService() { + return userDetailsService; + } } diff --git a/config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/userdetails/DaoAuthenticationConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/userdetails/DaoAuthenticationConfigurer.java index 241d7545b3..1ec228b430 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/userdetails/DaoAuthenticationConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/userdetails/DaoAuthenticationConfigurer.java @@ -20,22 +20,24 @@ import org.springframework.security.config.annotation.authentication.ProviderMan import org.springframework.security.core.userdetails.UserDetailsService; /** -* Allows configuring a {@link DaoAuthenticationProvider} -* -* @author Rob Winch -* @since 3.2 -* -* @param The type of {@link ProviderManagerBuilder} this is -* @param The type of {@link UserDetailsService} that is being used -* -*/ -public class DaoAuthenticationConfigurer, U extends UserDetailsService> extends AbstractDaoAuthenticationConfigurer, U>{ + * Allows configuring a {@link DaoAuthenticationProvider} + * + * @author Rob Winch + * @since 3.2 + * + * @param The type of {@link ProviderManagerBuilder} this is + * @param The type of {@link UserDetailsService} that is being used + * + */ +public class DaoAuthenticationConfigurer, U extends UserDetailsService> + extends + AbstractDaoAuthenticationConfigurer, U> { - /** - * Creates a new instance - * @param userDetailsService - */ - public DaoAuthenticationConfigurer(U userDetailsService) { - super(userDetailsService); - } + /** + * Creates a new instance + * @param userDetailsService + */ + public DaoAuthenticationConfigurer(U userDetailsService) { + super(userDetailsService); + } } diff --git a/config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/userdetails/UserDetailsAwareConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/userdetails/UserDetailsAwareConfigurer.java index df19842056..8cd1852336 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/userdetails/UserDetailsAwareConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/userdetails/UserDetailsAwareConfigurer.java @@ -22,18 +22,20 @@ import org.springframework.security.config.annotation.authentication.builders.Au import org.springframework.security.core.userdetails.UserDetailsService; /** - * Base class that allows access to the {@link UserDetailsService} for using as a default value with {@link AuthenticationManagerBuilder}. + * Base class that allows access to the {@link UserDetailsService} for using as a default + * value with {@link AuthenticationManagerBuilder}. * * @author Rob Winch * * @param the type of the {@link ProviderManagerBuilder} * @param the type of {@link UserDetailsService} */ -public abstract class UserDetailsAwareConfigurer, U extends UserDetailsService> extends SecurityConfigurerAdapter { +public abstract class UserDetailsAwareConfigurer, U extends UserDetailsService> + extends SecurityConfigurerAdapter { - /** - * Gets the {@link UserDetailsService} or null if it is not available - * @return the {@link UserDetailsService} or null if it is not available - */ - public abstract U getUserDetailsService(); + /** + * Gets the {@link UserDetailsService} or null if it is not available + * @return the {@link UserDetailsService} or null if it is not available + */ + public abstract U getUserDetailsService(); } diff --git a/config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/userdetails/UserDetailsServiceConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/userdetails/UserDetailsServiceConfigurer.java index c37c49bd03..f29174b59a 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/userdetails/UserDetailsServiceConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/userdetails/UserDetailsServiceConfigurer.java @@ -21,38 +21,39 @@ import org.springframework.security.config.annotation.authentication.builders.Au import org.springframework.security.core.userdetails.UserDetailsService; /** - * Allows configuring a {@link UserDetailsService} within a {@link AuthenticationManagerBuilder}. + * Allows configuring a {@link UserDetailsService} within a + * {@link AuthenticationManagerBuilder}. * * @author Rob Winch * @since 3.2 * * @param the type of the {@link SecurityBuilder} * @param the {@link SecurityConfigurer} (or this) - * @param the type of UserDetailsService being used to allow for returning the concrete UserDetailsService. + * @param the type of UserDetailsService being used to allow for returning the + * concrete UserDetailsService. */ -public class UserDetailsServiceConfigurer, - C extends UserDetailsServiceConfigurer, - U extends UserDetailsService> - extends AbstractDaoAuthenticationConfigurer { +public class UserDetailsServiceConfigurer, C extends UserDetailsServiceConfigurer, U extends UserDetailsService> + extends AbstractDaoAuthenticationConfigurer { - /** - * Creates a new instance - * @param userDetailsService the {@link UserDetailsService} that should be used - */ - public UserDetailsServiceConfigurer(U userDetailsService) { - super(userDetailsService); - } + /** + * Creates a new instance + * @param userDetailsService the {@link UserDetailsService} that should be used + */ + public UserDetailsServiceConfigurer(U userDetailsService) { + super(userDetailsService); + } - @Override - public void configure(B builder) throws Exception { - initUserDetailsService(); + @Override + public void configure(B builder) throws Exception { + initUserDetailsService(); - super.configure(builder); - } + super.configure(builder); + } - /** - * Allows subclasses to initialize the {@link UserDetailsService}. For example, it might add users, initialize - * schema, etc. - */ - protected void initUserDetailsService() throws Exception {} + /** + * Allows subclasses to initialize the {@link UserDetailsService}. For example, it + * might add users, initialize schema, etc. + */ + protected void initUserDetailsService() throws Exception { + } } diff --git a/config/src/main/java/org/springframework/security/config/annotation/configuration/AutowireBeanFactoryObjectPostProcessor.java b/config/src/main/java/org/springframework/security/config/annotation/configuration/AutowireBeanFactoryObjectPostProcessor.java index df520f3578..218d4d6853 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/configuration/AutowireBeanFactoryObjectPostProcessor.java +++ b/config/src/main/java/org/springframework/security/config/annotation/configuration/AutowireBeanFactoryObjectPostProcessor.java @@ -28,58 +28,67 @@ import org.springframework.security.config.annotation.ObjectPostProcessor; import org.springframework.util.Assert; /** - * Allows registering Objects to participate with an - * {@link AutowireCapableBeanFactory}'s post processing of {@link Aware} - * methods, {@link InitializingBean#afterPropertiesSet()}, and - * {@link DisposableBean#destroy()}. + * Allows registering Objects to participate with an {@link AutowireCapableBeanFactory}'s + * post processing of {@link Aware} methods, {@link InitializingBean#afterPropertiesSet()} + * , and {@link DisposableBean#destroy()}. * * @author Rob Winch * @since 3.2 */ -final class AutowireBeanFactoryObjectPostProcessor implements ObjectPostProcessor, DisposableBean { - private final Log logger = LogFactory.getLog(getClass()); - private final AutowireCapableBeanFactory autowireBeanFactory; - private final List disposableBeans = new ArrayList(); +final class AutowireBeanFactoryObjectPostProcessor implements + ObjectPostProcessor, DisposableBean { + private final Log logger = LogFactory.getLog(getClass()); + private final AutowireCapableBeanFactory autowireBeanFactory; + private final List disposableBeans = new ArrayList(); - public AutowireBeanFactoryObjectPostProcessor( - AutowireCapableBeanFactory autowireBeanFactory) { - Assert.notNull(autowireBeanFactory, "autowireBeanFactory cannot be null"); - this.autowireBeanFactory = autowireBeanFactory; - } + public AutowireBeanFactoryObjectPostProcessor( + AutowireCapableBeanFactory autowireBeanFactory) { + Assert.notNull(autowireBeanFactory, "autowireBeanFactory cannot be null"); + this.autowireBeanFactory = autowireBeanFactory; + } - /* (non-Javadoc) - * @see org.springframework.security.config.annotation.web.Initializer#initialize(java.lang.Object) - */ - @SuppressWarnings("unchecked") - public T postProcess(T object) { - if(object == null) { - return null; - } - T result = null; - try { - result = (T) autowireBeanFactory.initializeBean(object, object.toString()); - } catch (RuntimeException e) { - Class type = object.getClass(); - throw new RuntimeException("Could not postProcess " + object + " of type " + type, e); - } - autowireBeanFactory.autowireBean(object); - if(result instanceof DisposableBean) { - disposableBeans.add((DisposableBean) result); - } - return result; - } + /* + * (non-Javadoc) + * + * @see + * org.springframework.security.config.annotation.web.Initializer#initialize(java. + * lang.Object) + */ + @SuppressWarnings("unchecked") + public T postProcess(T object) { + if (object == null) { + return null; + } + T result = null; + try { + result = (T) autowireBeanFactory.initializeBean(object, object.toString()); + } + catch (RuntimeException e) { + Class type = object.getClass(); + throw new RuntimeException("Could not postProcess " + object + " of type " + + type, e); + } + autowireBeanFactory.autowireBean(object); + if (result instanceof DisposableBean) { + disposableBeans.add((DisposableBean) result); + } + return result; + } - /* (non-Javadoc) - * @see org.springframework.beans.factory.DisposableBean#destroy() - */ - public void destroy() throws Exception { - for(DisposableBean disposable : disposableBeans) { - try { - disposable.destroy(); - } catch(Exception error) { - logger.error(error); - } - } - } + /* + * (non-Javadoc) + * + * @see org.springframework.beans.factory.DisposableBean#destroy() + */ + public void destroy() throws Exception { + for (DisposableBean disposable : disposableBeans) { + try { + disposable.destroy(); + } + catch (Exception error) { + logger.error(error); + } + } + } } diff --git a/config/src/main/java/org/springframework/security/config/annotation/configuration/ObjectPostProcessorConfiguration.java b/config/src/main/java/org/springframework/security/config/annotation/configuration/ObjectPostProcessorConfiguration.java index ee3f200e9c..745dd9e8d0 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/configuration/ObjectPostProcessorConfiguration.java +++ b/config/src/main/java/org/springframework/security/config/annotation/configuration/ObjectPostProcessorConfiguration.java @@ -23,10 +23,9 @@ import org.springframework.security.config.annotation.method.configuration.Enabl import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; /** - * Spring {@link Configuration} that exports the default - * {@link ObjectPostProcessor}. This class is not intended to be imported - * manually rather it is imported automatically when using - * {@link EnableWebSecurity} or {@link EnableGlobalMethodSecurity}. + * Spring {@link Configuration} that exports the default {@link ObjectPostProcessor}. This + * class is not intended to be imported manually rather it is imported automatically when + * using {@link EnableWebSecurity} or {@link EnableGlobalMethodSecurity}. * * @see EnableWebSecurity * @see EnableGlobalMethodSecurity @@ -37,8 +36,9 @@ import org.springframework.security.config.annotation.web.configuration.EnableWe @Configuration public class ObjectPostProcessorConfiguration { - @Bean - public ObjectPostProcessor objectPostProcessor(AutowireCapableBeanFactory beanFactory) { - return new AutowireBeanFactoryObjectPostProcessor(beanFactory); - } + @Bean + public ObjectPostProcessor objectPostProcessor( + AutowireCapableBeanFactory beanFactory) { + return new AutowireBeanFactoryObjectPostProcessor(beanFactory); + } } diff --git a/config/src/main/java/org/springframework/security/config/annotation/method/configuration/EnableGlobalMethodSecurity.java b/config/src/main/java/org/springframework/security/config/annotation/method/configuration/EnableGlobalMethodSecurity.java index e22327ab7b..d76d289497 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/method/configuration/EnableGlobalMethodSecurity.java +++ b/config/src/main/java/org/springframework/security/config/annotation/method/configuration/EnableGlobalMethodSecurity.java @@ -28,78 +28,83 @@ import org.springframework.security.config.annotation.authentication.configurati import org.springframework.security.config.annotation.configuration.ObjectPostProcessorConfiguration; /** - *

Enables Spring Security global method security similar to the - * xml support.

+ *

+ * Enables Spring Security global method security similar to the + * xml support. + *

* *

* More advanced configurations may wish to extend - * {@link GlobalMethodSecurityConfiguration} and override the protected methods - * to provide custom implementations. Note that - * {@link EnableGlobalMethodSecurity} still must be included on the class - * extending {@link GlobalMethodSecurityConfiguration} to determine the - * settings. + * {@link GlobalMethodSecurityConfiguration} and override the protected methods to provide + * custom implementations. Note that {@link EnableGlobalMethodSecurity} still must be + * included on the class extending {@link GlobalMethodSecurityConfiguration} to determine + * the settings. * * @author Rob Winch * @since 3.2 */ -@Retention(value=java.lang.annotation.RetentionPolicy.RUNTIME) -@Target(value={java.lang.annotation.ElementType.TYPE}) +@Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME) +@Target(value = { java.lang.annotation.ElementType.TYPE }) @Documented -@Import({GlobalMethodSecuritySelector.class,ObjectPostProcessorConfiguration.class}) +@Import({ GlobalMethodSecuritySelector.class, ObjectPostProcessorConfiguration.class }) @EnableGlobalAuthentication @Configuration public @interface EnableGlobalMethodSecurity { - /** - * Determines if Spring Security's pre post annotations should be enabled. Default is false. - * @return true if pre post annotations should be enabled false otherwise. - */ - boolean prePostEnabled() default false; + /** + * Determines if Spring Security's pre post annotations should be enabled. Default is + * false. + * @return true if pre post annotations should be enabled false otherwise. + */ + boolean prePostEnabled() default false; - /** - * Determines if Spring Security's {@link Secured} annotations should be enabled. - * @return true if {@link Secured} annotations should be enabled false otherwise. Default is false. - */ - boolean securedEnabled() default false; + /** + * Determines if Spring Security's {@link Secured} annotations should be enabled. + * @return true if {@link Secured} annotations should be enabled false otherwise. + * Default is false. + */ + boolean securedEnabled() default false; - /** - * Determines if JSR-250 annotations should be enabled. Default is false. - * @return true if JSR-250 should be enabled false otherwise. - */ - boolean jsr250Enabled() default false; + /** + * Determines if JSR-250 annotations should be enabled. Default is false. + * @return true if JSR-250 should be enabled false otherwise. + */ + boolean jsr250Enabled() default false; - /** - * Indicate whether subclass-based (CGLIB) proxies are to be created ({@code true}) as - * opposed to standard Java interface-based proxies ({@code false}). The default is - * {@code false}. Applicable only if {@link #mode()} is set to - * {@link AdviceMode#PROXY}. - * - *

Note that setting this attribute to {@code true} will affect all - * Spring-managed beans requiring proxying, not just those marked with - * the Security annotations. For example, other beans marked with Spring's - * {@code @Transactional} annotation will be upgraded to subclass proxying at the same - * time. This approach has no negative impact in practice unless one is explicitly - * expecting one type of proxy vs another, e.g. in tests. - * - * @return true if CGILIB proxies should be created instead of interface based proxies, else false - */ - boolean proxyTargetClass() default false; + /** + * Indicate whether subclass-based (CGLIB) proxies are to be created ({@code true}) as + * opposed to standard Java interface-based proxies ({@code false}). The default is + * {@code false}. Applicable only if {@link #mode()} is set to + * {@link AdviceMode#PROXY}. + * + *

+ * Note that setting this attribute to {@code true} will affect all + * Spring-managed beans requiring proxying, not just those marked with the Security + * annotations. For example, other beans marked with Spring's {@code @Transactional} + * annotation will be upgraded to subclass proxying at the same time. This approach + * has no negative impact in practice unless one is explicitly expecting one type of + * proxy vs another, e.g. in tests. + * + * @return true if CGILIB proxies should be created instead of interface based + * proxies, else false + */ + boolean proxyTargetClass() default false; - /** - * Indicate how security advice should be applied. The default is - * {@link AdviceMode#PROXY}. - * @see AdviceMode - * - * @return the {@link AdviceMode} to use - */ - AdviceMode mode() default AdviceMode.PROXY; + /** + * Indicate how security advice should be applied. The default is + * {@link AdviceMode#PROXY}. + * @see AdviceMode + * + * @return the {@link AdviceMode} to use + */ + AdviceMode mode() default AdviceMode.PROXY; - /** - * Indicate the ordering of the execution of the security advisor - * when multiple advices are applied at a specific joinpoint. - * The default is {@link Ordered#LOWEST_PRECEDENCE}. - * - * @return the order the security advisor should be applied - */ - int order() default Ordered.LOWEST_PRECEDENCE; + /** + * Indicate the ordering of the execution of the security advisor when multiple + * advices are applied at a specific joinpoint. The default is + * {@link Ordered#LOWEST_PRECEDENCE}. + * + * @return the order the security advisor should be applied + */ + int order() default Ordered.LOWEST_PRECEDENCE; } diff --git a/config/src/main/java/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityAspectJAutoProxyRegistrar.java b/config/src/main/java/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityAspectJAutoProxyRegistrar.java index 811c452e6f..f1a7cbae9c 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityAspectJAutoProxyRegistrar.java +++ b/config/src/main/java/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityAspectJAutoProxyRegistrar.java @@ -41,26 +41,27 @@ import org.springframework.core.type.AnnotationMetadata; * @since 3.2 */ class GlobalMethodSecurityAspectJAutoProxyRegistrar implements - ImportBeanDefinitionRegistrar { + ImportBeanDefinitionRegistrar { - /** - * Register, escalate, and configure the AspectJ auto proxy creator based on - * the value of the @{@link EnableGlobalMethodSecurity#proxyTargetClass()} - * attribute on the importing {@code @Configuration} class. - */ - public void registerBeanDefinitions( - AnnotationMetadata importingClassMetadata, - BeanDefinitionRegistry registry) { + /** + * Register, escalate, and configure the AspectJ auto proxy creator based on the value + * of the @{@link EnableGlobalMethodSecurity#proxyTargetClass()} attribute on the + * importing {@code @Configuration} class. + */ + public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, + BeanDefinitionRegistry registry) { - BeanDefinition interceptor = registry.getBeanDefinition("methodSecurityInterceptor"); + BeanDefinition interceptor = registry + .getBeanDefinition("methodSecurityInterceptor"); - BeanDefinitionBuilder aspect = - BeanDefinitionBuilder.rootBeanDefinition("org.springframework.security.access.intercept.aspectj.aspect.AnnotationSecurityAspect"); - aspect.setFactoryMethod("aspectOf"); - aspect.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); - aspect.addPropertyValue("securityInterceptor", interceptor); + BeanDefinitionBuilder aspect = BeanDefinitionBuilder + .rootBeanDefinition("org.springframework.security.access.intercept.aspectj.aspect.AnnotationSecurityAspect"); + aspect.setFactoryMethod("aspectOf"); + aspect.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); + aspect.addPropertyValue("securityInterceptor", interceptor); - registry.registerBeanDefinition("annotationSecurityAspect$0", aspect.getBeanDefinition()); - } + registry.registerBeanDefinition("annotationSecurityAspect$0", + aspect.getBeanDefinition()); + } } \ No newline at end of file diff --git a/config/src/main/java/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityConfiguration.java b/config/src/main/java/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityConfiguration.java index b4892e6da5..f417fd99c4 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityConfiguration.java +++ b/config/src/main/java/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityConfiguration.java @@ -65,8 +65,8 @@ import org.springframework.security.config.annotation.authentication.configurati import org.springframework.util.Assert; /** - * Base {@link Configuration} for enabling global method security. Classes may - * extend this class to customize the defaults, but must be sure to specify the + * Base {@link Configuration} for enabling global method security. Classes may extend this + * class to customize the defaults, but must be sure to specify the * {@link EnableGlobalMethodSecurity} annotation on the subclass. * * @author Rob Winch @@ -75,339 +75,352 @@ import org.springframework.util.Assert; */ @Configuration public class GlobalMethodSecurityConfiguration implements ImportAware { - private static final Log logger = LogFactory.getLog(GlobalMethodSecurityConfiguration.class); - private ObjectPostProcessor objectPostProcessor = new ObjectPostProcessor() { - public T postProcess(T object) { - throw new IllegalStateException(ObjectPostProcessor.class.getName()+ " is a required bean. Ensure you have used @"+EnableGlobalMethodSecurity.class.getName()); - } - }; - private DefaultMethodSecurityExpressionHandler defaultMethodExpressionHandler = new DefaultMethodSecurityExpressionHandler(); - private AuthenticationManager authenticationManager; - private AuthenticationManagerBuilder auth; - private boolean disableAuthenticationRegistry; - private AnnotationAttributes enableMethodSecurity; - private ApplicationContext context; - private MethodSecurityExpressionHandler expressionHandler; - private Jsr250MethodSecurityMetadataSource jsr250MethodSecurityMetadataSource; + private static final Log logger = LogFactory + .getLog(GlobalMethodSecurityConfiguration.class); + private ObjectPostProcessor objectPostProcessor = new ObjectPostProcessor() { + public T postProcess(T object) { + throw new IllegalStateException(ObjectPostProcessor.class.getName() + + " is a required bean. Ensure you have used @" + + EnableGlobalMethodSecurity.class.getName()); + } + }; + private DefaultMethodSecurityExpressionHandler defaultMethodExpressionHandler = new DefaultMethodSecurityExpressionHandler(); + private AuthenticationManager authenticationManager; + private AuthenticationManagerBuilder auth; + private boolean disableAuthenticationRegistry; + private AnnotationAttributes enableMethodSecurity; + private ApplicationContext context; + private MethodSecurityExpressionHandler expressionHandler; + private Jsr250MethodSecurityMetadataSource jsr250MethodSecurityMetadataSource; - /** - * Creates the default MethodInterceptor which is a MethodSecurityInterceptor using the following methods to - * construct it. - *
    - *
  • {@link #accessDecisionManager()}
  • - *
  • {@link #afterInvocationManager()}
  • - *
  • {@link #authenticationManager()}
  • - *
  • {@link #methodSecurityMetadataSource()}
  • - *
  • {@link #runAsManager()}
  • - * - *
- * - *

- * Subclasses can override this method to provide a different {@link MethodInterceptor}. - *

- * - * @return - * @throws Exception - */ - @Bean - public MethodInterceptor methodSecurityInterceptor() throws Exception { - MethodSecurityInterceptor methodSecurityInterceptor = isAspectJ() ? new AspectJMethodSecurityInterceptor() : new MethodSecurityInterceptor(); - methodSecurityInterceptor - .setAccessDecisionManager(accessDecisionManager()); - methodSecurityInterceptor - .setAfterInvocationManager(afterInvocationManager()); - methodSecurityInterceptor - .setAuthenticationManager(authenticationManager()); - methodSecurityInterceptor - .setSecurityMetadataSource(methodSecurityMetadataSource()); - RunAsManager runAsManager = runAsManager(); - if (runAsManager != null) { - methodSecurityInterceptor.setRunAsManager(runAsManager); - } - return methodSecurityInterceptor; - } + /** + * Creates the default MethodInterceptor which is a MethodSecurityInterceptor using + * the following methods to construct it. + *
    + *
  • {@link #accessDecisionManager()}
  • + *
  • {@link #afterInvocationManager()}
  • + *
  • {@link #authenticationManager()}
  • + *
  • {@link #methodSecurityMetadataSource()}
  • + *
  • {@link #runAsManager()}
  • + * + *
+ * + *

+ * Subclasses can override this method to provide a different + * {@link MethodInterceptor}. + *

+ * + * @return + * @throws Exception + */ + @Bean + public MethodInterceptor methodSecurityInterceptor() throws Exception { + MethodSecurityInterceptor methodSecurityInterceptor = isAspectJ() ? new AspectJMethodSecurityInterceptor() + : new MethodSecurityInterceptor(); + methodSecurityInterceptor.setAccessDecisionManager(accessDecisionManager()); + methodSecurityInterceptor.setAfterInvocationManager(afterInvocationManager()); + methodSecurityInterceptor.setAuthenticationManager(authenticationManager()); + methodSecurityInterceptor + .setSecurityMetadataSource(methodSecurityMetadataSource()); + RunAsManager runAsManager = runAsManager(); + if (runAsManager != null) { + methodSecurityInterceptor.setRunAsManager(runAsManager); + } + return methodSecurityInterceptor; + } - /** - * Provide a custom {@link AfterInvocationManager} for the default - * implementation of {@link #methodSecurityInterceptor()}. The default is - * null if pre post is not enabled. Otherwise, it returns a {@link AfterInvocationProviderManager}. - * - *

- * Subclasses should override this method to provide a custom {@link AfterInvocationManager} - *

- * - * @return - */ - protected AfterInvocationManager afterInvocationManager() { - if(prePostEnabled()) { - AfterInvocationProviderManager invocationProviderManager = new AfterInvocationProviderManager(); - ExpressionBasedPostInvocationAdvice postAdvice = new ExpressionBasedPostInvocationAdvice(getExpressionHandler()); - PostInvocationAdviceProvider postInvocationAdviceProvider = new PostInvocationAdviceProvider(postAdvice); - List afterInvocationProviders = new ArrayList(); - afterInvocationProviders.add(postInvocationAdviceProvider); - invocationProviderManager.setProviders(afterInvocationProviders); - return invocationProviderManager; - } - return null; - } + /** + * Provide a custom {@link AfterInvocationManager} for the default implementation of + * {@link #methodSecurityInterceptor()}. The default is null if pre post is not + * enabled. Otherwise, it returns a {@link AfterInvocationProviderManager}. + * + *

+ * Subclasses should override this method to provide a custom + * {@link AfterInvocationManager} + *

+ * + * @return + */ + protected AfterInvocationManager afterInvocationManager() { + if (prePostEnabled()) { + AfterInvocationProviderManager invocationProviderManager = new AfterInvocationProviderManager(); + ExpressionBasedPostInvocationAdvice postAdvice = new ExpressionBasedPostInvocationAdvice( + getExpressionHandler()); + PostInvocationAdviceProvider postInvocationAdviceProvider = new PostInvocationAdviceProvider( + postAdvice); + List afterInvocationProviders = new ArrayList(); + afterInvocationProviders.add(postInvocationAdviceProvider); + invocationProviderManager.setProviders(afterInvocationProviders); + return invocationProviderManager; + } + return null; + } - /** - * Provide a custom {@link RunAsManager} for the default implementation of - * {@link #methodSecurityInterceptor()}. The default is null. - * - * @return - */ - protected RunAsManager runAsManager() { - return null; - } + /** + * Provide a custom {@link RunAsManager} for the default implementation of + * {@link #methodSecurityInterceptor()}. The default is null. + * + * @return + */ + protected RunAsManager runAsManager() { + return null; + } - /** - * Allows subclasses to provide a custom {@link AccessDecisionManager}. The default is a {@link AffirmativeBased} - * with the following voters: - * - *
    - *
  • {@link PreInvocationAuthorizationAdviceVoter}
  • - *
  • {@link RoleVoter}
  • - *
  • {@link AuthenticatedVoter}
  • - *
- * - * @return - */ - protected AccessDecisionManager accessDecisionManager() { - List> decisionVoters = new ArrayList>(); - ExpressionBasedPreInvocationAdvice expressionAdvice = new ExpressionBasedPreInvocationAdvice(); - expressionAdvice.setExpressionHandler(getExpressionHandler()); - if(prePostEnabled()) { - decisionVoters.add(new PreInvocationAuthorizationAdviceVoter( - expressionAdvice)); - } - if(jsr250Enabled()) { - decisionVoters.add(new Jsr250Voter()); - } - decisionVoters.add(new RoleVoter()); - decisionVoters.add(new AuthenticatedVoter()); - return new AffirmativeBased(decisionVoters); - } + /** + * Allows subclasses to provide a custom {@link AccessDecisionManager}. The default is + * a {@link AffirmativeBased} with the following voters: + * + *
    + *
  • {@link PreInvocationAuthorizationAdviceVoter}
  • + *
  • {@link RoleVoter}
  • + *
  • {@link AuthenticatedVoter}
  • + *
+ * + * @return + */ + protected AccessDecisionManager accessDecisionManager() { + List> decisionVoters = new ArrayList>(); + ExpressionBasedPreInvocationAdvice expressionAdvice = new ExpressionBasedPreInvocationAdvice(); + expressionAdvice.setExpressionHandler(getExpressionHandler()); + if (prePostEnabled()) { + decisionVoters + .add(new PreInvocationAuthorizationAdviceVoter(expressionAdvice)); + } + if (jsr250Enabled()) { + decisionVoters.add(new Jsr250Voter()); + } + decisionVoters.add(new RoleVoter()); + decisionVoters.add(new AuthenticatedVoter()); + return new AffirmativeBased(decisionVoters); + } - /** - * Provide a {@link MethodSecurityExpressionHandler} that is registered with - * the {@link ExpressionBasedPreInvocationAdvice}. The default is - * {@link DefaultMethodSecurityExpressionHandler} which optionally will - * Autowire an {@link AuthenticationTrustResolver}. - * - *

- * Subclasses may override this method to provide a custom - * {@link MethodSecurityExpressionHandler} - *

- * - * @return - */ - protected MethodSecurityExpressionHandler createExpressionHandler() { - return defaultMethodExpressionHandler; - } + /** + * Provide a {@link MethodSecurityExpressionHandler} that is registered with the + * {@link ExpressionBasedPreInvocationAdvice}. The default is + * {@link DefaultMethodSecurityExpressionHandler} which optionally will Autowire an + * {@link AuthenticationTrustResolver}. + * + *

+ * Subclasses may override this method to provide a custom + * {@link MethodSecurityExpressionHandler} + *

+ * + * @return + */ + protected MethodSecurityExpressionHandler createExpressionHandler() { + return defaultMethodExpressionHandler; + } - /** - * Gets the {@link MethodSecurityExpressionHandler} or creates it using {@link #expressionHandler}. - * - * @return a non {@code null} {@link MethodSecurityExpressionHandler} - */ - protected final MethodSecurityExpressionHandler getExpressionHandler() { - if(expressionHandler == null) { - expressionHandler = createExpressionHandler(); - } - return expressionHandler; - } + /** + * Gets the {@link MethodSecurityExpressionHandler} or creates it using + * {@link #expressionHandler}. + * + * @return a non {@code null} {@link MethodSecurityExpressionHandler} + */ + protected final MethodSecurityExpressionHandler getExpressionHandler() { + if (expressionHandler == null) { + expressionHandler = createExpressionHandler(); + } + return expressionHandler; + } - /** - * Provides a custom {@link MethodSecurityMetadataSource} that is registered - * with the {@link #methodSecurityMetadataSource()}. Default is null. - * - * @return a custom {@link MethodSecurityMetadataSource} that is registered - * with the {@link #methodSecurityMetadataSource()} - */ - protected MethodSecurityMetadataSource customMethodSecurityMetadataSource() { - return null; - } + /** + * Provides a custom {@link MethodSecurityMetadataSource} that is registered with the + * {@link #methodSecurityMetadataSource()}. Default is null. + * + * @return a custom {@link MethodSecurityMetadataSource} that is registered with the + * {@link #methodSecurityMetadataSource()} + */ + protected MethodSecurityMetadataSource customMethodSecurityMetadataSource() { + return null; + } - /** - * Allows providing a custom {@link AuthenticationManager}. The default is - * to use any authentication mechanisms registered by {@link #configure(AuthenticationManagerBuilder)}. If - * {@link #configure(AuthenticationManagerBuilder)} was not overridden, then an {@link AuthenticationManager} - * is attempted to be autowired by type. - * - * @return - */ - protected AuthenticationManager authenticationManager() throws Exception { - if(authenticationManager == null) { - DefaultAuthenticationEventPublisher eventPublisher = objectPostProcessor.postProcess(new DefaultAuthenticationEventPublisher()); - auth = new AuthenticationManagerBuilder(objectPostProcessor); - auth.authenticationEventPublisher(eventPublisher); - configure(auth); - if(disableAuthenticationRegistry) { - authenticationManager = getAuthenticationConfiguration().getAuthenticationManager(); - } else { - authenticationManager = auth.build(); - } - } - return authenticationManager; - } + /** + * Allows providing a custom {@link AuthenticationManager}. The default is to use any + * authentication mechanisms registered by + * {@link #configure(AuthenticationManagerBuilder)}. If + * {@link #configure(AuthenticationManagerBuilder)} was not overridden, then an + * {@link AuthenticationManager} is attempted to be autowired by type. + * + * @return + */ + protected AuthenticationManager authenticationManager() throws Exception { + if (authenticationManager == null) { + DefaultAuthenticationEventPublisher eventPublisher = objectPostProcessor + .postProcess(new DefaultAuthenticationEventPublisher()); + auth = new AuthenticationManagerBuilder(objectPostProcessor); + auth.authenticationEventPublisher(eventPublisher); + configure(auth); + if (disableAuthenticationRegistry) { + authenticationManager = getAuthenticationConfiguration() + .getAuthenticationManager(); + } + else { + authenticationManager = auth.build(); + } + } + return authenticationManager; + } - /** - * Sub classes can override this method to register different types of authentication. If not overridden, - * {@link #configure(AuthenticationManagerBuilder)} will attempt to autowire by type. - * - * @param auth the {@link AuthenticationManagerBuilder} used to register different authentication mechanisms for the - * global method security. - * @throws Exception - */ - protected void configure(AuthenticationManagerBuilder auth) throws Exception { - this.disableAuthenticationRegistry = true; - } + /** + * Sub classes can override this method to register different types of authentication. + * If not overridden, {@link #configure(AuthenticationManagerBuilder)} will attempt to + * autowire by type. + * + * @param auth the {@link AuthenticationManagerBuilder} used to register different + * authentication mechanisms for the global method security. + * @throws Exception + */ + protected void configure(AuthenticationManagerBuilder auth) throws Exception { + this.disableAuthenticationRegistry = true; + } - /** - * Provides the default {@link MethodSecurityMetadataSource} that will be - * used. It creates a {@link DelegatingMethodSecurityMetadataSource} based - * upon {@link #customMethodSecurityMetadataSource()} and the attributes on - * {@link EnableGlobalMethodSecurity}. - * - * @return - */ - @Bean - public MethodSecurityMetadataSource methodSecurityMetadataSource() { - List sources = new ArrayList(); - ExpressionBasedAnnotationAttributeFactory attributeFactory = new ExpressionBasedAnnotationAttributeFactory( - getExpressionHandler()); - MethodSecurityMetadataSource customMethodSecurityMetadataSource = customMethodSecurityMetadataSource(); - if (customMethodSecurityMetadataSource != null) { - sources.add(customMethodSecurityMetadataSource); - } - if (prePostEnabled()) { - sources.add(new PrePostAnnotationSecurityMetadataSource(attributeFactory)); - } - if (securedEnabled()) { - sources.add(new SecuredAnnotationSecurityMetadataSource()); - } - if (jsr250Enabled()) { - sources.add(jsr250MethodSecurityMetadataSource); - } - return new DelegatingMethodSecurityMetadataSource(sources); - } + /** + * Provides the default {@link MethodSecurityMetadataSource} that will be used. It + * creates a {@link DelegatingMethodSecurityMetadataSource} based upon + * {@link #customMethodSecurityMetadataSource()} and the attributes on + * {@link EnableGlobalMethodSecurity}. + * + * @return + */ + @Bean + public MethodSecurityMetadataSource methodSecurityMetadataSource() { + List sources = new ArrayList(); + ExpressionBasedAnnotationAttributeFactory attributeFactory = new ExpressionBasedAnnotationAttributeFactory( + getExpressionHandler()); + MethodSecurityMetadataSource customMethodSecurityMetadataSource = customMethodSecurityMetadataSource(); + if (customMethodSecurityMetadataSource != null) { + sources.add(customMethodSecurityMetadataSource); + } + if (prePostEnabled()) { + sources.add(new PrePostAnnotationSecurityMetadataSource(attributeFactory)); + } + if (securedEnabled()) { + sources.add(new SecuredAnnotationSecurityMetadataSource()); + } + if (jsr250Enabled()) { + sources.add(jsr250MethodSecurityMetadataSource); + } + return new DelegatingMethodSecurityMetadataSource(sources); + } - /** - * Creates the {@link PreInvocationAuthorizationAdvice} to be used. The - * default is {@link ExpressionBasedPreInvocationAdvice}. - * - * @return - */ - @Bean - public PreInvocationAuthorizationAdvice preInvocationAuthorizationAdvice() { - ExpressionBasedPreInvocationAdvice preInvocationAdvice = new ExpressionBasedPreInvocationAdvice(); - preInvocationAdvice.setExpressionHandler(getExpressionHandler()); - return preInvocationAdvice; - } + /** + * Creates the {@link PreInvocationAuthorizationAdvice} to be used. The default is + * {@link ExpressionBasedPreInvocationAdvice}. + * + * @return + */ + @Bean + public PreInvocationAuthorizationAdvice preInvocationAuthorizationAdvice() { + ExpressionBasedPreInvocationAdvice preInvocationAdvice = new ExpressionBasedPreInvocationAdvice(); + preInvocationAdvice.setExpressionHandler(getExpressionHandler()); + return preInvocationAdvice; + } - /** - * Obtains the {@link MethodSecurityMetadataSourceAdvisor} to be used. - * - * @return - */ - @Role(BeanDefinition.ROLE_INFRASTRUCTURE) - @Bean - public MethodSecurityMetadataSourceAdvisor metaDataSourceAdvisor() { - MethodSecurityMetadataSourceAdvisor methodAdvisor = new MethodSecurityMetadataSourceAdvisor( - "methodSecurityInterceptor", methodSecurityMetadataSource(), - "methodSecurityMetadataSource"); - methodAdvisor.setOrder(order()); - return methodAdvisor; - } + /** + * Obtains the {@link MethodSecurityMetadataSourceAdvisor} to be used. + * + * @return + */ + @Role(BeanDefinition.ROLE_INFRASTRUCTURE) + @Bean + public MethodSecurityMetadataSourceAdvisor metaDataSourceAdvisor() { + MethodSecurityMetadataSourceAdvisor methodAdvisor = new MethodSecurityMetadataSourceAdvisor( + "methodSecurityInterceptor", methodSecurityMetadataSource(), + "methodSecurityMetadataSource"); + methodAdvisor.setOrder(order()); + return methodAdvisor; + } - /** - * Obtains the attributes from {@link EnableGlobalMethodSecurity} if this class was imported using the {@link EnableGlobalMethodSecurity} annotation. - */ - public final void setImportMetadata(AnnotationMetadata importMetadata) { - Map annotationAttributes = importMetadata - .getAnnotationAttributes(EnableGlobalMethodSecurity.class - .getName()); - enableMethodSecurity = AnnotationAttributes - .fromMap(annotationAttributes); - } + /** + * Obtains the attributes from {@link EnableGlobalMethodSecurity} if this class was + * imported using the {@link EnableGlobalMethodSecurity} annotation. + */ + public final void setImportMetadata(AnnotationMetadata importMetadata) { + Map annotationAttributes = importMetadata + .getAnnotationAttributes(EnableGlobalMethodSecurity.class.getName()); + enableMethodSecurity = AnnotationAttributes.fromMap(annotationAttributes); + } - @Autowired(required = false) - public void setAuthenticationTrustResolver(AuthenticationTrustResolver trustResolver) { - this.defaultMethodExpressionHandler.setTrustResolver(trustResolver); - } + @Autowired(required = false) + public void setAuthenticationTrustResolver(AuthenticationTrustResolver trustResolver) { + this.defaultMethodExpressionHandler.setTrustResolver(trustResolver); + } - @Autowired(required=false) - public void setObjectPostProcessor(ObjectPostProcessor objectPostProcessor) { - this.objectPostProcessor = objectPostProcessor; - this.defaultMethodExpressionHandler = objectPostProcessor.postProcess(defaultMethodExpressionHandler); - } + @Autowired(required = false) + public void setObjectPostProcessor(ObjectPostProcessor objectPostProcessor) { + this.objectPostProcessor = objectPostProcessor; + this.defaultMethodExpressionHandler = objectPostProcessor + .postProcess(defaultMethodExpressionHandler); + } - @Autowired(required = false) - public void setJsr250MethodSecurityMetadataSource( - Jsr250MethodSecurityMetadataSource jsr250MethodSecurityMetadataSource) { - this.jsr250MethodSecurityMetadataSource = jsr250MethodSecurityMetadataSource; - } + @Autowired(required = false) + public void setJsr250MethodSecurityMetadataSource( + Jsr250MethodSecurityMetadataSource jsr250MethodSecurityMetadataSource) { + this.jsr250MethodSecurityMetadataSource = jsr250MethodSecurityMetadataSource; + } - @Autowired(required = false) - public void setPermissionEvaluator(List permissionEvaluators) { - if(permissionEvaluators.size() != 1) { - logger.debug("Not autwiring PermissionEvaluator since size != 1. Got " + permissionEvaluators); - } - this.defaultMethodExpressionHandler.setPermissionEvaluator(permissionEvaluators.get(0)); - } + @Autowired(required = false) + public void setPermissionEvaluator(List permissionEvaluators) { + if (permissionEvaluators.size() != 1) { + logger.debug("Not autwiring PermissionEvaluator since size != 1. Got " + + permissionEvaluators); + } + this.defaultMethodExpressionHandler.setPermissionEvaluator(permissionEvaluators + .get(0)); + } - @Autowired(required = false) - public void setMethodSecurityExpressionHandler(List handlers) { - if(handlers.size() != 1) { - logger.debug("Not autwiring PermissionEvaluator since size != 1. Got " + handlers); - return; - } - this.expressionHandler = handlers.get(0); - } + @Autowired(required = false) + public void setMethodSecurityExpressionHandler( + List handlers) { + if (handlers.size() != 1) { + logger.debug("Not autwiring PermissionEvaluator since size != 1. Got " + + handlers); + return; + } + this.expressionHandler = handlers.get(0); + } - @Autowired - public void setApplicationContext(ApplicationContext context) { - this.context = context; - } + @Autowired + public void setApplicationContext(ApplicationContext context) { + this.context = context; + } - private AuthenticationConfiguration getAuthenticationConfiguration() { - return context.getBean(AuthenticationConfiguration.class); - } + private AuthenticationConfiguration getAuthenticationConfiguration() { + return context.getBean(AuthenticationConfiguration.class); + } - private boolean prePostEnabled() { - return enableMethodSecurity().getBoolean("prePostEnabled"); - } + private boolean prePostEnabled() { + return enableMethodSecurity().getBoolean("prePostEnabled"); + } - private boolean securedEnabled() { - return enableMethodSecurity().getBoolean("securedEnabled"); - } + private boolean securedEnabled() { + return enableMethodSecurity().getBoolean("securedEnabled"); + } - private boolean jsr250Enabled() { - return enableMethodSecurity().getBoolean("jsr250Enabled"); - } + private boolean jsr250Enabled() { + return enableMethodSecurity().getBoolean("jsr250Enabled"); + } - private int order() { - return (Integer) enableMethodSecurity().get("order"); - } + private int order() { + return (Integer) enableMethodSecurity().get("order"); + } - private boolean isAspectJ() { - return enableMethodSecurity().getEnum("mode") == AdviceMode.ASPECTJ; - } + private boolean isAspectJ() { + return enableMethodSecurity().getEnum("mode") == AdviceMode.ASPECTJ; + } - private AnnotationAttributes enableMethodSecurity() { - if (enableMethodSecurity == null) { - // if it is null look at this instance (i.e. a subclass was used) - EnableGlobalMethodSecurity methodSecurityAnnotation = AnnotationUtils - .findAnnotation(getClass(), - EnableGlobalMethodSecurity.class); - Assert.notNull(methodSecurityAnnotation, - EnableGlobalMethodSecurity.class.getName() + " is required"); - Map methodSecurityAttrs = AnnotationUtils - .getAnnotationAttributes(methodSecurityAnnotation); - this.enableMethodSecurity = AnnotationAttributes - .fromMap(methodSecurityAttrs); - } - return this.enableMethodSecurity; - } + private AnnotationAttributes enableMethodSecurity() { + if (enableMethodSecurity == null) { + // if it is null look at this instance (i.e. a subclass was used) + EnableGlobalMethodSecurity methodSecurityAnnotation = AnnotationUtils + .findAnnotation(getClass(), EnableGlobalMethodSecurity.class); + Assert.notNull(methodSecurityAnnotation, + EnableGlobalMethodSecurity.class.getName() + " is required"); + Map methodSecurityAttrs = AnnotationUtils + .getAnnotationAttributes(methodSecurityAnnotation); + this.enableMethodSecurity = AnnotationAttributes.fromMap(methodSecurityAttrs); + } + return this.enableMethodSecurity; + } } \ No newline at end of file diff --git a/config/src/main/java/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecuritySelector.java b/config/src/main/java/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecuritySelector.java index 8ad1b00bf7..02b5b4cb6c 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecuritySelector.java +++ b/config/src/main/java/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecuritySelector.java @@ -36,35 +36,41 @@ import org.springframework.util.ClassUtils; */ final class GlobalMethodSecuritySelector implements ImportSelector { - public final String[] selectImports(AnnotationMetadata importingClassMetadata) { - Class annoType = EnableGlobalMethodSecurity.class; - Map annotationAttributes = importingClassMetadata.getAnnotationAttributes(annoType.getName(), false); - AnnotationAttributes attributes = AnnotationAttributes.fromMap(annotationAttributes); - Assert.notNull(attributes, String.format( - "@%s is not present on importing class '%s' as expected", - annoType.getSimpleName(), importingClassMetadata.getClassName())); + public final String[] selectImports(AnnotationMetadata importingClassMetadata) { + Class annoType = EnableGlobalMethodSecurity.class; + Map annotationAttributes = importingClassMetadata + .getAnnotationAttributes(annoType.getName(), false); + AnnotationAttributes attributes = AnnotationAttributes + .fromMap(annotationAttributes); + Assert.notNull(attributes, String.format( + "@%s is not present on importing class '%s' as expected", + annoType.getSimpleName(), importingClassMetadata.getClassName())); - // TODO would be nice if could use BeanClassLoaderAware (does not work) - Class importingClass = ClassUtils.resolveClassName(importingClassMetadata.getClassName(), ClassUtils.getDefaultClassLoader()); - boolean skipMethodSecurityConfiguration = GlobalMethodSecurityConfiguration.class.isAssignableFrom(importingClass); + // TODO would be nice if could use BeanClassLoaderAware (does not work) + Class importingClass = ClassUtils + .resolveClassName(importingClassMetadata.getClassName(), + ClassUtils.getDefaultClassLoader()); + boolean skipMethodSecurityConfiguration = GlobalMethodSecurityConfiguration.class + .isAssignableFrom(importingClass); - AdviceMode mode = attributes.getEnum("mode"); - String autoProxyClassName = AdviceMode.PROXY == mode ? AutoProxyRegistrar.class.getName() - : GlobalMethodSecurityAspectJAutoProxyRegistrar.class.getName(); + AdviceMode mode = attributes.getEnum("mode"); + String autoProxyClassName = AdviceMode.PROXY == mode ? AutoProxyRegistrar.class + .getName() : GlobalMethodSecurityAspectJAutoProxyRegistrar.class + .getName(); - boolean jsr250Enabled = attributes.getBoolean("jsr250Enabled"); + boolean jsr250Enabled = attributes.getBoolean("jsr250Enabled"); - List classNames = new ArrayList(4); - classNames.add(autoProxyClassName); + List classNames = new ArrayList(4); + classNames.add(autoProxyClassName); - if(!skipMethodSecurityConfiguration) { - classNames.add(GlobalMethodSecurityConfiguration.class.getName()); - } + if (!skipMethodSecurityConfiguration) { + classNames.add(GlobalMethodSecurityConfiguration.class.getName()); + } - if(jsr250Enabled) { - classNames.add(Jsr250MetadataSourceConfiguration.class.getName()); - } + if (jsr250Enabled) { + classNames.add(Jsr250MetadataSourceConfiguration.class.getName()); + } - return classNames.toArray(new String[0]); - } + return classNames.toArray(new String[0]); + } } diff --git a/config/src/main/java/org/springframework/security/config/annotation/method/configuration/Jsr250MetadataSourceConfiguration.java b/config/src/main/java/org/springframework/security/config/annotation/method/configuration/Jsr250MetadataSourceConfiguration.java index 3a6faaa76b..4f1f5980cd 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/method/configuration/Jsr250MetadataSourceConfiguration.java +++ b/config/src/main/java/org/springframework/security/config/annotation/method/configuration/Jsr250MetadataSourceConfiguration.java @@ -7,8 +7,8 @@ import org.springframework.security.access.annotation.Jsr250MethodSecurityMetada @Configuration class Jsr250MetadataSourceConfiguration { - @Bean - public Jsr250MethodSecurityMetadataSource jsr250MethodSecurityMetadataSource() { - return new Jsr250MethodSecurityMetadataSource(); - } + @Bean + public Jsr250MethodSecurityMetadataSource jsr250MethodSecurityMetadataSource() { + return new Jsr250MethodSecurityMetadataSource(); + } } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/AbstractRequestMatcherRegistry.java b/config/src/main/java/org/springframework/security/config/annotation/web/AbstractRequestMatcherRegistry.java index b595bf1f1c..e97d137f95 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/AbstractRequestMatcherRegistry.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/AbstractRequestMatcherRegistry.java @@ -27,8 +27,8 @@ import org.springframework.security.web.util.matcher.RegexRequestMatcher; import org.springframework.security.web.util.matcher.RequestMatcher; /** - * A base class for registering {@link RequestMatcher}'s. For example, it might allow for specifying which - * {@link RequestMatcher} require a certain level of authorization. + * A base class for registering {@link RequestMatcher}'s. For example, it might allow for + * specifying which {@link RequestMatcher} require a certain level of authorization. * * * @param The object that is returned or Chained after creating the RequestMatcher @@ -37,154 +37,174 @@ import org.springframework.security.web.util.matcher.RequestMatcher; * @since 3.2 */ public abstract class AbstractRequestMatcherRegistry { - private static final RequestMatcher ANY_REQUEST = AnyRequestMatcher.INSTANCE; - /** - * Maps any request. - * - * @return the object that is chained after creating the {@link RequestMatcher} - */ - public C anyRequest() { - return requestMatchers(ANY_REQUEST); - } + private static final RequestMatcher ANY_REQUEST = AnyRequestMatcher.INSTANCE; - /** - * Maps a {@link List} of {@link org.springframework.security.web.util.matcher.AntPathRequestMatcher} instances. - * - * @param method the {@link HttpMethod} to use or {@code null} for any {@link HttpMethod}. - * @param antPatterns the ant patterns to create {@link org.springframework.security.web.util.matcher.AntPathRequestMatcher} - * from - * - * @return the object that is chained after creating the {@link RequestMatcher} - */ - public C antMatchers(HttpMethod method, String... antPatterns) { - return chainRequestMatchers(RequestMatchers.antMatchers(method, antPatterns)); - } + /** + * Maps any request. + * + * @return the object that is chained after creating the {@link RequestMatcher} + */ + public C anyRequest() { + return requestMatchers(ANY_REQUEST); + } - /** - * Maps a {@link List} of {@link org.springframework.security.web.util.matcher.AntPathRequestMatcher} instances that do - * not care which {@link HttpMethod} is used. - * - * @param antPatterns the ant patterns to create {@link org.springframework.security.web.util.matcher.AntPathRequestMatcher} - * from - * - * @return the object that is chained after creating the {@link RequestMatcher} - */ - public C antMatchers(String... antPatterns) { - return chainRequestMatchers(RequestMatchers.antMatchers(antPatterns)); - } + /** + * Maps a {@link List} of + * {@link org.springframework.security.web.util.matcher.AntPathRequestMatcher} + * instances. + * + * @param method the {@link HttpMethod} to use or {@code null} for any + * {@link HttpMethod}. + * @param antPatterns the ant patterns to create + * {@link org.springframework.security.web.util.matcher.AntPathRequestMatcher} from + * + * @return the object that is chained after creating the {@link RequestMatcher} + */ + public C antMatchers(HttpMethod method, String... antPatterns) { + return chainRequestMatchers(RequestMatchers.antMatchers(method, antPatterns)); + } - /** - * Maps a {@link List} of {@link org.springframework.security.web.util.matcher.RegexRequestMatcher} instances. - * - * @param method the {@link HttpMethod} to use or {@code null} for any {@link HttpMethod}. - * @param regexPatterns the regular expressions to create - * {@link org.springframework.security.web.util.matcher.RegexRequestMatcher} from - * - * @return the object that is chained after creating the {@link RequestMatcher} - */ - public C regexMatchers(HttpMethod method, String... regexPatterns) { - return chainRequestMatchers(RequestMatchers.regexMatchers(method, - regexPatterns)); - } + /** + * Maps a {@link List} of + * {@link org.springframework.security.web.util.matcher.AntPathRequestMatcher} + * instances that do not care which {@link HttpMethod} is used. + * + * @param antPatterns the ant patterns to create + * {@link org.springframework.security.web.util.matcher.AntPathRequestMatcher} from + * + * @return the object that is chained after creating the {@link RequestMatcher} + */ + public C antMatchers(String... antPatterns) { + return chainRequestMatchers(RequestMatchers.antMatchers(antPatterns)); + } - /** - * Create a {@link List} of {@link org.springframework.security.web.util.matcher.RegexRequestMatcher} instances that do not - * specify an {@link HttpMethod}. - * - * @param regexPatterns the regular expressions to create - * {@link org.springframework.security.web.util.matcher.RegexRequestMatcher} from - * - * @return the object that is chained after creating the {@link RequestMatcher} - */ - public C regexMatchers(String... regexPatterns) { - return chainRequestMatchers(RequestMatchers.regexMatchers(regexPatterns)); - } + /** + * Maps a {@link List} of + * {@link org.springframework.security.web.util.matcher.RegexRequestMatcher} + * instances. + * + * @param method the {@link HttpMethod} to use or {@code null} for any + * {@link HttpMethod}. + * @param regexPatterns the regular expressions to create + * {@link org.springframework.security.web.util.matcher.RegexRequestMatcher} from + * + * @return the object that is chained after creating the {@link RequestMatcher} + */ + public C regexMatchers(HttpMethod method, String... regexPatterns) { + return chainRequestMatchers(RequestMatchers.regexMatchers(method, regexPatterns)); + } - /** - * Associates a list of {@link RequestMatcher} instances with the {@link AbstractConfigAttributeRequestMatcherRegistry} - * - * @param requestMatchers the {@link RequestMatcher} instances - * - * @return the object that is chained after creating the {@link RequestMatcher} - */ - public C requestMatchers(RequestMatcher... requestMatchers) { - return chainRequestMatchers(Arrays.asList(requestMatchers)); - } + /** + * Create a {@link List} of + * {@link org.springframework.security.web.util.matcher.RegexRequestMatcher} instances + * that do not specify an {@link HttpMethod}. + * + * @param regexPatterns the regular expressions to create + * {@link org.springframework.security.web.util.matcher.RegexRequestMatcher} from + * + * @return the object that is chained after creating the {@link RequestMatcher} + */ + public C regexMatchers(String... regexPatterns) { + return chainRequestMatchers(RequestMatchers.regexMatchers(regexPatterns)); + } - /** - * Subclasses should implement this method for returning the object that is chained to the creation of the - * {@link RequestMatcher} instances. - * - * @param requestMatchers the {@link RequestMatcher} instances that were created - * @return the chained Object for the subclass which allows association of something else to the - * {@link RequestMatcher} - */ - protected abstract C chainRequestMatchers(List requestMatchers); + /** + * Associates a list of {@link RequestMatcher} instances with the + * {@link AbstractConfigAttributeRequestMatcherRegistry} + * + * @param requestMatchers the {@link RequestMatcher} instances + * + * @return the object that is chained after creating the {@link RequestMatcher} + */ + public C requestMatchers(RequestMatcher... requestMatchers) { + return chainRequestMatchers(Arrays.asList(requestMatchers)); + } - /** - * Utilities for creating {@link RequestMatcher} instances. - * - * @author Rob Winch - * @since 3.2 - */ - private static final class RequestMatchers { + /** + * Subclasses should implement this method for returning the object that is chained to + * the creation of the {@link RequestMatcher} instances. + * + * @param requestMatchers the {@link RequestMatcher} instances that were created + * @return the chained Object for the subclass which allows association of something + * else to the {@link RequestMatcher} + */ + protected abstract C chainRequestMatchers(List requestMatchers); - /** - * Create a {@link List} of {@link AntPathRequestMatcher} instances. - * - * @param httpMethod the {@link HttpMethod} to use or {@code null} for any {@link HttpMethod}. - * @param antPatterns the ant patterns to create {@link AntPathRequestMatcher} from - * - * @return a {@link List} of {@link AntPathRequestMatcher} instances - */ - public static List antMatchers(HttpMethod httpMethod, String...antPatterns) { - String method = httpMethod == null ? null : httpMethod.toString(); - List matchers = new ArrayList(); - for(String pattern : antPatterns) { - matchers.add(new AntPathRequestMatcher(pattern, method)); - } - return matchers; - } + /** + * Utilities for creating {@link RequestMatcher} instances. + * + * @author Rob Winch + * @since 3.2 + */ + private static final class RequestMatchers { - /** - * Create a {@link List} of {@link AntPathRequestMatcher} instances that do not specify an {@link HttpMethod}. - * - * @param antPatterns the ant patterns to create {@link AntPathRequestMatcher} from - * - * @return a {@link List} of {@link AntPathRequestMatcher} instances - */ - public static List antMatchers(String...antPatterns) { - return antMatchers(null, antPatterns); - } + /** + * Create a {@link List} of {@link AntPathRequestMatcher} instances. + * + * @param httpMethod the {@link HttpMethod} to use or {@code null} for any + * {@link HttpMethod}. + * @param antPatterns the ant patterns to create {@link AntPathRequestMatcher} + * from + * + * @return a {@link List} of {@link AntPathRequestMatcher} instances + */ + public static List antMatchers(HttpMethod httpMethod, + String... antPatterns) { + String method = httpMethod == null ? null : httpMethod.toString(); + List matchers = new ArrayList(); + for (String pattern : antPatterns) { + matchers.add(new AntPathRequestMatcher(pattern, method)); + } + return matchers; + } - /** - * Create a {@link List} of {@link RegexRequestMatcher} instances. - * - * @param httpMethod the {@link HttpMethod} to use or {@code null} for any {@link HttpMethod}. - * @param regexPatterns the regular expressions to create {@link RegexRequestMatcher} from - * - * @return a {@link List} of {@link RegexRequestMatcher} instances - */ - public static List regexMatchers(HttpMethod httpMethod, String...regexPatterns) { - String method = httpMethod == null ? null : httpMethod.toString(); - List matchers = new ArrayList(); - for(String pattern : regexPatterns) { - matchers.add(new RegexRequestMatcher(pattern, method)); - } - return matchers; - } + /** + * Create a {@link List} of {@link AntPathRequestMatcher} instances that do not + * specify an {@link HttpMethod}. + * + * @param antPatterns the ant patterns to create {@link AntPathRequestMatcher} + * from + * + * @return a {@link List} of {@link AntPathRequestMatcher} instances + */ + public static List antMatchers(String... antPatterns) { + return antMatchers(null, antPatterns); + } - /** - * Create a {@link List} of {@link RegexRequestMatcher} instances that do not specify an {@link HttpMethod}. - * - * @param regexPatterns the regular expressions to create {@link RegexRequestMatcher} from - * - * @return a {@link List} of {@link RegexRequestMatcher} instances - */ - public static List regexMatchers(String...regexPatterns) { - return regexMatchers(null, regexPatterns); - } + /** + * Create a {@link List} of {@link RegexRequestMatcher} instances. + * + * @param httpMethod the {@link HttpMethod} to use or {@code null} for any + * {@link HttpMethod}. + * @param regexPatterns the regular expressions to create + * {@link RegexRequestMatcher} from + * + * @return a {@link List} of {@link RegexRequestMatcher} instances + */ + public static List regexMatchers(HttpMethod httpMethod, + String... regexPatterns) { + String method = httpMethod == null ? null : httpMethod.toString(); + List matchers = new ArrayList(); + for (String pattern : regexPatterns) { + matchers.add(new RegexRequestMatcher(pattern, method)); + } + return matchers; + } - private RequestMatchers() {} - } + /** + * Create a {@link List} of {@link RegexRequestMatcher} instances that do not + * specify an {@link HttpMethod}. + * + * @param regexPatterns the regular expressions to create + * {@link RegexRequestMatcher} from + * + * @return a {@link List} of {@link RegexRequestMatcher} instances + */ + public static List regexMatchers(String... regexPatterns) { + return regexMatchers(null, regexPatterns); + } + + private RequestMatchers() { + } + } } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/HttpSecurityBuilder.java b/config/src/main/java/org/springframework/security/config/annotation/web/HttpSecurityBuilder.java index 3208628fd2..b36e3379ef 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/HttpSecurityBuilder.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/HttpSecurityBuilder.java @@ -50,125 +50,119 @@ import org.springframework.security.web.session.SessionManagementFilter; * * @param */ -public interface HttpSecurityBuilder> extends SecurityBuilder { +public interface HttpSecurityBuilder> extends + SecurityBuilder { - /** - * Gets the {@link SecurityConfigurer} by its class name or - * null if not found. Note that object hierarchies are not - * considered. - * - * @param clazz the Class of the {@link SecurityConfigurer} to attempt to get. - */ - > C getConfigurer( - Class clazz); + /** + * Gets the {@link SecurityConfigurer} by its class name or null if not + * found. Note that object hierarchies are not considered. + * + * @param clazz the Class of the {@link SecurityConfigurer} to attempt to get. + */ + > C getConfigurer( + Class clazz); - /** - * Removes the {@link SecurityConfigurer} by its class name or - * null if not found. Note that object hierarchies are not - * considered. - * - * @param clazz the Class of the {@link SecurityConfigurer} to attempt to remove. - * @return the {@link SecurityConfigurer} that was removed or null if not found - */ - > C removeConfigurer(Class clazz); + /** + * Removes the {@link SecurityConfigurer} by its class name or null if + * not found. Note that object hierarchies are not considered. + * + * @param clazz the Class of the {@link SecurityConfigurer} to attempt to remove. + * @return the {@link SecurityConfigurer} that was removed or null if not found + */ + > C removeConfigurer( + Class clazz); - /** - * Sets an object that is shared by multiple {@link SecurityConfigurer}. - * - * @param sharedType the Class to key the shared object by. - * @param object the Object to store - */ - void setSharedObject(Class sharedType, C object); + /** + * Sets an object that is shared by multiple {@link SecurityConfigurer}. + * + * @param sharedType the Class to key the shared object by. + * @param object the Object to store + */ + void setSharedObject(Class sharedType, C object); - /** - * Gets a shared Object. Note that object heirarchies are not considered. - * - * @param sharedType the type of the shared Object - * @return the shared Object or null if it is not found - */ - C getSharedObject(Class sharedType); + /** + * Gets a shared Object. Note that object heirarchies are not considered. + * + * @param sharedType the type of the shared Object + * @return the shared Object or null if it is not found + */ + C getSharedObject(Class sharedType); - /** - * Allows adding an additional {@link AuthenticationProvider} to be used - * - * @param authenticationProvider the {@link AuthenticationProvider} to be added - * @return the {@link HttpSecurity} for further customizations - */ - H authenticationProvider( - AuthenticationProvider authenticationProvider); + /** + * Allows adding an additional {@link AuthenticationProvider} to be used + * + * @param authenticationProvider the {@link AuthenticationProvider} to be added + * @return the {@link HttpSecurity} for further customizations + */ + H authenticationProvider(AuthenticationProvider authenticationProvider); - /** - * Allows adding an additional {@link UserDetailsService} to be used - * - * @param userDetailsService the {@link UserDetailsService} to be added - * @return the {@link HttpSecurity} for further customizations - */ - H userDetailsService( - UserDetailsService userDetailsService) throws Exception; + /** + * Allows adding an additional {@link UserDetailsService} to be used + * + * @param userDetailsService the {@link UserDetailsService} to be added + * @return the {@link HttpSecurity} for further customizations + */ + H userDetailsService(UserDetailsService userDetailsService) throws Exception; - /** - * Allows adding a {@link Filter} after one of the known {@link Filter} - * classes. The known {@link Filter} instances are either a {@link Filter} - * listed in {@link #addFilter(Filter)} or a {@link Filter} that has already - * been added using {@link #addFilterAfter(Filter, Class)} or - * {@link #addFilterBefore(Filter, Class)}. - * - * @param filter the {@link Filter} to register after the type {@code afterFilter} - * @param afterFilter the Class of the known {@link Filter}. - * @return the {@link HttpSecurity} for further customizations - */ - H addFilterAfter(Filter filter, - Class afterFilter); + /** + * Allows adding a {@link Filter} after one of the known {@link Filter} classes. The + * known {@link Filter} instances are either a {@link Filter} listed in + * {@link #addFilter(Filter)} or a {@link Filter} that has already been added using + * {@link #addFilterAfter(Filter, Class)} or {@link #addFilterBefore(Filter, Class)}. + * + * @param filter the {@link Filter} to register after the type {@code afterFilter} + * @param afterFilter the Class of the known {@link Filter}. + * @return the {@link HttpSecurity} for further customizations + */ + H addFilterAfter(Filter filter, Class afterFilter); - /** - * Allows adding a {@link Filter} before one of the known {@link Filter} - * classes. The known {@link Filter} instances are either a {@link Filter} - * listed in {@link #addFilter(Filter)} or a {@link Filter} that has already - * been added using {@link #addFilterAfter(Filter, Class)} or - * {@link #addFilterBefore(Filter, Class)}. - * - * @param filter the {@link Filter} to register before the type {@code beforeFilter} - * @param beforeFilter the Class of the known {@link Filter}. - * @return the {@link HttpSecurity} for further customizations - */ - H addFilterBefore(Filter filter, - Class beforeFilter); + /** + * Allows adding a {@link Filter} before one of the known {@link Filter} classes. The + * known {@link Filter} instances are either a {@link Filter} listed in + * {@link #addFilter(Filter)} or a {@link Filter} that has already been added using + * {@link #addFilterAfter(Filter, Class)} or {@link #addFilterBefore(Filter, Class)}. + * + * @param filter the {@link Filter} to register before the type {@code beforeFilter} + * @param beforeFilter the Class of the known {@link Filter}. + * @return the {@link HttpSecurity} for further customizations + */ + H addFilterBefore(Filter filter, Class beforeFilter); - /** - * Adds a {@link Filter} that must be an instance of or extend one of the - * Filters provided within the Security framework. The method ensures that - * the ordering of the Filters is automatically taken care of. - * - * The ordering of the Filters is: - * - *
    - *
  • {@link ChannelProcessingFilter}
  • - *
  • {@link ConcurrentSessionFilter}
  • - *
  • {@link SecurityContextPersistenceFilter}
  • - *
  • {@link LogoutFilter}
  • - *
  • {@link X509AuthenticationFilter}
  • - *
  • {@link AbstractPreAuthenticatedProcessingFilter}
  • - *
  • {@link org.springframework.security.cas.web.CasAuthenticationFilter}
  • - *
  • {@link UsernamePasswordAuthenticationFilter}
  • - *
  • {@link ConcurrentSessionFilter}
  • - *
  • {@link OpenIDAuthenticationFilter}
  • - *
  • {@link DefaultLoginPageGeneratingFilter}
  • - *
  • {@link ConcurrentSessionFilter}
  • - *
  • {@link DigestAuthenticationFilter}
  • - *
  • {@link BasicAuthenticationFilter}
  • - *
  • {@link RequestCacheAwareFilter}
  • - *
  • {@link SecurityContextHolderAwareRequestFilter}
  • - *
  • {@link JaasApiIntegrationFilter}
  • - *
  • {@link RememberMeAuthenticationFilter}
  • - *
  • {@link AnonymousAuthenticationFilter}
  • - *
  • {@link SessionManagementFilter}
  • - *
  • {@link ExceptionTranslationFilter}
  • - *
  • {@link FilterSecurityInterceptor}
  • - *
  • {@link SwitchUserFilter}
  • - *
- * - * @param filter the {@link Filter} to add - * @return the {@link HttpSecurity} for further customizations - */ - H addFilter(Filter filter); + /** + * Adds a {@link Filter} that must be an instance of or extend one of the Filters + * provided within the Security framework. The method ensures that the ordering of the + * Filters is automatically taken care of. + * + * The ordering of the Filters is: + * + *
    + *
  • {@link ChannelProcessingFilter}
  • + *
  • {@link ConcurrentSessionFilter}
  • + *
  • {@link SecurityContextPersistenceFilter}
  • + *
  • {@link LogoutFilter}
  • + *
  • {@link X509AuthenticationFilter}
  • + *
  • {@link AbstractPreAuthenticatedProcessingFilter}
  • + *
  • {@link org.springframework.security.cas.web.CasAuthenticationFilter}
  • + *
  • {@link UsernamePasswordAuthenticationFilter}
  • + *
  • {@link ConcurrentSessionFilter}
  • + *
  • {@link OpenIDAuthenticationFilter}
  • + *
  • {@link DefaultLoginPageGeneratingFilter}
  • + *
  • {@link ConcurrentSessionFilter}
  • + *
  • {@link DigestAuthenticationFilter}
  • + *
  • {@link BasicAuthenticationFilter}
  • + *
  • {@link RequestCacheAwareFilter}
  • + *
  • {@link SecurityContextHolderAwareRequestFilter}
  • + *
  • {@link JaasApiIntegrationFilter}
  • + *
  • {@link RememberMeAuthenticationFilter}
  • + *
  • {@link AnonymousAuthenticationFilter}
  • + *
  • {@link SessionManagementFilter}
  • + *
  • {@link ExceptionTranslationFilter}
  • + *
  • {@link FilterSecurityInterceptor}
  • + *
  • {@link SwitchUserFilter}
  • + *
+ * + * @param filter the {@link Filter} to add + * @return the {@link HttpSecurity} for further customizations + */ + H addFilter(Filter filter); } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/WebSecurityConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/WebSecurityConfigurer.java index 19ab476ea6..d25d7e3233 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/WebSecurityConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/WebSecurityConfigurer.java @@ -25,17 +25,17 @@ import org.springframework.security.config.annotation.web.configuration.EnableWe import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; /** - * Allows customization to the {@link WebSecurity}. In most instances - * users will use {@link EnableWebSecurity} and a create {@link Configuration} - * that extends {@link WebSecurityConfigurerAdapter} which will automatically be - * applied to the {@link WebSecurity} by the {@link EnableWebSecurity} - * annotation. + * Allows customization to the {@link WebSecurity}. In most instances users will use + * {@link EnableWebSecurity} and a create {@link Configuration} that extends + * {@link WebSecurityConfigurerAdapter} which will automatically be applied to the + * {@link WebSecurity} by the {@link EnableWebSecurity} annotation. * * @see WebSecurityConfigurerAdapter * * @author Rob Winch * @since 3.2 */ -public interface WebSecurityConfigurer> extends SecurityConfigurer { +public interface WebSecurityConfigurer> extends + SecurityConfigurer { } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/builders/FilterComparator.java b/config/src/main/java/org/springframework/security/config/annotation/web/builders/FilterComparator.java index fc257364bc..0f456107b3 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/builders/FilterComparator.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/builders/FilterComparator.java @@ -46,8 +46,8 @@ import org.springframework.security.web.session.ConcurrentSessionFilter; import org.springframework.security.web.session.SessionManagementFilter; /** - * An internal use only {@link Comparator} that sorts the Security {@link Filter} instances to ensure they are in the - * correct order. + * An internal use only {@link Comparator} that sorts the Security {@link Filter} + * instances to ensure they are in the correct order. * * @author Rob Winch * @since 3.2 @@ -55,127 +55,138 @@ import org.springframework.security.web.session.SessionManagementFilter; @SuppressWarnings("serial") final class FilterComparator implements Comparator, Serializable { - private static final int STEP = 100; - private Map filterToOrder = new HashMap(); + private static final int STEP = 100; + private Map filterToOrder = new HashMap(); - FilterComparator() { - int order = 100; - put(ChannelProcessingFilter.class, order); - order += STEP; - put(ConcurrentSessionFilter.class, order); - order += STEP; - put(WebAsyncManagerIntegrationFilter.class, order); - order += STEP; - put(SecurityContextPersistenceFilter.class, order); - order += STEP; - put(HeaderWriterFilter.class, order); - order += STEP; - put(CsrfFilter.class, order); - order += STEP; - put(LogoutFilter.class, order); - order += STEP; - put(X509AuthenticationFilter.class, order); - order += STEP; - put(AbstractPreAuthenticatedProcessingFilter.class, order); - order += STEP; - filterToOrder.put("org.springframework.security.cas.web.CasAuthenticationFilter", order); - order += STEP; - put(UsernamePasswordAuthenticationFilter.class, order); - order += STEP; - put(ConcurrentSessionFilter.class, order); - order += STEP; - filterToOrder.put("org.springframework.security.openid.OpenIDAuthenticationFilter", order); - order += STEP; - put(DefaultLoginPageGeneratingFilter.class, order); - order += STEP; - put(ConcurrentSessionFilter.class, order); - order += STEP; - put(DigestAuthenticationFilter.class, order); - order += STEP; - put(BasicAuthenticationFilter.class, order); - order += STEP; - put(RequestCacheAwareFilter.class, order); - order += STEP; - put(SecurityContextHolderAwareRequestFilter.class, order); - order += STEP; - put(JaasApiIntegrationFilter.class, order); - order += STEP; - put(RememberMeAuthenticationFilter.class, order); - order += STEP; - put(AnonymousAuthenticationFilter.class, order); - order += STEP; - put(SessionManagementFilter.class, order); - order += STEP; - put(ExceptionTranslationFilter.class, order); - order += STEP; - put(FilterSecurityInterceptor.class, order); - order += STEP; - put(SwitchUserFilter.class, order); - } + FilterComparator() { + int order = 100; + put(ChannelProcessingFilter.class, order); + order += STEP; + put(ConcurrentSessionFilter.class, order); + order += STEP; + put(WebAsyncManagerIntegrationFilter.class, order); + order += STEP; + put(SecurityContextPersistenceFilter.class, order); + order += STEP; + put(HeaderWriterFilter.class, order); + order += STEP; + put(CsrfFilter.class, order); + order += STEP; + put(LogoutFilter.class, order); + order += STEP; + put(X509AuthenticationFilter.class, order); + order += STEP; + put(AbstractPreAuthenticatedProcessingFilter.class, order); + order += STEP; + filterToOrder.put("org.springframework.security.cas.web.CasAuthenticationFilter", + order); + order += STEP; + put(UsernamePasswordAuthenticationFilter.class, order); + order += STEP; + put(ConcurrentSessionFilter.class, order); + order += STEP; + filterToOrder.put( + "org.springframework.security.openid.OpenIDAuthenticationFilter", order); + order += STEP; + put(DefaultLoginPageGeneratingFilter.class, order); + order += STEP; + put(ConcurrentSessionFilter.class, order); + order += STEP; + put(DigestAuthenticationFilter.class, order); + order += STEP; + put(BasicAuthenticationFilter.class, order); + order += STEP; + put(RequestCacheAwareFilter.class, order); + order += STEP; + put(SecurityContextHolderAwareRequestFilter.class, order); + order += STEP; + put(JaasApiIntegrationFilter.class, order); + order += STEP; + put(RememberMeAuthenticationFilter.class, order); + order += STEP; + put(AnonymousAuthenticationFilter.class, order); + order += STEP; + put(SessionManagementFilter.class, order); + order += STEP; + put(ExceptionTranslationFilter.class, order); + order += STEP; + put(FilterSecurityInterceptor.class, order); + order += STEP; + put(SwitchUserFilter.class, order); + } - public int compare(Filter lhs, Filter rhs) { - Integer left = getOrder(lhs.getClass()); - Integer right = getOrder(rhs.getClass()); - return left - right; - } + public int compare(Filter lhs, Filter rhs) { + Integer left = getOrder(lhs.getClass()); + Integer right = getOrder(rhs.getClass()); + return left - right; + } - /** - * Determines if a particular {@link Filter} is registered to be sorted - * - * @param filter - * @return - */ - public boolean isRegistered(Class filter) { - return getOrder(filter) != null; - } + /** + * Determines if a particular {@link Filter} is registered to be sorted + * + * @param filter + * @return + */ + public boolean isRegistered(Class filter) { + return getOrder(filter) != null; + } - /** - * Registers a {@link Filter} to exist after a particular {@link Filter} that is already registered. - * @param filter the {@link Filter} to register - * @param afterFilter the {@link Filter} that is already registered and that {@code filter} should be placed after. - */ - public void registerAfter(Class filter, Class afterFilter) { - Integer position = getOrder(afterFilter); - if(position == null) { - throw new IllegalArgumentException("Cannot register after unregistered Filter "+afterFilter); - } + /** + * Registers a {@link Filter} to exist after a particular {@link Filter} that is + * already registered. + * @param filter the {@link Filter} to register + * @param afterFilter the {@link Filter} that is already registered and that + * {@code filter} should be placed after. + */ + public void registerAfter(Class filter, + Class afterFilter) { + Integer position = getOrder(afterFilter); + if (position == null) { + throw new IllegalArgumentException( + "Cannot register after unregistered Filter " + afterFilter); + } - put(filter, position + 1); - } + put(filter, position + 1); + } - /** - * Registers a {@link Filter} to exist before a particular {@link Filter} that is already registered. - * @param filter the {@link Filter} to register - * @param beforeFilter the {@link Filter} that is already registered and that {@code filter} should be placed before. - */ - public void registerBefore(Class filter, Class beforeFilter) { - Integer position = getOrder(beforeFilter); - if(position == null) { - throw new IllegalArgumentException("Cannot register after unregistered Filter "+beforeFilter); - } + /** + * Registers a {@link Filter} to exist before a particular {@link Filter} that is + * already registered. + * @param filter the {@link Filter} to register + * @param beforeFilter the {@link Filter} that is already registered and that + * {@code filter} should be placed before. + */ + public void registerBefore(Class filter, + Class beforeFilter) { + Integer position = getOrder(beforeFilter); + if (position == null) { + throw new IllegalArgumentException( + "Cannot register after unregistered Filter " + beforeFilter); + } - put(filter, position - 1); - } + put(filter, position - 1); + } - private void put(Class filter, int position) { - String className = filter.getName(); - filterToOrder.put(className, position); - } + private void put(Class filter, int position) { + String className = filter.getName(); + filterToOrder.put(className, position); + } - /** - * Gets the order of a particular {@link Filter} class taking into consideration superclasses. - * - * @param clazz the {@link Filter} class to determine the sort order - * @return the sort order or null if not defined - */ - private Integer getOrder(Class clazz) { - while(clazz != null) { - Integer result = filterToOrder.get(clazz.getName()); - if(result != null) { - return result; - } - clazz = clazz.getSuperclass(); - } - return null; - } + /** + * Gets the order of a particular {@link Filter} class taking into consideration + * superclasses. + * + * @param clazz the {@link Filter} class to determine the sort order + * @return the sort order or null if not defined + */ + private Integer getOrder(Class clazz) { + while (clazz != null) { + Integer result = filterToOrder.get(clazz.getName()); + if (result != null) { + return result; + } + clazz = clazz.getSuperclass(); + } + return null; + } } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/builders/HttpSecurity.java b/config/src/main/java/org/springframework/security/config/annotation/web/builders/HttpSecurity.java index f77546531d..d387d25874 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/builders/HttpSecurity.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/builders/HttpSecurity.java @@ -71,40 +71,33 @@ import org.springframework.security.web.util.matcher.RequestMatcher; import org.springframework.util.Assert; /** - * A {@link HttpSecurity} is similar to Spring Security's XML element in the namespace - * configuration. It allows configuring web based security for specific http requests. By default - * it will be applied to all requests, but can be restricted using {@link #requestMatcher(RequestMatcher)} - * or other similar methods. + * A {@link HttpSecurity} is similar to Spring Security's XML element in the + * namespace configuration. It allows configuring web based security for specific http + * requests. By default it will be applied to all requests, but can be restricted using + * {@link #requestMatcher(RequestMatcher)} or other similar methods. * *

Example Usage

* - * The most basic form based configuration can be seen below. The configuration will require that any URL - * that is requested will require a User with the role "ROLE_USER". It also defines an in memory authentication - * scheme with a user that has the username "user", the password "password", and the role "ROLE_USER". For - * additional examples, refer to the Java Doc of individual methods on {@link HttpSecurity}. + * The most basic form based configuration can be seen below. The configuration will + * require that any URL that is requested will require a User with the role "ROLE_USER". + * It also defines an in memory authentication scheme with a user that has the username + * "user", the password "password", and the role "ROLE_USER". For additional examples, + * refer to the Java Doc of individual methods on {@link HttpSecurity}. * *
  * @Configuration
  * @EnableWebSecurity
  * public class FormLoginSecurityConfig extends WebSecurityConfigurerAdapter {
- *
- *     @Override
- *     protected void configure(HttpSecurity http) throws Exception {
- *         http
- *             .authorizeRequests()
- *                 .antMatchers("/**").hasRole("USER")
- *                 .and()
- *             .formLogin();
- *     }
- *
- *     @Override
- *     protected void configure(AuthenticationManagerBuilder auth) throws Exception {
- *         auth
- *              .inMemoryAuthentication()
- *                   .withUser("user")
- *                        .password("password")
- *                        .roles("USER");
- *     }
+ * 
+ * 	@Override
+ * 	protected void configure(HttpSecurity http) throws Exception {
+ * 		http.authorizeRequests().antMatchers("/**").hasRole("USER").and().formLogin();
+ * 	}
+ * 
+ * 	@Override
+ * 	protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+ * 		auth.inMemoryAuthentication().withUser("user").password("password").roles("USER");
+ * 	}
  * }
  * 
* @@ -112,1241 +105,1085 @@ import org.springframework.util.Assert; * @since 3.2 * @see EnableWebSecurity */ -public final class HttpSecurity extends AbstractConfiguredSecurityBuilder implements SecurityBuilder, HttpSecurityBuilder { - private final RequestMatcherConfigurer requestMatcherConfigurer = new RequestMatcherConfigurer(); - private List filters = new ArrayList(); - private RequestMatcher requestMatcher = AnyRequestMatcher.INSTANCE; - private FilterComparator comparitor = new FilterComparator(); +public final class HttpSecurity extends + AbstractConfiguredSecurityBuilder + implements SecurityBuilder, + HttpSecurityBuilder { + private final RequestMatcherConfigurer requestMatcherConfigurer = new RequestMatcherConfigurer(); + private List filters = new ArrayList(); + private RequestMatcher requestMatcher = AnyRequestMatcher.INSTANCE; + private FilterComparator comparitor = new FilterComparator(); - /** - * Creates a new instance - * @param objectPostProcessor the {@link ObjectPostProcessor} that should be used - * @param authenticationBuilder the {@link AuthenticationManagerBuilder} to use for additional updates - * @param sharedObjects the shared Objects to initialize the {@link HttpSecurity} with - * @see WebSecurityConfiguration - */ - public HttpSecurity(ObjectPostProcessor objectPostProcessor, AuthenticationManagerBuilder authenticationBuilder, Map,Object> sharedObjects) { - super(objectPostProcessor); - Assert.notNull(authenticationBuilder, "authenticationBuilder cannot be null"); - setSharedObject(AuthenticationManagerBuilder.class, authenticationBuilder); - for(Map.Entry, Object> entry : sharedObjects.entrySet()) { - setSharedObject(entry.getKey(), entry.getValue()); - } - } + /** + * Creates a new instance + * @param objectPostProcessor the {@link ObjectPostProcessor} that should be used + * @param authenticationBuilder the {@link AuthenticationManagerBuilder} to use for + * additional updates + * @param sharedObjects the shared Objects to initialize the {@link HttpSecurity} with + * @see WebSecurityConfiguration + */ + public HttpSecurity(ObjectPostProcessor objectPostProcessor, + AuthenticationManagerBuilder authenticationBuilder, + Map, Object> sharedObjects) { + super(objectPostProcessor); + Assert.notNull(authenticationBuilder, "authenticationBuilder cannot be null"); + setSharedObject(AuthenticationManagerBuilder.class, authenticationBuilder); + for (Map.Entry, Object> entry : sharedObjects.entrySet()) { + setSharedObject(entry.getKey(), entry.getValue()); + } + } - /** - * Allows configuring OpenID based authentication. - * - *

Example Configurations

- * - * A basic example accepting the defaults and not using attribute exchange: - * - *
-     * @Configuration
-     * @EnableWebSecurity
-     * public class OpenIDLoginConfig extends WebSecurityConfigurerAdapter {
-     *
-     *     @Override
-     *     protected void configure(HttpSecurity http) {
-     *         http
-     *             .authorizeRequests()
-     *                 .antMatchers("/**").hasRole("USER")
-     *                 .and()
-     *             .openidLogin()
-     *                 .permitAll();
-     *     }
-     *
-     *     @Override
-     *     protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-     *         auth
-     *                 .inMemoryAuthentication()
-     *                     // the username must match the OpenID of the user you are
-     *                     // logging in with
-     *                     .withUser("https://www.google.com/accounts/o8/id?id=lmkCn9xzPdsxVwG7pjYMuDgNNdASFmobNkcRPaWU")
-     *                         .password("password")
-     *                         .roles("USER");
-     *     }
-     * }
-     * 
- * - * A more advanced example demonstrating using attribute exchange and - * providing a custom AuthenticationUserDetailsService that will make any - * user that authenticates a valid user. - * - *
-     * @Configuration
-     * @EnableWebSecurity
-     * public class OpenIDLoginConfig extends WebSecurityConfigurerAdapter {
-     *
-     *     @Override
-     *     protected void configure(HttpSecurity http) {
-     *         http
-     *             .authorizeRequests()
-     *                 .antMatchers("/**").hasRole("USER")
-     *                 .and()
-     *             .openidLogin()
-     *                 .loginPage("/login")
-     *                 .permitAll()
-     *                 .authenticationUserDetailsService(new AutoProvisioningUserDetailsService())
-     *                     .attributeExchange("https://www.google.com/.*")
-     *                         .attribute("email")
-     *                             .type("http://axschema.org/contact/email")
-     *                             .required(true)
-     *                             .and()
-     *                         .attribute("firstname")
-     *                             .type("http://axschema.org/namePerson/first")
-     *                             .required(true)
-     *                             .and()
-     *                         .attribute("lastname")
-     *                             .type("http://axschema.org/namePerson/last")
-     *                             .required(true)
-     *                             .and()
-     *                         .and()
-     *                     .attributeExchange(".*yahoo.com.*")
-     *                         .attribute("email")
-     *                             .type("http://schema.openid.net/contact/email")
-     *                             .required(true)
-     *                             .and()
-     *                         .attribute("fullname")
-     *                             .type("http://axschema.org/namePerson")
-     *                             .required(true)
-     *                             .and()
-     *                         .and()
-     *                     .attributeExchange(".*myopenid.com.*")
-     *                         .attribute("email")
-     *                             .type("http://schema.openid.net/contact/email")
-     *                             .required(true)
-     *                             .and()
-     *                         .attribute("fullname")
-     *                             .type("http://schema.openid.net/namePerson")
-     *                             .required(true);
-     *     }
-     * }
-     *
-     * public class AutoProvisioningUserDetailsService implements
-     *         AuthenticationUserDetailsService<OpenIDAuthenticationToken> {
-     *     public UserDetails loadUserDetails(OpenIDAuthenticationToken token) throws UsernameNotFoundException {
-     *         return new User(token.getName(), "NOTUSED", AuthorityUtils.createAuthorityList("ROLE_USER"));
-     *     }
-     * }
-     * 
- * - * @return the {@link OpenIDLoginConfigurer} for further customizations. - * - * @throws Exception - * @see OpenIDLoginConfigurer - */ - public OpenIDLoginConfigurer openidLogin() throws Exception { - return getOrApply(new OpenIDLoginConfigurer()); - } + /** + * Allows configuring OpenID based authentication. + * + *

Example Configurations

+ * + * A basic example accepting the defaults and not using attribute exchange: + * + *
+	 * @Configuration
+	 * @EnableWebSecurity
+	 * public class OpenIDLoginConfig extends WebSecurityConfigurerAdapter {
+	 * 
+	 * 	@Override
+	 * 	protected void configure(HttpSecurity http) {
+	 * 		http.authorizeRequests().antMatchers("/**").hasRole("USER").and().openidLogin()
+	 * 				.permitAll();
+	 * 	}
+	 * 
+	 * 	@Override
+	 * 	protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+	 * 		auth.inMemoryAuthentication()
+	 * 				// the username must match the OpenID of the user you are
+	 * 				// logging in with
+	 * 				.withUser(
+	 * 						"https://www.google.com/accounts/o8/id?id=lmkCn9xzPdsxVwG7pjYMuDgNNdASFmobNkcRPaWU")
+	 * 				.password("password").roles("USER");
+	 * 	}
+	 * }
+	 * 
+ * + * A more advanced example demonstrating using attribute exchange and providing a + * custom AuthenticationUserDetailsService that will make any user that authenticates + * a valid user. + * + *
+	 * @Configuration
+	 * @EnableWebSecurity
+	 * public class OpenIDLoginConfig extends WebSecurityConfigurerAdapter {
+	 * 
+	 * 	@Override
+	 * 	protected void configure(HttpSecurity http) {
+	 * 		http.authorizeRequests()
+	 * 				.antMatchers("/**")
+	 * 				.hasRole("USER")
+	 * 				.and()
+	 * 				.openidLogin()
+	 * 				.loginPage("/login")
+	 * 				.permitAll()
+	 * 				.authenticationUserDetailsService(
+	 * 						new AutoProvisioningUserDetailsService())
+	 * 				.attributeExchange("https://www.google.com/.*").attribute("email")
+	 * 				.type("http://axschema.org/contact/email").required(true).and()
+	 * 				.attribute("firstname").type("http://axschema.org/namePerson/first")
+	 * 				.required(true).and().attribute("lastname")
+	 * 				.type("http://axschema.org/namePerson/last").required(true).and().and()
+	 * 				.attributeExchange(".*yahoo.com.*").attribute("email")
+	 * 				.type("http://schema.openid.net/contact/email").required(true).and()
+	 * 				.attribute("fullname").type("http://axschema.org/namePerson")
+	 * 				.required(true).and().and().attributeExchange(".*myopenid.com.*")
+	 * 				.attribute("email").type("http://schema.openid.net/contact/email")
+	 * 				.required(true).and().attribute("fullname")
+	 * 				.type("http://schema.openid.net/namePerson").required(true);
+	 * 	}
+	 * }
+	 * 
+	 * public class AutoProvisioningUserDetailsService implements
+	 * 		AuthenticationUserDetailsService<OpenIDAuthenticationToken> {
+	 * 	public UserDetails loadUserDetails(OpenIDAuthenticationToken token)
+	 * 			throws UsernameNotFoundException {
+	 * 		return new User(token.getName(), "NOTUSED",
+	 * 				AuthorityUtils.createAuthorityList("ROLE_USER"));
+	 * 	}
+	 * }
+	 * 
+ * + * @return the {@link OpenIDLoginConfigurer} for further customizations. + * + * @throws Exception + * @see OpenIDLoginConfigurer + */ + public OpenIDLoginConfigurer openidLogin() throws Exception { + return getOrApply(new OpenIDLoginConfigurer()); + } - /** - * Adds the Security headers to the response. This is activated by default - * when using {@link WebSecurityConfigurerAdapter}'s default constructor. - * Only invoking the {@link #headers()} without invoking additional methods - * on it, or accepting the default provided by - * {@link WebSecurityConfigurerAdapter}, is the equivalent of: - * - *
-     * @Configuration
-     * @EnableWebSecurity
-     * public class CsrfSecurityConfig extends WebSecurityConfigurerAdapter {
-     *
-     * 	@Override
-     *     protected void configure(HttpSecurity http) throws Exception {
-     *         http
-     *             .headers()
-     *                 .contentTypeOptions();
-     *                 .xssProtection()
-     *                 .cacheControl()
-     *                 .httpStrictTransportSecurity()
-     *                 .frameOptions()
-     *                 .and()
-     *             ...;
-     *     }
-     * }
-     * 
- * - * You can disable the headers using the following: - * - *
-     * @Configuration
-     * @EnableWebSecurity
-     * public class CsrfSecurityConfig extends WebSecurityConfigurerAdapter {
-     *
-     * 	@Override
-     *     protected void configure(HttpSecurity http) throws Exception {
-     *         http
-     *             .headers().disable()
-     *             ...;
-     *     }
-     * }
-     * 
- * - * You can enable only a few of the headers by invoking the appropriate - * methods on {@link #headers()} result. For example, the following will - * enable {@link HeadersConfigurer#cacheControl()} and - * {@link HeadersConfigurer#frameOptions()} only. - * - *
-     * @Configuration
-     * @EnableWebSecurity
-     * public class CsrfSecurityConfig extends WebSecurityConfigurerAdapter {
-     *
-     * 	@Override
-     *     protected void configure(HttpSecurity http) throws Exception {
-     *         http
-     *             .headers()
-     *                 .cacheControl()
-     *                 .frameOptions()
-     *                 .and()
-     *             ...;
-     *     }
-     * }
-     * 
- * - * @return - * @throws Exception - * @see {@link HeadersConfigurer} - */ - public HeadersConfigurer headers() throws Exception { - return getOrApply(new HeadersConfigurer()); - } + /** + * Adds the Security headers to the response. This is activated by default when using + * {@link WebSecurityConfigurerAdapter}'s default constructor. Only invoking the + * {@link #headers()} without invoking additional methods on it, or accepting the + * default provided by {@link WebSecurityConfigurerAdapter}, is the equivalent of: + * + *
+	 * @Configuration
+	 * @EnableWebSecurity
+	 * public class CsrfSecurityConfig extends WebSecurityConfigurerAdapter {
+	 * 
+	 * 	@Override
+	 *     protected void configure(HttpSecurity http) throws Exception {
+	 *         http
+	 *             .headers()
+	 *                 .contentTypeOptions();
+	 *                 .xssProtection()
+	 *                 .cacheControl()
+	 *                 .httpStrictTransportSecurity()
+	 *                 .frameOptions()
+	 *                 .and()
+	 *             ...;
+	 *     }
+	 * }
+	 * 
+ * + * You can disable the headers using the following: + * + *
+	 * @Configuration
+	 * @EnableWebSecurity
+	 * public class CsrfSecurityConfig extends WebSecurityConfigurerAdapter {
+	 * 
+	 * 	@Override
+	 *     protected void configure(HttpSecurity http) throws Exception {
+	 *         http
+	 *             .headers().disable()
+	 *             ...;
+	 *     }
+	 * }
+	 * 
+ * + * You can enable only a few of the headers by invoking the appropriate methods on + * {@link #headers()} result. For example, the following will enable + * {@link HeadersConfigurer#cacheControl()} and + * {@link HeadersConfigurer#frameOptions()} only. + * + *
+	 * @Configuration
+	 * @EnableWebSecurity
+	 * public class CsrfSecurityConfig extends WebSecurityConfigurerAdapter {
+	 * 
+	 * 	@Override
+	 *     protected void configure(HttpSecurity http) throws Exception {
+	 *         http
+	 *             .headers()
+	 *                 .cacheControl()
+	 *                 .frameOptions()
+	 *                 .and()
+	 *             ...;
+	 *     }
+	 * }
+	 * 
+ * + * @return + * @throws Exception + * @see {@link HeadersConfigurer} + */ + public HeadersConfigurer headers() throws Exception { + return getOrApply(new HeadersConfigurer()); + } - /** - * Allows configuring of Session Management. - * - *

Example Configuration

- * - * The following configuration demonstrates how to enforce that only a - * single instance of a user is authenticated at a time. If a user - * authenticates with the username "user" without logging out and an attempt - * to authenticate with "user" is made the first session will be forcibly - * terminated and sent to the "/login?expired" URL. - * - *
-     * @Configuration
-     * @EnableWebSecurity
-     * public class SessionManagementSecurityConfig extends
-     *         WebSecurityConfigurerAdapter {
-     *
-     *     @Override
-     *     protected void configure(HttpSecurity http) throws Exception {
-     *         http
-     *             .authorizeRequests()
-     *                 .anyRequest().hasRole("USER")
-     *                 .and()
-     *            .formLogin()
-     *                 .permitAll()
-     *                 .and()
-     *            .sessionManagement()
-     *                 .maximumSessions(1)
-     *                 .expiredUrl("/login?expired");
-     *     }
-     *
-     *     @Override
-     *     protected void configure(AuthenticationManagerBuilder auth)
-     *             throws Exception {
-     *         auth.
-     *             inMemoryAuthentication()
-     *                 .withUser("user")
-     *                     .password("password")
-     *                     .roles("USER");
-     *     }
-     * }
-     * 
- * - * When using {@link SessionManagementConfigurer#maximumSessions(int)}, do - * not forget to configure {@link HttpSessionEventPublisher} for the - * application to ensure that expired sessions are cleaned up. - * - * In a web.xml this can be configured using the following: - * - *
-     * <listener>
-     *      <listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
-     * </listener>
-     * 
- * - * Alternatively, - * {@link AbstractSecurityWebApplicationInitializer#enableHttpSessionEventPublisher()} - * could return true. - * - * @return the {@link SessionManagementConfigurer} for further - * customizations - * @throws Exception - */ - public SessionManagementConfigurer sessionManagement() throws Exception { - return getOrApply(new SessionManagementConfigurer()); - } + /** + * Allows configuring of Session Management. + * + *

Example Configuration

+ * + * The following configuration demonstrates how to enforce that only a single instance + * of a user is authenticated at a time. If a user authenticates with the username + * "user" without logging out and an attempt to authenticate with "user" is made the + * first session will be forcibly terminated and sent to the "/login?expired" URL. + * + *
+	 * @Configuration
+	 * @EnableWebSecurity
+	 * public class SessionManagementSecurityConfig extends WebSecurityConfigurerAdapter {
+	 * 
+	 * 	@Override
+	 * 	protected void configure(HttpSecurity http) throws Exception {
+	 * 		http.authorizeRequests().anyRequest().hasRole("USER").and().formLogin()
+	 * 				.permitAll().and().sessionManagement().maximumSessions(1)
+	 * 				.expiredUrl("/login?expired");
+	 * 	}
+	 * 
+	 * 	@Override
+	 * 	protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+	 * 		auth.inMemoryAuthentication().withUser("user").password("password").roles("USER");
+	 * 	}
+	 * }
+	 * 
+ * + * When using {@link SessionManagementConfigurer#maximumSessions(int)}, do not forget + * to configure {@link HttpSessionEventPublisher} for the application to ensure that + * expired sessions are cleaned up. + * + * In a web.xml this can be configured using the following: + * + *
+	 * <listener>
+	 *      <listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
+	 * </listener>
+	 * 
+ * + * Alternatively, + * {@link AbstractSecurityWebApplicationInitializer#enableHttpSessionEventPublisher()} + * could return true. + * + * @return the {@link SessionManagementConfigurer} for further customizations + * @throws Exception + */ + public SessionManagementConfigurer sessionManagement() throws Exception { + return getOrApply(new SessionManagementConfigurer()); + } - /** - * Allows configuring a {@link PortMapper} that is available from - * {@link HttpSecurity#getSharedObject(Class)}. Other provided - * {@link SecurityConfigurer} objects use this configured - * {@link PortMapper} as a default {@link PortMapper} when redirecting from - * HTTP to HTTPS or from HTTPS to HTTP (for example when used in combination - * with {@link #requiresChannel()}. By default Spring Security uses a - * {@link PortMapperImpl} which maps the HTTP port 8080 to the HTTPS port - * 8443 and the HTTP port of 80 to the HTTPS port of 443. - * - *

Example Configuration

- * - * The following configuration will ensure that redirects within Spring - * Security from HTTP of a port of 9090 will redirect to HTTPS port of 9443 - * and the HTTP port of 80 to the HTTPS port of 443. - * - *
-     * @Configuration
-     * @EnableWebSecurity
-     * public class PortMapperSecurityConfig extends WebSecurityConfigurerAdapter {
-     *
-     *     @Override
-     *     protected void configure(HttpSecurity http) throws Exception {
-     *         http
-     *             .authorizeRequests()
-     *                 .antMatchers("/**").hasRole("USER")
-     *                 .and()
-     *             .formLogin()
-     *                 .permitAll()
-     *                 .and()
-     *                 // Example portMapper() configuration
-     *                 .portMapper()
-     *                     .http(9090).mapsTo(9443)
-     *                     .http(80).mapsTo(443);
-     *     }
-     *
-     *     @Override
-     *     protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-     *         auth
-     *             .inMemoryAuthentication()
-     *                 .withUser("user")
-     *                     .password("password")
-     *                     .roles("USER");
-     *     }
-     * }
-     * 
- * - * @return the {@link PortMapperConfigurer} for further customizations - * @throws Exception - * @see {@link #requiresChannel()} - */ - public PortMapperConfigurer portMapper() throws Exception { - return getOrApply(new PortMapperConfigurer()); - } + /** + * Allows configuring a {@link PortMapper} that is available from + * {@link HttpSecurity#getSharedObject(Class)}. Other provided + * {@link SecurityConfigurer} objects use this configured {@link PortMapper} as a + * default {@link PortMapper} when redirecting from HTTP to HTTPS or from HTTPS to + * HTTP (for example when used in combination with {@link #requiresChannel()}. By + * default Spring Security uses a {@link PortMapperImpl} which maps the HTTP port 8080 + * to the HTTPS port 8443 and the HTTP port of 80 to the HTTPS port of 443. + * + *

Example Configuration

+ * + * The following configuration will ensure that redirects within Spring Security from + * HTTP of a port of 9090 will redirect to HTTPS port of 9443 and the HTTP port of 80 + * to the HTTPS port of 443. + * + *
+	 * @Configuration
+	 * @EnableWebSecurity
+	 * public class PortMapperSecurityConfig extends WebSecurityConfigurerAdapter {
+	 * 
+	 * 	@Override
+	 * 	protected void configure(HttpSecurity http) throws Exception {
+	 * 		http.authorizeRequests().antMatchers("/**").hasRole("USER").and().formLogin()
+	 * 				.permitAll().and()
+	 * 				// Example portMapper() configuration
+	 * 				.portMapper().http(9090).mapsTo(9443).http(80).mapsTo(443);
+	 * 	}
+	 * 
+	 * 	@Override
+	 * 	protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+	 * 		auth.inMemoryAuthentication().withUser("user").password("password").roles("USER");
+	 * 	}
+	 * }
+	 * 
+ * + * @return the {@link PortMapperConfigurer} for further customizations + * @throws Exception + * @see {@link #requiresChannel()} + */ + public PortMapperConfigurer portMapper() throws Exception { + return getOrApply(new PortMapperConfigurer()); + } - /** - * Configures container based based pre authentication. In this case, - * authentication is managed by the Servlet Container. - * - *

Example Configuration

- * - * The following configuration will use the principal found on the - * {@link HttpServletRequest} and if the user is in the role "ROLE_USER" or - * "ROLE_ADMIN" will add that to the resulting {@link Authentication}. - * - *
-     * @Configuration
-     * @EnableWebSecurity
-     * public class JeeSecurityConfig extends WebSecurityConfigurerAdapter {
-     *
-     *     @Override
-     *     protected void configure(HttpSecurity http) throws Exception {
-     *         http
-     *             .authorizeRequests()
-     *                 .antMatchers("/**").hasRole("USER")
-     *                 .and()
-     *             // Example jee() configuration
-     *             .jee()
-     *                 .mappableRoles("ROLE_USER", "ROLE_ADMIN");
-     *     }
-     * }
-     * 
- * - * Developers wishing to use pre authentication with the container will need - * to ensure their web.xml configures the security constraints. For example, - * the web.xml (there is no equivalent Java based configuration supported by - * the Servlet specification) might look like: - * - *
-     * <login-config>
-     *     <auth-method>FORM</auth-method>
-     *     <form-login-config>
-     *         <form-login-page>/login</form-login-page>
-     *         <form-error-page>/login?error</form-error-page>
-     *     </form-login-config>
-     * </login-config>
-     *
-     * <security-role>
-     *     <role-name>ROLE_USER</role-name>
-     * </security-role>
-     * <security-constraint>
-     *     <web-resource-collection>
-     *     <web-resource-name>Public</web-resource-name>
-     *         <description>Matches unconstrained pages</description>
-     *         <url-pattern>/login</url-pattern>
-     *         <url-pattern>/logout</url-pattern>
-     *         <url-pattern>/resources/*</url-pattern>
-     *     </web-resource-collection>
-     * </security-constraint>
-     * <security-constraint>
-     *     <web-resource-collection>
-     *         <web-resource-name>Secured Areas</web-resource-name>
-     *         <url-pattern>/*</url-pattern>
-     *     </web-resource-collection>
-     *     <auth-constraint>
-     *         <role-name>ROLE_USER</role-name>
-     *     </auth-constraint>
-     * </security-constraint>
-     * 
- * - * Last you will need to configure your container to contain the user with the - * correct roles. This configuration is specific to the Servlet Container, so consult - * your Servlet Container's documentation. - * - * @return the {@link JeeConfigurer} for further customizations - * @throws Exception - */ - public JeeConfigurer jee() throws Exception { - return getOrApply(new JeeConfigurer()); - } + /** + * Configures container based based pre authentication. In this case, authentication + * is managed by the Servlet Container. + * + *

Example Configuration

+ * + * The following configuration will use the principal found on the + * {@link HttpServletRequest} and if the user is in the role "ROLE_USER" or + * "ROLE_ADMIN" will add that to the resulting {@link Authentication}. + * + *
+	 * @Configuration
+	 * @EnableWebSecurity
+	 * public class JeeSecurityConfig extends WebSecurityConfigurerAdapter {
+	 * 
+	 * 	@Override
+	 * 	protected void configure(HttpSecurity http) throws Exception {
+	 * 		http.authorizeRequests().antMatchers("/**").hasRole("USER").and()
+	 * 		// Example jee() configuration
+	 * 				.jee().mappableRoles("ROLE_USER", "ROLE_ADMIN");
+	 * 	}
+	 * }
+	 * 
+ * + * Developers wishing to use pre authentication with the container will need to ensure + * their web.xml configures the security constraints. For example, the web.xml (there + * is no equivalent Java based configuration supported by the Servlet specification) + * might look like: + * + *
+	 * <login-config>
+	 *     <auth-method>FORM</auth-method>
+	 *     <form-login-config>
+	 *         <form-login-page>/login</form-login-page>
+	 *         <form-error-page>/login?error</form-error-page>
+	 *     </form-login-config>
+	 * </login-config>
+	 * 
+	 * <security-role>
+	 *     <role-name>ROLE_USER</role-name>
+	 * </security-role>
+	 * <security-constraint>
+	 *     <web-resource-collection>
+	 *     <web-resource-name>Public</web-resource-name>
+	 *         <description>Matches unconstrained pages</description>
+	 *         <url-pattern>/login</url-pattern>
+	 *         <url-pattern>/logout</url-pattern>
+	 *         <url-pattern>/resources/*</url-pattern>
+	 *     </web-resource-collection>
+	 * </security-constraint>
+	 * <security-constraint>
+	 *     <web-resource-collection>
+	 *         <web-resource-name>Secured Areas</web-resource-name>
+	 *         <url-pattern>/*</url-pattern>
+	 *     </web-resource-collection>
+	 *     <auth-constraint>
+	 *         <role-name>ROLE_USER</role-name>
+	 *     </auth-constraint>
+	 * </security-constraint>
+	 * 
+ * + * Last you will need to configure your container to contain the user with the correct + * roles. This configuration is specific to the Servlet Container, so consult your + * Servlet Container's documentation. + * + * @return the {@link JeeConfigurer} for further customizations + * @throws Exception + */ + public JeeConfigurer jee() throws Exception { + return getOrApply(new JeeConfigurer()); + } - /** - * Configures X509 based pre authentication. - * - *

Example Configuration

- * - * The following configuration will attempt to extract the username from - * the X509 certificate. Remember that the Servlet Container will need to be - * configured to request client certificates in order for this to work. - * - *
-     * @Configuration
-     * @EnableWebSecurity
-     * public class X509SecurityConfig extends WebSecurityConfigurerAdapter {
-     *
-     *     @Override
-     *     protected void configure(HttpSecurity http) throws Exception {
-     *         http
-     *             .authorizeRequests()
-     *                 .antMatchers("/**").hasRole("USER")
-     *                 .and()
-     *             // Example x509() configuration
-     *             .x509();
-     *     }
-     * }
-     * 
- * - * @return the {@link X509Configurer} for further customizations - * @throws Exception - */ - public X509Configurer x509() throws Exception { - return getOrApply(new X509Configurer()); - } + /** + * Configures X509 based pre authentication. + * + *

Example Configuration

+ * + * The following configuration will attempt to extract the username from the X509 + * certificate. Remember that the Servlet Container will need to be configured to + * request client certificates in order for this to work. + * + *
+	 * @Configuration
+	 * @EnableWebSecurity
+	 * public class X509SecurityConfig extends WebSecurityConfigurerAdapter {
+	 * 
+	 * 	@Override
+	 * 	protected void configure(HttpSecurity http) throws Exception {
+	 * 		http.authorizeRequests().antMatchers("/**").hasRole("USER").and()
+	 * 		// Example x509() configuration
+	 * 				.x509();
+	 * 	}
+	 * }
+	 * 
+ * + * @return the {@link X509Configurer} for further customizations + * @throws Exception + */ + public X509Configurer x509() throws Exception { + return getOrApply(new X509Configurer()); + } - /** - * Allows configuring of Remember Me authentication. - * - *

Example Configuration

- * - * The following configuration demonstrates how to allow token based remember me - * authentication. Upon authenticating if the HTTP parameter named "remember-me" exists, - * then the user will be remembered even after their {@link javax.servlet.http.HttpSession} expires. - * - *
-     * @Configuration
-     * @EnableWebSecurity
-     * public class RememberMeSecurityConfig extends WebSecurityConfigurerAdapter {
-     *
-     *     @Override
-     *     protected void configure(AuthenticationManagerBuilder auth)
-     *             throws Exception {
-     *         auth
-     *              .inMemoryAuthentication()
-     *                   .withUser("user")
-     *                        .password("password")
-     *                        .roles("USER");
-     *     }
-     *
-     *     @Override
-     *     protected void configure(HttpSecurity http) throws Exception {
-     *         http
-     *             .authorizeRequests()
-     *                 .antMatchers("/**").hasRole("USER")
-     *                 .and()
-     *             .formLogin()
-     *                 .permitAll()
-     *                 .and()
-     *              // Example Remember Me Configuration
-     *             .rememberMe();
-     *     }
-     * }
-     * 
- * - * @return the {@link RememberMeConfigurer} for further customizations - * @throws Exception - */ - public RememberMeConfigurer rememberMe() throws Exception { - return getOrApply(new RememberMeConfigurer()); - } + /** + * Allows configuring of Remember Me authentication. + * + *

Example Configuration

+ * + * The following configuration demonstrates how to allow token based remember me + * authentication. Upon authenticating if the HTTP parameter named "remember-me" + * exists, then the user will be remembered even after their + * {@link javax.servlet.http.HttpSession} expires. + * + *
+	 * @Configuration
+	 * @EnableWebSecurity
+	 * public class RememberMeSecurityConfig extends WebSecurityConfigurerAdapter {
+	 * 
+	 * 	@Override
+	 * 	protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+	 * 		auth.inMemoryAuthentication().withUser("user").password("password").roles("USER");
+	 * 	}
+	 * 
+	 * 	@Override
+	 * 	protected void configure(HttpSecurity http) throws Exception {
+	 * 		http.authorizeRequests().antMatchers("/**").hasRole("USER").and().formLogin()
+	 * 				.permitAll().and()
+	 * 				// Example Remember Me Configuration
+	 * 				.rememberMe();
+	 * 	}
+	 * }
+	 * 
+ * + * @return the {@link RememberMeConfigurer} for further customizations + * @throws Exception + */ + public RememberMeConfigurer rememberMe() throws Exception { + return getOrApply(new RememberMeConfigurer()); + } + /** + * Allows restricting access based upon the {@link HttpServletRequest} using + * + *

Example Configurations

+ * + * The most basic example is to configure all URLs to require the role "ROLE_USER". + * The configuration below requires authentication to every URL and will grant access + * to both the user "admin" and "user". + * + *
+	 * @Configuration
+	 * @EnableWebSecurity
+	 * public class AuthorizeUrlsSecurityConfig extends WebSecurityConfigurerAdapter {
+	 * 
+	 * 	@Override
+	 * 	protected void configure(HttpSecurity http) throws Exception {
+	 * 		http.authorizeRequests().antMatchers("/**").hasRole("USER").and().formLogin();
+	 * 	}
+	 * 
+	 * 	@Override
+	 * 	protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+	 * 		auth.inMemoryAuthentication().withUser("user").password("password").roles("USER")
+	 * 				.and().withUser("adminr").password("password").roles("ADMIN", "USER");
+	 * 	}
+	 * }
+	 * 
+ * + * We can also configure multiple URLs. The configuration below requires + * authentication to every URL and will grant access to URLs starting with /admin/ to + * only the "admin" user. All other URLs either user can access. + * + *
+	 * @Configuration
+	 * @EnableWebSecurity
+	 * public class AuthorizeUrlsSecurityConfig extends WebSecurityConfigurerAdapter {
+	 * 
+	 * 	@Override
+	 * 	protected void configure(HttpSecurity http) throws Exception {
+	 * 		http.authorizeRequests().antMatchers("/admin/**").hasRole("ADMIN")
+	 * 				.antMatchers("/**").hasRole("USER").and().formLogin();
+	 * 	}
+	 * 
+	 * 	@Override
+	 * 	protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+	 * 		auth.inMemoryAuthentication().withUser("user").password("password").roles("USER")
+	 * 				.and().withUser("adminr").password("password").roles("ADMIN", "USER");
+	 * 	}
+	 * }
+	 * 
+ * + * Note that the matchers are considered in order. Therefore, the following is invalid + * because the first matcher matches every request and will never get to the second + * mapping: + * + *
+	 * http.authorizeRequests().antMatchers("/**").hasRole("USER").antMatchers("/admin/**")
+	 * 		.hasRole("ADMIN")
+	 * 
+ * + * @see #requestMatcher(RequestMatcher) + * + * @return + * @throws Exception + */ + public ExpressionUrlAuthorizationConfigurer.ExpressionInterceptUrlRegistry authorizeRequests() + throws Exception { + return getOrApply(new ExpressionUrlAuthorizationConfigurer()) + .getRegistry(); + } - /** - * Allows restricting access based upon the {@link HttpServletRequest} using - * - *

Example Configurations

- * - * The most basic example is to configure all URLs to require the role "ROLE_USER". The - * configuration below requires authentication to every URL and will grant access to - * both the user "admin" and "user". - * - *
-     * @Configuration
-     * @EnableWebSecurity
-     * public class AuthorizeUrlsSecurityConfig extends WebSecurityConfigurerAdapter {
-     *
-     *     @Override
-     *     protected void configure(HttpSecurity http) throws Exception {
-     *         http
-     *             .authorizeRequests()
-     *                 .antMatchers("/**").hasRole("USER")
-     *                 .and()
-     *             .formLogin();
-     *     }
-     *
-     *     @Override
-     *     protected void configure(AuthenticationManagerBuilder auth)
-     *             throws Exception {
-     *         auth
-     *              .inMemoryAuthentication()
-     *                   .withUser("user")
-     *                        .password("password")
-     *                        .roles("USER")
-     *                        .and()
-     *                   .withUser("adminr")
-     *                        .password("password")
-     *                        .roles("ADMIN","USER");
-     *     }
-     * }
-     * 
- * - * We can also configure multiple URLs. The configuration below requires authentication to every URL - * and will grant access to URLs starting with /admin/ to only the "admin" user. All other URLs either - * user can access. - * - *
-     * @Configuration
-     * @EnableWebSecurity
-     * public class AuthorizeUrlsSecurityConfig extends WebSecurityConfigurerAdapter {
-     *
-     *     @Override
-     *     protected void configure(HttpSecurity http) throws Exception {
-     *         http
-     *             .authorizeRequests()
-     *                 .antMatchers("/admin/**").hasRole("ADMIN")
-     *                 .antMatchers("/**").hasRole("USER")
-     *                 .and()
-     *             .formLogin();
-     *     }
-     *
-     *     @Override
-     *     protected void configure(AuthenticationManagerBuilder auth)
-     *             throws Exception {
-     *         auth
-     *              .inMemoryAuthentication()
-     *                   .withUser("user")
-     *                        .password("password")
-     *                        .roles("USER")
-     *                        .and()
-     *                   .withUser("adminr")
-     *                        .password("password")
-     *                        .roles("ADMIN","USER");
-     *     }
-     * }
-     * 
- * - * Note that the matchers are considered in order. Therefore, the following is invalid because the first - * matcher matches every request and will never get to the second mapping: - * - *
-     * http
-     *     .authorizeRequests()
-     *         .antMatchers("/**").hasRole("USER")
-     *         .antMatchers("/admin/**").hasRole("ADMIN")
-     * 
- * - * @see #requestMatcher(RequestMatcher) - * - * @return - * @throws Exception - */ - public ExpressionUrlAuthorizationConfigurer.ExpressionInterceptUrlRegistry authorizeRequests() throws Exception { - return getOrApply(new ExpressionUrlAuthorizationConfigurer()).getRegistry(); - } + /** + * Allows configuring the Request Cache. For example, a protected page (/protected) + * may be requested prior to authentication. The application will redirect the user to + * a login page. After authentication, Spring Security will redirect the user to the + * originally requested protected page (/protected). This is automatically applied + * when using {@link WebSecurityConfigurerAdapter}. + * + * @return the {@link RequestCacheConfigurer} for further customizations + * @throws Exception + */ + public RequestCacheConfigurer requestCache() throws Exception { + return getOrApply(new RequestCacheConfigurer()); + } - /** - * Allows configuring the Request Cache. For example, a protected page (/protected) may be requested prior - * to authentication. The application will redirect the user to a login page. After authentication, Spring - * Security will redirect the user to the originally requested protected page (/protected). This is - * automatically applied when using {@link WebSecurityConfigurerAdapter}. - * - * @return the {@link RequestCacheConfigurer} for further customizations - * @throws Exception - */ - public RequestCacheConfigurer requestCache() throws Exception { - return getOrApply(new RequestCacheConfigurer()); - } + /** + * Allows configuring exception handling. This is automatically applied when using + * {@link WebSecurityConfigurerAdapter}. + * + * @return the {@link ExceptionHandlingConfigurer} for further customizations + * @throws Exception + */ + public ExceptionHandlingConfigurer exceptionHandling() throws Exception { + return getOrApply(new ExceptionHandlingConfigurer()); + } - /** - * Allows configuring exception handling. This is automatically applied when using - * {@link WebSecurityConfigurerAdapter}. - * - * @return the {@link ExceptionHandlingConfigurer} for further customizations - * @throws Exception - */ - public ExceptionHandlingConfigurer exceptionHandling() throws Exception { - return getOrApply(new ExceptionHandlingConfigurer()); - } + /** + * Sets up management of the {@link SecurityContext} on the + * {@link SecurityContextHolder} between {@link HttpServletRequest}'s. This is + * automatically applied when using {@link WebSecurityConfigurerAdapter}. + * + * @return the {@link SecurityContextConfigurer} for further customizations + * @throws Exception + */ + public SecurityContextConfigurer securityContext() throws Exception { + return getOrApply(new SecurityContextConfigurer()); + } - /** - * Sets up management of the {@link SecurityContext} on the - * {@link SecurityContextHolder} between {@link HttpServletRequest}'s. This is automatically - * applied when using {@link WebSecurityConfigurerAdapter}. - * - * @return the {@link SecurityContextConfigurer} for further customizations - * @throws Exception - */ - public SecurityContextConfigurer securityContext() throws Exception { - return getOrApply(new SecurityContextConfigurer()); - } + /** + * Integrates the {@link HttpServletRequest} methods with the values found on the + * {@link SecurityContext}. This is automatically applied when using + * {@link WebSecurityConfigurerAdapter}. + * + * @return the {@link ServletApiConfigurer} for further customizations + * @throws Exception + */ + public ServletApiConfigurer servletApi() throws Exception { + return getOrApply(new ServletApiConfigurer()); + } - /** - * Integrates the {@link HttpServletRequest} methods with the values found - * on the {@link SecurityContext}. This is automatically applied when using - * {@link WebSecurityConfigurerAdapter}. - * - * @return the {@link ServletApiConfigurer} for further customizations - * @throws Exception - */ - public ServletApiConfigurer servletApi() throws Exception { - return getOrApply(new ServletApiConfigurer()); - } + /** + * Adds CSRF support. This is activated by default when using + * {@link WebSecurityConfigurerAdapter}'s default constructor. You can disable it + * using: + * + *
+	 * @Configuration
+	 * @EnableWebSecurity
+	 * public class CsrfSecurityConfig extends WebSecurityConfigurerAdapter {
+	 * 
+	 * 	@Override
+	 *     protected void configure(HttpSecurity http) throws Exception {
+	 *         http
+	 *             .csrf().disable()
+	 *             ...;
+	 *     }
+	 * }
+	 * 
+ * + * @return the {@link ServletApiConfigurer} for further customizations + * @throws Exception + */ + public CsrfConfigurer csrf() throws Exception { + return getOrApply(new CsrfConfigurer()); + } + /** + * Provides logout support. This is automatically applied when using + * {@link WebSecurityConfigurerAdapter}. The default is that accessing the URL + * "/logout" will log the user out by invalidating the HTTP Session, cleaning up any + * {@link #rememberMe()} authentication that was configured, clearing the + * {@link SecurityContextHolder}, and then redirect to "/login?success". + * + *

Example Custom Configuration

+ * + * The following customization to log out when the URL "/custom-logout" is invoked. + * Log out will remove the cookie named "remove", not invalidate the HttpSession, + * clear the SecurityContextHolder, and upon completion redirect to "/logout-success". + * + *
+	 * @Configuration
+	 * @EnableWebSecurity
+	 * public class LogoutSecurityConfig extends WebSecurityConfigurerAdapter {
+	 * 
+	 * 	@Override
+	 * 	protected void configure(HttpSecurity http) throws Exception {
+	 * 		http.authorizeRequests().antMatchers("/**").hasRole("USER").and().formLogin()
+	 * 				.and()
+	 * 				// sample logout customization
+	 * 				.logout().logout().deleteCookies("remove").invalidateHttpSession(false)
+	 * 				.logoutUrl("/custom-logout").logoutSuccessUrl("/logout-success");
+	 * 	}
+	 * 
+	 * 	@Override
+	 * 	protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+	 * 		auth.inMemoryAuthentication().withUser("user").password("password").roles("USER");
+	 * 	}
+	 * }
+	 * 
+ * + * @return + * @throws Exception + */ + public LogoutConfigurer logout() throws Exception { + return getOrApply(new LogoutConfigurer()); + } - /** - * Adds CSRF support. This is activated by default when using - * {@link WebSecurityConfigurerAdapter}'s default constructor. You can - * disable it using: - * - *
-     * @Configuration
-     * @EnableWebSecurity
-     * public class CsrfSecurityConfig extends WebSecurityConfigurerAdapter {
-     *
-     *     @Override
-     *     protected void configure(HttpSecurity http) throws Exception {
-     *         http
-     *             .csrf().disable()
-     *             ...;
-     *     }
-     * }
-     * 
- * - * @return the {@link ServletApiConfigurer} for further customizations - * @throws Exception - */ - public CsrfConfigurer csrf() throws Exception { - return getOrApply(new CsrfConfigurer()); - } + /** + * Allows configuring how an anonymous user is represented. This is automatically + * applied when used in conjunction with {@link WebSecurityConfigurerAdapter}. By + * default anonymous users will be represented with an + * {@link org.springframework.security.authentication.AnonymousAuthenticationToken} + * and contain the role "ROLE_ANONYMOUS". + * + *

Example Configuration

+ * @Configuration + * @EnableWebSecurity + * public class AnononymousSecurityConfig extends WebSecurityConfigurerAdapter { + * + * @Override + * protected void configure(HttpSecurity http) throws Exception { + * http.authorizeRequests().antMatchers("/**").hasRole("USER").and().formLogin() + * .and() + * // sample anonymous customization + * .anonymous().authorities("ROLE_ANON"); + * } + * + * @Override + * protected void configure(AuthenticationManagerBuilder auth) throws Exception { + * auth.inMemoryAuthentication().withUser("user").password("password").roles("USER"); + * } + * } + * + * + * The following demonstrates how to represent anonymous users as null. Note that this + * can cause {@link NullPointerException} in code that assumes anonymous + * authentication is enabled. + * + *
+	 * @Configuration
+	 * @EnableWebSecurity
+	 * public class AnononymousSecurityConfig extends WebSecurityConfigurerAdapter {
+	 * 
+	 * 	@Override
+	 * 	protected void configure(HttpSecurity http) throws Exception {
+	 * 		http.authorizeRequests().antMatchers("/**").hasRole("USER").and().formLogin()
+	 * 				.and()
+	 * 				// sample anonymous customization
+	 * 				.anonymous().disabled();
+	 * 	}
+	 * 
+	 * 	@Override
+	 * 	protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+	 * 		auth.inMemoryAuthentication().withUser("user").password("password").roles("USER");
+	 * 	}
+	 * }
+	 * 
+ * + * @return + * @throws Exception + */ + public AnonymousConfigurer anonymous() throws Exception { + return getOrApply(new AnonymousConfigurer()); + } - /** - * Provides logout support. This is automatically applied when using - * {@link WebSecurityConfigurerAdapter}. The default is that accessing - * the URL "/logout" will log the user out by invalidating the HTTP Session, - * cleaning up any {@link #rememberMe()} authentication that was configured, - * clearing the {@link SecurityContextHolder}, and then redirect to - * "/login?success". - * - *

Example Custom Configuration

- * - * The following customization to log out when the URL "/custom-logout" is - * invoked. Log out will remove the cookie named "remove", not invalidate the - * HttpSession, clear the SecurityContextHolder, and upon completion redirect - * to "/logout-success". - * - *
-     * @Configuration
-     * @EnableWebSecurity
-     * public class LogoutSecurityConfig extends WebSecurityConfigurerAdapter {
-     *
-     *     @Override
-     *     protected void configure(HttpSecurity http) throws Exception {
-     *         http
-     *             .authorizeRequests()
-     *                 .antMatchers("/**").hasRole("USER")
-     *                 .and()
-     *             .formLogin()
-     *                 .and()
-     *             // sample logout customization
-     *             .logout()
-     *                 .logout()
-     *                    .deleteCookies("remove")
-     *                    .invalidateHttpSession(false)
-     *                    .logoutUrl("/custom-logout")
-     *                    .logoutSuccessUrl("/logout-success");
-     *     }
-     *
-     *     @Override
-     *     protected void configure(AuthenticationManagerBuilder auth)
-     *             throws Exception {
-     *         auth
-     *              .inMemoryAuthentication()
-     *                   .withUser("user")
-     *                        .password("password")
-     *                        .roles("USER");
-     *     }
-     * }
-     * 
- * - * @return - * @throws Exception - */ - public LogoutConfigurer logout() throws Exception { - return getOrApply(new LogoutConfigurer()); - } + /** + * Specifies to support form based authentication. If + * {@link FormLoginConfigurer#loginPage(String)} is not specified a default login page + * will be generated. + * + *

Example Configurations

+ * + * The most basic configuration defaults to automatically generating a login page at + * the URL "/login", redirecting to "/login?error" for authentication failure. The + * details of the login page can be found on + * {@link FormLoginConfigurer#loginPage(String)} + * + *
+	 * @Configuration
+	 * @EnableWebSecurity
+	 * public class FormLoginSecurityConfig extends WebSecurityConfigurerAdapter {
+	 * 
+	 * 	@Override
+	 * 	protected void configure(HttpSecurity http) throws Exception {
+	 * 		http.authorizeRequests().antMatchers("/**").hasRole("USER").and().formLogin();
+	 * 	}
+	 * 
+	 * 	@Override
+	 * 	protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+	 * 		auth.inMemoryAuthentication().withUser("user").password("password").roles("USER");
+	 * 	}
+	 * }
+	 * 
+ * + * The configuration below demonstrates customizing the defaults. + * + *
+	 * @Configuration
+	 * @EnableWebSecurity
+	 * public class FormLoginSecurityConfig extends WebSecurityConfigurerAdapter {
+	 * 
+	 * 	@Override
+	 * 	protected void configure(HttpSecurity http) throws Exception {
+	 * 		http.authorizeRequests().antMatchers("/**").hasRole("USER").and().formLogin()
+	 * 				.usernameParameter("username") // default is username
+	 * 				.passwordParameter("password") // default is password
+	 * 				.loginPage("/authentication/login") // default is /login with an HTTP get
+	 * 				.failureUrl("/authentication/login?failed") // default is /login?error
+	 * 				.loginProcessingUrl("/authentication/login/process"); // default is /login
+	 * 																		// with an HTTP
+	 * 																		// post
+	 * 	}
+	 * 
+	 * 	@Override
+	 * 	protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+	 * 		auth.inMemoryAuthentication().withUser("user").password("password").roles("USER");
+	 * 	}
+	 * }
+	 * 
+ * + * @see FormLoginConfigurer#loginPage(String) + * + * @return + * @throws Exception + */ + public FormLoginConfigurer formLogin() throws Exception { + return getOrApply(new FormLoginConfigurer()); + } - /** - * Allows configuring how an anonymous user is represented. This is automatically applied - * when used in conjunction with {@link WebSecurityConfigurerAdapter}. By default anonymous - * users will be represented with an {@link org.springframework.security.authentication.AnonymousAuthenticationToken} and contain the role - * "ROLE_ANONYMOUS". - * - *

Example Configuration

- * @Configuration - * @EnableWebSecurity - * public class AnononymousSecurityConfig extends WebSecurityConfigurerAdapter { - * - * @Override - * protected void configure(HttpSecurity http) throws Exception { - * http - * .authorizeRequests() - * .antMatchers("/**").hasRole("USER") - * .and() - * .formLogin() - * .and() - * // sample anonymous customization - * .anonymous() - * .authorities("ROLE_ANON"); - * } - * - * @Override - * protected void configure(AuthenticationManagerBuilder auth) - * throws Exception { - * auth - * .inMemoryAuthentication() - * .withUser("user") - * .password("password") - * .roles("USER"); - * } - * } - * - * - * The following demonstrates how to represent anonymous users as null. Note that this can cause - * {@link NullPointerException} in code that assumes anonymous authentication is enabled. - * - *
-     * @Configuration
-     * @EnableWebSecurity
-     * public class AnononymousSecurityConfig extends WebSecurityConfigurerAdapter {
-     *
-     *     @Override
-     *     protected void configure(HttpSecurity http) throws Exception {
-     *         http
-     *             .authorizeRequests()
-     *                 .antMatchers("/**").hasRole("USER")
-     *                 .and()
-     *             .formLogin()
-     *                 .and()
-     *             // sample anonymous customization
-     *             .anonymous()
-     *                 .disabled();
-     *     }
-     *
-     *     @Override
-     *     protected void configure(AuthenticationManagerBuilder auth)
-     *             throws Exception {
-     *         auth
-     *              .inMemoryAuthentication()
-     *                   .withUser("user")
-     *                        .password("password")
-     *                        .roles("USER");
-     *     }
-     * }
-     * 
- * - * @return - * @throws Exception - */ - public AnonymousConfigurer anonymous() throws Exception { - return getOrApply(new AnonymousConfigurer()); - } + /** + * Configures channel security. In order for this configuration to be useful at least + * one mapping to a required channel must be provided. + * + *

Example Configuration

+ * + * The example below demonstrates how to require HTTPs for every request. Only + * requiring HTTPS for some requests is supported, but not recommended since an + * application that allows for HTTP introduces many security vulnerabilities. For one + * such example, read about Firesheep. + * + *
+	 * @Configuration
+	 * @EnableWebSecurity
+	 * public class ChannelSecurityConfig extends WebSecurityConfigurerAdapter {
+	 * 
+	 * 	@Override
+	 * 	protected void configure(HttpSecurity http) throws Exception {
+	 * 		http.authorizeRequests().antMatchers("/**").hasRole("USER").and().formLogin()
+	 * 				.and().requiresChannel().anyRequest().requiresSecure();
+	 * 	}
+	 * 
+	 * 	@Override
+	 * 	protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+	 * 		auth.inMemoryAuthentication().withUser("user").password("password").roles("USER");
+	 * 	}
+	 * }
+	 * 
+ * + * + * @return the {@link ChannelSecurityConfigurer} for further customizations + * @throws Exception + */ + public ChannelSecurityConfigurer.ChannelRequestMatcherRegistry requiresChannel() + throws Exception { + return getOrApply(new ChannelSecurityConfigurer()).getRegistry(); + } - /** - * Specifies to support form based authentication. If - * {@link FormLoginConfigurer#loginPage(String)} is not specified a - * default login page will be generated. - * - *

Example Configurations

- * - * The most basic configuration defaults to automatically generating a login - * page at the URL "/login", redirecting to "/login?error" for - * authentication failure. The details of the login page can be found on - * {@link FormLoginConfigurer#loginPage(String)} - * - *
-     * @Configuration
-     * @EnableWebSecurity
-     * public class FormLoginSecurityConfig extends WebSecurityConfigurerAdapter {
-     *
-     *     @Override
-     *     protected void configure(HttpSecurity http) throws Exception {
-     *         http
-     *             .authorizeRequests()
-     *                 .antMatchers("/**").hasRole("USER")
-     *                 .and()
-     *             .formLogin();
-     *     }
-     *
-     *     @Override
-     *     protected void configure(AuthenticationManagerBuilder auth)
-     *             throws Exception {
-     *         auth
-     *              .inMemoryAuthentication()
-     *                   .withUser("user")
-     *                        .password("password")
-     *                        .roles("USER");
-     *     }
-     * }
-     * 
- * - * The configuration below demonstrates customizing the defaults. - * - *
-     * @Configuration
-     * @EnableWebSecurity
-     * public class FormLoginSecurityConfig extends WebSecurityConfigurerAdapter {
-     *
-     *     @Override
-     *     protected void configure(HttpSecurity http) throws Exception {
-     *         http
-     *             .authorizeRequests()
-     *                 .antMatchers("/**").hasRole("USER")
-     *                 .and()
-     *             .formLogin()
-     *                    .usernameParameter("username") // default is username
-     *                    .passwordParameter("password") // default is password
-     *                    .loginPage("/authentication/login") // default is /login with an HTTP get
-     *                    .failureUrl("/authentication/login?failed") // default is /login?error
-     *                    .loginProcessingUrl("/authentication/login/process"); // default is /login with an HTTP post
-     *     }
-     *
-     *     @Override
-     *     protected void configure(AuthenticationManagerBuilder auth)
-     *             throws Exception {
-     *         auth
-     *              .inMemoryAuthentication()
-     *                   .withUser("user")
-     *                        .password("password")
-     *                        .roles("USER");
-     *     }
-     * }
-     * 
- * - * @see FormLoginConfigurer#loginPage(String) - * - * @return - * @throws Exception - */ - public FormLoginConfigurer formLogin() throws Exception { - return getOrApply(new FormLoginConfigurer()); - } + /** + * Configures HTTP Basic authentication. + * + *

Example Configuration

+ * + * The example below demonstrates how to configure HTTP Basic authentication for an + * application. The default realm is "Spring Security Application", but can be + * customized using {@link HttpBasicConfigurer#realmName(String)}. + * + *
+	 * @Configuration
+	 * @EnableWebSecurity
+	 * public class HttpBasicSecurityConfig extends WebSecurityConfigurerAdapter {
+	 * 
+	 * 	@Override
+	 * 	protected void configure(HttpSecurity http) throws Exception {
+	 * 		http.authorizeRequests().antMatchers("/**").hasRole("USER").and().httpBasic();
+	 * 	}
+	 * 
+	 * 	@Override
+	 * 	protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+	 * 		auth.inMemoryAuthentication().withUser("user").password("password").roles("USER");
+	 * 	}
+	 * }
+	 * 
+ * + * @return the {@link HttpBasicConfigurer} for further customizations + * @throws Exception + */ + public HttpBasicConfigurer httpBasic() throws Exception { + return getOrApply(new HttpBasicConfigurer()); + } - /** - * Configures channel security. In order for this configuration to be useful at least - * one mapping to a required channel must be provided. - * - *

Example Configuration

- * - * The example below demonstrates how to require HTTPs for every request. Only requiring HTTPS - * for some requests is supported, but not recommended since an application that allows for HTTP - * introduces many security vulnerabilities. For one such example, read about - * Firesheep. - * - *
-     * @Configuration
-     * @EnableWebSecurity
-     * public class ChannelSecurityConfig extends WebSecurityConfigurerAdapter {
-     *
-     *     @Override
-     *     protected void configure(HttpSecurity http) throws Exception {
-     *         http
-     *             .authorizeRequests()
-     *                 .antMatchers("/**").hasRole("USER")
-     *                 .and()
-     *             .formLogin()
-     *                 .and()
-     *             .requiresChannel()
-     *                 .anyRequest().requiresSecure();
-     *     }
-     *
-     *     @Override
-     *     protected void configure(AuthenticationManagerBuilder auth)
-     *             throws Exception {
-     *         auth
-     *              .inMemoryAuthentication()
-     *                   .withUser("user")
-     *                        .password("password")
-     *                        .roles("USER");
-     *     }
-     * }
-     * 
- * - * - * @return the {@link ChannelSecurityConfigurer} for further customizations - * @throws Exception - */ - public ChannelSecurityConfigurer.ChannelRequestMatcherRegistry requiresChannel() throws Exception { - return getOrApply(new ChannelSecurityConfigurer()).getRegistry(); - } + @Override + protected void beforeConfigure() throws Exception { + setSharedObject(AuthenticationManager.class, getAuthenticationRegistry().build()); + } - /** - * Configures HTTP Basic authentication. - * - *

Example Configuration

- * - * The example below demonstrates how to configure HTTP Basic authentication - * for an application. The default realm is "Spring Security Application", - * but can be customized using - * {@link HttpBasicConfigurer#realmName(String)}. - * - *
-     * @Configuration
-     * @EnableWebSecurity
-     * public class HttpBasicSecurityConfig extends WebSecurityConfigurerAdapter {
-     *
-     *     @Override
-     *     protected void configure(HttpSecurity http) throws Exception {
-     *         http
-     *             .authorizeRequests()
-     *                 .antMatchers("/**").hasRole("USER").and()
-     *                 .httpBasic();
-     *     }
-     *
-     *     @Override
-     *     protected void configure(AuthenticationManagerBuilder auth)
-     *             throws Exception {
-     *         auth
-     *             .inMemoryAuthentication()
-     *                 .withUser("user")
-     *                     .password("password")
-     *                     .roles("USER");
-     *     }
-     * }
-     * 
- * - * @return the {@link HttpBasicConfigurer} for further customizations - * @throws Exception - */ - public HttpBasicConfigurer httpBasic() throws Exception { - return getOrApply(new HttpBasicConfigurer()); - } + @Override + protected DefaultSecurityFilterChain performBuild() throws Exception { + Collections.sort(filters, comparitor); + return new DefaultSecurityFilterChain(requestMatcher, filters); + } - @Override - protected void beforeConfigure() throws Exception { - setSharedObject(AuthenticationManager.class,getAuthenticationRegistry().build()); - } + /* + * (non-Javadoc) + * + * @see + * org.springframework.security.config.annotation.web.HttpBuilder#authenticationProvider + * (org.springframework.security.authentication.AuthenticationProvider) + */ + public HttpSecurity authenticationProvider( + AuthenticationProvider authenticationProvider) { + getAuthenticationRegistry().authenticationProvider(authenticationProvider); + return this; + } - @Override - protected DefaultSecurityFilterChain performBuild() throws Exception { - Collections.sort(filters,comparitor); - return new DefaultSecurityFilterChain(requestMatcher, filters); - } + /* + * (non-Javadoc) + * + * @see + * org.springframework.security.config.annotation.web.HttpBuilder#userDetailsService + * (org.springframework.security.core.userdetails.UserDetailsService) + */ + public HttpSecurity userDetailsService(UserDetailsService userDetailsService) + throws Exception { + getAuthenticationRegistry().userDetailsService(userDetailsService); + return this; + } - /* (non-Javadoc) - * @see org.springframework.security.config.annotation.web.HttpBuilder#authenticationProvider(org.springframework.security.authentication.AuthenticationProvider) - */ - public HttpSecurity authenticationProvider(AuthenticationProvider authenticationProvider) { - getAuthenticationRegistry().authenticationProvider(authenticationProvider); - return this; - } + private AuthenticationManagerBuilder getAuthenticationRegistry() { + return getSharedObject(AuthenticationManagerBuilder.class); + } - /* (non-Javadoc) - * @see org.springframework.security.config.annotation.web.HttpBuilder#userDetailsService(org.springframework.security.core.userdetails.UserDetailsService) - */ - public HttpSecurity userDetailsService(UserDetailsService userDetailsService) throws Exception { - getAuthenticationRegistry().userDetailsService(userDetailsService); - return this; - } + /* + * (non-Javadoc) + * + * @see + * org.springframework.security.config.annotation.web.HttpBuilder#addFilterAfter(javax + * .servlet.Filter, java.lang.Class) + */ + public HttpSecurity addFilterAfter(Filter filter, Class afterFilter) { + comparitor.registerAfter(filter.getClass(), afterFilter); + return addFilter(filter); + } - private AuthenticationManagerBuilder getAuthenticationRegistry() { - return getSharedObject(AuthenticationManagerBuilder.class); - } + /* + * (non-Javadoc) + * + * @see + * org.springframework.security.config.annotation.web.HttpBuilder#addFilterBefore( + * javax.servlet.Filter, java.lang.Class) + */ + public HttpSecurity addFilterBefore(Filter filter, + Class beforeFilter) { + comparitor.registerBefore(filter.getClass(), beforeFilter); + return addFilter(filter); + } - /* (non-Javadoc) - * @see org.springframework.security.config.annotation.web.HttpBuilder#addFilterAfter(javax.servlet.Filter, java.lang.Class) - */ - public HttpSecurity addFilterAfter(Filter filter, Class afterFilter) { - comparitor.registerAfter(filter.getClass(), afterFilter); - return addFilter(filter); - } + /* + * (non-Javadoc) + * + * @see + * org.springframework.security.config.annotation.web.HttpBuilder#addFilter(javax. + * servlet.Filter) + */ + public HttpSecurity addFilter(Filter filter) { + Class filterClass = filter.getClass(); + if (!comparitor.isRegistered(filterClass)) { + throw new IllegalArgumentException( + "The Filter class " + + filterClass.getName() + + " does not have a registered order and cannot be added without a specified order. Consider using addFilterBefore or addFilterAfter instead."); + } + this.filters.add(filter); + return this; + } - /* (non-Javadoc) - * @see org.springframework.security.config.annotation.web.HttpBuilder#addFilterBefore(javax.servlet.Filter, java.lang.Class) - */ - public HttpSecurity addFilterBefore(Filter filter, Class beforeFilter) { - comparitor.registerBefore(filter.getClass(), beforeFilter); - return addFilter(filter); - } + /** + * Allows specifying which {@link HttpServletRequest} instances this + * {@link HttpSecurity} will be invoked on. This method allows for easily invoking the + * {@link HttpSecurity} for multiple different {@link RequestMatcher} instances. If + * only a single {@link RequestMatcher} is necessary consider using + * {@link #antMatcher(String)}, {@link #regexMatcher(String)}, or + * {@link #requestMatcher(RequestMatcher)}. + * + *

+ * Invoking {@link #requestMatchers()} will override previous invocations of + * {@link #requestMatchers()}, {@link #antMatcher(String)}, + * {@link #regexMatcher(String)}, and {@link #requestMatcher(RequestMatcher)}. + *

+ * + *

Example Configurations

+ * + * The following configuration enables the {@link HttpSecurity} for URLs that begin + * with "/api/" or "/oauth/". + * + *
+	 * @Configuration
+	 * @EnableWebSecurity
+	 * public class RequestMatchersSecurityConfig extends WebSecurityConfigurerAdapter {
+	 * 
+	 * 	@Override
+	 * 	protected void configure(HttpSecurity http) throws Exception {
+	 * 		http.requestMatchers().antMatchers("/api/**", "/oauth/**").and()
+	 * 				.authorizeRequests().antMatchers("/**").hasRole("USER").and().httpBasic();
+	 * 	}
+	 * 
+	 * 	@Override
+	 * 	protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+	 * 		auth.inMemoryAuthentication().withUser("user").password("password").roles("USER");
+	 * 	}
+	 * }
+	 * 
+ * + * The configuration below is the same as the previous configuration. + * + *
+	 * @Configuration
+	 * @EnableWebSecurity
+	 * public class RequestMatchersSecurityConfig extends WebSecurityConfigurerAdapter {
+	 * 
+	 * 	@Override
+	 * 	protected void configure(HttpSecurity http) throws Exception {
+	 * 		http.requestMatchers().antMatchers("/api/**").antMatchers("/oauth/**").and()
+	 * 				.authorizeRequests().antMatchers("/**").hasRole("USER").and().httpBasic();
+	 * 	}
+	 * 
+	 * 	@Override
+	 * 	protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+	 * 		auth.inMemoryAuthentication().withUser("user").password("password").roles("USER");
+	 * 	}
+	 * }
+	 * 
+ * + * The configuration below is also the same as the above configuration. + * + *
+	 * @Configuration
+	 * @EnableWebSecurity
+	 * public class RequestMatchersSecurityConfig extends WebSecurityConfigurerAdapter {
+	 * 
+	 * 	@Override
+	 * 	protected void configure(HttpSecurity http) throws Exception {
+	 * 		http.requestMatchers().antMatchers("/api/**").and().requestMatchers()
+	 * 				.antMatchers("/oauth/**").and().authorizeRequests().antMatchers("/**")
+	 * 				.hasRole("USER").and().httpBasic();
+	 * 	}
+	 * 
+	 * 	@Override
+	 * 	protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+	 * 		auth.inMemoryAuthentication().withUser("user").password("password").roles("USER");
+	 * 	}
+	 * }
+	 * 
+ * + * @return the {@link RequestMatcherConfigurer} for further customizations + */ + public RequestMatcherConfigurer requestMatchers() { + return requestMatcherConfigurer; + } - /* (non-Javadoc) - * @see org.springframework.security.config.annotation.web.HttpBuilder#addFilter(javax.servlet.Filter) - */ - public HttpSecurity addFilter(Filter filter) { - Class filterClass = filter.getClass(); - if(!comparitor.isRegistered(filterClass)) { - throw new IllegalArgumentException( - "The Filter class " + filterClass.getName() - + " does not have a registered order and cannot be added without a specified order. Consider using addFilterBefore or addFilterAfter instead."); - } - this.filters.add(filter); - return this; - } + /** + * Allows configuring the {@link HttpSecurity} to only be invoked when matching the + * provided {@link RequestMatcher}. If more advanced configuration is necessary, + * consider using {@link #requestMatchers()}. + * + *

+ * Invoking {@link #requestMatcher(RequestMatcher)} will override previous invocations + * of {@link #requestMatchers()}, {@link #antMatcher(String)}, + * {@link #regexMatcher(String)}, and {@link #requestMatcher(RequestMatcher)}. + *

+ * + * @param requestMatcher the {@link RequestMatcher} to use (i.e. new + * AntPathRequestMatcher("/admin/**","GET") ) + * @return the {@link HttpSecurity} for further customizations + * @see #requestMatchers() + * @see #antMatcher(String) + * @see #regexMatcher(String) + */ + public HttpSecurity requestMatcher(RequestMatcher requestMatcher) { + this.requestMatcher = requestMatcher; + return this; + } - /** - * Allows specifying which {@link HttpServletRequest} instances this - * {@link HttpSecurity} will be invoked on. This method allows for - * easily invoking the {@link HttpSecurity} for multiple - * different {@link RequestMatcher} instances. If only a single {@link RequestMatcher} - * is necessary consider using {@link #antMatcher(String)}, - * {@link #regexMatcher(String)}, or {@link #requestMatcher(RequestMatcher)}. - * - *

- * Invoking {@link #requestMatchers()} will override previous invocations of - * {@link #requestMatchers()}, {@link #antMatcher(String)}, {@link #regexMatcher(String)}, - * and {@link #requestMatcher(RequestMatcher)}. - *

- * - *

Example Configurations

- * - * The following configuration enables the {@link HttpSecurity} for URLs that - * begin with "/api/" or "/oauth/". - * - *
-     * @Configuration
-     * @EnableWebSecurity
-     * public class RequestMatchersSecurityConfig extends WebSecurityConfigurerAdapter {
-     *
-     *     @Override
-     *     protected void configure(HttpSecurity http) throws Exception {
-     *         http
-     *             .requestMatchers()
-     *                 .antMatchers("/api/**","/oauth/**")
-     *                 .and()
-     *             .authorizeRequests()
-     *                 .antMatchers("/**").hasRole("USER").and()
-     *                 .httpBasic();
-     *     }
-     *
-     *     @Override
-     *     protected void configure(AuthenticationManagerBuilder auth)
-     *             throws Exception {
-     *         auth
-     *             .inMemoryAuthentication()
-     *                 .withUser("user")
-     *                     .password("password")
-     *                     .roles("USER");
-     *     }
-     * }
-     * 
- * - * The configuration below is the same as the previous configuration. - * - *
-     * @Configuration
-     * @EnableWebSecurity
-     * public class RequestMatchersSecurityConfig extends WebSecurityConfigurerAdapter {
-     *
-     *     @Override
-     *     protected void configure(HttpSecurity http) throws Exception {
-     *         http
-     *             .requestMatchers()
-     *                 .antMatchers("/api/**")
-     *                 .antMatchers("/oauth/**")
-     *                 .and()
-     *             .authorizeRequests()
-     *                 .antMatchers("/**").hasRole("USER").and()
-     *                 .httpBasic();
-     *     }
-     *
-     *     @Override
-     *     protected void configure(AuthenticationManagerBuilder auth)
-     *             throws Exception {
-     *         auth
-     *             .inMemoryAuthentication()
-     *                 .withUser("user")
-     *                     .password("password")
-     *                     .roles("USER");
-     *     }
-     * }
-     * 
- * - * The configuration below is also the same as the above configuration. - * - *
-     * @Configuration
-     * @EnableWebSecurity
-     * public class RequestMatchersSecurityConfig extends WebSecurityConfigurerAdapter {
-     *
-     *     @Override
-     *     protected void configure(HttpSecurity http) throws Exception {
-     *         http
-     *             .requestMatchers()
-     *                 .antMatchers("/api/**")
-     *                 .and()
-     *             .requestMatchers()
-     *                 .antMatchers("/oauth/**")
-     *                 .and()
-     *             .authorizeRequests()
-     *                 .antMatchers("/**").hasRole("USER").and()
-     *                 .httpBasic();
-     *     }
-     *
-     *     @Override
-     *     protected void configure(AuthenticationManagerBuilder auth)
-     *             throws Exception {
-     *         auth
-     *             .inMemoryAuthentication()
-     *                 .withUser("user")
-     *                     .password("password")
-     *                     .roles("USER");
-     *     }
-     * }
-     * 
- * - * @return the {@link RequestMatcherConfigurer} for further customizations - */ - public RequestMatcherConfigurer requestMatchers() { - return requestMatcherConfigurer; - } + /** + * Allows configuring the {@link HttpSecurity} to only be invoked when matching the + * provided ant pattern. If more advanced configuration is necessary, consider using + * {@link #requestMatchers()} or {@link #requestMatcher(RequestMatcher)}. + * + *

+ * Invoking {@link #antMatcher(String)} will override previous invocations of + * {@link #requestMatchers()}, {@link #antMatcher(String)}, + * {@link #regexMatcher(String)}, and {@link #requestMatcher(RequestMatcher)}. + *

+ * + * @param antPattern the Ant Pattern to match on (i.e. "/admin/**") + * @return the {@link HttpSecurity} for further customizations + * @see AntPathRequestMatcher + */ + public HttpSecurity antMatcher(String antPattern) { + return requestMatcher(new AntPathRequestMatcher(antPattern)); + } - /** - * Allows configuring the {@link HttpSecurity} to only be invoked when - * matching the provided {@link RequestMatcher}. If more advanced configuration is - * necessary, consider using {@link #requestMatchers()}. - * - *

- * Invoking {@link #requestMatcher(RequestMatcher)} will override previous invocations of - * {@link #requestMatchers()}, {@link #antMatcher(String)}, {@link #regexMatcher(String)}, - * and {@link #requestMatcher(RequestMatcher)}. - *

- * - * @param requestMatcher the {@link RequestMatcher} to use (i.e. new AntPathRequestMatcher("/admin/**","GET") ) - * @return the {@link HttpSecurity} for further customizations - * @see #requestMatchers() - * @see #antMatcher(String) - * @see #regexMatcher(String) - */ - public HttpSecurity requestMatcher(RequestMatcher requestMatcher) { - this.requestMatcher = requestMatcher; - return this; - } + /** + * Allows configuring the {@link HttpSecurity} to only be invoked when matching the + * provided regex pattern. If more advanced configuration is necessary, consider using + * {@link #requestMatchers()} or {@link #requestMatcher(RequestMatcher)}. + * + *

+ * Invoking {@link #regexMatcher(String)} will override previous invocations of + * {@link #requestMatchers()}, {@link #antMatcher(String)}, + * {@link #regexMatcher(String)}, and {@link #requestMatcher(RequestMatcher)}. + *

+ * + * @param pattern the Regular Expression to match on (i.e. "/admin/.+") + * @return the {@link HttpSecurity} for further customizations + * @see RegexRequestMatcher + */ + public HttpSecurity regexMatcher(String pattern) { + return requestMatcher(new RegexRequestMatcher(pattern, null)); + } - /** - * Allows configuring the {@link HttpSecurity} to only be invoked when - * matching the provided ant pattern. If more advanced configuration is - * necessary, consider using {@link #requestMatchers()} or - * {@link #requestMatcher(RequestMatcher)}. - * - *

- * Invoking {@link #antMatcher(String)} will override previous invocations of - * {@link #requestMatchers()}, {@link #antMatcher(String)}, {@link #regexMatcher(String)}, - * and {@link #requestMatcher(RequestMatcher)}. - *

- * - * @param antPattern the Ant Pattern to match on (i.e. "/admin/**") - * @return the {@link HttpSecurity} for further customizations - * @see AntPathRequestMatcher - */ - public HttpSecurity antMatcher(String antPattern) { - return requestMatcher(new AntPathRequestMatcher(antPattern)); - } + /** + * Allows mapping HTTP requests that this {@link HttpSecurity} will be used for + * + * @author Rob Winch + * @since 3.2 + */ + public final class RequestMatcherConfigurer extends + AbstractRequestMatcherRegistry { + private List matchers = new ArrayList(); - /** - * Allows configuring the {@link HttpSecurity} to only be invoked when - * matching the provided regex pattern. If more advanced configuration is - * necessary, consider using {@link #requestMatchers()} or - * {@link #requestMatcher(RequestMatcher)}. - * - *

- * Invoking {@link #regexMatcher(String)} will override previous invocations of - * {@link #requestMatchers()}, {@link #antMatcher(String)}, {@link #regexMatcher(String)}, - * and {@link #requestMatcher(RequestMatcher)}. - *

- * - * @param pattern the Regular Expression to match on (i.e. "/admin/.+") - * @return the {@link HttpSecurity} for further customizations - * @see RegexRequestMatcher - */ - public HttpSecurity regexMatcher(String pattern) { - return requestMatcher(new RegexRequestMatcher(pattern, null)); - } + protected RequestMatcherConfigurer chainRequestMatchers( + List requestMatchers) { + matchers.addAll(requestMatchers); + requestMatcher(new OrRequestMatcher(matchers)); + return this; + } - /** - * Allows mapping HTTP requests that this {@link HttpSecurity} will be used for - * - * @author Rob Winch - * @since 3.2 - */ - public final class RequestMatcherConfigurer extends AbstractRequestMatcherRegistry { - private List matchers = new ArrayList(); + /** + * Return the {@link HttpSecurity} for further customizations + * + * @return the {@link HttpSecurity} for further customizations + */ + public HttpSecurity and() { + return HttpSecurity.this; + } - protected RequestMatcherConfigurer chainRequestMatchers(List requestMatchers) { - matchers.addAll(requestMatchers); - requestMatcher(new OrRequestMatcher(matchers)); - return this; - } + private RequestMatcherConfigurer() { + } + } - /** - * Return the {@link HttpSecurity} for further customizations - * - * @return the {@link HttpSecurity} for further customizations - */ - public HttpSecurity and() { - return HttpSecurity.this; - } - - private RequestMatcherConfigurer(){} - } - - /** - * If the {@link SecurityConfigurer} has already been specified get the original, otherwise apply the new {@link SecurityConfigurerAdapter}. - * - * @param configurer the {@link SecurityConfigurer} to apply if one is not found for this {@link SecurityConfigurer} class. - * @return the current {@link SecurityConfigurer} for the configurer passed in - * @throws Exception - */ - @SuppressWarnings("unchecked") - private > C getOrApply(C configurer) - throws Exception { - C existingConfig = (C) getConfigurer(configurer.getClass()); - if(existingConfig != null) { - return existingConfig; - } - return apply(configurer); - } + /** + * If the {@link SecurityConfigurer} has already been specified get the original, + * otherwise apply the new {@link SecurityConfigurerAdapter}. + * + * @param configurer the {@link SecurityConfigurer} to apply if one is not found for + * this {@link SecurityConfigurer} class. + * @return the current {@link SecurityConfigurer} for the configurer passed in + * @throws Exception + */ + @SuppressWarnings("unchecked") + private > C getOrApply( + C configurer) throws Exception { + C existingConfig = (C) getConfigurer(configurer.getClass()); + if (existingConfig != null) { + return existingConfig; + } + return apply(configurer); + } } \ No newline at end of file diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/builders/WebSecurity.java b/config/src/main/java/org/springframework/security/config/annotation/web/builders/WebSecurity.java index 7cc60e646a..c495ade82e 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/builders/WebSecurity.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/builders/WebSecurity.java @@ -53,10 +53,10 @@ import org.springframework.web.filter.DelegatingFilterProxy; /** *

- * The {@link WebSecurity} is created by {@link WebSecurityConfiguration} - * to create the {@link FilterChainProxy} known as the Spring Security Filter - * Chain (springSecurityFilterChain). The springSecurityFilterChain is the - * {@link Filter} that the {@link DelegatingFilterProxy} delegates to. + * The {@link WebSecurity} is created by {@link WebSecurityConfiguration} to create the + * {@link FilterChainProxy} known as the Spring Security Filter Chain + * (springSecurityFilterChain). The springSecurityFilterChain is the {@link Filter} that + * the {@link DelegatingFilterProxy} delegates to. *

* *

@@ -72,273 +72,272 @@ import org.springframework.web.filter.DelegatingFilterProxy; * @since 3.2 */ public final class WebSecurity extends - AbstractConfiguredSecurityBuilder implements SecurityBuilder, ApplicationContextAware { - private final Log logger = LogFactory.getLog(getClass()); + AbstractConfiguredSecurityBuilder implements + SecurityBuilder, ApplicationContextAware { + private final Log logger = LogFactory.getLog(getClass()); - private final List ignoredRequests = new ArrayList(); + private final List ignoredRequests = new ArrayList(); - private final List> securityFilterChainBuilders = - new ArrayList>(); + private final List> securityFilterChainBuilders = new ArrayList>(); - private final IgnoredRequestConfigurer ignoredRequestRegistry = - new IgnoredRequestConfigurer(); + private final IgnoredRequestConfigurer ignoredRequestRegistry = new IgnoredRequestConfigurer(); - private FilterSecurityInterceptor filterSecurityInterceptor; + private FilterSecurityInterceptor filterSecurityInterceptor; - private HttpFirewall httpFirewall; + private HttpFirewall httpFirewall; - private boolean debugEnabled; + private boolean debugEnabled; - private WebInvocationPrivilegeEvaluator privilegeEvaluator; + private WebInvocationPrivilegeEvaluator privilegeEvaluator; - private DefaultWebSecurityExpressionHandler defaultWebSecurityExpressionHandler = new DefaultWebSecurityExpressionHandler(); + private DefaultWebSecurityExpressionHandler defaultWebSecurityExpressionHandler = new DefaultWebSecurityExpressionHandler(); - private SecurityExpressionHandler expressionHandler = defaultWebSecurityExpressionHandler; + private SecurityExpressionHandler expressionHandler = defaultWebSecurityExpressionHandler; + private Runnable postBuildAction = new Runnable() { + public void run() { + } + }; - private Runnable postBuildAction = new Runnable() { - public void run() {} - }; + /** + * Creates a new instance + * @param objectPostProcessor the {@link ObjectPostProcessor} to use + * @see WebSecurityConfiguration + */ + public WebSecurity(ObjectPostProcessor objectPostProcessor) { + super(objectPostProcessor); + } - /** - * Creates a new instance - * @param objectPostProcessor the {@link ObjectPostProcessor} to use - * @see WebSecurityConfiguration - */ - public WebSecurity(ObjectPostProcessor objectPostProcessor) { - super(objectPostProcessor); - } + /** + *

+ * Allows adding {@link RequestMatcher} instances that should that Spring Security + * should ignore. Web Security provided by Spring Security (including the + * {@link SecurityContext}) will not be available on {@link HttpServletRequest} that + * match. Typically the requests that are registered should be that of only static + * resources. For requests that are dynamic, consider mapping the request to allow all + * users instead. + *

+ * + * Example Usage: + * + *
+	 * webSecurityBuilder.ignoring()
+	 * // ignore all URLs that start with /resources/ or /static/
+	 * 		.antMatchers("/resources/**", "/static/**");
+	 * 
+ * + * Alternatively this will accomplish the same result: + * + *
+	 * webSecurityBuilder.ignoring()
+	 * // ignore all URLs that start with /resources/ or /static/
+	 * 		.antMatchers("/resources/**").antMatchers("/static/**");
+	 * 
+ * + * Multiple invocations of ignoring() are also additive, so the following is also + * equivalent to the previous two examples: + * + * Alternatively this will accomplish the same result: + * + *
+	 * webSecurityBuilder.ignoring()
+	 * // ignore all URLs that start with /resources/
+	 * 		.antMatchers("/resources/**");
+	 * webSecurityBuilder.ignoring()
+	 * // ignore all URLs that start with /static/
+	 * 		.antMatchers("/static/**");
+	 * // now both URLs that start with /resources/ and /static/ will be ignored
+	 * 
+ * + * @return the {@link IgnoredRequestConfigurer} to use for registering request that + * should be ignored + */ + public IgnoredRequestConfigurer ignoring() { + return ignoredRequestRegistry; + } - /** - *

- * Allows adding {@link RequestMatcher} instances that should that Spring - * Security should ignore. Web Security provided by Spring Security - * (including the {@link SecurityContext}) will not be available on - * {@link HttpServletRequest} that match. Typically the requests that are - * registered should be that of only static resources. For requests that are - * dynamic, consider mapping the request to allow all users instead. - *

- * - * Example Usage: - * - *
-     * webSecurityBuilder
-     *     .ignoring()
-     *         // ignore all URLs that start with /resources/ or /static/
-     *         .antMatchers("/resources/**", "/static/**");
-     * 
- * - * Alternatively this will accomplish the same result: - * - *
-     * webSecurityBuilder
-     *     .ignoring()
-     *         // ignore all URLs that start with /resources/ or /static/
-     *         .antMatchers("/resources/**")
-     *         .antMatchers("/static/**");
-     * 
- * - * Multiple invocations of ignoring() are also additive, so the following is - * also equivalent to the previous two examples: - * - * Alternatively this will accomplish the same result: - * - *
-     * webSecurityBuilder
-     *     .ignoring()
-     *         // ignore all URLs that start with /resources/
-     *         .antMatchers("/resources/**");
-     * webSecurityBuilder
-     *     .ignoring()
-     *         // ignore all URLs that start with /static/
-     *         .antMatchers("/static/**");
-     * // now both URLs that start with /resources/ and /static/ will be ignored
-     * 
- * - * @return the {@link IgnoredRequestConfigurer} to use for registering request - * that should be ignored - */ - public IgnoredRequestConfigurer ignoring() { - return ignoredRequestRegistry; - } + /** + * Allows customizing the {@link HttpFirewall}. The default is + * {@link DefaultHttpFirewall}. + * + * @param httpFirewall the custom {@link HttpFirewall} + * @return the {@link WebSecurity} for further customizations + */ + public WebSecurity httpFirewall(HttpFirewall httpFirewall) { + this.httpFirewall = httpFirewall; + return this; + } - /** - * Allows customizing the {@link HttpFirewall}. The default is - * {@link DefaultHttpFirewall}. - * - * @param httpFirewall the custom {@link HttpFirewall} - * @return the {@link WebSecurity} for further customizations - */ - public WebSecurity httpFirewall(HttpFirewall httpFirewall) { - this.httpFirewall = httpFirewall; - return this; - } + /** + * Controls debugging support for Spring Security. + * + * @param debugEnabled if true, enables debug support with Spring Security. Default is + * false. + * + * @return the {@link WebSecurity} for further customization. + * @see EnableWebSecurity#debug() + */ + public WebSecurity debug(boolean debugEnabled) { + this.debugEnabled = debugEnabled; + return this; + } - /** - * Controls debugging support for Spring Security. - * - * @param debugEnabled - * if true, enables debug support with Spring Security. Default - * is false. - * - * @return the {@link WebSecurity} for further customization. - * @see EnableWebSecurity#debug() - */ - public WebSecurity debug(boolean debugEnabled) { - this.debugEnabled = debugEnabled; - return this; - } + /** + *

+ * Adds builders to create {@link SecurityFilterChain} instances. + *

+ * + *

+ * Typically this method is invoked automatically within the framework from + * {@link WebSecurityConfigurerAdapter#init(WebSecurity)} + *

+ * + * @param securityFilterChainBuilder the builder to use to create the + * {@link SecurityFilterChain} instances + * @return the {@link WebSecurity} for further customizations + */ + public WebSecurity addSecurityFilterChainBuilder( + SecurityBuilder securityFilterChainBuilder) { + this.securityFilterChainBuilders.add(securityFilterChainBuilder); + return this; + } - /** - *

- * Adds builders to create {@link SecurityFilterChain} instances. - *

- * - *

- * Typically this method is invoked automatically within the framework from - * {@link WebSecurityConfigurerAdapter#init(WebSecurity)} - *

- * - * @param securityFilterChainBuilder - * the builder to use to create the {@link SecurityFilterChain} - * instances - * @return the {@link WebSecurity} for further customizations - */ - public WebSecurity addSecurityFilterChainBuilder(SecurityBuilder securityFilterChainBuilder) { - this.securityFilterChainBuilders.add(securityFilterChainBuilder); - return this; - } + /** + * Set the {@link WebInvocationPrivilegeEvaluator} to be used. If this is null, then a + * {@link DefaultWebInvocationPrivilegeEvaluator} will be created when + * {@link #securityInterceptor(FilterSecurityInterceptor)} is non null. + * + * @param privilegeEvaluator the {@link WebInvocationPrivilegeEvaluator} to use + * @return the {@link WebSecurity} for further customizations + */ + public WebSecurity privilegeEvaluator( + WebInvocationPrivilegeEvaluator privilegeEvaluator) { + this.privilegeEvaluator = privilegeEvaluator; + return this; + } - /** - * Set the {@link WebInvocationPrivilegeEvaluator} to be used. If this is - * null, then a {@link DefaultWebInvocationPrivilegeEvaluator} will be - * created when {@link #securityInterceptor(FilterSecurityInterceptor)} - * is non null. - * - * @param privilegeEvaluator - * the {@link WebInvocationPrivilegeEvaluator} to use - * @return the {@link WebSecurity} for further customizations - */ - public WebSecurity privilegeEvaluator(WebInvocationPrivilegeEvaluator privilegeEvaluator) { - this.privilegeEvaluator = privilegeEvaluator; - return this; - } + /** + * Set the {@link SecurityExpressionHandler} to be used. If this is null, then a + * {@link DefaultWebSecurityExpressionHandler} will be used. + * + * @param expressionHandler the {@link SecurityExpressionHandler} to use + * @return the {@link WebSecurity} for further customizations + */ + public WebSecurity expressionHandler( + SecurityExpressionHandler expressionHandler) { + Assert.notNull(expressionHandler, "expressionHandler cannot be null"); + this.expressionHandler = expressionHandler; + return this; + } - /** - * Set the {@link SecurityExpressionHandler} to be used. If this is null, - * then a {@link DefaultWebSecurityExpressionHandler} will be used. - * - * @param expressionHandler - * the {@link SecurityExpressionHandler} to use - * @return the {@link WebSecurity} for further customizations - */ - public WebSecurity expressionHandler(SecurityExpressionHandler expressionHandler) { - Assert.notNull(expressionHandler, "expressionHandler cannot be null"); - this.expressionHandler = expressionHandler; - return this; - } + /** + * Gets the {@link SecurityExpressionHandler} to be used. + * @return + */ + public SecurityExpressionHandler getExpressionHandler() { + return expressionHandler; + } - /** - * Gets the {@link SecurityExpressionHandler} to be used. - * @return - */ - public SecurityExpressionHandler getExpressionHandler() { - return expressionHandler; - } + /** + * Gets the {@link WebInvocationPrivilegeEvaluator} to be used. + * @return + */ + public WebInvocationPrivilegeEvaluator getPrivilegeEvaluator() { + if (privilegeEvaluator != null) { + return privilegeEvaluator; + } + return filterSecurityInterceptor == null ? null + : new DefaultWebInvocationPrivilegeEvaluator(filterSecurityInterceptor); + } - /** - * Gets the {@link WebInvocationPrivilegeEvaluator} to be used. - * @return - */ - public WebInvocationPrivilegeEvaluator getPrivilegeEvaluator() { - if(privilegeEvaluator != null) { - return privilegeEvaluator; - } - return filterSecurityInterceptor == null ? null : new DefaultWebInvocationPrivilegeEvaluator(filterSecurityInterceptor); - } + /** + * Sets the {@link FilterSecurityInterceptor}. This is typically invoked by + * {@link WebSecurityConfigurerAdapter}. + * @param securityInterceptor the {@link FilterSecurityInterceptor} to use + * @return the {@link WebSecurity} for further customizations + */ + public WebSecurity securityInterceptor(FilterSecurityInterceptor securityInterceptor) { + this.filterSecurityInterceptor = securityInterceptor; + return this; + } - /** - * Sets the {@link FilterSecurityInterceptor}. This is typically invoked by {@link WebSecurityConfigurerAdapter}. - * @param securityInterceptor the {@link FilterSecurityInterceptor} to use - * @return the {@link WebSecurity} for further customizations - */ - public WebSecurity securityInterceptor(FilterSecurityInterceptor securityInterceptor) { - this.filterSecurityInterceptor = securityInterceptor; - return this; - } + /** + * Executes the Runnable immediately after the build takes place + * + * @param postBuildAction + * @return the {@link WebSecurity} for further customizations + */ + public WebSecurity postBuildAction(Runnable postBuildAction) { + this.postBuildAction = postBuildAction; + return this; + } - /** - * Executes the Runnable immediately after the build takes place - * - * @param postBuildAction - * @return the {@link WebSecurity} for further customizations - */ - public WebSecurity postBuildAction(Runnable postBuildAction) { - this.postBuildAction = postBuildAction; - return this; - } + @Override + protected Filter performBuild() throws Exception { + Assert.state( + !securityFilterChainBuilders.isEmpty(), + "At least one SecurityBuilder needs to be specified. Typically this done by adding a @Configuration that extends WebSecurityConfigurerAdapter. More advanced users can invoke " + + WebSecurity.class.getSimpleName() + + ".addSecurityFilterChainBuilder directly"); + int chainSize = ignoredRequests.size() + securityFilterChainBuilders.size(); + List securityFilterChains = new ArrayList( + chainSize); + for (RequestMatcher ignoredRequest : ignoredRequests) { + securityFilterChains.add(new DefaultSecurityFilterChain(ignoredRequest)); + } + for (SecurityBuilder securityFilterChainBuilder : securityFilterChainBuilders) { + securityFilterChains.add(securityFilterChainBuilder.build()); + } + FilterChainProxy filterChainProxy = new FilterChainProxy(securityFilterChains); + if (httpFirewall != null) { + filterChainProxy.setFirewall(httpFirewall); + } + filterChainProxy.afterPropertiesSet(); - @Override - protected Filter performBuild() throws Exception { - Assert.state(!securityFilterChainBuilders.isEmpty(), - "At least one SecurityBuilder needs to be specified. Typically this done by adding a @Configuration that extends WebSecurityConfigurerAdapter. More advanced users can invoke " - + WebSecurity.class.getSimpleName() - + ".addSecurityFilterChainBuilder directly"); - int chainSize = ignoredRequests.size() + securityFilterChainBuilders.size(); - List securityFilterChains = new ArrayList(chainSize); - for(RequestMatcher ignoredRequest : ignoredRequests) { - securityFilterChains.add(new DefaultSecurityFilterChain(ignoredRequest)); - } - for(SecurityBuilder securityFilterChainBuilder : securityFilterChainBuilders) { - securityFilterChains.add(securityFilterChainBuilder.build()); - } - FilterChainProxy filterChainProxy = new FilterChainProxy(securityFilterChains); - if(httpFirewall != null) { - filterChainProxy.setFirewall(httpFirewall); - } - filterChainProxy.afterPropertiesSet(); + Filter result = filterChainProxy; + if (debugEnabled) { + logger.warn("\n\n" + + "********************************************************************\n" + + "********** Security debugging is enabled. *************\n" + + "********** This may include sensitive information. *************\n" + + "********** Do not use in a production system! *************\n" + + "********************************************************************\n\n"); + result = new DebugFilter(filterChainProxy); + } + postBuildAction.run(); + return result; + } - Filter result = filterChainProxy; - if(debugEnabled) { - logger.warn("\n\n" + - "********************************************************************\n" + - "********** Security debugging is enabled. *************\n" + - "********** This may include sensitive information. *************\n" + - "********** Do not use in a production system! *************\n" + - "********************************************************************\n\n"); - result = new DebugFilter(filterChainProxy); - } - postBuildAction.run(); - return result; - } + /** + * Allows registering {@link RequestMatcher} instances that should be ignored by + * Spring Security. + * + * @author Rob Winch + * @since 3.2 + */ + public final class IgnoredRequestConfigurer extends + AbstractRequestMatcherRegistry { - /** - * Allows registering {@link RequestMatcher} instances that should be - * ignored by Spring Security. - * - * @author Rob Winch - * @since 3.2 - */ - public final class IgnoredRequestConfigurer extends AbstractRequestMatcherRegistry { + @Override + protected IgnoredRequestConfigurer chainRequestMatchers( + List requestMatchers) { + ignoredRequests.addAll(requestMatchers); + return this; + } - @Override - protected IgnoredRequestConfigurer chainRequestMatchers(List requestMatchers) { - ignoredRequests.addAll(requestMatchers); - return this; - } + /** + * Returns the {@link WebSecurity} to be returned for chaining. + */ + public WebSecurity and() { + return WebSecurity.this; + } - /** - * Returns the {@link WebSecurity} to be returned for chaining. - */ - public WebSecurity and() { - return WebSecurity.this; - } + private IgnoredRequestConfigurer() { + } + } - private IgnoredRequestConfigurer(){} - } - - public void setApplicationContext(ApplicationContext applicationContext) - throws BeansException { - defaultWebSecurityExpressionHandler.setApplicationContext(applicationContext); - } + public void setApplicationContext(ApplicationContext applicationContext) + throws BeansException { + defaultWebSecurityExpressionHandler.setApplicationContext(applicationContext); + } } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configuration/AutowiredWebSecurityConfigurersIgnoreParents.java b/config/src/main/java/org/springframework/security/config/annotation/web/configuration/AutowiredWebSecurityConfigurersIgnoreParents.java index 1e034739c0..56767240ab 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configuration/AutowiredWebSecurityConfigurersIgnoreParents.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configuration/AutowiredWebSecurityConfigurersIgnoreParents.java @@ -29,30 +29,31 @@ import org.springframework.security.config.annotation.web.WebSecurityConfigurer; import org.springframework.security.config.annotation.web.builders.WebSecurity; import org.springframework.util.Assert; - /** - * A class used to get all the {@link WebSecurityConfigurer} instances from the - * current {@link ApplicationContext} but ignoring the parent. + * A class used to get all the {@link WebSecurityConfigurer} instances from the current + * {@link ApplicationContext} but ignoring the parent. * * @author Rob Winch * */ final class AutowiredWebSecurityConfigurersIgnoreParents { - private final ConfigurableListableBeanFactory beanFactory; + private final ConfigurableListableBeanFactory beanFactory; - public AutowiredWebSecurityConfigurersIgnoreParents(ConfigurableListableBeanFactory beanFactory) { - Assert.notNull(beanFactory,"beanFactory cannot be null"); - this.beanFactory = beanFactory; - } + public AutowiredWebSecurityConfigurersIgnoreParents( + ConfigurableListableBeanFactory beanFactory) { + Assert.notNull(beanFactory, "beanFactory cannot be null"); + this.beanFactory = beanFactory; + } - @SuppressWarnings({ "rawtypes", "unchecked" }) - public List> getWebSecurityConfigurers() { - List> webSecurityConfigurers = new ArrayList>(); - Map beansOfType = beanFactory.getBeansOfType(WebSecurityConfigurer.class); - for(Entry entry : beansOfType.entrySet()) { - webSecurityConfigurers.add(entry.getValue()); - } - return webSecurityConfigurers; - } + @SuppressWarnings({ "rawtypes", "unchecked" }) + public List> getWebSecurityConfigurers() { + List> webSecurityConfigurers = new ArrayList>(); + Map beansOfType = beanFactory + .getBeansOfType(WebSecurityConfigurer.class); + for (Entry entry : beansOfType.entrySet()) { + webSecurityConfigurers.add(entry.getValue()); + } + return webSecurityConfigurers; + } } \ No newline at end of file diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configuration/ConditionalOnMissingBean.java b/config/src/main/java/org/springframework/security/config/annotation/web/configuration/ConditionalOnMissingBean.java index 9534273a92..2b131c77dd 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configuration/ConditionalOnMissingBean.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configuration/ConditionalOnMissingBean.java @@ -9,5 +9,5 @@ import org.springframework.context.annotation.Conditional; @Conditional(OnMissingBeanCondition.class) @interface ConditionalOnMissingBean { - Class value(); + Class value(); } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configuration/EnableWebSecurity.java b/config/src/main/java/org/springframework/security/config/annotation/web/configuration/EnableWebSecurity.java index d5bce5e2fe..f55e5575cd 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configuration/EnableWebSecurity.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configuration/EnableWebSecurity.java @@ -27,45 +27,40 @@ import org.springframework.security.config.annotation.web.WebSecurityConfigurer; /** * Add this annotation to an {@code @Configuration} class to have the Spring Security - * configuration defined in any {@link WebSecurityConfigurer} or more likely by extending the - * {@link WebSecurityConfigurerAdapter} base class and overriding individual methods: + * configuration defined in any {@link WebSecurityConfigurer} or more likely by extending + * the {@link WebSecurityConfigurerAdapter} base class and overriding individual methods: * *
  * @Configuration
  * @EnableWebSecurity
  * public class MyWebSecurityConfiguration extends WebSecurityConfigurerAdapter {
- *
- *    @Override
- *    public void configure(WebSecurity web) throws Exception {
- *        web
- *            .ignoring()
- *                // Spring Security should completely ignore URLs starting with /resources/
- *                .antMatchers("/resources/**");
- *    }
- *
- *    @Override
- *    protected void configure(HttpSecurity http) throws Exception {
- *        http
- *            .authorizeRequests()
- *                .antMatchers("/public/**").permitAll()
- *                .anyRequest().hasRole("USER")
- *                .and()
- *            // Possibly more configuration ...
- *            .formLogin() // enable form based log in
- *                // set permitAll for all URLs associated with Form Login
- *               .permitAll();
- *    }
- *
- *    @Override
- *    protected void configure(AuthenticationManagerBuilder auth) {
- *        auth
- *            // enable in memory based authentication with a user named "user" and "admin"
- *            .inMemoryAuthentication()
- *                .withUser("user").password("password").roles("USER").and()
- *                .withUser("admin").password("password").roles("USER", "ADMIN");
- *    }
- *
- *    // Possibly more overridden methods ...
+ * 
+ * 	@Override
+ * 	public void configure(WebSecurity web) throws Exception {
+ * 		web.ignoring()
+ * 		// Spring Security should completely ignore URLs starting with /resources/
+ * 				.antMatchers("/resources/**");
+ * 	}
+ * 
+ * 	@Override
+ * 	protected void configure(HttpSecurity http) throws Exception {
+ * 		http.authorizeRequests().antMatchers("/public/**").permitAll().anyRequest()
+ * 				.hasRole("USER").and()
+ * 				// Possibly more configuration ...
+ * 				.formLogin() // enable form based log in
+ * 				// set permitAll for all URLs associated with Form Login
+ * 				.permitAll();
+ * 	}
+ * 
+ * 	@Override
+ * 	protected void configure(AuthenticationManagerBuilder auth) {
+ * 		auth
+ * 		// enable in memory based authentication with a user named "user" and "admin"
+ * 		.inMemoryAuthentication().withUser("user").password("password").roles("USER")
+ * 				.and().withUser("admin").password("password").roles("USER", "ADMIN");
+ * 	}
+ * 
+ * 	// Possibly more overridden methods ...
  * }
  * 
* @@ -75,17 +70,18 @@ import org.springframework.security.config.annotation.web.WebSecurityConfigurer; * @author Rob Winch * @since 3.2 */ -@Retention(value=java.lang.annotation.RetentionPolicy.RUNTIME) -@Target(value={java.lang.annotation.ElementType.TYPE}) +@Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME) +@Target(value = { java.lang.annotation.ElementType.TYPE }) @Documented -@Import({WebSecurityConfiguration.class,ObjectPostProcessorConfiguration.class, SpringWebMvcImportSelector.class}) +@Import({ WebSecurityConfiguration.class, ObjectPostProcessorConfiguration.class, + SpringWebMvcImportSelector.class }) @EnableGlobalAuthentication @Configuration public @interface EnableWebSecurity { - /** - * Controls debugging support for Spring Security. Default is false. - * @return if true, enables debug support with Spring Security - */ - boolean debug() default false; + /** + * Controls debugging support for Spring Security. Default is false. + * @return if true, enables debug support with Spring Security + */ + boolean debug() default false; } \ No newline at end of file diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configuration/OnBeanCondition.java b/config/src/main/java/org/springframework/security/config/annotation/web/configuration/OnBeanCondition.java index 7f485a9e01..924c17ba15 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configuration/OnBeanCondition.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configuration/OnBeanCondition.java @@ -26,15 +26,16 @@ import java.util.Map; * @author Rob Winch */ class OnMissingBeanCondition implements ConfigurationCondition { - public ConfigurationPhase getConfigurationPhase() { - return ConfigurationPhase.REGISTER_BEAN; - } + public ConfigurationPhase getConfigurationPhase() { + return ConfigurationPhase.REGISTER_BEAN; + } - public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { - Map attrs = metadata.getAnnotationAttributes(ConditionalOnMissingBean.class.getName()); + public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { + Map attrs = metadata + .getAnnotationAttributes(ConditionalOnMissingBean.class.getName()); - Class type = (Class) attrs.get("value"); - final Map beans = context.getBeanFactory().getBeansOfType(type); - return beans.isEmpty(); - } + Class type = (Class) attrs.get("value"); + final Map beans = context.getBeanFactory().getBeansOfType(type); + return beans.isEmpty(); + } } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configuration/SpringWebMvcImportSelector.java b/config/src/main/java/org/springframework/security/config/annotation/web/configuration/SpringWebMvcImportSelector.java index 5d430b7bf6..22960557b3 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configuration/SpringWebMvcImportSelector.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configuration/SpringWebMvcImportSelector.java @@ -29,11 +29,18 @@ import org.springframework.util.ClassUtils; */ class SpringWebMvcImportSelector implements ImportSelector { - /* (non-Javadoc) - * @see org.springframework.context.annotation.ImportSelector#selectImports(org.springframework.core.type.AnnotationMetadata) - */ - public String[] selectImports(AnnotationMetadata importingClassMetadata) { - boolean webmvcPresent = ClassUtils.isPresent("org.springframework.web.servlet.DispatcherServlet", getClass().getClassLoader()); - return webmvcPresent ? new String[] {"org.springframework.security.config.annotation.web.configuration.WebMvcSecurityConfiguration"} : new String[] {}; - } + /* + * (non-Javadoc) + * + * @see + * org.springframework.context.annotation.ImportSelector#selectImports(org.springframework + * .core.type.AnnotationMetadata) + */ + public String[] selectImports(AnnotationMetadata importingClassMetadata) { + boolean webmvcPresent = ClassUtils.isPresent( + "org.springframework.web.servlet.DispatcherServlet", getClass() + .getClassLoader()); + return webmvcPresent ? new String[] { "org.springframework.security.config.annotation.web.configuration.WebMvcSecurityConfiguration" } + : new String[] {}; + } } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configuration/WebMvcSecurityConfiguration.java b/config/src/main/java/org/springframework/security/config/annotation/web/configuration/WebMvcSecurityConfiguration.java index 1bdf1156b8..97abb5c21f 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configuration/WebMvcSecurityConfiguration.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configuration/WebMvcSecurityConfiguration.java @@ -27,11 +27,10 @@ import org.springframework.web.servlet.support.RequestDataValueProcessor; import java.util.List; /** - * Used to add a {@link RequestDataValueProcessor} for Spring MVC and Spring - * Security CSRF integration. This configuration is added whenever - * {@link EnableWebMvc} is added by {@link SpringWebMvcImportSelector} and the - * DispatcherServlet is present on the classpath. It also adds the - * {@link AuthenticationPrincipalArgumentResolver} as a + * Used to add a {@link RequestDataValueProcessor} for Spring MVC and Spring Security CSRF + * integration. This configuration is added whenever {@link EnableWebMvc} is added by + * {@link SpringWebMvcImportSelector} and the DispatcherServlet is present on the + * classpath. It also adds the {@link AuthenticationPrincipalArgumentResolver} as a * {@link HandlerMethodArgumentResolver}. * * @author Rob Winch @@ -39,18 +38,18 @@ import java.util.List; */ class WebMvcSecurityConfiguration extends WebMvcConfigurerAdapter { - @Override - @SuppressWarnings("deprecation") - public void addArgumentResolvers( - List argumentResolvers) { - argumentResolvers.add(new AuthenticationPrincipalArgumentResolver()); - argumentResolvers.add(new org.springframework.security.web.bind.support.AuthenticationPrincipalArgumentResolver()); - argumentResolvers.add(new CsrfTokenArgumentResolver()); - } + @Override + @SuppressWarnings("deprecation") + public void addArgumentResolvers(List argumentResolvers) { + argumentResolvers.add(new AuthenticationPrincipalArgumentResolver()); + argumentResolvers + .add(new org.springframework.security.web.bind.support.AuthenticationPrincipalArgumentResolver()); + argumentResolvers.add(new CsrfTokenArgumentResolver()); + } - @ConditionalOnMissingBean(RequestDataValueProcessor.class) - @Bean - public RequestDataValueProcessor requestDataValueProcessor() { - return new CsrfRequestDataValueProcessor(); - } + @ConditionalOnMissingBean(RequestDataValueProcessor.class) + @Bean + public RequestDataValueProcessor requestDataValueProcessor() { + return new CsrfRequestDataValueProcessor(); + } } \ No newline at end of file diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration.java b/config/src/main/java/org/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration.java index 224e97b8a1..80903d7bf1 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration.java @@ -49,13 +49,12 @@ import org.springframework.security.web.context.AbstractSecurityWebApplicationIn import org.springframework.util.ClassUtils; /** - * Uses a {@link WebSecurity} to create the {@link FilterChainProxy} that - * performs the web based security for Spring Security. It then exports the - * necessary beans. Customizations can be made to {@link WebSecurity} by - * extending {@link WebSecurityConfigurerAdapter} and exposing it as a - * {@link Configuration} or implementing {@link WebSecurityConfigurer} and - * exposing it as a {@link Configuration}. This configuration is imported when - * using {@link EnableWebSecurity}. + * Uses a {@link WebSecurity} to create the {@link FilterChainProxy} that performs the web + * based security for Spring Security. It then exports the necessary beans. Customizations + * can be made to {@link WebSecurity} by extending {@link WebSecurityConfigurerAdapter} + * and exposing it as a {@link Configuration} or implementing + * {@link WebSecurityConfigurer} and exposing it as a {@link Configuration}. This + * configuration is imported when using {@link EnableWebSecurity}. * * @see EnableWebSecurity * @see WebSecurity @@ -66,150 +65,178 @@ import org.springframework.util.ClassUtils; */ @Configuration public class WebSecurityConfiguration implements ImportAware, BeanClassLoaderAware { - private WebSecurity webSecurity; + private WebSecurity webSecurity; - private Boolean debugEnabled; + private Boolean debugEnabled; - private List> webSecurityConfigurers; + private List> webSecurityConfigurers; - private ClassLoader beanClassLoader; + private ClassLoader beanClassLoader; - @Autowired(required = false) - private ObjectPostProcessor objectObjectPostProcessor; + @Autowired(required = false) + private ObjectPostProcessor objectObjectPostProcessor; - @Bean - public static DelegatingApplicationListener delegatingApplicationListener() { - return new DelegatingApplicationListener(); - } + @Bean + public static DelegatingApplicationListener delegatingApplicationListener() { + return new DelegatingApplicationListener(); + } - @Bean - @DependsOn(AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME) - public SecurityExpressionHandler webSecurityExpressionHandler() { - return webSecurity.getExpressionHandler(); - } + @Bean + @DependsOn(AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME) + public SecurityExpressionHandler webSecurityExpressionHandler() { + return webSecurity.getExpressionHandler(); + } - /** - * Creates the Spring Security Filter Chain - * @return - * @throws Exception - */ - @Bean(name=AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME) - public Filter springSecurityFilterChain() throws Exception { - boolean hasConfigurers = webSecurityConfigurers != null && !webSecurityConfigurers.isEmpty(); - if(!hasConfigurers) { - WebSecurityConfigurerAdapter adapter = objectObjectPostProcessor.postProcess(new WebSecurityConfigurerAdapter() {}); - webSecurity.apply(adapter); - } - return webSecurity.build(); - } + /** + * Creates the Spring Security Filter Chain + * @return + * @throws Exception + */ + @Bean(name = AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME) + public Filter springSecurityFilterChain() throws Exception { + boolean hasConfigurers = webSecurityConfigurers != null + && !webSecurityConfigurers.isEmpty(); + if (!hasConfigurers) { + WebSecurityConfigurerAdapter adapter = objectObjectPostProcessor + .postProcess(new WebSecurityConfigurerAdapter() { + }); + webSecurity.apply(adapter); + } + return webSecurity.build(); + } - /** - * Creates the {@link WebInvocationPrivilegeEvaluator} that is necessary for the JSP tag support. - * @return the {@link WebInvocationPrivilegeEvaluator} - * @throws Exception - */ - @Bean - @DependsOn(AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME) - public WebInvocationPrivilegeEvaluator privilegeEvaluator() throws Exception { - return webSecurity.getPrivilegeEvaluator(); - } + /** + * Creates the {@link WebInvocationPrivilegeEvaluator} that is necessary for the JSP + * tag support. + * @return the {@link WebInvocationPrivilegeEvaluator} + * @throws Exception + */ + @Bean + @DependsOn(AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME) + public WebInvocationPrivilegeEvaluator privilegeEvaluator() throws Exception { + return webSecurity.getPrivilegeEvaluator(); + } - /** - * Sets the {@code } instances used to create the web configuration. - * - * @param objectPostProcessor the {@link ObjectPostProcessor} used to create a {@link WebSecurity} instance - * @param webSecurityConfigurers the {@code } instances used to create the web configuration - * @throws Exception - */ - @Autowired(required = false) - public void setFilterChainProxySecurityConfigurer(ObjectPostProcessor objectPostProcessor, - @Value("#{@autowiredWebSecurityConfigurersIgnoreParents.getWebSecurityConfigurers()}") List> webSecurityConfigurers) throws Exception { - webSecurity = objectPostProcessor.postProcess(new WebSecurity(objectPostProcessor)); - if(debugEnabled != null) { - webSecurity.debug(debugEnabled); - } + /** + * Sets the {@code } + * instances used to create the web configuration. + * + * @param objectPostProcessor the {@link ObjectPostProcessor} used to create a + * {@link WebSecurity} instance + * @param webSecurityConfigurers the + * {@code } instances used to + * create the web configuration + * @throws Exception + */ + @Autowired(required = false) + public void setFilterChainProxySecurityConfigurer( + ObjectPostProcessor objectPostProcessor, + @Value("#{@autowiredWebSecurityConfigurersIgnoreParents.getWebSecurityConfigurers()}") List> webSecurityConfigurers) + throws Exception { + webSecurity = objectPostProcessor + .postProcess(new WebSecurity(objectPostProcessor)); + if (debugEnabled != null) { + webSecurity.debug(debugEnabled); + } - Collections.sort(webSecurityConfigurers, AnnotationAwareOrderComparator.INSTANCE); + Collections.sort(webSecurityConfigurers, AnnotationAwareOrderComparator.INSTANCE); - Integer previousOrder = null; - for(SecurityConfigurer config : webSecurityConfigurers) { - Integer order = AnnotationAwareOrderComparator.lookupOrder(config); - if(previousOrder != null && previousOrder.equals(order)) { - throw new IllegalStateException("@Order on WebSecurityConfigurers must be unique. Order of " + order + " was already used, so it cannot be used on " + config + " too."); - } - previousOrder = order; - } - for(SecurityConfigurer webSecurityConfigurer : webSecurityConfigurers) { - webSecurity.apply(webSecurityConfigurer); - } - this.webSecurityConfigurers = webSecurityConfigurers; - } + Integer previousOrder = null; + for (SecurityConfigurer config : webSecurityConfigurers) { + Integer order = AnnotationAwareOrderComparator.lookupOrder(config); + if (previousOrder != null && previousOrder.equals(order)) { + throw new IllegalStateException( + "@Order on WebSecurityConfigurers must be unique. Order of " + + order + " was already used, so it cannot be used on " + + config + " too."); + } + previousOrder = order; + } + for (SecurityConfigurer webSecurityConfigurer : webSecurityConfigurers) { + webSecurity.apply(webSecurityConfigurer); + } + this.webSecurityConfigurers = webSecurityConfigurers; + } - @Bean - public AutowiredWebSecurityConfigurersIgnoreParents autowiredWebSecurityConfigurersIgnoreParents(ConfigurableListableBeanFactory beanFactory) { - return new AutowiredWebSecurityConfigurersIgnoreParents(beanFactory); - } + @Bean + public AutowiredWebSecurityConfigurersIgnoreParents autowiredWebSecurityConfigurersIgnoreParents( + ConfigurableListableBeanFactory beanFactory) { + return new AutowiredWebSecurityConfigurersIgnoreParents(beanFactory); + } - /** - * A custom verision of the Spring provided AnnotationAwareOrderComparator - * that uses {@link AnnotationUtils#findAnnotation(Class, Class)} to look on - * super class instances for the {@link Order} annotation. - * - * @author Rob Winch - * @since 3.2 - */ - private static class AnnotationAwareOrderComparator extends OrderComparator { - private static final AnnotationAwareOrderComparator INSTANCE = new AnnotationAwareOrderComparator(); + /** + * A custom verision of the Spring provided AnnotationAwareOrderComparator that uses + * {@link AnnotationUtils#findAnnotation(Class, Class)} to look on super class + * instances for the {@link Order} annotation. + * + * @author Rob Winch + * @since 3.2 + */ + private static class AnnotationAwareOrderComparator extends OrderComparator { + private static final AnnotationAwareOrderComparator INSTANCE = new AnnotationAwareOrderComparator(); - @Override - protected int getOrder(Object obj) { - return lookupOrder(obj); - } + @Override + protected int getOrder(Object obj) { + return lookupOrder(obj); + } - private static int lookupOrder(Object obj) { - if (obj instanceof Ordered) { - return ((Ordered) obj).getOrder(); - } - if (obj != null) { - Class clazz = (obj instanceof Class ? (Class) obj : obj.getClass()); - Order order = AnnotationUtils.findAnnotation(clazz,Order.class); - if (order != null) { - return order.value(); - } - } - return Ordered.LOWEST_PRECEDENCE; - } - } + private static int lookupOrder(Object obj) { + if (obj instanceof Ordered) { + return ((Ordered) obj).getOrder(); + } + if (obj != null) { + Class clazz = (obj instanceof Class ? (Class) obj : obj.getClass()); + Order order = AnnotationUtils.findAnnotation(clazz, Order.class); + if (order != null) { + return order.value(); + } + } + return Ordered.LOWEST_PRECEDENCE; + } + } - /* (non-Javadoc) - * @see org.springframework.context.annotation.ImportAware#setImportMetadata(org.springframework.core.type.AnnotationMetadata) - */ - public void setImportMetadata(AnnotationMetadata importMetadata) { - Map enableWebSecurityAttrMap = importMetadata.getAnnotationAttributes(EnableWebSecurity.class.getName()); - AnnotationAttributes enableWebSecurityAttrs = AnnotationAttributes.fromMap(enableWebSecurityAttrMap); - if(enableWebSecurityAttrs == null) { - // search parent classes - Class currentClass = ClassUtils.resolveClassName(importMetadata.getClassName(), beanClassLoader); - for(Class classToInspect = currentClass ;classToInspect != null; classToInspect = classToInspect.getSuperclass()) { - EnableWebSecurity enableWebSecurityAnnotation = AnnotationUtils.findAnnotation(classToInspect, EnableWebSecurity.class); - if(enableWebSecurityAnnotation == null) { - continue; - } - enableWebSecurityAttrMap = AnnotationUtils - .getAnnotationAttributes(enableWebSecurityAnnotation); - enableWebSecurityAttrs = AnnotationAttributes.fromMap(enableWebSecurityAttrMap); - } - } - debugEnabled = enableWebSecurityAttrs.getBoolean("debug"); - if(webSecurity != null) { - webSecurity.debug(debugEnabled); - } - } + /* + * (non-Javadoc) + * + * @see org.springframework.context.annotation.ImportAware#setImportMetadata(org. + * springframework.core.type.AnnotationMetadata) + */ + public void setImportMetadata(AnnotationMetadata importMetadata) { + Map enableWebSecurityAttrMap = importMetadata + .getAnnotationAttributes(EnableWebSecurity.class.getName()); + AnnotationAttributes enableWebSecurityAttrs = AnnotationAttributes + .fromMap(enableWebSecurityAttrMap); + if (enableWebSecurityAttrs == null) { + // search parent classes + Class currentClass = ClassUtils.resolveClassName( + importMetadata.getClassName(), beanClassLoader); + for (Class classToInspect = currentClass; classToInspect != null; classToInspect = classToInspect + .getSuperclass()) { + EnableWebSecurity enableWebSecurityAnnotation = AnnotationUtils + .findAnnotation(classToInspect, EnableWebSecurity.class); + if (enableWebSecurityAnnotation == null) { + continue; + } + enableWebSecurityAttrMap = AnnotationUtils + .getAnnotationAttributes(enableWebSecurityAnnotation); + enableWebSecurityAttrs = AnnotationAttributes + .fromMap(enableWebSecurityAttrMap); + } + } + debugEnabled = enableWebSecurityAttrs.getBoolean("debug"); + if (webSecurity != null) { + webSecurity.debug(debugEnabled); + } + } - /* (non-Javadoc) - * @see org.springframework.beans.factory.BeanClassLoaderAware#setBeanClassLoader(java.lang.ClassLoader) - */ - public void setBeanClassLoader(ClassLoader classLoader) { - this.beanClassLoader = classLoader; - } + /* + * (non-Javadoc) + * + * @see + * org.springframework.beans.factory.BeanClassLoaderAware#setBeanClassLoader(java. + * lang.ClassLoader) + */ + public void setBeanClassLoader(ClassLoader classLoader) { + this.beanClassLoader = classLoader; + } } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configuration/WebSecurityConfigurerAdapter.java b/config/src/main/java/org/springframework/security/config/annotation/web/configuration/WebSecurityConfigurerAdapter.java index 7404c5ecc6..b2d9af370d 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configuration/WebSecurityConfigurerAdapter.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configuration/WebSecurityConfigurerAdapter.java @@ -15,7 +15,6 @@ */ package org.springframework.security.config.annotation.web.configuration; - import java.lang.reflect.Field; import java.util.Arrays; import java.util.Collections; @@ -58,413 +57,428 @@ import org.springframework.web.accept.ContentNegotiationStrategy; import org.springframework.web.accept.HeaderContentNegotiationStrategy; /** - * Provides a convenient base class for creating a {@link WebSecurityConfigurer} - * instance. The implementation allows customization by overriding methods. + * Provides a convenient base class for creating a {@link WebSecurityConfigurer} instance. + * The implementation allows customization by overriding methods. * * @see EnableWebSecurity * * @author Rob Winch */ @Order(100) -public abstract class WebSecurityConfigurerAdapter implements WebSecurityConfigurer { - private final Log logger = LogFactory.getLog(WebSecurityConfigurerAdapter.class); +public abstract class WebSecurityConfigurerAdapter implements + WebSecurityConfigurer { + private final Log logger = LogFactory.getLog(WebSecurityConfigurerAdapter.class); - private ApplicationContext context; + private ApplicationContext context; - private ContentNegotiationStrategy contentNegotiationStrategy = new HeaderContentNegotiationStrategy(); + private ContentNegotiationStrategy contentNegotiationStrategy = new HeaderContentNegotiationStrategy(); - private ObjectPostProcessor objectPostProcessor = new ObjectPostProcessor() { - public T postProcess(T object) { - throw new IllegalStateException(ObjectPostProcessor.class.getName()+ " is a required bean. Ensure you have used @EnableWebSecurity and @Configuration"); - } - }; + private ObjectPostProcessor objectPostProcessor = new ObjectPostProcessor() { + public T postProcess(T object) { + throw new IllegalStateException( + ObjectPostProcessor.class.getName() + + " is a required bean. Ensure you have used @EnableWebSecurity and @Configuration"); + } + }; - private AuthenticationConfiguration authenticationConfiguration; - private AuthenticationManagerBuilder authenticationBuilder; - private AuthenticationManagerBuilder localConfigureAuthenticationBldr; - private boolean disableLocalConfigureAuthenticationBldr; - private boolean authenticationManagerInitialized; - private AuthenticationManager authenticationManager; - private AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl(); - private HttpSecurity http; - private boolean disableDefaults; + private AuthenticationConfiguration authenticationConfiguration; + private AuthenticationManagerBuilder authenticationBuilder; + private AuthenticationManagerBuilder localConfigureAuthenticationBldr; + private boolean disableLocalConfigureAuthenticationBldr; + private boolean authenticationManagerInitialized; + private AuthenticationManager authenticationManager; + private AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl(); + private HttpSecurity http; + private boolean disableDefaults; - /** - * Creates an instance with the default configuration enabled. - */ - protected WebSecurityConfigurerAdapter() { - this(false); - } + /** + * Creates an instance with the default configuration enabled. + */ + protected WebSecurityConfigurerAdapter() { + this(false); + } - /** - * Creates an instance which allows specifying if the default configuration - * should be enabled. Disabling the default configuration should be - * considered more advanced usage as it requires more understanding of how - * the framework is implemented. - * - * @param disableDefaults - * true if the default configuration should be enabled, else - * false - */ - protected WebSecurityConfigurerAdapter(boolean disableDefaults) { - this.disableDefaults = disableDefaults; - } + /** + * Creates an instance which allows specifying if the default configuration should be + * enabled. Disabling the default configuration should be considered more advanced + * usage as it requires more understanding of how the framework is implemented. + * + * @param disableDefaults true if the default configuration should be enabled, else + * false + */ + protected WebSecurityConfigurerAdapter(boolean disableDefaults) { + this.disableDefaults = disableDefaults; + } - /** - * Used by the default implementation of {@link #authenticationManager()} to - * attempt to obtain an {@link AuthenticationManager}. If overridden, the - * {@link AuthenticationManagerBuilder} should be used to specify the - * {@link AuthenticationManager}. - * - *

- * The {@link #authenticationManagerBean()} method can be used to expose the - * resulting {@link AuthenticationManager} as a Bean. The - * {@link #userDetailsServiceBean()} can be used to expose the last - * populated {@link UserDetailsService} that is created with the - * {@link AuthenticationManagerBuilder} as a Bean. The - * {@link UserDetailsService} will also automatically be populated on - * {@link HttpSecurity#getSharedObject(Class)} for use with other - * {@link SecurityContextConfigurer} (i.e. RememberMeConfigurer ) - *

- * - *

- * For example, the following configuration could be used to register in - * memory authentication that exposes an in memory - * {@link UserDetailsService}: - *

- * - *
-     * @Override
-     * protected void configure(AuthenticationManagerBuilder auth) {
-     *     auth
-     *         // enable in memory based authentication with a user named
-     *         // "user" and "admin"
-     *         .inMemoryAuthentication()
-     *             .withUser("user").password("password").roles("USER").and()
-     *             .withUser("admin").password("password").roles("USER", "ADMIN");
-     * }
-     *
-     * // Expose the UserDetailsService as a Bean
-     * @Bean
-     * @Override
-     * public UserDetailsService userDetailsServiceBean() throws Exception {
-     *     return super.userDetailsServiceBean();
-     * }
-     *
-     * 
- * - * @param auth - * the {@link AuthenticationManagerBuilder} to use - * @throws Exception - */ - protected void configure(AuthenticationManagerBuilder auth) throws Exception { - this.disableLocalConfigureAuthenticationBldr = true; - } + /** + * Used by the default implementation of {@link #authenticationManager()} to attempt + * to obtain an {@link AuthenticationManager}. If overridden, the + * {@link AuthenticationManagerBuilder} should be used to specify the + * {@link AuthenticationManager}. + * + *

+ * The {@link #authenticationManagerBean()} method can be used to expose the resulting + * {@link AuthenticationManager} as a Bean. The {@link #userDetailsServiceBean()} can + * be used to expose the last populated {@link UserDetailsService} that is created + * with the {@link AuthenticationManagerBuilder} as a Bean. The + * {@link UserDetailsService} will also automatically be populated on + * {@link HttpSecurity#getSharedObject(Class)} for use with other + * {@link SecurityContextConfigurer} (i.e. RememberMeConfigurer ) + *

+ * + *

+ * For example, the following configuration could be used to register in memory + * authentication that exposes an in memory {@link UserDetailsService}: + *

+ * + *
+	 * @Override
+	 * protected void configure(AuthenticationManagerBuilder auth) {
+	 * 	auth
+	 * 	// enable in memory based authentication with a user named
+	 * 	// "user" and "admin"
+	 * 	.inMemoryAuthentication().withUser("user").password("password").roles("USER").and()
+	 * 			.withUser("admin").password("password").roles("USER", "ADMIN");
+	 * }
+	 *
+	 * // Expose the UserDetailsService as a Bean
+	 * @Bean
+	 * @Override
+	 * public UserDetailsService userDetailsServiceBean() throws Exception {
+	 * 	return super.userDetailsServiceBean();
+	 * }
+	 *
+	 * 
+ * + * @param auth the {@link AuthenticationManagerBuilder} to use + * @throws Exception + */ + protected void configure(AuthenticationManagerBuilder auth) throws Exception { + this.disableLocalConfigureAuthenticationBldr = true; + } - /** - * Creates the {@link HttpSecurity} or returns the current instance - * - * @return the {@link HttpSecurity} - * @throws Exception - */ - protected final HttpSecurity getHttp() throws Exception { - if(http != null) { - return http; - } + /** + * Creates the {@link HttpSecurity} or returns the current instance + * + * ] * @return the {@link HttpSecurity} + * @throws Exception + */ + protected final HttpSecurity getHttp() throws Exception { + if (http != null) { + return http; + } - DefaultAuthenticationEventPublisher eventPublisher = objectPostProcessor.postProcess(new DefaultAuthenticationEventPublisher()); - localConfigureAuthenticationBldr.authenticationEventPublisher(eventPublisher); + DefaultAuthenticationEventPublisher eventPublisher = objectPostProcessor + .postProcess(new DefaultAuthenticationEventPublisher()); + localConfigureAuthenticationBldr.authenticationEventPublisher(eventPublisher); - AuthenticationManager authenticationManager = authenticationManager(); - authenticationBuilder.parentAuthenticationManager(authenticationManager); - http = new HttpSecurity(objectPostProcessor,authenticationBuilder, localConfigureAuthenticationBldr.getSharedObjects()); - http.setSharedObject(UserDetailsService.class, userDetailsService()); - http.setSharedObject(ApplicationContext.class, context); - http.setSharedObject(ContentNegotiationStrategy.class, contentNegotiationStrategy); - http.setSharedObject(AuthenticationTrustResolver.class, trustResolver); - if(!disableDefaults) { - http - .csrf().and() - .addFilter(new WebAsyncManagerIntegrationFilter()) - .exceptionHandling().and() - .headers().and() - .sessionManagement().and() - .securityContext().and() - .requestCache().and() - .anonymous().and() - .servletApi().and() - .apply(new DefaultLoginPageConfigurer()).and() - .logout(); - } - configure(http); - return http; - } + AuthenticationManager authenticationManager = authenticationManager(); + authenticationBuilder.parentAuthenticationManager(authenticationManager); + http = new HttpSecurity(objectPostProcessor, authenticationBuilder, + localConfigureAuthenticationBldr.getSharedObjects()); + http.setSharedObject(UserDetailsService.class, userDetailsService()); + http.setSharedObject(ApplicationContext.class, context); + http.setSharedObject(ContentNegotiationStrategy.class, contentNegotiationStrategy); + http.setSharedObject(AuthenticationTrustResolver.class, trustResolver); + if (!disableDefaults) { + // @formatter:off + http + .csrf().and() + .addFilter(new WebAsyncManagerIntegrationFilter()) + .exceptionHandling().and() + .headers().and() + .sessionManagement().and() + .securityContext().and() + .requestCache().and() + .anonymous().and() + .servletApi().and() + .apply(new DefaultLoginPageConfigurer()).and() + .logout(); + // @formatter:on + } + configure(http); + return http; + } - /** - * Override this method to expose the {@link AuthenticationManager} from - * {@link #configure(AuthenticationManagerBuilder)} to be exposed as - * a Bean. For example: - * - *
-     * @Bean(name name="myAuthenticationManager")
-     * @Override
-     * public AuthenticationManager authenticationManagerBean() throws Exception {
-     *     return super.authenticationManagerBean();
-     * }
-     * 
- * - * @return the {@link AuthenticationManager} - * @throws Exception - */ - public AuthenticationManager authenticationManagerBean() throws Exception { - return new AuthenticationManagerDelegator(authenticationBuilder, context); - } + /** + * Override this method to expose the {@link AuthenticationManager} from + * {@link #configure(AuthenticationManagerBuilder)} to be exposed as a Bean. For + * example: + * + *
+	 * @Bean(name name="myAuthenticationManager")
+	 * @Override
+	 * public AuthenticationManager authenticationManagerBean() throws Exception {
+	 *     return super.authenticationManagerBean();
+	 * }
+	 * 
+ * + * @return the {@link AuthenticationManager} + * @throws Exception + */ + public AuthenticationManager authenticationManagerBean() throws Exception { + return new AuthenticationManagerDelegator(authenticationBuilder, context); + } - /** - * Gets the {@link AuthenticationManager} to use. The default strategy is if - * {@link #configure(AuthenticationManagerBuilder)} method is - * overridden to use the {@link AuthenticationManagerBuilder} that was passed in. - * Otherwise, autowire the {@link AuthenticationManager} by type. - * - * @return - * @throws Exception - */ - protected AuthenticationManager authenticationManager() throws Exception { - if(!authenticationManagerInitialized) { - configure(localConfigureAuthenticationBldr); - if(disableLocalConfigureAuthenticationBldr) { - authenticationManager = authenticationConfiguration.getAuthenticationManager(); - } else { - authenticationManager = localConfigureAuthenticationBldr.build(); - } - authenticationManagerInitialized = true; - } - return authenticationManager; - } + /** + * Gets the {@link AuthenticationManager} to use. The default strategy is if + * {@link #configure(AuthenticationManagerBuilder)} method is overridden to use the + * {@link AuthenticationManagerBuilder} that was passed in. Otherwise, autowire the + * {@link AuthenticationManager} by type. + * + * @return + * @throws Exception + */ + protected AuthenticationManager authenticationManager() throws Exception { + if (!authenticationManagerInitialized) { + configure(localConfigureAuthenticationBldr); + if (disableLocalConfigureAuthenticationBldr) { + authenticationManager = authenticationConfiguration + .getAuthenticationManager(); + } + else { + authenticationManager = localConfigureAuthenticationBldr.build(); + } + authenticationManagerInitialized = true; + } + return authenticationManager; + } - /** - * Override this method to expose a {@link UserDetailsService} created from - * {@link #configure(AuthenticationManagerBuilder)} as a bean. In - * general only the following override should be done of this method: - * - *
-     * @Bean(name = "myUserDetailsService") // any or no name specified is allowed
-     * @Override
-     * public UserDetailsService userDetailsServiceBean() throws Exception {
-     *     return super.userDetailsServiceBean();
-     * }
-     * 
- * - * To change the instance returned, developers should change - * {@link #userDetailsService()} instead - * @return - * @throws Exception - * @see {@link #userDetailsService()} - */ - public UserDetailsService userDetailsServiceBean() throws Exception { - AuthenticationManagerBuilder globalAuthBuilder = context.getBean(AuthenticationManagerBuilder.class); - return new UserDetailsServiceDelegator(Arrays.asList(localConfigureAuthenticationBldr, globalAuthBuilder)); - } + /** + * Override this method to expose a {@link UserDetailsService} created from + * {@link #configure(AuthenticationManagerBuilder)} as a bean. In general only the + * following override should be done of this method: + * + *
+	 * @Bean(name = "myUserDetailsService")
+	 * // any or no name specified is allowed
+	 * @Override
+	 * public UserDetailsService userDetailsServiceBean() throws Exception {
+	 * 	return super.userDetailsServiceBean();
+	 * }
+	 * 
+ * + * To change the instance returned, developers should change + * {@link #userDetailsService()} instead + * @return + * @throws Exception + * @see {@link #userDetailsService()} + */ + public UserDetailsService userDetailsServiceBean() throws Exception { + AuthenticationManagerBuilder globalAuthBuilder = context + .getBean(AuthenticationManagerBuilder.class); + return new UserDetailsServiceDelegator(Arrays.asList( + localConfigureAuthenticationBldr, globalAuthBuilder)); + } - /** - * Allows modifying and accessing the {@link UserDetailsService} from - * {@link #userDetailsServiceBean()()} without interacting with the - * {@link ApplicationContext}. Developers should override this method when - * changing the instance of {@link #userDetailsServiceBean()}. - * - * @return - */ - protected UserDetailsService userDetailsService() { - AuthenticationManagerBuilder globalAuthBuilder = context.getBean(AuthenticationManagerBuilder.class); - return new UserDetailsServiceDelegator(Arrays.asList(localConfigureAuthenticationBldr, globalAuthBuilder)); - } + /** + * Allows modifying and accessing the {@link UserDetailsService} from + * {@link #userDetailsServiceBean()()} without interacting with the + * {@link ApplicationContext}. Developers should override this method when changing + * the instance of {@link #userDetailsServiceBean()}. + * + * @return + */ + protected UserDetailsService userDetailsService() { + AuthenticationManagerBuilder globalAuthBuilder = context + .getBean(AuthenticationManagerBuilder.class); + return new UserDetailsServiceDelegator(Arrays.asList( + localConfigureAuthenticationBldr, globalAuthBuilder)); + } - public void init(final WebSecurity web) throws Exception { - final HttpSecurity http = getHttp(); - web - .addSecurityFilterChainBuilder(http) - .postBuildAction(new Runnable() { - public void run() { - FilterSecurityInterceptor securityInterceptor = http.getSharedObject(FilterSecurityInterceptor.class); - web.securityInterceptor(securityInterceptor); - } - }); - } + public void init(final WebSecurity web) throws Exception { + final HttpSecurity http = getHttp(); + web.addSecurityFilterChainBuilder(http).postBuildAction(new Runnable() { + public void run() { + FilterSecurityInterceptor securityInterceptor = http + .getSharedObject(FilterSecurityInterceptor.class); + web.securityInterceptor(securityInterceptor); + } + }); + } - /** - * Override this method to configure {@link WebSecurity}. For - * example, if you wish to ignore certain requests. - */ - public void configure(WebSecurity web) throws Exception { - } + /** + * Override this method to configure {@link WebSecurity}. For example, if you wish to + * ignore certain requests. + */ + public void configure(WebSecurity web) throws Exception { + } - /** - * Override this method to configure the {@link HttpSecurity}. - * Typically subclasses should not invoke this method by calling super - * as it may override their configuration. The default configuration is: - * - *
-     * http
-     *     .authorizeRequests()
-     *         .anyRequest().authenticated().and()
-     *     .formLogin().and()
-     *     .httpBasic();
-     * 
- * - * @param http - * the {@link HttpSecurity} to modify - * @throws Exception - * if an error occurs - */ - protected void configure(HttpSecurity http) throws Exception { - logger.debug("Using default configure(HttpSecurity). If subclassed this will potentially override subclass configure(HttpSecurity)."); + /** + * Override this method to configure the {@link HttpSecurity}. Typically subclasses + * should not invoke this method by calling super as it may override their + * configuration. The default configuration is: + * + *
+	 * http.authorizeRequests().anyRequest().authenticated().and().formLogin().and().httpBasic();
+	 * 
+ * + * @param http the {@link HttpSecurity} to modify + * @throws Exception if an error occurs + */ + // @formatter:off + protected void configure(HttpSecurity http) throws Exception { + logger.debug("Using default configure(HttpSecurity). If subclassed this will potentially override subclass configure(HttpSecurity)."); - http - .authorizeRequests() - .anyRequest().authenticated() - .and() - .formLogin().and() - .httpBasic(); - } + http + .authorizeRequests() + .anyRequest().authenticated() + .and() + .formLogin().and() + .httpBasic(); + } + // @formatter:on - @Autowired - public void setApplicationContext(ApplicationContext context) { - this.context = context; - } + @Autowired + public void setApplicationContext(ApplicationContext context) { + this.context = context; + } - @Autowired(required=false) - public void setTrustResolver(AuthenticationTrustResolver trustResolver) { - this.trustResolver = trustResolver; - } + @Autowired(required = false) + public void setTrustResolver(AuthenticationTrustResolver trustResolver) { + this.trustResolver = trustResolver; + } - @Autowired(required=false) - public void setContentNegotationStrategy(ContentNegotiationStrategy contentNegotiationStrategy) { - this.contentNegotiationStrategy = contentNegotiationStrategy; - } + @Autowired(required = false) + public void setContentNegotationStrategy( + ContentNegotiationStrategy contentNegotiationStrategy) { + this.contentNegotiationStrategy = contentNegotiationStrategy; + } - @Autowired - public void setObjectPostProcessor(ObjectPostProcessor objectPostProcessor) { - this.objectPostProcessor = objectPostProcessor; + @Autowired + public void setObjectPostProcessor(ObjectPostProcessor objectPostProcessor) { + this.objectPostProcessor = objectPostProcessor; - authenticationBuilder = new AuthenticationManagerBuilder(objectPostProcessor); - localConfigureAuthenticationBldr = new AuthenticationManagerBuilder(objectPostProcessor) { - @Override - public AuthenticationManagerBuilder eraseCredentials(boolean eraseCredentials) { - authenticationBuilder.eraseCredentials(eraseCredentials); - return super.eraseCredentials(eraseCredentials); - } + authenticationBuilder = new AuthenticationManagerBuilder(objectPostProcessor); + localConfigureAuthenticationBldr = new AuthenticationManagerBuilder( + objectPostProcessor) { + @Override + public AuthenticationManagerBuilder eraseCredentials(boolean eraseCredentials) { + authenticationBuilder.eraseCredentials(eraseCredentials); + return super.eraseCredentials(eraseCredentials); + } - }; - } + }; + } - @Autowired - public void setAuthenticationConfiguration(AuthenticationConfiguration authenticationConfiguration) { - this.authenticationConfiguration = authenticationConfiguration; - } + @Autowired + public void setAuthenticationConfiguration( + AuthenticationConfiguration authenticationConfiguration) { + this.authenticationConfiguration = authenticationConfiguration; + } - /** - * Delays the use of the {@link UserDetailsService} from the - * {@link AuthenticationManagerBuilder} to ensure that it has been fully - * configured. - * - * @author Rob Winch - * @since 3.2 - */ - static final class UserDetailsServiceDelegator implements UserDetailsService { - private List delegateBuilders; - private UserDetailsService delegate; - private final Object delegateMonitor = new Object(); + /** + * Delays the use of the {@link UserDetailsService} from the + * {@link AuthenticationManagerBuilder} to ensure that it has been fully configured. + * + * @author Rob Winch + * @since 3.2 + */ + static final class UserDetailsServiceDelegator implements UserDetailsService { + private List delegateBuilders; + private UserDetailsService delegate; + private final Object delegateMonitor = new Object(); - UserDetailsServiceDelegator(List delegateBuilders) { - if(delegateBuilders.contains(null)) { - throw new IllegalArgumentException("delegateBuilders cannot contain null values. Got " + delegateBuilders); - } - this.delegateBuilders = delegateBuilders; - } + UserDetailsServiceDelegator(List delegateBuilders) { + if (delegateBuilders.contains(null)) { + throw new IllegalArgumentException( + "delegateBuilders cannot contain null values. Got " + + delegateBuilders); + } + this.delegateBuilders = delegateBuilders; + } - public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { - if(delegate != null) { - return delegate.loadUserByUsername(username); - } + public UserDetails loadUserByUsername(String username) + throws UsernameNotFoundException { + if (delegate != null) { + return delegate.loadUserByUsername(username); + } - synchronized(delegateMonitor) { - if (delegate == null) { - for(AuthenticationManagerBuilder delegateBuilder : delegateBuilders) { - delegate = delegateBuilder.getDefaultUserDetailsService(); - if(delegate != null) { - break; - } - } + synchronized (delegateMonitor) { + if (delegate == null) { + for (AuthenticationManagerBuilder delegateBuilder : delegateBuilders) { + delegate = delegateBuilder.getDefaultUserDetailsService(); + if (delegate != null) { + break; + } + } - if(delegate == null) { - throw new IllegalStateException("UserDetailsService is required."); - } - this.delegateBuilders = null; - } - } + if (delegate == null) { + throw new IllegalStateException("UserDetailsService is required."); + } + this.delegateBuilders = null; + } + } - return delegate.loadUserByUsername(username); - } - } + return delegate.loadUserByUsername(username); + } + } + /** + * Delays the use of the {@link AuthenticationManager} build from the + * {@link AuthenticationManagerBuilder} to ensure that it has been fully configured. + * + * @author Rob Winch + * @since 3.2 + */ + static final class AuthenticationManagerDelegator implements AuthenticationManager { + private AuthenticationManagerBuilder delegateBuilder; + private AuthenticationManager delegate; + private final Object delegateMonitor = new Object(); + private Set beanNames; - /** - * Delays the use of the {@link AuthenticationManager} build from the - * {@link AuthenticationManagerBuilder} to ensure that it has been fully - * configured. - * - * @author Rob Winch - * @since 3.2 - */ - static final class AuthenticationManagerDelegator implements AuthenticationManager { - private AuthenticationManagerBuilder delegateBuilder; - private AuthenticationManager delegate; - private final Object delegateMonitor = new Object(); - private Set beanNames; + AuthenticationManagerDelegator(AuthenticationManagerBuilder delegateBuilder, + ApplicationContext context) { + Assert.notNull(delegateBuilder, "delegateBuilder cannot be null"); + Field parentAuthMgrField = ReflectionUtils.findField( + AuthenticationManagerBuilder.class, "parentAuthenticationManager"); + ReflectionUtils.makeAccessible(parentAuthMgrField); + beanNames = getAuthenticationManagerBeanNames(context); + validateBeanCycle( + ReflectionUtils.getField(parentAuthMgrField, delegateBuilder), + beanNames); + this.delegateBuilder = delegateBuilder; + } - AuthenticationManagerDelegator(AuthenticationManagerBuilder delegateBuilder, ApplicationContext context) { - Assert.notNull(delegateBuilder,"delegateBuilder cannot be null"); - Field parentAuthMgrField = ReflectionUtils.findField(AuthenticationManagerBuilder.class, "parentAuthenticationManager"); - ReflectionUtils.makeAccessible(parentAuthMgrField); - beanNames = getAuthenticationManagerBeanNames(context); - validateBeanCycle(ReflectionUtils.getField(parentAuthMgrField, delegateBuilder), beanNames); - this.delegateBuilder = delegateBuilder; - } + public Authentication authenticate(Authentication authentication) + throws AuthenticationException { + if (delegate != null) { + return delegate.authenticate(authentication); + } - public Authentication authenticate(Authentication authentication) throws AuthenticationException { - if(delegate != null) { - return delegate.authenticate(authentication); - } + synchronized (delegateMonitor) { + if (delegate == null) { + delegate = this.delegateBuilder.getObject(); + this.delegateBuilder = null; + } + } - synchronized(delegateMonitor) { - if (delegate == null) { - delegate = this.delegateBuilder.getObject(); - this.delegateBuilder = null; - } - } + return delegate.authenticate(authentication); + } - return delegate.authenticate(authentication); - } + private static Set getAuthenticationManagerBeanNames( + ApplicationContext applicationContext) { + String[] beanNamesForType = BeanFactoryUtils + .beanNamesForTypeIncludingAncestors(applicationContext, + AuthenticationManager.class); + return new HashSet(Arrays.asList(beanNamesForType)); + } - private static Set getAuthenticationManagerBeanNames(ApplicationContext applicationContext) { - String[] beanNamesForType = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(applicationContext, AuthenticationManager.class); - return new HashSet(Arrays.asList(beanNamesForType)); - } - - private static void validateBeanCycle(Object auth, Set beanNames) { - if(auth != null && !beanNames.isEmpty()) { - if(auth instanceof Advised){ - Advised advised = (Advised) auth; - TargetSource targetSource = advised.getTargetSource(); - if(targetSource instanceof LazyInitTargetSource) { - LazyInitTargetSource lits = (LazyInitTargetSource) targetSource; - if(beanNames.contains(lits.getTargetBeanName())) { - throw new FatalBeanException("A dependency cycle was detected when trying to resolve the AuthenticationManager. Please ensure you have configured authentication."); - } - } - } - beanNames = Collections.emptySet(); - } - } - } + private static void validateBeanCycle(Object auth, Set beanNames) { + if (auth != null && !beanNames.isEmpty()) { + if (auth instanceof Advised) { + Advised advised = (Advised) auth; + TargetSource targetSource = advised.getTargetSource(); + if (targetSource instanceof LazyInitTargetSource) { + LazyInitTargetSource lits = (LazyInitTargetSource) targetSource; + if (beanNames.contains(lits.getTargetBeanName())) { + throw new FatalBeanException( + "A dependency cycle was detected when trying to resolve the AuthenticationManager. Please ensure you have configured authentication."); + } + } + } + beanNames = Collections.emptySet(); + } + } + } } \ No newline at end of file diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/AbstractAuthenticationFilterConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/AbstractAuthenticationFilterConfigurer.java index e2a56e37a3..a539364245 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/AbstractAuthenticationFilterConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/AbstractAuthenticationFilterConfigurer.java @@ -42,329 +42,339 @@ import org.springframework.web.accept.ContentNegotiationStrategy; import org.springframework.web.accept.HeaderContentNegotiationStrategy; /** - * Base class for confuring {@link AbstractAuthenticationFilterConfigurer}. This is intended for internal use only. + * Base class for confuring {@link AbstractAuthenticationFilterConfigurer}. This is + * intended for internal use only. * * @see FormLoginConfigurer * @see OpenIDLoginConfigurer * * @param T refers to "this" for returning the current configurer - * @param F refers to the {@link AbstractAuthenticationProcessingFilter} that is being built + * @param F refers to the {@link AbstractAuthenticationProcessingFilter} that is being + * built * * @author Rob Winch * @since 3.2 */ -public abstract class AbstractAuthenticationFilterConfigurer,T extends AbstractAuthenticationFilterConfigurer, F extends AbstractAuthenticationProcessingFilter> extends AbstractHttpConfigurer { +public abstract class AbstractAuthenticationFilterConfigurer, T extends AbstractAuthenticationFilterConfigurer, F extends AbstractAuthenticationProcessingFilter> + extends AbstractHttpConfigurer { - private final F authFilter; + private final F authFilter; - private AuthenticationDetailsSource authenticationDetailsSource; + private AuthenticationDetailsSource authenticationDetailsSource; - private AuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler(); + private AuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler(); - private LoginUrlAuthenticationEntryPoint authenticationEntryPoint; + private LoginUrlAuthenticationEntryPoint authenticationEntryPoint; - private boolean customLoginPage; - private String loginPage; - private String loginProcessingUrl; + private boolean customLoginPage; + private String loginPage; + private String loginProcessingUrl; - private AuthenticationFailureHandler failureHandler; + private AuthenticationFailureHandler failureHandler; - private boolean permitAll; + private boolean permitAll; - private String failureUrl; + private String failureUrl; - /** - * Creates a new instance - * @param authenticationFilter the {@link AbstractAuthenticationProcessingFilter} to use - * @param defaultLoginProcessingUrl the default URL to use for {@link #loginProcessingUrl(String)} - */ - protected AbstractAuthenticationFilterConfigurer(F authenticationFilter, String defaultLoginProcessingUrl) { - this.authFilter = authenticationFilter; - setLoginPage("/login"); - if(defaultLoginProcessingUrl != null) { - loginProcessingUrl(defaultLoginProcessingUrl); - } - } + /** + * Creates a new instance + * @param authenticationFilter the {@link AbstractAuthenticationProcessingFilter} to + * use + * @param defaultLoginProcessingUrl the default URL to use for + * {@link #loginProcessingUrl(String)} + */ + protected AbstractAuthenticationFilterConfigurer(F authenticationFilter, + String defaultLoginProcessingUrl) { + this.authFilter = authenticationFilter; + setLoginPage("/login"); + if (defaultLoginProcessingUrl != null) { + loginProcessingUrl(defaultLoginProcessingUrl); + } + } - /** - * Specifies where users will go after authenticating successfully if they - * have not visited a secured page prior to authenticating. This is a - * shortcut for calling {@link #defaultSuccessUrl(String)}. - * - * @param defaultSuccessUrl - * the default success url - * @return the {@link FormLoginConfigurer} for additional customization - */ - public final T defaultSuccessUrl(String defaultSuccessUrl) { - return defaultSuccessUrl(defaultSuccessUrl, false); - } + /** + * Specifies where users will go after authenticating successfully if they have not + * visited a secured page prior to authenticating. This is a shortcut for calling + * {@link #defaultSuccessUrl(String)}. + * + * @param defaultSuccessUrl the default success url + * @return the {@link FormLoginConfigurer} for additional customization + */ + public final T defaultSuccessUrl(String defaultSuccessUrl) { + return defaultSuccessUrl(defaultSuccessUrl, false); + } - /** - * Specifies where users will go after authenticating successfully if they - * have not visited a secured page prior to authenticating or - * {@code alwaysUse} is true. This is a shortcut for calling - * {@link #successHandler(AuthenticationSuccessHandler)}. - * - * @param defaultSuccessUrl - * the default success url - * @param alwaysUse - * true if the {@code defaultSuccesUrl} should be used after - * authentication despite if a protected page had been previously - * visited - * @return the {@link FormLoginConfigurer} for additional customization - */ - public final T defaultSuccessUrl(String defaultSuccessUrl, boolean alwaysUse) { - SavedRequestAwareAuthenticationSuccessHandler handler = new SavedRequestAwareAuthenticationSuccessHandler(); - handler.setDefaultTargetUrl(defaultSuccessUrl); - handler.setAlwaysUseDefaultTargetUrl(alwaysUse); - return successHandler(handler); - } + /** + * Specifies where users will go after authenticating successfully if they have not + * visited a secured page prior to authenticating or {@code alwaysUse} is true. This + * is a shortcut for calling {@link #successHandler(AuthenticationSuccessHandler)}. + * + * @param defaultSuccessUrl the default success url + * @param alwaysUse true if the {@code defaultSuccesUrl} should be used after + * authentication despite if a protected page had been previously visited + * @return the {@link FormLoginConfigurer} for additional customization + */ + public final T defaultSuccessUrl(String defaultSuccessUrl, boolean alwaysUse) { + SavedRequestAwareAuthenticationSuccessHandler handler = new SavedRequestAwareAuthenticationSuccessHandler(); + handler.setDefaultTargetUrl(defaultSuccessUrl); + handler.setAlwaysUseDefaultTargetUrl(alwaysUse); + return successHandler(handler); + } - /** - * Specifies the URL to validate the credentials. - * - * @param loginProcessingUrl - * the URL to validate username and password - * @return the {@link FormLoginConfigurer} for additional customization - */ - public T loginProcessingUrl(String loginProcessingUrl) { - this.loginProcessingUrl = loginProcessingUrl; - authFilter.setRequiresAuthenticationRequestMatcher(createLoginProcessingUrlMatcher(loginProcessingUrl)); - return getSelf(); - } + /** + * Specifies the URL to validate the credentials. + * + * @param loginProcessingUrl the URL to validate username and password + * @return the {@link FormLoginConfigurer} for additional customization + */ + public T loginProcessingUrl(String loginProcessingUrl) { + this.loginProcessingUrl = loginProcessingUrl; + authFilter + .setRequiresAuthenticationRequestMatcher(createLoginProcessingUrlMatcher(loginProcessingUrl)); + return getSelf(); + } - /** - * Create the {@link RequestMatcher} given a loginProcessingUrl - * @param loginProcessingUrl creates the {@link RequestMatcher} based upon the loginProcessingUrl - * @return the {@link RequestMatcher} to use based upon the loginProcessingUrl - */ - protected abstract RequestMatcher createLoginProcessingUrlMatcher(String loginProcessingUrl); + /** + * Create the {@link RequestMatcher} given a loginProcessingUrl + * @param loginProcessingUrl creates the {@link RequestMatcher} based upon the + * loginProcessingUrl + * @return the {@link RequestMatcher} to use based upon the loginProcessingUrl + */ + protected abstract RequestMatcher createLoginProcessingUrlMatcher( + String loginProcessingUrl); - /** - * Specifies a custom {@link AuthenticationDetailsSource}. The default is {@link WebAuthenticationDetailsSource}. - * - * @param authenticationDetailsSource the custom {@link AuthenticationDetailsSource} - * @return the {@link FormLoginConfigurer} for additional customization - */ - public final T authenticationDetailsSource(AuthenticationDetailsSource authenticationDetailsSource) { - this.authenticationDetailsSource = authenticationDetailsSource; - return getSelf(); - } + /** + * Specifies a custom {@link AuthenticationDetailsSource}. The default is + * {@link WebAuthenticationDetailsSource}. + * + * @param authenticationDetailsSource the custom {@link AuthenticationDetailsSource} + * @return the {@link FormLoginConfigurer} for additional customization + */ + public final T authenticationDetailsSource( + AuthenticationDetailsSource authenticationDetailsSource) { + this.authenticationDetailsSource = authenticationDetailsSource; + return getSelf(); + } - /** - * Specifies the {@link AuthenticationSuccessHandler} to be used. The - * default is {@link SavedRequestAwareAuthenticationSuccessHandler} with no - * additional properites set. - * - * @param successHandler - * the {@link AuthenticationSuccessHandler}. - * @return the {@link FormLoginConfigurer} for additional customization - */ - public final T successHandler(AuthenticationSuccessHandler successHandler) { - this.successHandler = successHandler; - return getSelf(); - } + /** + * Specifies the {@link AuthenticationSuccessHandler} to be used. The default is + * {@link SavedRequestAwareAuthenticationSuccessHandler} with no additional properites + * set. + * + * @param successHandler the {@link AuthenticationSuccessHandler}. + * @return the {@link FormLoginConfigurer} for additional customization + */ + public final T successHandler(AuthenticationSuccessHandler successHandler) { + this.successHandler = successHandler; + return getSelf(); + } - /** - * Equivalent of invoking permitAll(true) - * @return - */ - public final T permitAll() { - return permitAll(true); - } + /** + * Equivalent of invoking permitAll(true) + * @return + */ + public final T permitAll() { + return permitAll(true); + } - /** - * Ensures the urls for {@link #failureUrl(String)} and - * {@link #authenticationUrls(String)} are granted access to any user. - * - * @param permitAll true to grant access to the URLs false to skip this step - * @return the {@link FormLoginConfigurer} for additional customization - */ - public final T permitAll(boolean permitAll) { - this.permitAll = permitAll; - return getSelf(); - } + /** + * Ensures the urls for {@link #failureUrl(String)} and + * {@link #authenticationUrls(String)} are granted access to any user. + * + * @param permitAll true to grant access to the URLs false to skip this step + * @return the {@link FormLoginConfigurer} for additional customization + */ + public final T permitAll(boolean permitAll) { + this.permitAll = permitAll; + return getSelf(); + } - /** - * The URL to send users if authentication fails. This is a shortcut for - * invoking {@link #failureHandler(AuthenticationFailureHandler)}. The - * default is "/login?error". - * - * @param authenticationFailureUrl - * the URL to send users if authentication fails (i.e. - * "/login?error"). - * @return the {@link FormLoginConfigurer} for additional customization - */ - public final T failureUrl(String authenticationFailureUrl) { - T result = failureHandler(new SimpleUrlAuthenticationFailureHandler(authenticationFailureUrl)); - this.failureUrl = authenticationFailureUrl; - return result; - } + /** + * The URL to send users if authentication fails. This is a shortcut for invoking + * {@link #failureHandler(AuthenticationFailureHandler)}. The default is + * "/login?error". + * + * @param authenticationFailureUrl the URL to send users if authentication fails (i.e. + * "/login?error"). + * @return the {@link FormLoginConfigurer} for additional customization + */ + public final T failureUrl(String authenticationFailureUrl) { + T result = failureHandler(new SimpleUrlAuthenticationFailureHandler( + authenticationFailureUrl)); + this.failureUrl = authenticationFailureUrl; + return result; + } - /** - * Specifies the {@link AuthenticationFailureHandler} to use when - * authentication fails. The default is redirecting to "/login?error" using - * {@link SimpleUrlAuthenticationFailureHandler} - * - * @param authenticationFailureHandler - * the {@link AuthenticationFailureHandler} to use when - * authentication fails. - * @return the {@link FormLoginConfigurer} for additional customization - */ - public final T failureHandler(AuthenticationFailureHandler authenticationFailureHandler) { - this.failureUrl = null; - this.failureHandler = authenticationFailureHandler; - return getSelf(); - } + /** + * Specifies the {@link AuthenticationFailureHandler} to use when authentication + * fails. The default is redirecting to "/login?error" using + * {@link SimpleUrlAuthenticationFailureHandler} + * + * @param authenticationFailureHandler the {@link AuthenticationFailureHandler} to use + * when authentication fails. + * @return the {@link FormLoginConfigurer} for additional customization + */ + public final T failureHandler( + AuthenticationFailureHandler authenticationFailureHandler) { + this.failureUrl = null; + this.failureHandler = authenticationFailureHandler; + return getSelf(); + } - @Override - public void init(B http) throws Exception { - updateAuthenticationDefaults(); - if(permitAll) { - PermitAllSupport.permitAll(http, loginPage, loginProcessingUrl, failureUrl); - } + @Override + public void init(B http) throws Exception { + updateAuthenticationDefaults(); + if (permitAll) { + PermitAllSupport.permitAll(http, loginPage, loginProcessingUrl, failureUrl); + } - registerDefaultAuthenticationEntryPoint(http); - } + registerDefaultAuthenticationEntryPoint(http); + } - @SuppressWarnings("unchecked") - private void registerDefaultAuthenticationEntryPoint(B http) { - ExceptionHandlingConfigurer exceptionHandling = http.getConfigurer(ExceptionHandlingConfigurer.class); - if(exceptionHandling == null) { - return; - } - ContentNegotiationStrategy contentNegotiationStrategy = http.getSharedObject(ContentNegotiationStrategy.class); - if(contentNegotiationStrategy == null) { - contentNegotiationStrategy = new HeaderContentNegotiationStrategy(); - } - MediaTypeRequestMatcher preferredMatcher = new MediaTypeRequestMatcher(contentNegotiationStrategy, MediaType.APPLICATION_XHTML_XML, new MediaType("image","*"), MediaType.TEXT_HTML, MediaType.TEXT_PLAIN); - preferredMatcher.setIgnoredMediaTypes(Collections.singleton(MediaType.ALL)); - exceptionHandling.defaultAuthenticationEntryPointFor(postProcess(authenticationEntryPoint), preferredMatcher); - } + @SuppressWarnings("unchecked") + private void registerDefaultAuthenticationEntryPoint(B http) { + ExceptionHandlingConfigurer exceptionHandling = http + .getConfigurer(ExceptionHandlingConfigurer.class); + if (exceptionHandling == null) { + return; + } + ContentNegotiationStrategy contentNegotiationStrategy = http + .getSharedObject(ContentNegotiationStrategy.class); + if (contentNegotiationStrategy == null) { + contentNegotiationStrategy = new HeaderContentNegotiationStrategy(); + } + MediaTypeRequestMatcher preferredMatcher = new MediaTypeRequestMatcher( + contentNegotiationStrategy, MediaType.APPLICATION_XHTML_XML, + new MediaType("image", "*"), MediaType.TEXT_HTML, MediaType.TEXT_PLAIN); + preferredMatcher.setIgnoredMediaTypes(Collections.singleton(MediaType.ALL)); + exceptionHandling.defaultAuthenticationEntryPointFor( + postProcess(authenticationEntryPoint), preferredMatcher); + } - @Override - public void configure(B http) throws Exception { - PortMapper portMapper = http.getSharedObject(PortMapper.class); - if(portMapper != null) { - authenticationEntryPoint.setPortMapper(portMapper); - } + @Override + public void configure(B http) throws Exception { + PortMapper portMapper = http.getSharedObject(PortMapper.class); + if (portMapper != null) { + authenticationEntryPoint.setPortMapper(portMapper); + } - authFilter.setAuthenticationManager(http.getSharedObject(AuthenticationManager.class)); - authFilter.setAuthenticationSuccessHandler(successHandler); - authFilter.setAuthenticationFailureHandler(failureHandler); - if(authenticationDetailsSource != null) { - authFilter.setAuthenticationDetailsSource(authenticationDetailsSource); - } - SessionAuthenticationStrategy sessionAuthenticationStrategy = http.getSharedObject(SessionAuthenticationStrategy.class); - if(sessionAuthenticationStrategy != null) { - authFilter.setSessionAuthenticationStrategy(sessionAuthenticationStrategy); - } - RememberMeServices rememberMeServices = http.getSharedObject(RememberMeServices.class); - if(rememberMeServices != null) { - authFilter.setRememberMeServices(rememberMeServices); - } - F filter = postProcess(authFilter); - http.addFilter(filter); - } + authFilter.setAuthenticationManager(http + .getSharedObject(AuthenticationManager.class)); + authFilter.setAuthenticationSuccessHandler(successHandler); + authFilter.setAuthenticationFailureHandler(failureHandler); + if (authenticationDetailsSource != null) { + authFilter.setAuthenticationDetailsSource(authenticationDetailsSource); + } + SessionAuthenticationStrategy sessionAuthenticationStrategy = http + .getSharedObject(SessionAuthenticationStrategy.class); + if (sessionAuthenticationStrategy != null) { + authFilter.setSessionAuthenticationStrategy(sessionAuthenticationStrategy); + } + RememberMeServices rememberMeServices = http + .getSharedObject(RememberMeServices.class); + if (rememberMeServices != null) { + authFilter.setRememberMeServices(rememberMeServices); + } + F filter = postProcess(authFilter); + http.addFilter(filter); + } - /** - *

- * Specifies the URL to send users to if login is required. If used with - * {@link WebSecurityConfigurerAdapter} a default login page will be - * generated when this attribute is not specified. - *

- * - *

- * If a URL is specified or this is not being used in conjuction with - * {@link WebSecurityConfigurerAdapter}, users are required to process the - * specified URL to generate a login page. - *

- */ - protected T loginPage(String loginPage) { - setLoginPage(loginPage); - updateAuthenticationDefaults(); - this.customLoginPage = true; - return getSelf(); - } + /** + *

+ * Specifies the URL to send users to if login is required. If used with + * {@link WebSecurityConfigurerAdapter} a default login page will be generated when + * this attribute is not specified. + *

+ * + *

+ * If a URL is specified or this is not being used in conjuction with + * {@link WebSecurityConfigurerAdapter}, users are required to process the specified + * URL to generate a login page. + *

+ */ + protected T loginPage(String loginPage) { + setLoginPage(loginPage); + updateAuthenticationDefaults(); + this.customLoginPage = true; + return getSelf(); + } - /** - * - * @return true if a custom login page has been specified, else false - */ - public final boolean isCustomLoginPage() { - return customLoginPage; - } + /** + * + * @return true if a custom login page has been specified, else false + */ + public final boolean isCustomLoginPage() { + return customLoginPage; + } - /** - * Gets the Authentication Filter - * - * @return - */ - protected final F getAuthenticationFilter() { - return authFilter; - } + /** + * Gets the Authentication Filter + * + * @return + */ + protected final F getAuthenticationFilter() { + return authFilter; + } - /** - * Gets the login page - * - * @return the login page - */ - protected final String getLoginPage() { - return loginPage; - } + /** + * Gets the login page + * + * @return the login page + */ + protected final String getLoginPage() { + return loginPage; + } - /** - * Gets the URL to submit an authentication request to (i.e. where - * username/password must be submitted) - * - * @return the URL to submit an authentication request to - */ - protected final String getLoginProcessingUrl() { - return loginProcessingUrl; - } + /** + * Gets the URL to submit an authentication request to (i.e. where username/password + * must be submitted) + * + * @return the URL to submit an authentication request to + */ + protected final String getLoginProcessingUrl() { + return loginProcessingUrl; + } - /** - * Gets the URL to send users to if authentication fails - * - * @return - */ - protected final String getFailureUrl() { - return failureUrl; - } + /** + * Gets the URL to send users to if authentication fails + * + * @return + */ + protected final String getFailureUrl() { + return failureUrl; + } - /** - * Updates the default values for authentication. - * - * @throws Exception - */ - private void updateAuthenticationDefaults() { - if (loginProcessingUrl == null) { - loginProcessingUrl(loginPage); - } - if (failureHandler == null) { - failureUrl(loginPage + "?error"); - } + /** + * Updates the default values for authentication. + * + * @throws Exception + */ + private void updateAuthenticationDefaults() { + if (loginProcessingUrl == null) { + loginProcessingUrl(loginPage); + } + if (failureHandler == null) { + failureUrl(loginPage + "?error"); + } - final LogoutConfigurer logoutConfigurer = getBuilder() - .getConfigurer(LogoutConfigurer.class); - if (logoutConfigurer != null - && !logoutConfigurer.isCustomLogoutSuccess()) { - logoutConfigurer.logoutSuccessUrl(loginPage + "?logout"); - } - } + final LogoutConfigurer logoutConfigurer = getBuilder().getConfigurer( + LogoutConfigurer.class); + if (logoutConfigurer != null && !logoutConfigurer.isCustomLogoutSuccess()) { + logoutConfigurer.logoutSuccessUrl(loginPage + "?logout"); + } + } - /** - * Sets the loginPage and updates the {@link AuthenticationEntryPoint}. - * @param loginPage - */ - private void setLoginPage(String loginPage) { - this.loginPage = loginPage; - this.authenticationEntryPoint = new LoginUrlAuthenticationEntryPoint( - loginPage); - } + /** + * Sets the loginPage and updates the {@link AuthenticationEntryPoint}. + * @param loginPage + */ + private void setLoginPage(String loginPage) { + this.loginPage = loginPage; + this.authenticationEntryPoint = new LoginUrlAuthenticationEntryPoint(loginPage); + } - @SuppressWarnings("unchecked") - private T getSelf() { - return (T) this; - } + @SuppressWarnings("unchecked") + private T getSelf() { + return (T) this; + } } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/AbstractConfigAttributeRequestMatcherRegistry.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/AbstractConfigAttributeRequestMatcherRegistry.java index dba0458553..e6a22be222 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/AbstractConfigAttributeRequestMatcherRegistry.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/AbstractConfigAttributeRequestMatcherRegistry.java @@ -25,8 +25,8 @@ import org.springframework.security.config.annotation.web.AbstractRequestMatcher import org.springframework.security.web.util.matcher.RequestMatcher; /** - * A base class for registering {@link RequestMatcher}'s. For example, it might allow for specifying which - * {@link RequestMatcher} require a certain level of authorization. + * A base class for registering {@link RequestMatcher}'s. For example, it might allow for + * specifying which {@link RequestMatcher} require a certain level of authorization. * * @author Rob Winch * @since 3.2 @@ -37,105 +37,111 @@ import org.springframework.security.web.util.matcher.RequestMatcher; * @see UrlAuthorizationConfigurer * @see ExpressionUrlAuthorizationConfigurer */ -public abstract class AbstractConfigAttributeRequestMatcherRegistry extends AbstractRequestMatcherRegistry { - private List urlMappings = new ArrayList(); - private List unmappedMatchers; +public abstract class AbstractConfigAttributeRequestMatcherRegistry extends + AbstractRequestMatcherRegistry { + private List urlMappings = new ArrayList(); + private List unmappedMatchers; - /** - * Gets the {@link UrlMapping} added by subclasses in {@link #chainRequestMatchers(java.util.List)}. May be empty. - * - * @return the {@link UrlMapping} added by subclasses in {@link #chainRequestMatchers(java.util.List)} - */ - final List getUrlMappings() { - return urlMappings; - } + /** + * Gets the {@link UrlMapping} added by subclasses in + * {@link #chainRequestMatchers(java.util.List)}. May be empty. + * + * @return the {@link UrlMapping} added by subclasses in + * {@link #chainRequestMatchers(java.util.List)} + */ + final List getUrlMappings() { + return urlMappings; + } - /** - * Adds a {@link UrlMapping} added by subclasses in - * {@link #chainRequestMatchers(java.util.List)} and resets the unmapped - * {@link RequestMatcher}'s. - * - * @param urlMapping - * {@link UrlMapping} the mapping to add - */ - final void addMapping(UrlMapping urlMapping) { - this.unmappedMatchers = null; - this.urlMappings.add(urlMapping); - } + /** + * Adds a {@link UrlMapping} added by subclasses in + * {@link #chainRequestMatchers(java.util.List)} and resets the unmapped + * {@link RequestMatcher}'s. + * + * @param urlMapping {@link UrlMapping} the mapping to add + */ + final void addMapping(UrlMapping urlMapping) { + this.unmappedMatchers = null; + this.urlMappings.add(urlMapping); + } - /** - * Marks the {@link RequestMatcher}'s as unmapped and then calls {@link #chainRequestMatchersInternal(List)}. - * - * @param requestMatchers the {@link RequestMatcher} instances that were created - * @return the chained Object for the subclass which allows association of something else to the - * {@link RequestMatcher} - */ - protected final C chainRequestMatchers(List requestMatchers) { - this.unmappedMatchers = requestMatchers; - return chainRequestMatchersInternal(requestMatchers); - } + /** + * Marks the {@link RequestMatcher}'s as unmapped and then calls + * {@link #chainRequestMatchersInternal(List)}. + * + * @param requestMatchers the {@link RequestMatcher} instances that were created + * @return the chained Object for the subclass which allows association of something + * else to the {@link RequestMatcher} + */ + protected final C chainRequestMatchers(List requestMatchers) { + this.unmappedMatchers = requestMatchers; + return chainRequestMatchersInternal(requestMatchers); + } - /** - * Subclasses should implement this method for returning the object that is chained to the creation of the - * {@link RequestMatcher} instances. - * - * @param requestMatchers the {@link RequestMatcher} instances that were created - * @return the chained Object for the subclass which allows association of something else to the - * {@link RequestMatcher} - */ - protected abstract C chainRequestMatchersInternal(List requestMatchers); + /** + * Subclasses should implement this method for returning the object that is chained to + * the creation of the {@link RequestMatcher} instances. + * + * @param requestMatchers the {@link RequestMatcher} instances that were created + * @return the chained Object for the subclass which allows association of something + * else to the {@link RequestMatcher} + */ + protected abstract C chainRequestMatchersInternal(List requestMatchers); - /** - * Adds a {@link UrlMapping} added by subclasses in {@link #chainRequestMatchers(java.util.List)} at a particular - * index. - * - * @param index the index to add a {@link UrlMapping} - * @param urlMapping {@link UrlMapping} the mapping to add - */ - final void addMapping(int index, UrlMapping urlMapping) { - this.urlMappings.add(index, urlMapping); - } + /** + * Adds a {@link UrlMapping} added by subclasses in + * {@link #chainRequestMatchers(java.util.List)} at a particular index. + * + * @param index the index to add a {@link UrlMapping} + * @param urlMapping {@link UrlMapping} the mapping to add + */ + final void addMapping(int index, UrlMapping urlMapping) { + this.urlMappings.add(index, urlMapping); + } - /** - * Creates the mapping of {@link RequestMatcher} to {@link Collection} of {@link ConfigAttribute} instances - * - * @return the mapping of {@link RequestMatcher} to {@link Collection} of {@link ConfigAttribute} instances. Cannot - * be null. - */ - final LinkedHashMap> createRequestMap() { - if(unmappedMatchers != null) { - throw new IllegalStateException("An incomplete mapping was found for " + unmappedMatchers +". Try completing it with something like requestUrls()..hasRole('USER')"); - } + /** + * Creates the mapping of {@link RequestMatcher} to {@link Collection} of + * {@link ConfigAttribute} instances + * + * @return the mapping of {@link RequestMatcher} to {@link Collection} of + * {@link ConfigAttribute} instances. Cannot be null. + */ + final LinkedHashMap> createRequestMap() { + if (unmappedMatchers != null) { + throw new IllegalStateException( + "An incomplete mapping was found for " + + unmappedMatchers + + ". Try completing it with something like requestUrls()..hasRole('USER')"); + } - LinkedHashMap> requestMap = new LinkedHashMap>(); - for (UrlMapping mapping : getUrlMappings()) { - RequestMatcher matcher = mapping.getRequestMatcher(); - Collection configAttrs = mapping.getConfigAttrs(); - requestMap.put(matcher,configAttrs); - } - return requestMap; - } + LinkedHashMap> requestMap = new LinkedHashMap>(); + for (UrlMapping mapping : getUrlMappings()) { + RequestMatcher matcher = mapping.getRequestMatcher(); + Collection configAttrs = mapping.getConfigAttrs(); + requestMap.put(matcher, configAttrs); + } + return requestMap; + } - /** - * A mapping of {@link RequestMatcher} to {@link Collection} of {@link ConfigAttribute} instances - */ - static final class UrlMapping { - private RequestMatcher requestMatcher; - private Collection configAttrs; + /** + * A mapping of {@link RequestMatcher} to {@link Collection} of + * {@link ConfigAttribute} instances + */ + static final class UrlMapping { + private RequestMatcher requestMatcher; + private Collection configAttrs; - UrlMapping(RequestMatcher requestMatcher, - Collection configAttrs) { - this.requestMatcher = requestMatcher; - this.configAttrs = configAttrs; - } + UrlMapping(RequestMatcher requestMatcher, Collection configAttrs) { + this.requestMatcher = requestMatcher; + this.configAttrs = configAttrs; + } - public RequestMatcher getRequestMatcher() { - return requestMatcher; - } + public RequestMatcher getRequestMatcher() { + return requestMatcher; + } - public Collection getConfigAttrs() { - return configAttrs; - } - } + public Collection getConfigAttrs() { + return configAttrs; + } + } } - diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/AbstractHttpConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/AbstractHttpConfigurer.java index 4bd4d0479e..127b79be8d 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/AbstractHttpConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/AbstractHttpConfigurer.java @@ -23,29 +23,30 @@ import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.web.DefaultSecurityFilterChain; /** - * Adds a convenient base class for {@link SecurityConfigurer} instances that - * operate on {@link HttpSecurity}. + * Adds a convenient base class for {@link SecurityConfigurer} instances that operate on + * {@link HttpSecurity}. * * @author Rob Winch * */ -abstract class AbstractHttpConfigurer,B extends HttpSecurityBuilder> extends SecurityConfigurerAdapter { +abstract class AbstractHttpConfigurer, B extends HttpSecurityBuilder> + extends SecurityConfigurerAdapter { - /** - * Disables the {@link AbstractHttpConfigurer} by removing it. After doing - * so a fresh version of the configuration can be applied. - * - * @return the {@link HttpSecurityBuilder} for additional customizations - */ - @SuppressWarnings("unchecked") - public B disable() { - getBuilder().removeConfigurer(getClass()); - return getBuilder(); - } + /** + * Disables the {@link AbstractHttpConfigurer} by removing it. After doing so a fresh + * version of the configuration can be applied. + * + * @return the {@link HttpSecurityBuilder} for additional customizations + */ + @SuppressWarnings("unchecked") + public B disable() { + getBuilder().removeConfigurer(getClass()); + return getBuilder(); + } - @SuppressWarnings("unchecked") - public T withObjectPostProcessor(ObjectPostProcessor objectPostProcessor) { - addObjectPostProcessor(objectPostProcessor); - return (T) this; - } + @SuppressWarnings("unchecked") + public T withObjectPostProcessor(ObjectPostProcessor objectPostProcessor) { + addObjectPostProcessor(objectPostProcessor); + return (T) this; + } } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/AbstractInterceptUrlConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/AbstractInterceptUrlConfigurer.java index b65c2c1d22..4fe6e09571 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/AbstractInterceptUrlConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/AbstractInterceptUrlConfigurer.java @@ -34,14 +34,15 @@ import org.springframework.security.web.access.intercept.FilterSecurityIntercept * The following Filters are populated * *
    - *
  • {@link FilterSecurityInterceptor}
  • + *
  • {@link FilterSecurityInterceptor}
  • *
- * + * *

Shared Objects Created

* - * The following shared objects are populated to allow other {@link SecurityConfigurer}'s to customize: + * The following shared objects are populated to allow other {@link SecurityConfigurer}'s + * to customize: *
    - *
  • {@link FilterSecurityInterceptor}
  • + *
  • {@link FilterSecurityInterceptor}
  • *
* *

Shared Objects Used

@@ -49,7 +50,9 @@ import org.springframework.security.web.access.intercept.FilterSecurityIntercept * The following shared objects are used: * *
    - *
  • {@link org.springframework.security.config.annotation.web.builders.HttpSecurity#getAuthenticationManager()}
  • + *
  • + * {@link org.springframework.security.config.annotation.web.builders.HttpSecurity#getAuthenticationManager()} + *
  • *
* * @@ -61,130 +64,135 @@ import org.springframework.security.web.access.intercept.FilterSecurityIntercept * @see ExpressionUrlAuthorizationConfigurer * @see UrlAuthorizationConfigurer */ -abstract class AbstractInterceptUrlConfigurer, H extends HttpSecurityBuilder> extends - AbstractHttpConfigurer{ - private Boolean filterSecurityInterceptorOncePerRequest; +abstract class AbstractInterceptUrlConfigurer, H extends HttpSecurityBuilder> + extends AbstractHttpConfigurer { + private Boolean filterSecurityInterceptorOncePerRequest; - private AccessDecisionManager accessDecisionManager; + private AccessDecisionManager accessDecisionManager; - @Override - public void configure(H http) throws Exception { - FilterInvocationSecurityMetadataSource metadataSource = createMetadataSource(http); - if(metadataSource == null) { - return; - } - FilterSecurityInterceptor securityInterceptor = createFilterSecurityInterceptor(http, metadataSource, http.getSharedObject(AuthenticationManager.class)); - if(filterSecurityInterceptorOncePerRequest != null) { - securityInterceptor.setObserveOncePerRequest(filterSecurityInterceptorOncePerRequest); - } - securityInterceptor = postProcess(securityInterceptor); - http.addFilter(securityInterceptor); - http.setSharedObject(FilterSecurityInterceptor.class, securityInterceptor); - } + @Override + public void configure(H http) throws Exception { + FilterInvocationSecurityMetadataSource metadataSource = createMetadataSource(http); + if (metadataSource == null) { + return; + } + FilterSecurityInterceptor securityInterceptor = createFilterSecurityInterceptor( + http, metadataSource, http.getSharedObject(AuthenticationManager.class)); + if (filterSecurityInterceptorOncePerRequest != null) { + securityInterceptor + .setObserveOncePerRequest(filterSecurityInterceptorOncePerRequest); + } + securityInterceptor = postProcess(securityInterceptor); + http.addFilter(securityInterceptor); + http.setSharedObject(FilterSecurityInterceptor.class, securityInterceptor); + } - /** - * Subclasses should implement this method to provide a {@link FilterInvocationSecurityMetadataSource} for the - * {@link FilterSecurityInterceptor}. - * - * @param http the builder to use - * - * @return the {@link FilterInvocationSecurityMetadataSource} to set on the {@link FilterSecurityInterceptor}. - * Cannot be null. - */ - abstract FilterInvocationSecurityMetadataSource createMetadataSource(H http); + /** + * Subclasses should implement this method to provide a + * {@link FilterInvocationSecurityMetadataSource} for the + * {@link FilterSecurityInterceptor}. + * + * @param http the builder to use + * + * @return the {@link FilterInvocationSecurityMetadataSource} to set on the + * {@link FilterSecurityInterceptor}. Cannot be null. + */ + abstract FilterInvocationSecurityMetadataSource createMetadataSource(H http); - /** - * Subclasses should implement this method to provide the {@link AccessDecisionVoter} instances used to create the - * default {@link AccessDecisionManager} - * - * @param http the builder to use - * - * @return the {@link AccessDecisionVoter} instances used to create the - * default {@link AccessDecisionManager} - */ - @SuppressWarnings("rawtypes") - abstract List> getDecisionVoters(H http); + /** + * Subclasses should implement this method to provide the {@link AccessDecisionVoter} + * instances used to create the default {@link AccessDecisionManager} + * + * @param http the builder to use + * + * @return the {@link AccessDecisionVoter} instances used to create the default + * {@link AccessDecisionManager} + */ + @SuppressWarnings("rawtypes") + abstract List> getDecisionVoters(H http); - abstract class AbstractInterceptUrlRegistry,T> extends AbstractConfigAttributeRequestMatcherRegistry { + abstract class AbstractInterceptUrlRegistry, T> + extends AbstractConfigAttributeRequestMatcherRegistry { - /** - * Allows setting the {@link AccessDecisionManager}. If none is provided, a default {@l AccessDecisionManager} is - * created. - * - * @param accessDecisionManager the {@link AccessDecisionManager} to use - * @return the {@link AbstractInterceptUrlConfigurer} for further customization - */ - public R accessDecisionManager( - AccessDecisionManager accessDecisionManager) { - AbstractInterceptUrlConfigurer.this.accessDecisionManager = accessDecisionManager; - return getSelf(); - } + /** + * Allows setting the {@link AccessDecisionManager}. If none is provided, a + * default {@l AccessDecisionManager} is created. + * + * @param accessDecisionManager the {@link AccessDecisionManager} to use + * @return the {@link AbstractInterceptUrlConfigurer} for further customization + */ + public R accessDecisionManager(AccessDecisionManager accessDecisionManager) { + AbstractInterceptUrlConfigurer.this.accessDecisionManager = accessDecisionManager; + return getSelf(); + } - /** - * Allows setting if the {@link FilterSecurityInterceptor} should be only applied once per request (i.e. if the - * filter intercepts on a forward, should it be applied again). - * - * @param filterSecurityInterceptorOncePerRequest if the {@link FilterSecurityInterceptor} should be only applied - * once per request - * @return the {@link AbstractInterceptUrlConfigurer} for further customization - */ - public R filterSecurityInterceptorOncePerRequest( - boolean filterSecurityInterceptorOncePerRequest) { - AbstractInterceptUrlConfigurer.this.filterSecurityInterceptorOncePerRequest = filterSecurityInterceptorOncePerRequest; - return getSelf(); - } + /** + * Allows setting if the {@link FilterSecurityInterceptor} should be only applied + * once per request (i.e. if the filter intercepts on a forward, should it be + * applied again). + * + * @param filterSecurityInterceptorOncePerRequest if the + * {@link FilterSecurityInterceptor} should be only applied once per request + * @return the {@link AbstractInterceptUrlConfigurer} for further customization + */ + public R filterSecurityInterceptorOncePerRequest( + boolean filterSecurityInterceptorOncePerRequest) { + AbstractInterceptUrlConfigurer.this.filterSecurityInterceptorOncePerRequest = filterSecurityInterceptorOncePerRequest; + return getSelf(); + } - /** - * Returns a reference to the current object with a single suppression of - * the type - * - * @return a reference to the current object - */ - @SuppressWarnings("unchecked") - private R getSelf() { - return (R) this; - } - } + /** + * Returns a reference to the current object with a single suppression of the type + * + * @return a reference to the current object + */ + @SuppressWarnings("unchecked") + private R getSelf() { + return (R) this; + } + } - /** - * Creates the default {@code AccessDecisionManager} - * @return the default {@code AccessDecisionManager} - */ - private AccessDecisionManager createDefaultAccessDecisionManager(H http) { - return new AffirmativeBased(getDecisionVoters(http)); - } + /** + * Creates the default {@code AccessDecisionManager} + * @return the default {@code AccessDecisionManager} + */ + private AccessDecisionManager createDefaultAccessDecisionManager(H http) { + return new AffirmativeBased(getDecisionVoters(http)); + } - /** - * If currently null, creates a default {@link AccessDecisionManager} using - * {@link #createDefaultAccessDecisionManager()}. Otherwise returns the {@link AccessDecisionManager}. - * - * @param http the builder to use - * - * @return the {@link AccessDecisionManager} to use - */ - private AccessDecisionManager getAccessDecisionManager(H http) { - if (accessDecisionManager == null) { - accessDecisionManager = createDefaultAccessDecisionManager(http); - } - return accessDecisionManager; - } + /** + * If currently null, creates a default {@link AccessDecisionManager} using + * {@link #createDefaultAccessDecisionManager()}. Otherwise returns the + * {@link AccessDecisionManager}. + * + * @param http the builder to use + * + * @return the {@link AccessDecisionManager} to use + */ + private AccessDecisionManager getAccessDecisionManager(H http) { + if (accessDecisionManager == null) { + accessDecisionManager = createDefaultAccessDecisionManager(http); + } + return accessDecisionManager; + } - /** - * Creates the {@link FilterSecurityInterceptor} - * - * @param http the builder to use - * @param metadataSource the {@link FilterInvocationSecurityMetadataSource} to use - * @param authenticationManager the {@link AuthenticationManager} to use - * @return the {@link FilterSecurityInterceptor} - * @throws Exception - */ - private FilterSecurityInterceptor createFilterSecurityInterceptor(H http, FilterInvocationSecurityMetadataSource metadataSource, - AuthenticationManager authenticationManager) throws Exception { - FilterSecurityInterceptor securityInterceptor = new FilterSecurityInterceptor(); - securityInterceptor.setSecurityMetadataSource(metadataSource); - securityInterceptor.setAccessDecisionManager(getAccessDecisionManager(http)); - securityInterceptor.setAuthenticationManager(authenticationManager); - securityInterceptor.afterPropertiesSet(); - return securityInterceptor; - } + /** + * Creates the {@link FilterSecurityInterceptor} + * + * @param http the builder to use + * @param metadataSource the {@link FilterInvocationSecurityMetadataSource} to use + * @param authenticationManager the {@link AuthenticationManager} to use + * @return the {@link FilterSecurityInterceptor} + * @throws Exception + */ + private FilterSecurityInterceptor createFilterSecurityInterceptor(H http, + FilterInvocationSecurityMetadataSource metadataSource, + AuthenticationManager authenticationManager) throws Exception { + FilterSecurityInterceptor securityInterceptor = new FilterSecurityInterceptor(); + securityInterceptor.setSecurityMetadataSource(metadataSource); + securityInterceptor.setAccessDecisionManager(getAccessDecisionManager(http)); + securityInterceptor.setAuthenticationManager(authenticationManager); + securityInterceptor.afterPropertiesSet(); + return securityInterceptor; + } } \ No newline at end of file diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/AnonymousConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/AnonymousConfigurer.java index 19cfcc9185..f5d0f3382b 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/AnonymousConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/AnonymousConfigurer.java @@ -29,123 +29,144 @@ import org.springframework.security.core.authority.AuthorityUtils; import org.springframework.security.web.authentication.AnonymousAuthenticationFilter; /** - * Configures Anonymous authentication (i.e. populate an {@link Authentication} that represents an anonymous user - * instead of having a null value) for an {@link HttpSecurity}. Specifically this will configure an - * {@link AnonymousAuthenticationFilter} and an {@link AnonymousAuthenticationProvider}. All properties have reasonable - * defaults, so no additional configuration is required other than applying this {@link SecurityConfigurer}. + * Configures Anonymous authentication (i.e. populate an {@link Authentication} that + * represents an anonymous user instead of having a null value) for an + * {@link HttpSecurity}. Specifically this will configure an + * {@link AnonymousAuthenticationFilter} and an {@link AnonymousAuthenticationProvider}. + * All properties have reasonable defaults, so no additional configuration is required + * other than applying this {@link SecurityConfigurer}. * - * @author Rob Winch - * @since 3.2 + * @author Rob Winch + * @since 3.2 */ -public final class AnonymousConfigurer> extends AbstractHttpConfigurer,H> { - private String key; - private AuthenticationProvider authenticationProvider; - private AnonymousAuthenticationFilter authenticationFilter; - private Object principal = "anonymousUser"; - private List authorities = AuthorityUtils.createAuthorityList("ROLE_ANONYMOUS"); +public final class AnonymousConfigurer> extends + AbstractHttpConfigurer, H> { + private String key; + private AuthenticationProvider authenticationProvider; + private AnonymousAuthenticationFilter authenticationFilter; + private Object principal = "anonymousUser"; + private List authorities = AuthorityUtils + .createAuthorityList("ROLE_ANONYMOUS"); - /** - * Creates a new instance - * @see HttpSecurity#anonymous() - */ - public AnonymousConfigurer() { - } + /** + * Creates a new instance + * @see HttpSecurity#anonymous() + */ + public AnonymousConfigurer() { + } - /** - * Sets the key to identify tokens created for anonymous authentication. Default is a secure randomly generated - * key. - * - * @param key the key to identify tokens created for anonymous authentication. Default is a secure randomly generated - * key. - * @return the {@link AnonymousConfigurer} for further customization of anonymous authentication - */ - public AnonymousConfigurer key(String key) { - this.key = key; - return this; - } + /** + * Sets the key to identify tokens created for anonymous authentication. Default is a + * secure randomly generated key. + * + * @param key the key to identify tokens created for anonymous authentication. Default + * is a secure randomly generated key. + * @return the {@link AnonymousConfigurer} for further customization of anonymous + * authentication + */ + public AnonymousConfigurer key(String key) { + this.key = key; + return this; + } - /** - * Sets the principal for {@link Authentication} objects of anonymous users - * - * @param principal used for the {@link Authentication} object of anonymous users - * @return the {@link AnonymousConfigurer} for further customization of anonymous authentication - */ - public AnonymousConfigurer principal(Object principal) { - this.principal = principal; - return this; - } + /** + * Sets the principal for {@link Authentication} objects of anonymous users + * + * @param principal used for the {@link Authentication} object of anonymous users + * @return the {@link AnonymousConfigurer} for further customization of anonymous + * authentication + */ + public AnonymousConfigurer principal(Object principal) { + this.principal = principal; + return this; + } - /** - * Sets the {@link org.springframework.security.core.Authentication#getAuthorities()} for anonymous users - * - * @param authorities Sets the {@link org.springframework.security.core.Authentication#getAuthorities()} for anonymous users - * @return the {@link AnonymousConfigurer} for further customization of anonymous authentication - */ - public AnonymousConfigurer authorities(List authorities) { - this.authorities = authorities; - return this; - } + /** + * Sets the {@link org.springframework.security.core.Authentication#getAuthorities()} + * for anonymous users + * + * @param authorities Sets the + * {@link org.springframework.security.core.Authentication#getAuthorities()} for + * anonymous users + * @return the {@link AnonymousConfigurer} for further customization of anonymous + * authentication + */ + public AnonymousConfigurer authorities(List authorities) { + this.authorities = authorities; + return this; + } - /** - * Sets the {@link org.springframework.security.core.Authentication#getAuthorities()} for anonymous users - * - * @param authorities Sets the {@link org.springframework.security.core.Authentication#getAuthorities()} for - * anonymous users (i.e. "ROLE_ANONYMOUS") - * @return the {@link AnonymousConfigurer} for further customization of anonymous authentication - */ - public AnonymousConfigurer authorities(String... authorities) { - return authorities(AuthorityUtils.createAuthorityList(authorities)); - } + /** + * Sets the {@link org.springframework.security.core.Authentication#getAuthorities()} + * for anonymous users + * + * @param authorities Sets the + * {@link org.springframework.security.core.Authentication#getAuthorities()} for + * anonymous users (i.e. "ROLE_ANONYMOUS") + * @return the {@link AnonymousConfigurer} for further customization of anonymous + * authentication + */ + public AnonymousConfigurer authorities(String... authorities) { + return authorities(AuthorityUtils.createAuthorityList(authorities)); + } - /** - * Sets the {@link AuthenticationProvider} used to validate an anonymous user. If this is set, no attributes - * on the {@link AnonymousConfigurer} will be set on the {@link AuthenticationProvider}. - * - * @param authenticationProvider the {@link AuthenticationProvider} used to validate an anonymous user. Default is - * {@link AnonymousAuthenticationProvider} - * - * @return the {@link AnonymousConfigurer} for further customization of anonymous authentication - */ - public AnonymousConfigurer authenticationProvider(AuthenticationProvider authenticationProvider) { - this.authenticationProvider = authenticationProvider; - return this; - } + /** + * Sets the {@link AuthenticationProvider} used to validate an anonymous user. If this + * is set, no attributes on the {@link AnonymousConfigurer} will be set on the + * {@link AuthenticationProvider}. + * + * @param authenticationProvider the {@link AuthenticationProvider} used to validate + * an anonymous user. Default is {@link AnonymousAuthenticationProvider} + * + * @return the {@link AnonymousConfigurer} for further customization of anonymous + * authentication + */ + public AnonymousConfigurer authenticationProvider( + AuthenticationProvider authenticationProvider) { + this.authenticationProvider = authenticationProvider; + return this; + } - /** - * Sets the {@link AnonymousAuthenticationFilter} used to populate an anonymous user. If this is set, no attributes - * on the {@link AnonymousConfigurer} will be set on the {@link AnonymousAuthenticationFilter}. - * - * @param authenticationFilter the {@link AnonymousAuthenticationFilter} used to populate an anonymous user. - * - * @return the {@link AnonymousConfigurer} for further customization of anonymous authentication - */ - public AnonymousConfigurer authenticationFilter(AnonymousAuthenticationFilter authenticationFilter) { - this.authenticationFilter = authenticationFilter; - return this; - } + /** + * Sets the {@link AnonymousAuthenticationFilter} used to populate an anonymous user. + * If this is set, no attributes on the {@link AnonymousConfigurer} will be set on the + * {@link AnonymousAuthenticationFilter}. + * + * @param authenticationFilter the {@link AnonymousAuthenticationFilter} used to + * populate an anonymous user. + * + * @return the {@link AnonymousConfigurer} for further customization of anonymous + * authentication + */ + public AnonymousConfigurer authenticationFilter( + AnonymousAuthenticationFilter authenticationFilter) { + this.authenticationFilter = authenticationFilter; + return this; + } - @Override - public void init(H http) throws Exception { - if(authenticationProvider == null) { - authenticationProvider = new AnonymousAuthenticationProvider(getKey()); - } - if(authenticationFilter == null) { - authenticationFilter = new AnonymousAuthenticationFilter(getKey(), principal, authorities); - } - authenticationProvider = postProcess(authenticationProvider); - http.authenticationProvider(authenticationProvider); - } + @Override + public void init(H http) throws Exception { + if (authenticationProvider == null) { + authenticationProvider = new AnonymousAuthenticationProvider(getKey()); + } + if (authenticationFilter == null) { + authenticationFilter = new AnonymousAuthenticationFilter(getKey(), principal, + authorities); + } + authenticationProvider = postProcess(authenticationProvider); + http.authenticationProvider(authenticationProvider); + } - @Override - public void configure(H http) throws Exception { - authenticationFilter.afterPropertiesSet(); - http.addFilter(authenticationFilter); - } + @Override + public void configure(H http) throws Exception { + authenticationFilter.afterPropertiesSet(); + http.addFilter(authenticationFilter); + } - private String getKey() { - if(key == null) { - key = UUID.randomUUID().toString(); - } - return key; - } + private String getKey() { + if (key == null) { + key = UUID.randomUUID().toString(); + } + return key; + } } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/ChannelSecurityConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/ChannelSecurityConfigurer.java index 691bd02674..fe28944d7f 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/ChannelSecurityConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/ChannelSecurityConfigurer.java @@ -40,11 +40,12 @@ import org.springframework.security.web.util.matcher.RequestMatcher; /** * Adds channel security (i.e. requires HTTPS or HTTP) to an application. In order for - * {@link ChannelSecurityConfigurer} to be useful, at least one {@link RequestMatcher} should be mapped to HTTP - * or HTTPS. + * {@link ChannelSecurityConfigurer} to be useful, at least one {@link RequestMatcher} + * should be mapped to HTTP or HTTPS. * *

- * By default an {@link InsecureChannelProcessor} and a {@link SecureChannelProcessor} will be registered. + * By default an {@link InsecureChannelProcessor} and a {@link SecureChannelProcessor} + * will be registered. *

* *

Security Filters

@@ -52,7 +53,7 @@ import org.springframework.security.web.util.matcher.RequestMatcher; * The following Filters are populated * *
    - *
  • {@link ChannelProcessingFilter}
  • + *
  • {@link ChannelProcessingFilter}
  • *
* *

Shared Objects Created

@@ -64,7 +65,8 @@ import org.springframework.security.web.util.matcher.RequestMatcher; * The following shared objects are used: * *
    - *
  • {@link PortMapper} is used to create the default {@link ChannelProcessor} instances
  • + *
  • {@link PortMapper} is used to create the default {@link ChannelProcessor} instances + *
  • *
* * @param the type of {@link HttpSecurityBuilder} that is being configured @@ -73,130 +75,138 @@ import org.springframework.security.web.util.matcher.RequestMatcher; * @since 3.2 */ public final class ChannelSecurityConfigurer> extends - AbstractHttpConfigurer, H> { - private ChannelProcessingFilter channelFilter = new ChannelProcessingFilter(); - private LinkedHashMap> requestMap = new LinkedHashMap>(); - private List channelProcessors; + AbstractHttpConfigurer, H> { + private ChannelProcessingFilter channelFilter = new ChannelProcessingFilter(); + private LinkedHashMap> requestMap = new LinkedHashMap>(); + private List channelProcessors; - private final ChannelRequestMatcherRegistry REGISTRY = new ChannelRequestMatcherRegistry(); + private final ChannelRequestMatcherRegistry REGISTRY = new ChannelRequestMatcherRegistry(); - /** - * Creates a new instance - * @see HttpSecurity#requiresChannel() - */ - public ChannelSecurityConfigurer() { - } + /** + * Creates a new instance + * @see HttpSecurity#requiresChannel() + */ + public ChannelSecurityConfigurer() { + } - public ChannelRequestMatcherRegistry getRegistry() { - return REGISTRY; - } + public ChannelRequestMatcherRegistry getRegistry() { + return REGISTRY; + } - @Override - public void configure(H http) throws Exception { - ChannelDecisionManagerImpl channelDecisionManager = new ChannelDecisionManagerImpl(); - channelDecisionManager.setChannelProcessors(getChannelProcessors(http)); - channelDecisionManager = postProcess(channelDecisionManager); + @Override + public void configure(H http) throws Exception { + ChannelDecisionManagerImpl channelDecisionManager = new ChannelDecisionManagerImpl(); + channelDecisionManager.setChannelProcessors(getChannelProcessors(http)); + channelDecisionManager = postProcess(channelDecisionManager); - channelFilter.setChannelDecisionManager(channelDecisionManager); + channelFilter.setChannelDecisionManager(channelDecisionManager); - DefaultFilterInvocationSecurityMetadataSource filterInvocationSecurityMetadataSource = - new DefaultFilterInvocationSecurityMetadataSource(requestMap); - channelFilter.setSecurityMetadataSource(filterInvocationSecurityMetadataSource); + DefaultFilterInvocationSecurityMetadataSource filterInvocationSecurityMetadataSource = new DefaultFilterInvocationSecurityMetadataSource( + requestMap); + channelFilter.setSecurityMetadataSource(filterInvocationSecurityMetadataSource); - channelFilter = postProcess(channelFilter); - http.addFilter(channelFilter); - } + channelFilter = postProcess(channelFilter); + http.addFilter(channelFilter); + } - private List getChannelProcessors(H http) { - if(channelProcessors != null) { - return channelProcessors; - } + private List getChannelProcessors(H http) { + if (channelProcessors != null) { + return channelProcessors; + } - InsecureChannelProcessor insecureChannelProcessor = new InsecureChannelProcessor(); - SecureChannelProcessor secureChannelProcessor = new SecureChannelProcessor(); + InsecureChannelProcessor insecureChannelProcessor = new InsecureChannelProcessor(); + SecureChannelProcessor secureChannelProcessor = new SecureChannelProcessor(); - PortMapper portMapper = http.getSharedObject(PortMapper.class); - if(portMapper != null) { - RetryWithHttpEntryPoint httpEntryPoint = new RetryWithHttpEntryPoint(); - httpEntryPoint.setPortMapper(portMapper); - insecureChannelProcessor.setEntryPoint(httpEntryPoint); + PortMapper portMapper = http.getSharedObject(PortMapper.class); + if (portMapper != null) { + RetryWithHttpEntryPoint httpEntryPoint = new RetryWithHttpEntryPoint(); + httpEntryPoint.setPortMapper(portMapper); + insecureChannelProcessor.setEntryPoint(httpEntryPoint); - RetryWithHttpsEntryPoint httpsEntryPoint = new RetryWithHttpsEntryPoint(); - httpsEntryPoint.setPortMapper(portMapper); - secureChannelProcessor.setEntryPoint(httpsEntryPoint); - } - insecureChannelProcessor = postProcess(insecureChannelProcessor); - secureChannelProcessor = postProcess(secureChannelProcessor); - return Arrays.asList(insecureChannelProcessor, secureChannelProcessor); - } + RetryWithHttpsEntryPoint httpsEntryPoint = new RetryWithHttpsEntryPoint(); + httpsEntryPoint.setPortMapper(portMapper); + secureChannelProcessor.setEntryPoint(httpsEntryPoint); + } + insecureChannelProcessor = postProcess(insecureChannelProcessor); + secureChannelProcessor = postProcess(secureChannelProcessor); + return Arrays. asList(insecureChannelProcessor, + secureChannelProcessor); + } + private ChannelRequestMatcherRegistry addAttribute(String attribute, + List matchers) { + for (RequestMatcher matcher : matchers) { + Collection attrs = Arrays + . asList(new SecurityConfig(attribute)); + requestMap.put(matcher, attrs); + } + return REGISTRY; + } - private ChannelRequestMatcherRegistry addAttribute(String attribute, List matchers) { - for(RequestMatcher matcher : matchers) { - Collection attrs = Arrays.asList(new SecurityConfig(attribute)); - requestMap.put(matcher, attrs); - } - return REGISTRY; - } + public final class ChannelRequestMatcherRegistry extends + AbstractConfigAttributeRequestMatcherRegistry { - public final class ChannelRequestMatcherRegistry extends AbstractConfigAttributeRequestMatcherRegistry { + @Override + protected RequiresChannelUrl chainRequestMatchersInternal( + List requestMatchers) { + return new RequiresChannelUrl(requestMatchers); + } - @Override - protected RequiresChannelUrl chainRequestMatchersInternal(List requestMatchers) { - return new RequiresChannelUrl(requestMatchers); - } + /** + * Adds an {@link ObjectPostProcessor} for this class. + * + * @param objectPostProcessor + * @return the {@link ChannelSecurityConfigurer} for further customizations + */ + public ChannelRequestMatcherRegistry withObjectPostProcessor( + ObjectPostProcessor objectPostProcessor) { + addObjectPostProcessor(objectPostProcessor); + return this; + } - /** - * Adds an {@link ObjectPostProcessor} for this class. - * - * @param objectPostProcessor - * @return the {@link ChannelSecurityConfigurer} for further customizations - */ - public ChannelRequestMatcherRegistry withObjectPostProcessor(ObjectPostProcessor objectPostProcessor) { - addObjectPostProcessor(objectPostProcessor); - return this; - } + /** + * Sets the {@link ChannelProcessor} instances to use in + * {@link ChannelDecisionManagerImpl} + * @param channelProcessors + * @return + */ + public ChannelRequestMatcherRegistry channelProcessors( + List channelProcessors) { + ChannelSecurityConfigurer.this.channelProcessors = channelProcessors; + return this; + } - /** - * Sets the {@link ChannelProcessor} instances to use in {@link ChannelDecisionManagerImpl} - * @param channelProcessors - * @return - */ - public ChannelRequestMatcherRegistry channelProcessors(List channelProcessors) { - ChannelSecurityConfigurer.this.channelProcessors = channelProcessors; - return this; - } + /** + * Return the {@link SecurityBuilder} when done using the + * {@link SecurityConfigurer}. This is useful for method chaining. + * + * @return + */ + public H and() { + return ChannelSecurityConfigurer.this.and(); + } - /** - * Return the {@link SecurityBuilder} when done using the - * {@link SecurityConfigurer}. This is useful for method chaining. - * - * @return - */ - public H and() { - return ChannelSecurityConfigurer.this.and(); - } + private ChannelRequestMatcherRegistry() { + } + } - private ChannelRequestMatcherRegistry() {} - } + public final class RequiresChannelUrl { + private List requestMatchers; - public final class RequiresChannelUrl { - private List requestMatchers; + private RequiresChannelUrl(List requestMatchers) { + this.requestMatchers = requestMatchers; + } - private RequiresChannelUrl(List requestMatchers) { - this.requestMatchers = requestMatchers; - } + public ChannelRequestMatcherRegistry requiresSecure() { + return requires("REQUIRES_SECURE_CHANNEL"); + } - public ChannelRequestMatcherRegistry requiresSecure() { - return requires("REQUIRES_SECURE_CHANNEL"); - } + public ChannelRequestMatcherRegistry requiresInsecure() { + return requires("REQUIRES_INSECURE_CHANNEL"); + } - public ChannelRequestMatcherRegistry requiresInsecure() { - return requires("REQUIRES_INSECURE_CHANNEL"); - } - - public ChannelRequestMatcherRegistry requires(String attribute) { - return addAttribute(attribute, requestMatchers); - } - } + public ChannelRequestMatcherRegistry requires(String attribute) { + return addAttribute(attribute, requestMatchers); + } + } } \ No newline at end of file diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/CsrfConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/CsrfConfigurer.java index 3a27c23a0e..e4cf68dd49 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/CsrfConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/CsrfConfigurer.java @@ -43,8 +43,7 @@ import org.springframework.security.web.util.matcher.RequestMatcher; import org.springframework.util.Assert; /** - * Adds CSRF protection for the methods as specified by * {@link #requireCsrfProtectionMatcher(RequestMatcher)}. * @@ -64,200 +63,212 @@ import org.springframework.util.Assert; * *
    *
  • - * {@link ExceptionHandlingConfigurer#accessDeniedHandler(AccessDeniedHandler)} - * is used to determine how to handle CSRF attempts
  • + * {@link ExceptionHandlingConfigurer#accessDeniedHandler(AccessDeniedHandler)} is used to + * determine how to handle CSRF attempts *
  • {@link InvalidSessionStrategy}
  • *
* * @author Rob Winch * @since 3.2 */ -public final class CsrfConfigurer> extends AbstractHttpConfigurer,H> { - private CsrfTokenRepository csrfTokenRepository = new HttpSessionCsrfTokenRepository(); - private RequestMatcher requireCsrfProtectionMatcher = CsrfFilter.DEFAULT_CSRF_MATCHER; - private List ignoredCsrfProtectionMatchers = new ArrayList(); +public final class CsrfConfigurer> extends + AbstractHttpConfigurer, H> { + private CsrfTokenRepository csrfTokenRepository = new HttpSessionCsrfTokenRepository(); + private RequestMatcher requireCsrfProtectionMatcher = CsrfFilter.DEFAULT_CSRF_MATCHER; + private List ignoredCsrfProtectionMatchers = new ArrayList(); - /** - * Creates a new instance - * @see HttpSecurity#csrf() - */ - public CsrfConfigurer() { - } + /** + * Creates a new instance + * @see HttpSecurity#csrf() + */ + public CsrfConfigurer() { + } - /** - * Specify the {@link CsrfTokenRepository} to use. The default is an {@link HttpSessionCsrfTokenRepository}. - * - * @param csrfTokenRepository the {@link CsrfTokenRepository} to use - * @return the {@link CsrfConfigurer} for further customizations - */ - public CsrfConfigurer csrfTokenRepository(CsrfTokenRepository csrfTokenRepository) { - Assert.notNull(csrfTokenRepository, "csrfTokenRepository cannot be null"); - this.csrfTokenRepository = csrfTokenRepository; - return this; - } + /** + * Specify the {@link CsrfTokenRepository} to use. The default is an + * {@link HttpSessionCsrfTokenRepository}. + * + * @param csrfTokenRepository the {@link CsrfTokenRepository} to use + * @return the {@link CsrfConfigurer} for further customizations + */ + public CsrfConfigurer csrfTokenRepository(CsrfTokenRepository csrfTokenRepository) { + Assert.notNull(csrfTokenRepository, "csrfTokenRepository cannot be null"); + this.csrfTokenRepository = csrfTokenRepository; + return this; + } - /** - * Specify the {@link RequestMatcher} to use for determining when CSRF - * should be applied. The default is to ignore GET, HEAD, TRACE, OPTIONS and - * process all other requests. - * - * @param requireCsrfProtectionMatcher - * the {@link RequestMatcher} to use - * @return the {@link CsrfConfigurer} for further customizations - */ - public CsrfConfigurer requireCsrfProtectionMatcher(RequestMatcher requireCsrfProtectionMatcher) { - Assert.notNull(requireCsrfProtectionMatcher, "requireCsrfProtectionMatcher cannot be null"); - this.requireCsrfProtectionMatcher = requireCsrfProtectionMatcher; - return this; - } + /** + * Specify the {@link RequestMatcher} to use for determining when CSRF should be + * applied. The default is to ignore GET, HEAD, TRACE, OPTIONS and process all other + * requests. + * + * @param requireCsrfProtectionMatcher the {@link RequestMatcher} to use + * @return the {@link CsrfConfigurer} for further customizations + */ + public CsrfConfigurer requireCsrfProtectionMatcher( + RequestMatcher requireCsrfProtectionMatcher) { + Assert.notNull(requireCsrfProtectionMatcher, + "requireCsrfProtectionMatcher cannot be null"); + this.requireCsrfProtectionMatcher = requireCsrfProtectionMatcher; + return this; + } - /** - *

- * Allows specifying {@link HttpServletRequest} that should not use CSRF Protection even if they match the {@link #requireCsrfProtectionMatcher(RequestMatcher)}. - *

- * - *

- * The following will ensure CSRF protection ignores: - *

- *
    - *
  • Any GET, HEAD, TRACE, OPTIONS (this is the default)
  • - *
  • We also explicitly state to ignore any request that starts with "/sockjs/"
  • - *
- * - *
-     * http
-     *     .csrf()
-     *         .ignoringAntMatchers("/sockjs/**")
-     *         .and()
-     *     ...
-     * 
- * - * @since 4.0 - */ - public CsrfConfigurer ignoringAntMatchers(String... antPatterns) { - return new IgnoreCsrfProtectionRegistry().antMatchers(antPatterns).and(); - } + /** + *

+ * Allows specifying {@link HttpServletRequest} that should not use CSRF Protection + * even if they match the {@link #requireCsrfProtectionMatcher(RequestMatcher)}. + *

+ * + *

+ * The following will ensure CSRF protection ignores: + *

+ *
    + *
  • Any GET, HEAD, TRACE, OPTIONS (this is the default)
  • + *
  • We also explicitly state to ignore any request that starts with "/sockjs/"
  • + *
+ * + *
+	 * http
+	 *     .csrf()
+	 *         .ignoringAntMatchers("/sockjs/**")
+	 *         .and()
+	 *     ...
+	 * 
+ * + * @since 4.0 + */ + public CsrfConfigurer ignoringAntMatchers(String... antPatterns) { + return new IgnoreCsrfProtectionRegistry().antMatchers(antPatterns).and(); + } - @SuppressWarnings("unchecked") - @Override - public void configure(H http) throws Exception { - CsrfFilter filter = new CsrfFilter(csrfTokenRepository); - RequestMatcher requireCsrfProtectionMatcher = getRequireCsrfProtectionMatcher(); - if(requireCsrfProtectionMatcher != null) { - filter.setRequireCsrfProtectionMatcher(requireCsrfProtectionMatcher); - } - AccessDeniedHandler accessDeniedHandler = createAccessDeniedHandler(http); - if(accessDeniedHandler != null) { - filter.setAccessDeniedHandler(accessDeniedHandler); - } - LogoutConfigurer logoutConfigurer = http.getConfigurer(LogoutConfigurer.class); - if(logoutConfigurer != null) { - logoutConfigurer.addLogoutHandler(new CsrfLogoutHandler(csrfTokenRepository)); - } - SessionManagementConfigurer sessionConfigurer = http.getConfigurer(SessionManagementConfigurer.class); - if(sessionConfigurer != null) { - sessionConfigurer.addSessionAuthenticationStrategy(new CsrfAuthenticationStrategy(csrfTokenRepository)); - } - filter = postProcess(filter); - http.addFilter(filter); - } + @SuppressWarnings("unchecked") + @Override + public void configure(H http) throws Exception { + CsrfFilter filter = new CsrfFilter(csrfTokenRepository); + RequestMatcher requireCsrfProtectionMatcher = getRequireCsrfProtectionMatcher(); + if (requireCsrfProtectionMatcher != null) { + filter.setRequireCsrfProtectionMatcher(requireCsrfProtectionMatcher); + } + AccessDeniedHandler accessDeniedHandler = createAccessDeniedHandler(http); + if (accessDeniedHandler != null) { + filter.setAccessDeniedHandler(accessDeniedHandler); + } + LogoutConfigurer logoutConfigurer = http.getConfigurer(LogoutConfigurer.class); + if (logoutConfigurer != null) { + logoutConfigurer.addLogoutHandler(new CsrfLogoutHandler(csrfTokenRepository)); + } + SessionManagementConfigurer sessionConfigurer = http + .getConfigurer(SessionManagementConfigurer.class); + if (sessionConfigurer != null) { + sessionConfigurer + .addSessionAuthenticationStrategy(new CsrfAuthenticationStrategy( + csrfTokenRepository)); + } + filter = postProcess(filter); + http.addFilter(filter); + } - /** - * Gets the final {@link RequestMatcher} to use by combining the {@link #requireCsrfProtectionMatcher(RequestMatcher)} and any {@link #ignore()}. - * - * @return the {@link RequestMatcher} to use - */ - private RequestMatcher getRequireCsrfProtectionMatcher() { - if(ignoredCsrfProtectionMatchers.isEmpty()) { - return requireCsrfProtectionMatcher; - } - return new AndRequestMatcher(requireCsrfProtectionMatcher, new NegatedRequestMatcher(new OrRequestMatcher(ignoredCsrfProtectionMatchers))); - } + /** + * Gets the final {@link RequestMatcher} to use by combining the + * {@link #requireCsrfProtectionMatcher(RequestMatcher)} and any {@link #ignore()}. + * + * @return the {@link RequestMatcher} to use + */ + private RequestMatcher getRequireCsrfProtectionMatcher() { + if (ignoredCsrfProtectionMatchers.isEmpty()) { + return requireCsrfProtectionMatcher; + } + return new AndRequestMatcher(requireCsrfProtectionMatcher, + new NegatedRequestMatcher(new OrRequestMatcher( + ignoredCsrfProtectionMatchers))); + } - /** - * Gets the default {@link AccessDeniedHandler} from the - * {@link ExceptionHandlingConfigurer#getAccessDeniedHandler()} or create a - * {@link AccessDeniedHandlerImpl} if not available. - * - * @param http the {@link HttpSecurityBuilder} - * @return the {@link AccessDeniedHandler} - */ - @SuppressWarnings("unchecked") - private AccessDeniedHandler getDefaultAccessDeniedHandler(H http) { - ExceptionHandlingConfigurer exceptionConfig = http.getConfigurer(ExceptionHandlingConfigurer.class); - AccessDeniedHandler handler = null; - if(exceptionConfig != null) { - handler = exceptionConfig.getAccessDeniedHandler(); - } - if(handler == null) { - handler = new AccessDeniedHandlerImpl(); - } - return handler; - } + /** + * Gets the default {@link AccessDeniedHandler} from the + * {@link ExceptionHandlingConfigurer#getAccessDeniedHandler()} or create a + * {@link AccessDeniedHandlerImpl} if not available. + * + * @param http the {@link HttpSecurityBuilder} + * @return the {@link AccessDeniedHandler} + */ + @SuppressWarnings("unchecked") + private AccessDeniedHandler getDefaultAccessDeniedHandler(H http) { + ExceptionHandlingConfigurer exceptionConfig = http + .getConfigurer(ExceptionHandlingConfigurer.class); + AccessDeniedHandler handler = null; + if (exceptionConfig != null) { + handler = exceptionConfig.getAccessDeniedHandler(); + } + if (handler == null) { + handler = new AccessDeniedHandlerImpl(); + } + return handler; + } - /** - * Gets the default {@link InvalidSessionStrategy} from the - * {@link SessionManagementConfigurer#getInvalidSessionStrategy()} or null - * if not available. - * - * @param http - * the {@link HttpSecurityBuilder} - * @return the {@link InvalidSessionStrategy} - */ - @SuppressWarnings("unchecked") - private InvalidSessionStrategy getInvalidSessionStrategy(H http) { - SessionManagementConfigurer sessionManagement = http.getConfigurer(SessionManagementConfigurer.class); - if(sessionManagement == null) { - return null; - } - return sessionManagement.getInvalidSessionStrategy(); - } + /** + * Gets the default {@link InvalidSessionStrategy} from the + * {@link SessionManagementConfigurer#getInvalidSessionStrategy()} or null if not + * available. + * + * @param http the {@link HttpSecurityBuilder} + * @return the {@link InvalidSessionStrategy} + */ + @SuppressWarnings("unchecked") + private InvalidSessionStrategy getInvalidSessionStrategy(H http) { + SessionManagementConfigurer sessionManagement = http + .getConfigurer(SessionManagementConfigurer.class); + if (sessionManagement == null) { + return null; + } + return sessionManagement.getInvalidSessionStrategy(); + } - /** - * Creates the {@link AccessDeniedHandler} from the result of - * {@link #getDefaultAccessDeniedHandler(HttpSecurityBuilder)} and - * {@link #getInvalidSessionStrategy(HttpSecurityBuilder)}. If - * {@link #getInvalidSessionStrategy(HttpSecurityBuilder)} is non-null, then - * a {@link DelegatingAccessDeniedHandler} is used in combination with - * {@link InvalidSessionAccessDeniedHandler} and the - * {@link #getDefaultAccessDeniedHandler(HttpSecurityBuilder)}. Otherwise, - * only {@link #getDefaultAccessDeniedHandler(HttpSecurityBuilder)} is used. - * - * @param http the {@link HttpSecurityBuilder} - * @return the {@link AccessDeniedHandler} - */ - private AccessDeniedHandler createAccessDeniedHandler(H http) { - InvalidSessionStrategy invalidSessionStrategy = getInvalidSessionStrategy(http); - AccessDeniedHandler defaultAccessDeniedHandler = getDefaultAccessDeniedHandler(http); - if(invalidSessionStrategy == null) { - return defaultAccessDeniedHandler; - } + /** + * Creates the {@link AccessDeniedHandler} from the result of + * {@link #getDefaultAccessDeniedHandler(HttpSecurityBuilder)} and + * {@link #getInvalidSessionStrategy(HttpSecurityBuilder)}. If + * {@link #getInvalidSessionStrategy(HttpSecurityBuilder)} is non-null, then a + * {@link DelegatingAccessDeniedHandler} is used in combination with + * {@link InvalidSessionAccessDeniedHandler} and the + * {@link #getDefaultAccessDeniedHandler(HttpSecurityBuilder)}. Otherwise, only + * {@link #getDefaultAccessDeniedHandler(HttpSecurityBuilder)} is used. + * + * @param http the {@link HttpSecurityBuilder} + * @return the {@link AccessDeniedHandler} + */ + private AccessDeniedHandler createAccessDeniedHandler(H http) { + InvalidSessionStrategy invalidSessionStrategy = getInvalidSessionStrategy(http); + AccessDeniedHandler defaultAccessDeniedHandler = getDefaultAccessDeniedHandler(http); + if (invalidSessionStrategy == null) { + return defaultAccessDeniedHandler; + } - InvalidSessionAccessDeniedHandler invalidSessionDeniedHandler = new InvalidSessionAccessDeniedHandler(invalidSessionStrategy); - LinkedHashMap, AccessDeniedHandler> handlers = - new LinkedHashMap, AccessDeniedHandler>(); - handlers.put(MissingCsrfTokenException.class, invalidSessionDeniedHandler); - return new DelegatingAccessDeniedHandler(handlers, defaultAccessDeniedHandler); - } + InvalidSessionAccessDeniedHandler invalidSessionDeniedHandler = new InvalidSessionAccessDeniedHandler( + invalidSessionStrategy); + LinkedHashMap, AccessDeniedHandler> handlers = new LinkedHashMap, AccessDeniedHandler>(); + handlers.put(MissingCsrfTokenException.class, invalidSessionDeniedHandler); + return new DelegatingAccessDeniedHandler(handlers, defaultAccessDeniedHandler); + } - /** - * Allows registering {@link RequestMatcher} instances that should be - * ignored (even if the {@link HttpServletRequest} matches the - * {@link CsrfConfigurer#requireCsrfProtectionMatcher(RequestMatcher)}. - * - * @author Rob Winch - * @since 4.0 - */ - private class IgnoreCsrfProtectionRegistry extends AbstractRequestMatcherRegistry{ + /** + * Allows registering {@link RequestMatcher} instances that should be ignored (even if + * the {@link HttpServletRequest} matches the + * {@link CsrfConfigurer#requireCsrfProtectionMatcher(RequestMatcher)}. + * + * @author Rob Winch + * @since 4.0 + */ + private class IgnoreCsrfProtectionRegistry extends + AbstractRequestMatcherRegistry { - public CsrfConfigurer and() { - return CsrfConfigurer.this; - } + public CsrfConfigurer and() { + return CsrfConfigurer.this; + } - protected IgnoreCsrfProtectionRegistry chainRequestMatchers( - List requestMatchers) { - ignoredCsrfProtectionMatchers.addAll(requestMatchers); - return this; - } - } + protected IgnoreCsrfProtectionRegistry chainRequestMatchers( + List requestMatchers) { + ignoredCsrfProtectionMatchers.addAll(requestMatchers); + return this; + } + } } \ No newline at end of file diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/DefaultLoginPageConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/DefaultLoginPageConfigurer.java index 2172e69371..57d03b5b76 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/DefaultLoginPageConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/DefaultLoginPageConfigurer.java @@ -21,10 +21,14 @@ import org.springframework.security.web.AuthenticationEntryPoint; import org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter; /** - * Adds a Filter that will generate a login page if one is not specified otherwise when using {@link WebSecurityConfigurerAdapter}. + * Adds a Filter that will generate a login page if one is not specified otherwise when + * using {@link WebSecurityConfigurerAdapter}. * *

- * By default an {@link org.springframework.security.web.access.channel.InsecureChannelProcessor} and a {@link org.springframework.security.web.access.channel.SecureChannelProcessor} will be registered. + * By default an + * {@link org.springframework.security.web.access.channel.InsecureChannelProcessor} and a + * {@link org.springframework.security.web.access.channel.SecureChannelProcessor} will be + * registered. *

* *

Security Filters

@@ -32,20 +36,21 @@ import org.springframework.security.web.authentication.ui.DefaultLoginPageGenera * The following Filters are conditionally populated * *
    - *
  • {@link DefaultLoginPageGeneratingFilter} if the {@link FormLoginConfigurer} did not have a login page specified
  • + *
  • {@link DefaultLoginPageGeneratingFilter} if the {@link FormLoginConfigurer} did not + * have a login page specified
  • *
* *

Shared Objects Created

* - * No shared objects are created. - *isLogoutRequest - *

Shared Objects Used

+ * No shared objects are created. isLogoutRequest

Shared Objects Used

* * The following shared objects are used: * *
    - *
  • {@link org.springframework.security.web.PortMapper} is used to create the default {@link org.springframework.security.web.access.channel.ChannelProcessor} instances
  • - *
  • {@link FormLoginConfigurer} is used to determine if the {@link DefaultLoginPageConfigurer} should be added and how to configure it.
  • + *
  • {@link org.springframework.security.web.PortMapper} is used to create the default + * {@link org.springframework.security.web.access.channel.ChannelProcessor} instances
  • + *
  • {@link FormLoginConfigurer} is used to determine if the + * {@link DefaultLoginPageConfigurer} should be added and how to configure it.
  • *
* * @see WebSecurityConfigurerAdapter @@ -54,29 +59,30 @@ import org.springframework.security.web.authentication.ui.DefaultLoginPageGenera * @since 3.2 */ public final class DefaultLoginPageConfigurer> extends - AbstractHttpConfigurer,H> { + AbstractHttpConfigurer, H> { - private DefaultLoginPageGeneratingFilter loginPageGeneratingFilter = new DefaultLoginPageGeneratingFilter(); + private DefaultLoginPageGeneratingFilter loginPageGeneratingFilter = new DefaultLoginPageGeneratingFilter(); - @Override - public void init(H http) throws Exception { - http.setSharedObject(DefaultLoginPageGeneratingFilter.class, loginPageGeneratingFilter); - } + @Override + public void init(H http) throws Exception { + http.setSharedObject(DefaultLoginPageGeneratingFilter.class, + loginPageGeneratingFilter); + } - @Override - @SuppressWarnings("unchecked") - public void configure(H http) throws Exception { - AuthenticationEntryPoint authenticationEntryPoint = null; - ExceptionHandlingConfigurer exceptionConf = http.getConfigurer(ExceptionHandlingConfigurer.class); - if(exceptionConf != null) { - authenticationEntryPoint = exceptionConf.getAuthenticationEntryPoint(); - } - - if(loginPageGeneratingFilter.isEnabled() && authenticationEntryPoint == null) { - loginPageGeneratingFilter = postProcess(loginPageGeneratingFilter); - http.addFilter(loginPageGeneratingFilter); - } - } + @Override + @SuppressWarnings("unchecked") + public void configure(H http) throws Exception { + AuthenticationEntryPoint authenticationEntryPoint = null; + ExceptionHandlingConfigurer exceptionConf = http + .getConfigurer(ExceptionHandlingConfigurer.class); + if (exceptionConf != null) { + authenticationEntryPoint = exceptionConf.getAuthenticationEntryPoint(); + } + if (loginPageGeneratingFilter.isEnabled() && authenticationEntryPoint == null) { + loginPageGeneratingFilter = postProcess(loginPageGeneratingFilter); + http.addFilter(loginPageGeneratingFilter); + } + } } \ No newline at end of file diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/ExceptionHandlingConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/ExceptionHandlingConfigurer.java index 19562ae22c..9cfb37e4c5 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/ExceptionHandlingConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/ExceptionHandlingConfigurer.java @@ -30,8 +30,9 @@ import org.springframework.security.web.savedrequest.RequestCache; import org.springframework.security.web.util.matcher.RequestMatcher; /** - * Adds exception handling for Spring Security related exceptions to an application. All properties have reasonable - * defaults, so no additional configuration is required other than applying this + * Adds exception handling for Spring Security related exceptions to an application. All + * properties have reasonable defaults, so no additional configuration is required other + * than applying this * {@link org.springframework.security.config.annotation.SecurityConfigurer}. * *

Security Filters

@@ -39,7 +40,7 @@ import org.springframework.security.web.util.matcher.RequestMatcher; * The following Filters are populated * *
    - *
  • {@link ExceptionTranslationFilter}
  • + *
  • {@link ExceptionTranslationFilter}
  • *
* *

Shared Objects Created

@@ -51,166 +52,173 @@ import org.springframework.security.web.util.matcher.RequestMatcher; * The following shared objects are used: * *
    - *
  • If no explicit {@link RequestCache}, is provided a {@link RequestCache} shared object is used to replay - * the request after authentication is successful
  • - *
  • {@link AuthenticationEntryPoint} - see {@link #authenticationEntryPoint(AuthenticationEntryPoint)}
  • + *
  • If no explicit {@link RequestCache}, is provided a {@link RequestCache} shared + * object is used to replay the request after authentication is successful
  • + *
  • {@link AuthenticationEntryPoint} - see + * {@link #authenticationEntryPoint(AuthenticationEntryPoint)}
  • *
* * @author Rob Winch * @since 3.2 */ -public final class ExceptionHandlingConfigurer> extends AbstractHttpConfigurer,H> { +public final class ExceptionHandlingConfigurer> extends + AbstractHttpConfigurer, H> { - private AuthenticationEntryPoint authenticationEntryPoint; + private AuthenticationEntryPoint authenticationEntryPoint; - private AccessDeniedHandler accessDeniedHandler; + private AccessDeniedHandler accessDeniedHandler; - private LinkedHashMap defaultEntryPointMappings = new LinkedHashMap(); + private LinkedHashMap defaultEntryPointMappings = new LinkedHashMap(); - /** - * Creates a new instance - * @see HttpSecurity#exceptionHandling() - */ - public ExceptionHandlingConfigurer() { - } + /** + * Creates a new instance + * @see HttpSecurity#exceptionHandling() + */ + public ExceptionHandlingConfigurer() { + } - /** - * Shortcut to specify the {@link AccessDeniedHandler} to be used is a specific error page - * - * @param accessDeniedUrl the URL to the access denied page (i.e. /errors/401) - * @return the {@link ExceptionHandlingConfigurer} for further customization - * @see AccessDeniedHandlerImpl - * @see {@link #accessDeniedHandler(org.springframework.security.web.access.AccessDeniedHandler)} - */ - public ExceptionHandlingConfigurer accessDeniedPage(String accessDeniedUrl) { - AccessDeniedHandlerImpl accessDeniedHandler = new AccessDeniedHandlerImpl(); - accessDeniedHandler.setErrorPage(accessDeniedUrl); - return accessDeniedHandler(accessDeniedHandler); - } + /** + * Shortcut to specify the {@link AccessDeniedHandler} to be used is a specific error + * page + * + * @param accessDeniedUrl the URL to the access denied page (i.e. /errors/401) + * @return the {@link ExceptionHandlingConfigurer} for further customization + * @see AccessDeniedHandlerImpl + * @see {@link #accessDeniedHandler(org.springframework.security.web.access.AccessDeniedHandler)} + */ + public ExceptionHandlingConfigurer accessDeniedPage(String accessDeniedUrl) { + AccessDeniedHandlerImpl accessDeniedHandler = new AccessDeniedHandlerImpl(); + accessDeniedHandler.setErrorPage(accessDeniedUrl); + return accessDeniedHandler(accessDeniedHandler); + } - /** - * Specifies the {@link AccessDeniedHandler} to be used - * - * @param accessDeniedHandler the {@link AccessDeniedHandler} to be used - * @return the {@link ExceptionHandlingConfigurer} for further customization - */ - public ExceptionHandlingConfigurer accessDeniedHandler(AccessDeniedHandler accessDeniedHandler) { - this.accessDeniedHandler = accessDeniedHandler; - return this; - } + /** + * Specifies the {@link AccessDeniedHandler} to be used + * + * @param accessDeniedHandler the {@link AccessDeniedHandler} to be used + * @return the {@link ExceptionHandlingConfigurer} for further customization + */ + public ExceptionHandlingConfigurer accessDeniedHandler( + AccessDeniedHandler accessDeniedHandler) { + this.accessDeniedHandler = accessDeniedHandler; + return this; + } - /** - * Sets the {@link AuthenticationEntryPoint} to be used. - * - *

- * If no {@link #authenticationEntryPoint(AuthenticationEntryPoint)} is - * specified, then - * {@link #defaultAuthenticationEntryPointFor(AuthenticationEntryPoint, RequestMatcher)} - * will be used. The first {@link AuthenticationEntryPoint} will be used as - * the default is no matches were found. - *

- * - *

- * If that is not provided defaults to {@link Http403ForbiddenEntryPoint}. - *

- * - * @param authenticationEntryPoint - * the {@link AuthenticationEntryPoint} to use - * @return the {@link ExceptionHandlingConfigurer} for further - * customizations - */ - public ExceptionHandlingConfigurer authenticationEntryPoint(AuthenticationEntryPoint authenticationEntryPoint) { - this.authenticationEntryPoint = authenticationEntryPoint; - return this; - } + /** + * Sets the {@link AuthenticationEntryPoint} to be used. + * + *

+ * If no {@link #authenticationEntryPoint(AuthenticationEntryPoint)} is specified, + * then + * {@link #defaultAuthenticationEntryPointFor(AuthenticationEntryPoint, RequestMatcher)} + * will be used. The first {@link AuthenticationEntryPoint} will be used as the + * default is no matches were found. + *

+ * + *

+ * If that is not provided defaults to {@link Http403ForbiddenEntryPoint}. + *

+ * + * @param authenticationEntryPoint the {@link AuthenticationEntryPoint} to use + * @return the {@link ExceptionHandlingConfigurer} for further customizations + */ + public ExceptionHandlingConfigurer authenticationEntryPoint( + AuthenticationEntryPoint authenticationEntryPoint) { + this.authenticationEntryPoint = authenticationEntryPoint; + return this; + } - /** - * Sets a default {@link AuthenticationEntryPoint} to be used which prefers - * being invoked for the provided {@link RequestMatcher}. If only a single - * default {@link AuthenticationEntryPoint} is specified, it will be what is - * used for the default {@link AuthenticationEntryPoint}. If multiple - * default {@link AuthenticationEntryPoint} instances are configured, then a - * {@link DelegatingAuthenticationEntryPoint} will be used. - * - * @param entryPoint - * the {@link AuthenticationEntryPoint} to use - * @param preferredMatcher - * the {@link RequestMatcher} for this default - * {@link AuthenticationEntryPoint} - * @return the {@link ExceptionHandlingConfigurer} for further - * customizations - */ - public ExceptionHandlingConfigurer defaultAuthenticationEntryPointFor(AuthenticationEntryPoint entryPoint, RequestMatcher preferredMatcher) { - this.defaultEntryPointMappings.put(preferredMatcher, entryPoint); - return this; - } + /** + * Sets a default {@link AuthenticationEntryPoint} to be used which prefers being + * invoked for the provided {@link RequestMatcher}. If only a single default + * {@link AuthenticationEntryPoint} is specified, it will be what is used for the + * default {@link AuthenticationEntryPoint}. If multiple default + * {@link AuthenticationEntryPoint} instances are configured, then a + * {@link DelegatingAuthenticationEntryPoint} will be used. + * + * @param entryPoint the {@link AuthenticationEntryPoint} to use + * @param preferredMatcher the {@link RequestMatcher} for this default + * {@link AuthenticationEntryPoint} + * @return the {@link ExceptionHandlingConfigurer} for further customizations + */ + public ExceptionHandlingConfigurer defaultAuthenticationEntryPointFor( + AuthenticationEntryPoint entryPoint, RequestMatcher preferredMatcher) { + this.defaultEntryPointMappings.put(preferredMatcher, entryPoint); + return this; + } - /** - * Gets any explicitly configured {@link AuthenticationEntryPoint} - * @return - */ - AuthenticationEntryPoint getAuthenticationEntryPoint() { - return this.authenticationEntryPoint; - } + /** + * Gets any explicitly configured {@link AuthenticationEntryPoint} + * @return + */ + AuthenticationEntryPoint getAuthenticationEntryPoint() { + return this.authenticationEntryPoint; + } - /** - * Gets the {@link AccessDeniedHandler} that is configured. - * - * @return the {@link AccessDeniedHandler} - */ - AccessDeniedHandler getAccessDeniedHandler() { - return this.accessDeniedHandler; - } + /** + * Gets the {@link AccessDeniedHandler} that is configured. + * + * @return the {@link AccessDeniedHandler} + */ + AccessDeniedHandler getAccessDeniedHandler() { + return this.accessDeniedHandler; + } - @Override - public void configure(H http) throws Exception { - AuthenticationEntryPoint entryPoint = getAuthenticationEntryPoint(http); - ExceptionTranslationFilter exceptionTranslationFilter = new ExceptionTranslationFilter(entryPoint, getRequestCache(http)); - if(accessDeniedHandler != null) { - exceptionTranslationFilter.setAccessDeniedHandler(accessDeniedHandler); - } - exceptionTranslationFilter = postProcess(exceptionTranslationFilter); - http.addFilter(exceptionTranslationFilter); - } - /** - * Gets the {@link AuthenticationEntryPoint} according to the rules specified by {@link #authenticationEntryPoint(AuthenticationEntryPoint)} - * @param http the {@link HttpSecurity} used to look up shared {@link AuthenticationEntryPoint} - * @return the {@link AuthenticationEntryPoint} to use - */ - AuthenticationEntryPoint getAuthenticationEntryPoint(H http) { - AuthenticationEntryPoint entryPoint = this.authenticationEntryPoint; - if(entryPoint == null) { - entryPoint = createDefaultEntryPoint(http); - } - return entryPoint; - } + @Override + public void configure(H http) throws Exception { + AuthenticationEntryPoint entryPoint = getAuthenticationEntryPoint(http); + ExceptionTranslationFilter exceptionTranslationFilter = new ExceptionTranslationFilter( + entryPoint, getRequestCache(http)); + if (accessDeniedHandler != null) { + exceptionTranslationFilter.setAccessDeniedHandler(accessDeniedHandler); + } + exceptionTranslationFilter = postProcess(exceptionTranslationFilter); + http.addFilter(exceptionTranslationFilter); + } - private AuthenticationEntryPoint createDefaultEntryPoint(H http) { - if(defaultEntryPointMappings.isEmpty()) { - return new Http403ForbiddenEntryPoint(); - } - if(defaultEntryPointMappings.size() == 1) { - return defaultEntryPointMappings.values().iterator().next(); - } - DelegatingAuthenticationEntryPoint entryPoint = new DelegatingAuthenticationEntryPoint(defaultEntryPointMappings); - entryPoint.setDefaultEntryPoint(defaultEntryPointMappings.values().iterator().next()); - return entryPoint; - } + /** + * Gets the {@link AuthenticationEntryPoint} according to the rules specified by + * {@link #authenticationEntryPoint(AuthenticationEntryPoint)} + * @param http the {@link HttpSecurity} used to look up shared + * {@link AuthenticationEntryPoint} + * @return the {@link AuthenticationEntryPoint} to use + */ + AuthenticationEntryPoint getAuthenticationEntryPoint(H http) { + AuthenticationEntryPoint entryPoint = this.authenticationEntryPoint; + if (entryPoint == null) { + entryPoint = createDefaultEntryPoint(http); + } + return entryPoint; + } - /** - * Gets the {@link RequestCache} to use. If one is defined using - * {@link #requestCache(org.springframework.security.web.savedrequest.RequestCache)}, then it is used. Otherwise, an - * attempt to find a {@link RequestCache} shared object is made. If that fails, an {@link HttpSessionRequestCache} - * is used - * - * @param http the {@link HttpSecurity} to attempt to fined the shared object - * @return the {@link RequestCache} to use - */ - private RequestCache getRequestCache(H http) { - RequestCache result = http.getSharedObject(RequestCache.class); - if(result != null) { - return result; - } - return new HttpSessionRequestCache(); - } + private AuthenticationEntryPoint createDefaultEntryPoint(H http) { + if (defaultEntryPointMappings.isEmpty()) { + return new Http403ForbiddenEntryPoint(); + } + if (defaultEntryPointMappings.size() == 1) { + return defaultEntryPointMappings.values().iterator().next(); + } + DelegatingAuthenticationEntryPoint entryPoint = new DelegatingAuthenticationEntryPoint( + defaultEntryPointMappings); + entryPoint.setDefaultEntryPoint(defaultEntryPointMappings.values().iterator() + .next()); + return entryPoint; + } + + /** + * Gets the {@link RequestCache} to use. If one is defined using + * {@link #requestCache(org.springframework.security.web.savedrequest.RequestCache)}, + * then it is used. Otherwise, an attempt to find a {@link RequestCache} shared object + * is made. If that fails, an {@link HttpSessionRequestCache} is used + * + * @param http the {@link HttpSecurity} to attempt to fined the shared object + * @return the {@link RequestCache} to use + */ + private RequestCache getRequestCache(H http) { + RequestCache result = http.getSharedObject(RequestCache.class); + if (result != null) { + return result; + } + return new HttpSessionRequestCache(); + } } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/ExpressionUrlAuthorizationConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/ExpressionUrlAuthorizationConfigurer.java index 84594a10bf..cf9fc82a01 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/ExpressionUrlAuthorizationConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/ExpressionUrlAuthorizationConfigurer.java @@ -37,28 +37,33 @@ import org.springframework.util.Assert; import org.springframework.util.StringUtils; /** - * Adds URL based authorization based upon SpEL expressions to an application. At least one - * {@link org.springframework.web.bind.annotation.RequestMapping} needs to be mapped to {@link ConfigAttribute}'s for - * this {@link SecurityContextConfigurer} to have meaning. - *

Security Filters

+ * Adds URL based authorization based upon SpEL expressions to an application. At least + * one {@link org.springframework.web.bind.annotation.RequestMapping} needs to be mapped + * to {@link ConfigAttribute}'s for this {@link SecurityContextConfigurer} to have + * meaning.

Security Filters

* * The following Filters are populated * *
    - *
  • {@link org.springframework.security.web.access.intercept.FilterSecurityInterceptor}
  • + *
  • {@link org.springframework.security.web.access.intercept.FilterSecurityInterceptor} + *
  • *
* *

Shared Objects Created

* - * The following shared objects are populated to allow other {@link org.springframework.security.config.annotation.SecurityConfigurer}'s to customize: + * The following shared objects are populated to allow other + * {@link org.springframework.security.config.annotation.SecurityConfigurer}'s to + * customize: *
    - *
  • {@link org.springframework.security.web.access.intercept.FilterSecurityInterceptor}
  • + *
  • {@link org.springframework.security.web.access.intercept.FilterSecurityInterceptor} + *
  • *
* *

Shared Objects Used

* *
    - *
  • {@link AuthenticationTrustResolver} is optionally used to populate the {@link DefaultWebSecurityExpressionHandler}
  • + *
  • {@link AuthenticationTrustResolver} is optionally used to populate the + * {@link DefaultWebSecurityExpressionHandler}
  • *
* * @param the type of {@link HttpSecurityBuilder} that is being configured @@ -67,287 +72,325 @@ import org.springframework.util.StringUtils; * @since 3.2 * @see {@link org.springframework.security.config.annotation.web.builders.HttpSecurity#authorizeRequests()} */ -public final class ExpressionUrlAuthorizationConfigurer> extends AbstractInterceptUrlConfigurer,H> { - static final String permitAll = "permitAll"; - private static final String denyAll = "denyAll"; - private static final String anonymous = "anonymous"; - private static final String authenticated = "authenticated"; - private static final String fullyAuthenticated = "fullyAuthenticated"; - private static final String rememberMe = "rememberMe"; +public final class ExpressionUrlAuthorizationConfigurer> + extends + AbstractInterceptUrlConfigurer, H> { + static final String permitAll = "permitAll"; + private static final String denyAll = "denyAll"; + private static final String anonymous = "anonymous"; + private static final String authenticated = "authenticated"; + private static final String fullyAuthenticated = "fullyAuthenticated"; + private static final String rememberMe = "rememberMe"; - private final ExpressionInterceptUrlRegistry REGISTRY = new ExpressionInterceptUrlRegistry(); + private final ExpressionInterceptUrlRegistry REGISTRY = new ExpressionInterceptUrlRegistry(); - private SecurityExpressionHandler expressionHandler; + private SecurityExpressionHandler expressionHandler; - /** - * Creates a new instance - * @see HttpSecurity#authorizeRequests() - */ - public ExpressionUrlAuthorizationConfigurer() { - } + /** + * Creates a new instance + * @see HttpSecurity#authorizeRequests() + */ + public ExpressionUrlAuthorizationConfigurer() { + } - public ExpressionInterceptUrlRegistry getRegistry() { - return REGISTRY; - } + public ExpressionInterceptUrlRegistry getRegistry() { + return REGISTRY; + } - public class ExpressionInterceptUrlRegistry extends ExpressionUrlAuthorizationConfigurer.AbstractInterceptUrlRegistry { + public class ExpressionInterceptUrlRegistry + extends + ExpressionUrlAuthorizationConfigurer.AbstractInterceptUrlRegistry { - @Override - protected final AuthorizedUrl chainRequestMatchersInternal(List requestMatchers) { - return new AuthorizedUrl(requestMatchers); - } + @Override + protected final AuthorizedUrl chainRequestMatchersInternal( + List requestMatchers) { + return new AuthorizedUrl(requestMatchers); + } + /** + * Allows customization of the {@link SecurityExpressionHandler} to be used. The + * default is {@link DefaultWebSecurityExpressionHandler} + * + * @param expressionHandler the {@link SecurityExpressionHandler} to be used + * @return the {@link ExpressionUrlAuthorizationConfigurer} for further + * customization. + */ + public ExpressionInterceptUrlRegistry expressionHandler( + SecurityExpressionHandler expressionHandler) { + ExpressionUrlAuthorizationConfigurer.this.expressionHandler = expressionHandler; + return this; + } - /** - * Allows customization of the {@link SecurityExpressionHandler} to be used. The default is {@link DefaultWebSecurityExpressionHandler} - * - * @param expressionHandler the {@link SecurityExpressionHandler} to be used - * @return the {@link ExpressionUrlAuthorizationConfigurer} for further customization. - */ - public ExpressionInterceptUrlRegistry expressionHandler(SecurityExpressionHandler expressionHandler) { - ExpressionUrlAuthorizationConfigurer.this.expressionHandler = expressionHandler; - return this; - } + /** + * Adds an {@link ObjectPostProcessor} for this class. + * + * @param objectPostProcessor + * @return the {@link ExpressionUrlAuthorizationConfigurer} for further + * customizations + */ + public ExpressionInterceptUrlRegistry withObjectPostProcessor( + ObjectPostProcessor objectPostProcessor) { + addObjectPostProcessor(objectPostProcessor); + return this; + } - /** - * Adds an {@link ObjectPostProcessor} for this class. - * - * @param objectPostProcessor - * @return the {@link ExpressionUrlAuthorizationConfigurer} for further customizations - */ - public ExpressionInterceptUrlRegistry withObjectPostProcessor(ObjectPostProcessor objectPostProcessor) { - addObjectPostProcessor(objectPostProcessor); - return this; - } + public H and() { + return ExpressionUrlAuthorizationConfigurer.this.and(); + } - public H and() { - return ExpressionUrlAuthorizationConfigurer.this.and(); - } + } - } + /** + * Allows registering multiple {@link RequestMatcher} instances to a collection of + * {@link ConfigAttribute} instances + * + * @param requestMatchers the {@link RequestMatcher} instances to register to the + * {@link ConfigAttribute} instances + * @param configAttributes the {@link ConfigAttribute} to be mapped by the + * {@link RequestMatcher} instances + */ + private void interceptUrl(Iterable requestMatchers, + Collection configAttributes) { + for (RequestMatcher requestMatcher : requestMatchers) { + REGISTRY.addMapping(new AbstractConfigAttributeRequestMatcherRegistry.UrlMapping( + requestMatcher, configAttributes)); + } + } + @Override + @SuppressWarnings("rawtypes") + final List> getDecisionVoters(H http) { + List> decisionVoters = new ArrayList>(); + WebExpressionVoter expressionVoter = new WebExpressionVoter(); + expressionVoter.setExpressionHandler(getExpressionHandler(http)); + decisionVoters.add(expressionVoter); + return decisionVoters; + } - /** - * Allows registering multiple {@link RequestMatcher} instances to a collection of {@link ConfigAttribute} instances - * - * @param requestMatchers the {@link RequestMatcher} instances to register to the {@link ConfigAttribute} instances - * @param configAttributes the {@link ConfigAttribute} to be mapped by the {@link RequestMatcher} instances - */ - private void interceptUrl(Iterable requestMatchers, Collection configAttributes) { - for(RequestMatcher requestMatcher : requestMatchers) { - REGISTRY.addMapping(new AbstractConfigAttributeRequestMatcherRegistry.UrlMapping(requestMatcher, configAttributes)); - } - } + @Override + final ExpressionBasedFilterInvocationSecurityMetadataSource createMetadataSource( + H http) { + LinkedHashMap> requestMap = REGISTRY + .createRequestMap(); + if (requestMap.isEmpty()) { + throw new IllegalStateException( + "At least one mapping is required (i.e. authorizeRequests().anyRequest.authenticated())"); + } + return new ExpressionBasedFilterInvocationSecurityMetadataSource(requestMap, + getExpressionHandler(http)); + } - @Override - @SuppressWarnings("rawtypes") - final List> getDecisionVoters(H http) { - List> decisionVoters = new ArrayList>(); - WebExpressionVoter expressionVoter = new WebExpressionVoter(); - expressionVoter.setExpressionHandler(getExpressionHandler(http)); - decisionVoters.add(expressionVoter); - return decisionVoters; - } + private SecurityExpressionHandler getExpressionHandler(H http) { + if (expressionHandler == null) { + DefaultWebSecurityExpressionHandler defaultHandler = new DefaultWebSecurityExpressionHandler(); + AuthenticationTrustResolver trustResolver = http + .getSharedObject(AuthenticationTrustResolver.class); + if (trustResolver != null) { + defaultHandler.setTrustResolver(trustResolver); + } + expressionHandler = postProcess(defaultHandler); + } - @Override - final ExpressionBasedFilterInvocationSecurityMetadataSource createMetadataSource(H http) { - LinkedHashMap> requestMap = REGISTRY.createRequestMap(); - if(requestMap.isEmpty()) { - throw new IllegalStateException("At least one mapping is required (i.e. authorizeRequests().anyRequest.authenticated())"); - } - return new ExpressionBasedFilterInvocationSecurityMetadataSource(requestMap, getExpressionHandler(http)); - } + return expressionHandler; + } - private SecurityExpressionHandler getExpressionHandler(H http) { - if(expressionHandler == null) { - DefaultWebSecurityExpressionHandler defaultHandler = new DefaultWebSecurityExpressionHandler(); - AuthenticationTrustResolver trustResolver = http.getSharedObject(AuthenticationTrustResolver.class); - if(trustResolver != null) { - defaultHandler.setTrustResolver(trustResolver); - } - expressionHandler = postProcess(defaultHandler); - } + private static String hasAnyRole(String... authorities) { + String anyAuthorities = StringUtils.arrayToDelimitedString(authorities, + "','ROLE_"); + return "hasAnyRole('ROLE_" + anyAuthorities + "')"; + } - return expressionHandler; - } + private static String hasRole(String role) { + Assert.notNull(role, "role cannot be null"); + if (role.startsWith("ROLE_")) { + throw new IllegalArgumentException( + "role should not start with 'ROLE_' since it is automatically inserted. Got '" + + role + "'"); + } + return "hasRole('ROLE_" + role + "')"; + } - private static String hasAnyRole(String... authorities) { - String anyAuthorities = StringUtils.arrayToDelimitedString(authorities, "','ROLE_"); - return "hasAnyRole('ROLE_" + anyAuthorities + "')"; - } + private static String hasAuthority(String authority) { + return "hasAuthority('" + authority + "')"; + } - private static String hasRole(String role) { - Assert.notNull(role, "role cannot be null"); - if (role.startsWith("ROLE_")) { - throw new IllegalArgumentException("role should not start with 'ROLE_' since it is automatically inserted. Got '" + role + "'"); - } - return "hasRole('ROLE_" + role + "')"; - } + private static String hasAnyAuthority(String... authorities) { + String anyAuthorities = StringUtils.arrayToDelimitedString(authorities, "','"); + return "hasAnyAuthority('" + anyAuthorities + "')"; + } - private static String hasAuthority(String authority) { - return "hasAuthority('" + authority + "')"; - } + private static String hasIpAddress(String ipAddressExpression) { + return "hasIpAddress('" + ipAddressExpression + "')"; + } - private static String hasAnyAuthority(String... authorities) { - String anyAuthorities = StringUtils.arrayToDelimitedString(authorities, "','"); - return "hasAnyAuthority('" + anyAuthorities + "')"; - } + public final class AuthorizedUrl { + private List requestMatchers; + private boolean not; - private static String hasIpAddress(String ipAddressExpression) { - return "hasIpAddress('" + ipAddressExpression + "')"; - } + /** + * Creates a new instance + * + * @param requestMatchers the {@link RequestMatcher} instances to map + */ + private AuthorizedUrl(List requestMatchers) { + this.requestMatchers = requestMatchers; + } - public final class AuthorizedUrl { - private List requestMatchers; - private boolean not; + /** + * Negates the following expression. + * + * @return the {@link ExpressionUrlAuthorizationConfigurer} for further + * customization + */ + public AuthorizedUrl not() { + this.not = true; + return this; + } - /** - * Creates a new instance - * - * @param requestMatchers the {@link RequestMatcher} instances to map - */ - private AuthorizedUrl(List requestMatchers) { - this.requestMatchers = requestMatchers; - } + /** + * Shortcut for specifying URLs require a particular role. If you do not want to + * have "ROLE_" automatically inserted see {@link #hasAuthority(String)}. + * + * @param role the role to require (i.e. USER, ADMIN, etc). Note, it should not + * start with "ROLE_" as this is automatically inserted. + * @return the {@link ExpressionUrlAuthorizationConfigurer} for further + * customization + */ + public ExpressionInterceptUrlRegistry hasRole(String role) { + return access(ExpressionUrlAuthorizationConfigurer.hasRole(role)); + } - /** - * Negates the following expression. - * - * @return the {@link ExpressionUrlAuthorizationConfigurer} for further customization - */ - public AuthorizedUrl not() { - this.not = true; - return this; - } + /** + * Shortcut for specifying URLs require any of a number of roles. If you do not + * want to have "ROLE_" automatically inserted see + * {@link #hasAnyAuthority(String...)} + * + * @param roles the roles to require (i.e. USER, ADMIN, etc). Note, it should not + * start with "ROLE_" as this is automatically inserted. + * @return the {@link ExpressionUrlAuthorizationConfigurer} for further + * customization + */ + public ExpressionInterceptUrlRegistry hasAnyRole(String... roles) { + return access(ExpressionUrlAuthorizationConfigurer.hasAnyRole(roles)); + } - /** - * Shortcut for specifying URLs require a particular role. If you do not want to have "ROLE_" automatically - * inserted see {@link #hasAuthority(String)}. - * - * @param role the role to require (i.e. USER, ADMIN, etc). Note, it should not start with "ROLE_" as - * this is automatically inserted. - * @return the {@link ExpressionUrlAuthorizationConfigurer} for further customization - */ - public ExpressionInterceptUrlRegistry hasRole(String role) { - return access(ExpressionUrlAuthorizationConfigurer.hasRole(role)); - } + /** + * Specify that URLs require a particular authority. + * + * @param authority the authority to require (i.e. ROLE_USER, ROLE_ADMIN, etc). + * @return the {@link ExpressionUrlAuthorizationConfigurer} for further + * customization + */ + public ExpressionInterceptUrlRegistry hasAuthority(String authority) { + return access(ExpressionUrlAuthorizationConfigurer.hasAuthority(authority)); + } - /** - * Shortcut for specifying URLs require any of a number of roles. If you - * do not want to have "ROLE_" automatically inserted see - * {@link #hasAnyAuthority(String...)} - * - * @param roles - * the roles to require (i.e. USER, ADMIN, etc). Note, it - * should not start with "ROLE_" as this is automatically - * inserted. - * @return the {@link ExpressionUrlAuthorizationConfigurer} for further - * customization - */ - public ExpressionInterceptUrlRegistry hasAnyRole(String... roles) { - return access(ExpressionUrlAuthorizationConfigurer.hasAnyRole(roles)); - } + /** + * Specify that URLs requires any of a number authorities. + * + * @param authorities the requests require at least one of the authorities (i.e. + * "ROLE_USER","ROLE_ADMIN" would mean either "ROLE_USER" or "ROLE_ADMIN" is + * required). + * @return the {@link ExpressionUrlAuthorizationConfigurer} for further + * customization + */ + public ExpressionInterceptUrlRegistry hasAnyAuthority(String... authorities) { + return access(ExpressionUrlAuthorizationConfigurer + .hasAnyAuthority(authorities)); + } - /** - * Specify that URLs require a particular authority. - * - * @param authority the authority to require (i.e. ROLE_USER, ROLE_ADMIN, etc). - * @return the {@link ExpressionUrlAuthorizationConfigurer} for further customization - */ - public ExpressionInterceptUrlRegistry hasAuthority(String authority) { - return access(ExpressionUrlAuthorizationConfigurer.hasAuthority(authority)); - } + /** + * Specify that URLs requires a specific IP Address or subnet. + * + * @param ipaddressExpression the ipaddress (i.e. 192.168.1.79) or local subnet + * (i.e. 192.168.0/24) + * @return the {@link ExpressionUrlAuthorizationConfigurer} for further + * customization + */ + public ExpressionInterceptUrlRegistry hasIpAddress(String ipaddressExpression) { + return access(ExpressionUrlAuthorizationConfigurer + .hasIpAddress(ipaddressExpression)); + } - /** - * Specify that URLs requires any of a number authorities. - * - * @param authorities the requests require at least one of the authorities (i.e. "ROLE_USER","ROLE_ADMIN" would - * mean either "ROLE_USER" or "ROLE_ADMIN" is required). - * @return the {@link ExpressionUrlAuthorizationConfigurer} for further customization - */ - public ExpressionInterceptUrlRegistry hasAnyAuthority(String... authorities) { - return access(ExpressionUrlAuthorizationConfigurer.hasAnyAuthority(authorities)); - } + /** + * Specify that URLs are allowed by anyone. + * + * @return the {@link ExpressionUrlAuthorizationConfigurer} for further + * customization + */ + public ExpressionInterceptUrlRegistry permitAll() { + return access(permitAll); + } - /** - * Specify that URLs requires a specific IP Address or - * subnet. - * - * @param ipaddressExpression the ipaddress (i.e. 192.168.1.79) or local subnet (i.e. 192.168.0/24) - * @return the {@link ExpressionUrlAuthorizationConfigurer} for further customization - */ - public ExpressionInterceptUrlRegistry hasIpAddress(String ipaddressExpression) { - return access(ExpressionUrlAuthorizationConfigurer.hasIpAddress(ipaddressExpression)); - } + /** + * Specify that URLs are allowed by anonymous users. + * + * @return the {@link ExpressionUrlAuthorizationConfigurer} for further + * customization + */ + public ExpressionInterceptUrlRegistry anonymous() { + return access(anonymous); + } - /** - * Specify that URLs are allowed by anyone. - * - * @return the {@link ExpressionUrlAuthorizationConfigurer} for further customization - */ - public ExpressionInterceptUrlRegistry permitAll() { - return access(permitAll); - } + /** + * Specify that URLs are allowed by users that have been remembered. + * + * @return the {@link ExpressionUrlAuthorizationConfigurer} for further + * customization + * @see {@link RememberMeConfigurer} + */ + public ExpressionInterceptUrlRegistry rememberMe() { + return access(rememberMe); + } - /** - * Specify that URLs are allowed by anonymous users. - * - * @return the {@link ExpressionUrlAuthorizationConfigurer} for further customization - */ - public ExpressionInterceptUrlRegistry anonymous() { - return access(anonymous); - } + /** + * Specify that URLs are not allowed by anyone. + * + * @return the {@link ExpressionUrlAuthorizationConfigurer} for further + * customization + */ + public ExpressionInterceptUrlRegistry denyAll() { + return access(denyAll); + } - /** - * Specify that URLs are allowed by users that have been remembered. - * - * @return the {@link ExpressionUrlAuthorizationConfigurer} for further customization - * @see {@link RememberMeConfigurer} - */ - public ExpressionInterceptUrlRegistry rememberMe() { - return access(rememberMe); - } + /** + * Specify that URLs are allowed by any authenticated user. + * + * @return the {@link ExpressionUrlAuthorizationConfigurer} for further + * customization + */ + public ExpressionInterceptUrlRegistry authenticated() { + return access(authenticated); + } - /** - * Specify that URLs are not allowed by anyone. - * - * @return the {@link ExpressionUrlAuthorizationConfigurer} for further customization - */ - public ExpressionInterceptUrlRegistry denyAll() { - return access(denyAll); - } + /** + * Specify that URLs are allowed by users who have authenticated and were not + * "remembered". + * + * @return the {@link ExpressionUrlAuthorizationConfigurer} for further + * customization + * @see {@link RememberMeConfigurer} + */ + public ExpressionInterceptUrlRegistry fullyAuthenticated() { + return access(fullyAuthenticated); + } - /** - * Specify that URLs are allowed by any authenticated user. - * - * @return the {@link ExpressionUrlAuthorizationConfigurer} for further customization - */ - public ExpressionInterceptUrlRegistry authenticated() { - return access(authenticated); - } - - /** - * Specify that URLs are allowed by users who have authenticated and were not "remembered". - * - * @return the {@link ExpressionUrlAuthorizationConfigurer} for further customization - * @see {@link RememberMeConfigurer} - */ - public ExpressionInterceptUrlRegistry fullyAuthenticated() { - return access(fullyAuthenticated); - } - - /** - * Allows specifying that URLs are secured by an arbitrary expression - * - * @param attribute the expression to secure the URLs (i.e. "hasRole('ROLE_USER') and hasRole('ROLE_SUPER')") - * @return the {@link ExpressionUrlAuthorizationConfigurer} for further customization - */ - public ExpressionInterceptUrlRegistry access(String attribute) { - if(not) { - attribute = "!" + attribute; - } - interceptUrl(requestMatchers, SecurityConfig.createList(attribute)); - return ExpressionUrlAuthorizationConfigurer.this.REGISTRY; - } - } + /** + * Allows specifying that URLs are secured by an arbitrary expression + * + * @param attribute the expression to secure the URLs (i.e. + * "hasRole('ROLE_USER') and hasRole('ROLE_SUPER')") + * @return the {@link ExpressionUrlAuthorizationConfigurer} for further + * customization + */ + public ExpressionInterceptUrlRegistry access(String attribute) { + if (not) { + attribute = "!" + attribute; + } + interceptUrl(requestMatchers, SecurityConfig.createList(attribute)); + return ExpressionUrlAuthorizationConfigurer.this.REGISTRY; + } + } } \ No newline at end of file diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/FormLoginConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/FormLoginConfigurer.java index 90e7060b09..98d33658f0 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/FormLoginConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/FormLoginConfigurer.java @@ -27,9 +27,9 @@ import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import org.springframework.security.web.util.matcher.RequestMatcher; /** - * Adds form based authentication. All attributes have reasonable defaults - * making all parameters are optional. If no {@link #loginPage(String)} is - * specified, a default login page will be generated by the framework. + * Adds form based authentication. All attributes have reasonable defaults making all + * parameters are optional. If no {@link #loginPage(String)} is specified, a default login + * page will be generated by the framework. * *

Security Filters

* @@ -37,8 +37,7 @@ import org.springframework.security.web.util.matcher.RequestMatcher; * *
    *
  • - * {@link UsernamePasswordAuthenticationFilter} - *
  • + * {@link UsernamePasswordAuthenticationFilter} *
* *

Shared Objects Created

@@ -46,7 +45,7 @@ import org.springframework.security.web.util.matcher.RequestMatcher; * The following shared objects are populated * *
    - *
  • {@link AuthenticationEntryPoint}
  • + *
  • {@link AuthenticationEntryPoint}
  • *
* *

Shared Objects Used

@@ -56,208 +55,209 @@ import org.springframework.security.web.util.matcher.RequestMatcher; *
    *
  • {@link AuthenticationManager}
  • *
  • {@link RememberMeServices} - is optionally used. See {@link RememberMeConfigurer}
  • - *
  • {@link SessionAuthenticationStrategy} - is optionally used. See {@link SessionManagementConfigurer}
  • - *
  • {@link DefaultLoginPageGeneratingFilter} - if present will be populated with information from the configuration
  • + *
  • {@link SessionAuthenticationStrategy} - is optionally used. See + * {@link SessionManagementConfigurer}
  • + *
  • {@link DefaultLoginPageGeneratingFilter} - if present will be populated with + * information from the configuration
  • *
* * @author Rob Winch * @since 3.2 */ -public final class FormLoginConfigurer> extends AbstractAuthenticationFilterConfigurer,UsernamePasswordAuthenticationFilter> { +public final class FormLoginConfigurer> + extends + AbstractAuthenticationFilterConfigurer, UsernamePasswordAuthenticationFilter> { - /** - * Creates a new instance - * @see HttpSecurity#formLogin() - */ - public FormLoginConfigurer() { - super(new UsernamePasswordAuthenticationFilter(),null); - usernameParameter("username"); - passwordParameter("password"); - } + /** + * Creates a new instance + * @see HttpSecurity#formLogin() + */ + public FormLoginConfigurer() { + super(new UsernamePasswordAuthenticationFilter(), null); + usernameParameter("username"); + passwordParameter("password"); + } - /** - *

- * Specifies the URL to send users to if login is required. If used with - * {@link WebSecurityConfigurerAdapter} a default login page will be - * generated when this attribute is not specified. - *

- * - *

- * If a URL is specified or this is not being used in conjuction with - * {@link WebSecurityConfigurerAdapter}, users are required to process the - * specified URL to generate a login page. In general, the login page should - * create a form that submits a request with the following requirements to - * work with {@link UsernamePasswordAuthenticationFilter}: - *

- * - *
    - *
  • It must be an HTTP POST
  • - *
  • It must be submitted to {@link #loginProcessingUrl(String)}
  • - *
  • It should include the username as an HTTP parameter by the name of - * {@link #usernameParameter(String)}
  • - *
  • It should include the password as an HTTP parameter by the name of - * {@link #passwordParameter(String)}
  • - *
- * - *

Example login.jsp

- * - * Login pages can be rendered with any technology you choose so long as the - * rules above are followed. Below is an example login.jsp that can be used as - * a quick start when using JSP's or as a baseline to translate into another view - * technology. - * - *
-     * 
-     * <c:url value="/login" var="loginProcessingUrl"/>
-     * <form action="${loginProcessingUrl}" method="post">
-     *    <fieldset>
-     *        <legend>Please Login</legend>
-     *        <!-- use param.error assuming FormLoginConfigurer#failureUrl contains the query parameter error -->
-     *        <c:if test="${param.error != null}">
-     *            <div>
-     *                Failed to login.
-     *                <c:if test="${SPRING_SECURITY_LAST_EXCEPTION != null}">
-     *                  Reason: <c:out value="${SPRING_SECURITY_LAST_EXCEPTION.message}" />
-     *                </c:if>
-     *            </div>
-     *        </c:if>
-     *        <!-- the configured LogoutConfigurer#logoutSuccessUrl is /login?logout and contains the query param logout -->
-     *        <c:if test="${param.logout != null}">
-     *            <div>
-     *                You have been logged out.
-     *            </div>
-     *        </c:if>
-     *        <p>
-     *        <label for="username">Username</label>
-     *        <input type="text" id="username" name="username"/>
-     *        </p>
-     *        <p>
-     *        <label for="password">Password</label>
-     *        <input type="password" id="password" name="password"/>
-     *        </p>
-     *        <!-- if using RememberMeConfigurer make sure remember-me matches RememberMeConfigurer#rememberMeParameter -->
-     *        <p>
-     *        <label for="remember-me">Remember Me?</label>
-     *        <input type="checkbox" id="remember-me" name="remember-me"/>
-     *        </p>
-     *        <div>
-     *            <button type="submit" class="btn">Log in</button>
-     *        </div>
-     *    </fieldset>
-     * </form>
-     * 
- * - *

Impact on other defaults

- * - * Updating this value, also impacts a number of other default values. For example, - * the following are the default values when only formLogin() was specified. - * - *
    - *
  • /login GET - the login form
  • - *
  • /login POST - process the credentials and if valid authenticate the - * user
  • - *
  • /login?error GET - redirect here for failed authentication attempts
  • - *
  • /login?logout GET - redirect here after successfully logging out
  • - *
- * - * If "/authenticate" was passed to this method it update the defaults as shown - * below: - * - *
    - *
  • /authenticate GET - the login form
  • - *
  • /authenticate POST - process the credentials and if valid authenticate the - * user
  • - *
  • /authenticate?error GET - redirect here for failed authentication attempts
  • - *
  • /authenticate?logout GET - redirect here after successfully logging out
  • - *
- * - * - * @param loginPage - * the login page to redirect to if authentication is required - * (i.e. "/login") - * @return the {@link FormLoginConfigurer} for additional customization - */ - public FormLoginConfigurer loginPage(String loginPage) { - return super.loginPage(loginPage); - } + /** + *

+ * Specifies the URL to send users to if login is required. If used with + * {@link WebSecurityConfigurerAdapter} a default login page will be generated when + * this attribute is not specified. + *

+ * + *

+ * If a URL is specified or this is not being used in conjuction with + * {@link WebSecurityConfigurerAdapter}, users are required to process the specified + * URL to generate a login page. In general, the login page should create a form that + * submits a request with the following requirements to work with + * {@link UsernamePasswordAuthenticationFilter}: + *

+ * + *
    + *
  • It must be an HTTP POST
  • + *
  • It must be submitted to {@link #loginProcessingUrl(String)}
  • + *
  • It should include the username as an HTTP parameter by the name of + * {@link #usernameParameter(String)}
  • + *
  • It should include the password as an HTTP parameter by the name of + * {@link #passwordParameter(String)}
  • + *
+ * + *

Example login.jsp

+ * + * Login pages can be rendered with any technology you choose so long as the rules + * above are followed. Below is an example login.jsp that can be used as a quick start + * when using JSP's or as a baseline to translate into another view technology. + * + *
+	 * 
+	 * <c:url value="/login" var="loginProcessingUrl"/>
+	 * <form action="${loginProcessingUrl}" method="post">
+	 *    <fieldset>
+	 *        <legend>Please Login</legend>
+	 *        <!-- use param.error assuming FormLoginConfigurer#failureUrl contains the query parameter error -->
+	 *        <c:if test="${param.error != null}">
+	 *            <div>
+	 *                Failed to login.
+	 *                <c:if test="${SPRING_SECURITY_LAST_EXCEPTION != null}">
+	 *                  Reason: <c:out value="${SPRING_SECURITY_LAST_EXCEPTION.message}" />
+	 *                </c:if>
+	 *            </div>
+	 *        </c:if>
+	 *        <!-- the configured LogoutConfigurer#logoutSuccessUrl is /login?logout and contains the query param logout -->
+	 *        <c:if test="${param.logout != null}">
+	 *            <div>
+	 *                You have been logged out.
+	 *            </div>
+	 *        </c:if>
+	 *        <p>
+	 *        <label for="username">Username</label>
+	 *        <input type="text" id="username" name="username"/>
+	 *        </p>
+	 *        <p>
+	 *        <label for="password">Password</label>
+	 *        <input type="password" id="password" name="password"/>
+	 *        </p>
+	 *        <!-- if using RememberMeConfigurer make sure remember-me matches RememberMeConfigurer#rememberMeParameter -->
+	 *        <p>
+	 *        <label for="remember-me">Remember Me?</label>
+	 *        <input type="checkbox" id="remember-me" name="remember-me"/>
+	 *        </p>
+	 *        <div>
+	 *            <button type="submit" class="btn">Log in</button>
+	 *        </div>
+	 *    </fieldset>
+	 * </form>
+	 * 
+ * + *

Impact on other defaults

+ * + * Updating this value, also impacts a number of other default values. For example, + * the following are the default values when only formLogin() was specified. + * + *
    + *
  • /login GET - the login form
  • + *
  • /login POST - process the credentials and if valid authenticate the user
  • + *
  • /login?error GET - redirect here for failed authentication attempts
  • + *
  • /login?logout GET - redirect here after successfully logging out
  • + *
+ * + * If "/authenticate" was passed to this method it update the defaults as shown below: + * + *
    + *
  • /authenticate GET - the login form
  • + *
  • /authenticate POST - process the credentials and if valid authenticate the user + *
  • + *
  • /authenticate?error GET - redirect here for failed authentication attempts
  • + *
  • /authenticate?logout GET - redirect here after successfully logging out
  • + *
+ * + * + * @param loginPage the login page to redirect to if authentication is required (i.e. + * "/login") + * @return the {@link FormLoginConfigurer} for additional customization + */ + public FormLoginConfigurer loginPage(String loginPage) { + return super.loginPage(loginPage); + } + /** + * The HTTP parameter to look for the username when performing authentication. Default + * is "username". + * + * @param usernameParameter the HTTP parameter to look for the username when + * performing authentication + * @return the {@link FormLoginConfigurer} for additional customization + */ + public FormLoginConfigurer usernameParameter(String usernameParameter) { + getAuthenticationFilter().setUsernameParameter(usernameParameter); + return this; + } + /** + * The HTTP parameter to look for the password when performing authentication. Default + * is "password". + * + * @param passwordParameter the HTTP parameter to look for the password when + * performing authentication + * @return the {@link FormLoginConfigurer} for additional customization + */ + public FormLoginConfigurer passwordParameter(String passwordParameter) { + getAuthenticationFilter().setPasswordParameter(passwordParameter); + return this; + } - /** - * The HTTP parameter to look for the username when performing - * authentication. Default is "username". - * - * @param usernameParameter - * the HTTP parameter to look for the username when performing - * authentication - * @return the {@link FormLoginConfigurer} for additional customization - */ - public FormLoginConfigurer usernameParameter(String usernameParameter) { - getAuthenticationFilter().setUsernameParameter(usernameParameter); - return this; - } + @Override + public void init(H http) throws Exception { + super.init(http); + initDefaultLoginFilter(http); + } - /** - * The HTTP parameter to look for the password when performing - * authentication. Default is "password". - * - * @param passwordParameter - * the HTTP parameter to look for the password when performing - * authentication - * @return the {@link FormLoginConfigurer} for additional customization - */ - public FormLoginConfigurer passwordParameter(String passwordParameter) { - getAuthenticationFilter().setPasswordParameter(passwordParameter); - return this; - } + /* + * (non-Javadoc) + * + * @see org.springframework.security.config.annotation.web.configurers. + * AbstractAuthenticationFilterConfigurer + * #createLoginProcessingUrlMatcher(java.lang.String) + */ + @Override + protected RequestMatcher createLoginProcessingUrlMatcher(String loginProcessingUrl) { + return new AntPathRequestMatcher(loginProcessingUrl, "POST"); + } - @Override - public void init(H http) throws Exception { - super.init(http); - initDefaultLoginFilter(http); - } + /** + * Gets the HTTP parameter that is used to submit the username. + * + * @return the HTTP parameter that is used to submit the username + */ + private String getUsernameParameter() { + return getAuthenticationFilter().getUsernameParameter(); + } - /* (non-Javadoc) - * @see org.springframework.security.config.annotation.web.configurers.AbstractAuthenticationFilterConfigurer#createLoginProcessingUrlMatcher(java.lang.String) - */ - @Override - protected RequestMatcher createLoginProcessingUrlMatcher( - String loginProcessingUrl) { - return new AntPathRequestMatcher(loginProcessingUrl, "POST"); - } + /** + * Gets the HTTP parameter that is used to submit the password. + * + * @return the HTTP parameter that is used to submit the password + */ + private String getPasswordParameter() { + return getAuthenticationFilter().getPasswordParameter(); + } - /** - * Gets the HTTP parameter that is used to submit the username. - * - * @return the HTTP parameter that is used to submit the username - */ - private String getUsernameParameter() { - return getAuthenticationFilter().getUsernameParameter(); - } - - /** - * Gets the HTTP parameter that is used to submit the password. - * - * @return the HTTP parameter that is used to submit the password - */ - private String getPasswordParameter() { - return getAuthenticationFilter().getPasswordParameter(); - } - - /** - * If available, initializes the {@link DefaultLoginPageGeneratingFilter} shared object. - * - * @param http the {@link HttpSecurityBuilder} to use - */ - private void initDefaultLoginFilter(H http) { - DefaultLoginPageGeneratingFilter loginPageGeneratingFilter = http.getSharedObject(DefaultLoginPageGeneratingFilter.class); - if(loginPageGeneratingFilter != null && !isCustomLoginPage()) { - loginPageGeneratingFilter.setFormLoginEnabled(true); - loginPageGeneratingFilter.setUsernameParameter(getUsernameParameter()); - loginPageGeneratingFilter.setPasswordParameter(getPasswordParameter()); - loginPageGeneratingFilter.setLoginPageUrl(getLoginPage()); - loginPageGeneratingFilter.setFailureUrl(getFailureUrl()); - loginPageGeneratingFilter.setAuthenticationUrl(getLoginProcessingUrl()); - } - } + /** + * If available, initializes the {@link DefaultLoginPageGeneratingFilter} shared + * object. + * + * @param http the {@link HttpSecurityBuilder} to use + */ + private void initDefaultLoginFilter(H http) { + DefaultLoginPageGeneratingFilter loginPageGeneratingFilter = http + .getSharedObject(DefaultLoginPageGeneratingFilter.class); + if (loginPageGeneratingFilter != null && !isCustomLoginPage()) { + loginPageGeneratingFilter.setFormLoginEnabled(true); + loginPageGeneratingFilter.setUsernameParameter(getUsernameParameter()); + loginPageGeneratingFilter.setPasswordParameter(getPasswordParameter()); + loginPageGeneratingFilter.setLoginPageUrl(getLoginPage()); + loginPageGeneratingFilter.setFailureUrl(getFailureUrl()); + loginPageGeneratingFilter.setAuthenticationUrl(getLoginProcessingUrl()); + } + } } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/HeadersConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/HeadersConfigurer.java index 0d3f2b7de2..71402ad2be 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/HeadersConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/HeadersConfigurer.java @@ -36,9 +36,8 @@ import org.springframework.util.Assert; /** *

- * Adds the Security HTTP headers to the response. Security HTTP headers is - * activated by default when using {@link WebSecurityConfigurerAdapter}'s - * default constructor. + * Adds the Security HTTP headers to the response. Security HTTP headers is activated by + * default when using {@link WebSecurityConfigurerAdapter}'s default constructor. *

* *

@@ -59,490 +58,481 @@ import org.springframework.util.Assert; * @since 3.2 */ public class HeadersConfigurer> extends - AbstractHttpConfigurer, H> { - private List headerWriters = new ArrayList(); + AbstractHttpConfigurer, H> { + private List headerWriters = new ArrayList(); - // --- default header writers --- + // --- default header writers --- - private final ContentTypeOptionsConfig contentTypeOptions = new ContentTypeOptionsConfig(); + private final ContentTypeOptionsConfig contentTypeOptions = new ContentTypeOptionsConfig(); - private final XXssConfig xssProtection = new XXssConfig(); + private final XXssConfig xssProtection = new XXssConfig(); - private final CacheControlConfig cacheControl = new CacheControlConfig(); + private final CacheControlConfig cacheControl = new CacheControlConfig(); - private final HstsConfig hsts = new HstsConfig(); + private final HstsConfig hsts = new HstsConfig(); - private final FrameOptionsConfig frameOptions = new FrameOptionsConfig(); + private final FrameOptionsConfig frameOptions = new FrameOptionsConfig(); - /** - * Creates a new instance - * - * @see HttpSecurity#headers() - */ - public HeadersConfigurer() { - } + /** + * Creates a new instance + * + * @see HttpSecurity#headers() + */ + public HeadersConfigurer() { + } - /** - * Adds a {@link HeaderWriter} instance - * - * @param headerWriter - * the {@link HeaderWriter} instance to add - * @return the {@link HeadersConfigurer} for additional customizations - */ - public HeadersConfigurer addHeaderWriter(HeaderWriter headerWriter) { - Assert.notNull(headerWriter, "headerWriter cannot be null"); - this.headerWriters.add(headerWriter); - return this; - } + /** + * Adds a {@link HeaderWriter} instance + * + * @param headerWriter the {@link HeaderWriter} instance to add + * @return the {@link HeadersConfigurer} for additional customizations + */ + public HeadersConfigurer addHeaderWriter(HeaderWriter headerWriter) { + Assert.notNull(headerWriter, "headerWriter cannot be null"); + this.headerWriters.add(headerWriter); + return this; + } - /** - * Configures the {@link XContentTypeOptionsHeaderWriter} which inserts the X-Content-Type-Options: - * - *

-     * X-Content-Type-Options: nosniff
-     * 
- * - * @return the ContentTypeOptionsConfig for additional customizations - */ - public ContentTypeOptionsConfig contentTypeOptions() { - return contentTypeOptions.enable(); - } + /** + * Configures the {@link XContentTypeOptionsHeaderWriter} which inserts the X-Content-Type-Options: + * + *
+	 * X-Content-Type-Options: nosniff
+	 * 
+ * + * @return the ContentTypeOptionsConfig for additional customizations + */ + public ContentTypeOptionsConfig contentTypeOptions() { + return contentTypeOptions.enable(); + } - public final class ContentTypeOptionsConfig { - private XContentTypeOptionsHeaderWriter writer; + public final class ContentTypeOptionsConfig { + private XContentTypeOptionsHeaderWriter writer; - private ContentTypeOptionsConfig() { - enable(); - } + private ContentTypeOptionsConfig() { + enable(); + } - /** - * Removes the X-XSS-Protection header. - * - * @return {@link HeadersConfigurer} for additional customization. - */ - public HeadersConfigurer disable() { - writer = null; - return and(); - } + /** + * Removes the X-XSS-Protection header. + * + * @return {@link HeadersConfigurer} for additional customization. + */ + public HeadersConfigurer disable() { + writer = null; + return and(); + } - /** - * Allows customizing the {@link HeadersConfigurer} - * @return the {@link HeadersConfigurer} for additional customization - */ - public HeadersConfigurer and() { - return HeadersConfigurer.this; - } + /** + * Allows customizing the {@link HeadersConfigurer} + * @return the {@link HeadersConfigurer} for additional customization + */ + public HeadersConfigurer and() { + return HeadersConfigurer.this; + } - /** - * Ensures that Content Type Options is enabled - * - * @return the {@link ContentTypeOptionsConfig} for additional customization - */ - private ContentTypeOptionsConfig enable() { - if(writer == null) { - writer = new XContentTypeOptionsHeaderWriter(); - } - return this; - } - } + /** + * Ensures that Content Type Options is enabled + * + * @return the {@link ContentTypeOptionsConfig} for additional customization + */ + private ContentTypeOptionsConfig enable() { + if (writer == null) { + writer = new XContentTypeOptionsHeaderWriter(); + } + return this; + } + } - /** - * Note this is not comprehensive XSS protection! - * - *

Allows customizing the {@link XXssProtectionHeaderWriter} which adds the X-XSS-Protection header

- * - * @return the {@link HeadersConfigurer} for additional customizations - */ - public XXssConfig xssProtection() { - return xssProtection.enable(); - } + /** + * Note this is not comprehensive XSS protection! + * + *

+ * Allows customizing the {@link XXssProtectionHeaderWriter} which adds the X-XSS-Protection header + *

+ * + * @return the {@link HeadersConfigurer} for additional customizations + */ + public XXssConfig xssProtection() { + return xssProtection.enable(); + } - public final class XXssConfig { - private XXssProtectionHeaderWriter writer; + public final class XXssConfig { + private XXssProtectionHeaderWriter writer; - private XXssConfig() { - enable(); - } + private XXssConfig() { + enable(); + } - /** - * If false, will not specify the mode as blocked. In this instance, any - * content will be attempted to be fixed. If true, the content will be - * replaced with "#". - * - * @param enabled - * the new value - */ - public XXssConfig block(boolean enabled) { - writer.setBlock(enabled); - return this; - } + /** + * If false, will not specify the mode as blocked. In this instance, any content + * will be attempted to be fixed. If true, the content will be replaced with "#". + * + * @param enabled the new value + */ + public XXssConfig block(boolean enabled) { + writer.setBlock(enabled); + return this; + } - /** - * If true, the header value will contain a value of 1. For example: - * - *
-         * X-XSS-Protection: 1
-         * 
- * - * or if {@link #setBlock(boolean)} is true - * - * - *
-         * X-XSS-Protection: 1; mode=block
-         * 
- * - * If false, will explicitly disable specify that X-XSS-Protection is - * disabled. For example: - * - *
-         * X-XSS-Protection: 0
-         * 
- * - * @param enabled the new value - */ - public XXssConfig xssProtectionEnabled(boolean enabled) { - writer.setEnabled(enabled); - return this; - } + /** + * If true, the header value will contain a value of 1. For example: + * + *
+		 * X-XSS-Protection: 1
+		 * 
+ * + * or if {@link #setBlock(boolean)} is true + * + * + *
+		 * X-XSS-Protection: 1; mode=block
+		 * 
+ * + * If false, will explicitly disable specify that X-XSS-Protection is disabled. + * For example: + * + *
+		 * X-XSS-Protection: 0
+		 * 
+ * + * @param enabled the new value + */ + public XXssConfig xssProtectionEnabled(boolean enabled) { + writer.setEnabled(enabled); + return this; + } - /** - * Disables X-XSS-Protection header (does not include it) - * - * @return the {@link HeadersConfigurer} for additional configuration - */ - public HeadersConfigurer disable() { - writer = null; - return and(); - } + /** + * Disables X-XSS-Protection header (does not include it) + * + * @return the {@link HeadersConfigurer} for additional configuration + */ + public HeadersConfigurer disable() { + writer = null; + return and(); + } - /** - * Allows completing configuration of Strict Transport Security and - * continuing configuration of headers. - * - * @return the {@link HeadersConfigurer} for additional configuration - */ - public HeadersConfigurer and() { - return HeadersConfigurer.this; - } + /** + * Allows completing configuration of Strict Transport Security and continuing + * configuration of headers. + * + * @return the {@link HeadersConfigurer} for additional configuration + */ + public HeadersConfigurer and() { + return HeadersConfigurer.this; + } - /** - * Ensures the X-XSS-Protection header is enabled if it is not already. - * - * @return the {@link XXssConfig} for additional customization - */ - private XXssConfig enable() { - if(writer == null) { - writer = new XXssProtectionHeaderWriter(); - } - return this; - } - } + /** + * Ensures the X-XSS-Protection header is enabled if it is not already. + * + * @return the {@link XXssConfig} for additional customization + */ + private XXssConfig enable() { + if (writer == null) { + writer = new XXssProtectionHeaderWriter(); + } + return this; + } + } - /** - * Allows customizing the {@link CacheControlHeadersWriter}. Specifically it adds the - * following headers: - *
    - *
  • Cache-Control: no-cache, no-store, max-age=0, must-revalidate
  • - *
  • Pragma: no-cache
  • - *
  • Expires: 0
  • - *
- * - * @return the {@link HeadersConfigurer} for additional customizations - */ - public CacheControlConfig cacheControl() { - return cacheControl.enable(); - } + /** + * Allows customizing the {@link CacheControlHeadersWriter}. Specifically it adds the + * following headers: + *
    + *
  • Cache-Control: no-cache, no-store, max-age=0, must-revalidate
  • + *
  • Pragma: no-cache
  • + *
  • Expires: 0
  • + *
+ * + * @return the {@link HeadersConfigurer} for additional customizations + */ + public CacheControlConfig cacheControl() { + return cacheControl.enable(); + } - public final class CacheControlConfig { - private CacheControlHeadersWriter writer; + public final class CacheControlConfig { + private CacheControlHeadersWriter writer; - private CacheControlConfig() { - enable(); - } + private CacheControlConfig() { + enable(); + } - /** - * Disables Cache Control - * - * @return the {@link HeadersConfigurer} for additional configuration - */ - public HeadersConfigurer disable() { - writer = null; - return HeadersConfigurer.this; - } + /** + * Disables Cache Control + * + * @return the {@link HeadersConfigurer} for additional configuration + */ + public HeadersConfigurer disable() { + writer = null; + return HeadersConfigurer.this; + } - /** - * Allows completing configuration of Strict Transport Security and - * continuing configuration of headers. - * - * @return the {@link HeadersConfigurer} for additional configuration - */ - public HeadersConfigurer and() { - return HeadersConfigurer.this; - } + /** + * Allows completing configuration of Strict Transport Security and continuing + * configuration of headers. + * + * @return the {@link HeadersConfigurer} for additional configuration + */ + public HeadersConfigurer and() { + return HeadersConfigurer.this; + } - /** - * Ensures the Cache Control headers are enabled if they are not already. - * - * @return the {@link CacheControlConfig} for additional customization - */ - private CacheControlConfig enable() { - if(writer == null) { - writer = new CacheControlHeadersWriter(); - } - return this; - } - } + /** + * Ensures the Cache Control headers are enabled if they are not already. + * + * @return the {@link CacheControlConfig} for additional customization + */ + private CacheControlConfig enable() { + if (writer == null) { + writer = new CacheControlHeadersWriter(); + } + return this; + } + } - /** - * Allows customizing the {@link HstsHeaderWriter} which provides support for HTTP Strict Transport Security - * (HSTS). - * - * @return the {@link HeadersConfigurer} for additional customizations - */ - public HstsConfig httpStrictTransportSecurity() { - return hsts.enable(); - } + /** + * Allows customizing the {@link HstsHeaderWriter} which provides support for HTTP Strict Transport Security + * (HSTS). + * + * @return the {@link HeadersConfigurer} for additional customizations + */ + public HstsConfig httpStrictTransportSecurity() { + return hsts.enable(); + } - public final class HstsConfig { - private HstsHeaderWriter writer; + public final class HstsConfig { + private HstsHeaderWriter writer; - private HstsConfig() { - enable(); - } + private HstsConfig() { + enable(); + } - /** - *

- * Sets the value (in seconds) for the max-age directive of the - * Strict-Transport-Security header. The default is one year. - *

- * - *

- * This instructs browsers how long to remember to keep this domain as a - * known HSTS Host. See Section 6.1.1 - * for additional details. - *

- * - * @param maxAgeInSeconds - * the maximum amount of time (in seconds) to consider this - * domain as a known HSTS Host. - * @throws IllegalArgumentException - * if maxAgeInSeconds is negative - */ - public HstsConfig maxAgeInSeconds(long maxAgeInSeconds) { - writer.setMaxAgeInSeconds(maxAgeInSeconds); - return this; - } + /** + *

+ * Sets the value (in seconds) for the max-age directive of the + * Strict-Transport-Security header. The default is one year. + *

+ * + *

+ * This instructs browsers how long to remember to keep this domain as a known + * HSTS Host. See Section 6.1.1 for + * additional details. + *

+ * + * @param maxAgeInSeconds the maximum amount of time (in seconds) to consider this + * domain as a known HSTS Host. + * @throws IllegalArgumentException if maxAgeInSeconds is negative + */ + public HstsConfig maxAgeInSeconds(long maxAgeInSeconds) { + writer.setMaxAgeInSeconds(maxAgeInSeconds); + return this; + } - /** - * Sets the {@link RequestMatcher} used to determine if the - * "Strict-Transport-Security" should be added. If true the header is added, - * else the header is not added. By default the header is added when - * {@link HttpServletRequest#isSecure()} returns true. - * - * @param requestMatcher - * the {@link RequestMatcher} to use. - * @throws IllegalArgumentException - * if {@link RequestMatcher} is null - */ - public HstsConfig requestMatcher(RequestMatcher requestMatcher) { - writer.setRequestMatcher(requestMatcher); - return this; - } + /** + * Sets the {@link RequestMatcher} used to determine if the + * "Strict-Transport-Security" should be added. If true the header is added, else + * the header is not added. By default the header is added when + * {@link HttpServletRequest#isSecure()} returns true. + * + * @param requestMatcher the {@link RequestMatcher} to use. + * @throws IllegalArgumentException if {@link RequestMatcher} is null + */ + public HstsConfig requestMatcher(RequestMatcher requestMatcher) { + writer.setRequestMatcher(requestMatcher); + return this; + } - /** - *

- * If true, subdomains should be considered HSTS Hosts too. The default is - * true. - *

- * - *

- * See Section - * 6.1.2 for additional details. - *

- * - * @param includeSubDomains - * true to include subdomains, else false - */ - public HstsConfig includeSubDomains(boolean includeSubDomains) { - writer.setIncludeSubDomains(includeSubDomains); - return this; - } + /** + *

+ * If true, subdomains should be considered HSTS Hosts too. The default is true. + *

+ * + *

+ * See Section + * 6.1.2 for additional details. + *

+ * + * @param includeSubDomains true to include subdomains, else false + */ + public HstsConfig includeSubDomains(boolean includeSubDomains) { + writer.setIncludeSubDomains(includeSubDomains); + return this; + } - /** - * Disables Strict Transport Security - * - * @return the {@link HeadersConfigurer} for additional configuration - */ - public HeadersConfigurer disable() { - writer = null; - return HeadersConfigurer.this; - } + /** + * Disables Strict Transport Security + * + * @return the {@link HeadersConfigurer} for additional configuration + */ + public HeadersConfigurer disable() { + writer = null; + return HeadersConfigurer.this; + } - /** - * Allows completing configuration of Strict Transport Security and - * continuing configuration of headers. - * - * @return the {@link HeadersConfigurer} for additional configuration - */ - public HeadersConfigurer and() { - return HeadersConfigurer.this; - } + /** + * Allows completing configuration of Strict Transport Security and continuing + * configuration of headers. + * + * @return the {@link HeadersConfigurer} for additional configuration + */ + public HeadersConfigurer and() { + return HeadersConfigurer.this; + } - /** - * Ensures that Strict-Transport-Security is enabled if it is not already - * - * @return the {@link HstsConfig} for additional customization - */ - private HstsConfig enable() { - if(writer == null) { - writer = new HstsHeaderWriter(); - } - return this; - } - } + /** + * Ensures that Strict-Transport-Security is enabled if it is not already + * + * @return the {@link HstsConfig} for additional customization + */ + private HstsConfig enable() { + if (writer == null) { + writer = new HstsHeaderWriter(); + } + return this; + } + } - /** - * Allows customizing the {@link XFrameOptionsHeaderWriter}. - * - * @return the {@link HeadersConfigurer} for additional customizations - */ - public FrameOptionsConfig frameOptions() { - return frameOptions.enable(); - } + /** + * Allows customizing the {@link XFrameOptionsHeaderWriter}. + * + * @return the {@link HeadersConfigurer} for additional customizations + */ + public FrameOptionsConfig frameOptions() { + return frameOptions.enable(); + } - public final class FrameOptionsConfig { - private XFrameOptionsHeaderWriter writer; + public final class FrameOptionsConfig { + private XFrameOptionsHeaderWriter writer; - private FrameOptionsConfig() { - enable(); - } + private FrameOptionsConfig() { + enable(); + } - /** - * Specify to DENY framing any content from this application. - * - * @return the {@link HeadersConfigurer} for additional customization. - */ - public HeadersConfigurer deny() { - writer = new XFrameOptionsHeaderWriter(XFrameOptionsMode.DENY); - return and(); - } + /** + * Specify to DENY framing any content from this application. + * + * @return the {@link HeadersConfigurer} for additional customization. + */ + public HeadersConfigurer deny() { + writer = new XFrameOptionsHeaderWriter(XFrameOptionsMode.DENY); + return and(); + } - /** - *

- * Specify to allow any request that comes from the same origin to frame - * this application. For example, if the application was hosted on - * example.com, then example.com could frame the application, but - * evil.com could not frame the application. - *

- * - * @return - */ - public HeadersConfigurer sameOrigin() { - writer = new XFrameOptionsHeaderWriter(XFrameOptionsMode.SAMEORIGIN); - return and(); - } + /** + *

+ * Specify to allow any request that comes from the same origin to frame this + * application. For example, if the application was hosted on example.com, then + * example.com could frame the application, but evil.com could not frame the + * application. + *

+ * + * @return + */ + public HeadersConfigurer sameOrigin() { + writer = new XFrameOptionsHeaderWriter(XFrameOptionsMode.SAMEORIGIN); + return and(); + } - /** - * Prevents the header from being added to the response. - * - * @return the {@link HeadersConfigurer} for additional configuration. - */ - public HeadersConfigurer disable() { - writer = null; - return and(); - } + /** + * Prevents the header from being added to the response. + * + * @return the {@link HeadersConfigurer} for additional configuration. + */ + public HeadersConfigurer disable() { + writer = null; + return and(); + } - /** - * Allows continuing customizing the headers configuration. - * - * @return the {@link HeadersConfigurer} for additional configuration - */ - public HeadersConfigurer and() { - return HeadersConfigurer.this; - } + /** + * Allows continuing customizing the headers configuration. + * + * @return the {@link HeadersConfigurer} for additional configuration + */ + public HeadersConfigurer and() { + return HeadersConfigurer.this; + } - /** - * Enables FrameOptionsConfig if it is not already enabled. - * - * @return the FrameOptionsConfig for additional customization. - */ - private FrameOptionsConfig enable() { - if(writer == null) { - writer = new XFrameOptionsHeaderWriter(XFrameOptionsMode.DENY); - } - return this; - } - } + /** + * Enables FrameOptionsConfig if it is not already enabled. + * + * @return the FrameOptionsConfig for additional customization. + */ + private FrameOptionsConfig enable() { + if (writer == null) { + writer = new XFrameOptionsHeaderWriter(XFrameOptionsMode.DENY); + } + return this; + } + } - /** - * Clears all of the default headers from the response. After doing so, one can add headers back. For example, if you only want to use Spring Security's cache control you can use the following: - * - *
-     * http
-     *    .headers()
-     *       .defaultsDisabled()
-     *       .cacheControl();
-     * 
- * - * @return the {@link HeadersConfigurer} for additional customization - */ - public HeadersConfigurer defaultsDisabled() { - contentTypeOptions.disable(); - xssProtection.disable(); - cacheControl.disable(); - hsts.disable(); - frameOptions.disable(); - return this; - } + /** + * Clears all of the default headers from the response. After doing so, one can add + * headers back. For example, if you only want to use Spring Security's cache control + * you can use the following: + * + *
+	 * http.headers().defaultsDisabled().cacheControl();
+	 * 
+ * + * @return the {@link HeadersConfigurer} for additional customization + */ + public HeadersConfigurer defaultsDisabled() { + contentTypeOptions.disable(); + xssProtection.disable(); + cacheControl.disable(); + hsts.disable(); + frameOptions.disable(); + return this; + } - @Override - public void configure(H http) throws Exception { - HeaderWriterFilter headersFilter = createHeaderWriterFilter(); - http.addFilter(headersFilter); - } + @Override + public void configure(H http) throws Exception { + HeaderWriterFilter headersFilter = createHeaderWriterFilter(); + http.addFilter(headersFilter); + } - /** - * Creates the {@link HeaderWriter} - * - * @return the {@link HeaderWriter} - */ - private HeaderWriterFilter createHeaderWriterFilter() { - List writers = getHeaderWriters(); - if(writers.isEmpty()) { - throw new IllegalStateException("Headers security is enabled, but no headers will be added. Either add headers or disable headers security"); - } - HeaderWriterFilter headersFilter = new HeaderWriterFilter( - writers); - headersFilter = postProcess(headersFilter); - return headersFilter; - } + /** + * Creates the {@link HeaderWriter} + * + * @return the {@link HeaderWriter} + */ + private HeaderWriterFilter createHeaderWriterFilter() { + List writers = getHeaderWriters(); + if (writers.isEmpty()) { + throw new IllegalStateException( + "Headers security is enabled, but no headers will be added. Either add headers or disable headers security"); + } + HeaderWriterFilter headersFilter = new HeaderWriterFilter(writers); + headersFilter = postProcess(headersFilter); + return headersFilter; + } - /** - * Gets the {@link HeaderWriter} instances and possibly initializes with the - * defaults. - * - * @return - */ - private List getHeaderWriters() { - List writers = new ArrayList(); - addIfNotNull(writers, contentTypeOptions.writer); - addIfNotNull(writers, xssProtection.writer); - addIfNotNull(writers, cacheControl.writer); - addIfNotNull(writers, hsts.writer); - addIfNotNull(writers, frameOptions.writer); - writers.addAll(headerWriters); - return writers; - } + /** + * Gets the {@link HeaderWriter} instances and possibly initializes with the defaults. + * + * @return + */ + private List getHeaderWriters() { + List writers = new ArrayList(); + addIfNotNull(writers, contentTypeOptions.writer); + addIfNotNull(writers, xssProtection.writer); + addIfNotNull(writers, cacheControl.writer); + addIfNotNull(writers, hsts.writer); + addIfNotNull(writers, frameOptions.writer); + writers.addAll(headerWriters); + return writers; + } - private void addIfNotNull(List values, T value) { - if(value != null) { - values.add(value); - } - } + private void addIfNotNull(List values, T value) { + if (value != null) { + values.add(value); + } + } } \ No newline at end of file diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/HttpBasicConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/HttpBasicConfigurer.java index 0ec279344f..fb759e9215 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/HttpBasicConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/HttpBasicConfigurer.java @@ -39,8 +39,8 @@ import org.springframework.web.accept.ContentNegotiationStrategy; import org.springframework.web.accept.HeaderContentNegotiationStrategy; /** - * Adds HTTP basic based authentication. All attributes have reasonable defaults - * making all parameters are optional. + * Adds HTTP basic based authentication. All attributes have reasonable defaults making + * all parameters are optional. * *

Security Filters

* @@ -70,101 +70,114 @@ import org.springframework.web.accept.HeaderContentNegotiationStrategy; * @author Rob Winch * @since 3.2 */ -public final class HttpBasicConfigurer> extends AbstractHttpConfigurer,B> { - private static final String DEFAULT_REALM = "Realm"; +public final class HttpBasicConfigurer> extends + AbstractHttpConfigurer, B> { + private static final String DEFAULT_REALM = "Realm"; - private AuthenticationEntryPoint authenticationEntryPoint; - private AuthenticationDetailsSource authenticationDetailsSource; - private BasicAuthenticationEntryPoint basicAuthEntryPoint = new BasicAuthenticationEntryPoint(); + private AuthenticationEntryPoint authenticationEntryPoint; + private AuthenticationDetailsSource authenticationDetailsSource; + private BasicAuthenticationEntryPoint basicAuthEntryPoint = new BasicAuthenticationEntryPoint(); - /** - * Creates a new instance - * @throws Exception - * @see {@link HttpSecurity#httpBasic()} - */ - public HttpBasicConfigurer() throws Exception { - realmName(DEFAULT_REALM); + /** + * Creates a new instance + * @throws Exception + * @see {@link HttpSecurity#httpBasic()} + */ + public HttpBasicConfigurer() throws Exception { + realmName(DEFAULT_REALM); - LinkedHashMap entryPoints = new LinkedHashMap(); - entryPoints.put(new RequestHeaderRequestMatcher("X-Requested-With","XMLHttpRequest"), new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED)); + LinkedHashMap entryPoints = new LinkedHashMap(); + entryPoints.put(new RequestHeaderRequestMatcher("X-Requested-With", + "XMLHttpRequest"), new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED)); - DelegatingAuthenticationEntryPoint defaultEntryPoint = new DelegatingAuthenticationEntryPoint(entryPoints); - defaultEntryPoint.setDefaultEntryPoint(basicAuthEntryPoint); - authenticationEntryPoint = defaultEntryPoint; - } + DelegatingAuthenticationEntryPoint defaultEntryPoint = new DelegatingAuthenticationEntryPoint( + entryPoints); + defaultEntryPoint.setDefaultEntryPoint(basicAuthEntryPoint); + authenticationEntryPoint = defaultEntryPoint; + } - /** - * Allows easily changing the realm, but leaving the remaining defaults in - * place. If {@link #authenticationEntryPoint(AuthenticationEntryPoint)} has - * been invoked, invoking this method will result in an error. - * - * @param realmName - * the HTTP Basic realm to use - * @return {@link HttpBasicConfigurer} for additional customization - * @throws Exception - */ - public HttpBasicConfigurer realmName(String realmName) throws Exception { - basicAuthEntryPoint.setRealmName(realmName); - basicAuthEntryPoint.afterPropertiesSet(); - return this; - } + /** + * Allows easily changing the realm, but leaving the remaining defaults in place. If + * {@link #authenticationEntryPoint(AuthenticationEntryPoint)} has been invoked, + * invoking this method will result in an error. + * + * @param realmName the HTTP Basic realm to use + * @return {@link HttpBasicConfigurer} for additional customization + * @throws Exception + */ + public HttpBasicConfigurer realmName(String realmName) throws Exception { + basicAuthEntryPoint.setRealmName(realmName); + basicAuthEntryPoint.afterPropertiesSet(); + return this; + } - /** - * The {@link AuthenticationEntryPoint} to be populated on - * {@link BasicAuthenticationFilter} in the event that authentication fails. - * The default to use {@link BasicAuthenticationEntryPoint} with the realm - * "Spring Security Application". - * - * @param authenticationEntryPoint the {@link AuthenticationEntryPoint} to use - * @return {@link HttpBasicConfigurer} for additional customization - */ - public HttpBasicConfigurer authenticationEntryPoint(AuthenticationEntryPoint authenticationEntryPoint) { - this.authenticationEntryPoint = authenticationEntryPoint; - return this; - } + /** + * The {@link AuthenticationEntryPoint} to be populated on + * {@link BasicAuthenticationFilter} in the event that authentication fails. The + * default to use {@link BasicAuthenticationEntryPoint} with the realm + * "Spring Security Application". + * + * @param authenticationEntryPoint the {@link AuthenticationEntryPoint} to use + * @return {@link HttpBasicConfigurer} for additional customization + */ + public HttpBasicConfigurer authenticationEntryPoint( + AuthenticationEntryPoint authenticationEntryPoint) { + this.authenticationEntryPoint = authenticationEntryPoint; + return this; + } - /** - * Specifies a custom {@link AuthenticationDetailsSource} to use for basic - * authentication. The default is {@link WebAuthenticationDetailsSource}. - * - * @param authenticationDetailsSource - * the custom {@link AuthenticationDetailsSource} to use - * @return {@link HttpBasicConfigurer} for additional customization - */ - public HttpBasicConfigurer authenticationDetailsSource(AuthenticationDetailsSource authenticationDetailsSource) { - this.authenticationDetailsSource = authenticationDetailsSource; - return this; - } + /** + * Specifies a custom {@link AuthenticationDetailsSource} to use for basic + * authentication. The default is {@link WebAuthenticationDetailsSource}. + * + * @param authenticationDetailsSource the custom {@link AuthenticationDetailsSource} + * to use + * @return {@link HttpBasicConfigurer} for additional customization + */ + public HttpBasicConfigurer authenticationDetailsSource( + AuthenticationDetailsSource authenticationDetailsSource) { + this.authenticationDetailsSource = authenticationDetailsSource; + return this; + } - public void init(B http) throws Exception { - registerDefaultAuthenticationEntryPoint(http); - } + public void init(B http) throws Exception { + registerDefaultAuthenticationEntryPoint(http); + } - @SuppressWarnings("unchecked") - private void registerDefaultAuthenticationEntryPoint(B http) { - ExceptionHandlingConfigurer exceptionHandling = http.getConfigurer(ExceptionHandlingConfigurer.class); - if(exceptionHandling == null) { - return; - } - ContentNegotiationStrategy contentNegotiationStrategy = http.getSharedObject(ContentNegotiationStrategy.class); - if(contentNegotiationStrategy == null) { - contentNegotiationStrategy = new HeaderContentNegotiationStrategy(); - } - MediaTypeRequestMatcher preferredMatcher = new MediaTypeRequestMatcher(contentNegotiationStrategy, MediaType.APPLICATION_ATOM_XML, MediaType.APPLICATION_FORM_URLENCODED, MediaType.APPLICATION_JSON, MediaType.APPLICATION_OCTET_STREAM, MediaType.APPLICATION_XML, MediaType.MULTIPART_FORM_DATA, MediaType.TEXT_XML); - preferredMatcher.setIgnoredMediaTypes(Collections.singleton(MediaType.ALL)); - exceptionHandling.defaultAuthenticationEntryPointFor(postProcess(authenticationEntryPoint), preferredMatcher); + @SuppressWarnings("unchecked") + private void registerDefaultAuthenticationEntryPoint(B http) { + ExceptionHandlingConfigurer exceptionHandling = http + .getConfigurer(ExceptionHandlingConfigurer.class); + if (exceptionHandling == null) { + return; + } + ContentNegotiationStrategy contentNegotiationStrategy = http + .getSharedObject(ContentNegotiationStrategy.class); + if (contentNegotiationStrategy == null) { + contentNegotiationStrategy = new HeaderContentNegotiationStrategy(); + } + MediaTypeRequestMatcher preferredMatcher = new MediaTypeRequestMatcher( + contentNegotiationStrategy, MediaType.APPLICATION_ATOM_XML, + MediaType.APPLICATION_FORM_URLENCODED, MediaType.APPLICATION_JSON, + MediaType.APPLICATION_OCTET_STREAM, MediaType.APPLICATION_XML, + MediaType.MULTIPART_FORM_DATA, MediaType.TEXT_XML); + preferredMatcher.setIgnoredMediaTypes(Collections.singleton(MediaType.ALL)); + exceptionHandling.defaultAuthenticationEntryPointFor( + postProcess(authenticationEntryPoint), preferredMatcher); + } - } - - @Override - public void configure(B http) throws Exception { - AuthenticationManager authenticationManager = http.getSharedObject(AuthenticationManager.class); - BasicAuthenticationFilter basicAuthenticationFilter = new BasicAuthenticationFilter(authenticationManager, authenticationEntryPoint); - if(authenticationDetailsSource != null) { - basicAuthenticationFilter.setAuthenticationDetailsSource(authenticationDetailsSource); - } - basicAuthenticationFilter = postProcess(basicAuthenticationFilter); - http.addFilter(basicAuthenticationFilter); - } + @Override + public void configure(B http) throws Exception { + AuthenticationManager authenticationManager = http + .getSharedObject(AuthenticationManager.class); + BasicAuthenticationFilter basicAuthenticationFilter = new BasicAuthenticationFilter( + authenticationManager, authenticationEntryPoint); + if (authenticationDetailsSource != null) { + basicAuthenticationFilter + .setAuthenticationDetailsSource(authenticationDetailsSource); + } + basicAuthenticationFilter = postProcess(basicAuthenticationFilter); + http.addFilter(basicAuthenticationFilter); + } } \ No newline at end of file diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/JeeConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/JeeConfigurer.java index 6434f1502f..09a2a3ccf6 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/JeeConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/JeeConfigurer.java @@ -50,8 +50,8 @@ import org.springframework.security.web.authentication.preauth.j2ee.J2eePreAuthe * *
    *
  • - * {@link AuthenticationEntryPoint} - * is populated with an {@link Http403ForbiddenEntryPoint}
  • + * {@link AuthenticationEntryPoint} is populated with an + * {@link Http403ForbiddenEntryPoint} *
  • A {@link PreAuthenticatedAuthenticationProvider} is populated into * {@link HttpSecurity#authenticationProvider(org.springframework.security.authentication.AuthenticationProvider)} *
  • @@ -68,193 +68,195 @@ import org.springframework.security.web.authentication.preauth.j2ee.J2eePreAuthe * @author Rob Winch * @since 3.2 */ -public final class JeeConfigurer> extends AbstractHttpConfigurer,H> { - private J2eePreAuthenticatedProcessingFilter j2eePreAuthenticatedProcessingFilter; - private AuthenticationUserDetailsService authenticationUserDetailsService; - private Set mappableRoles = new HashSet(); +public final class JeeConfigurer> extends + AbstractHttpConfigurer, H> { + private J2eePreAuthenticatedProcessingFilter j2eePreAuthenticatedProcessingFilter; + private AuthenticationUserDetailsService authenticationUserDetailsService; + private Set mappableRoles = new HashSet(); - /** - * Creates a new instance - * @see HttpSecurity#jee() - */ - public JeeConfigurer() { - } + /** + * Creates a new instance + * @see HttpSecurity#jee() + */ + public JeeConfigurer() { + } - /** - * Specifies roles to use map from the {@link HttpServletRequest} to the - * {@link UserDetails}. If {@link HttpServletRequest#isUserInRole(String)} - * returns true, the role is added to the {@link UserDetails}. This method - * is the equivalent of invoking {@link #mappableAuthorities(Set)}. Multiple - * invocations of {@link #mappableAuthorities(String...)} will override previous - * invocations. - * - *

    - * There are no default roles that are mapped. - *

    - * - * @param mappableRoles - * the roles to attempt to map to the {@link UserDetails} (i.e. - * "ROLE_USER", "ROLE_ADMIN", etc). - * @return the {@link JeeConfigurer} for further customizations - * @see SimpleMappableAttributesRetriever - * @see #mappableRoles(String...) - */ - public JeeConfigurer mappableAuthorities(String... mappableRoles) { - this.mappableRoles.clear(); - for(String role : mappableRoles) { - this.mappableRoles.add(role); - } - return this; - } + /** + * Specifies roles to use map from the {@link HttpServletRequest} to the + * {@link UserDetails}. If {@link HttpServletRequest#isUserInRole(String)} returns + * true, the role is added to the {@link UserDetails}. This method is the equivalent + * of invoking {@link #mappableAuthorities(Set)}. Multiple invocations of + * {@link #mappableAuthorities(String...)} will override previous invocations. + * + *

    + * There are no default roles that are mapped. + *

    + * + * @param mappableRoles the roles to attempt to map to the {@link UserDetails} (i.e. + * "ROLE_USER", "ROLE_ADMIN", etc). + * @return the {@link JeeConfigurer} for further customizations + * @see SimpleMappableAttributesRetriever + * @see #mappableRoles(String...) + */ + public JeeConfigurer mappableAuthorities(String... mappableRoles) { + this.mappableRoles.clear(); + for (String role : mappableRoles) { + this.mappableRoles.add(role); + } + return this; + } - /** - * Specifies roles to use map from the {@link HttpServletRequest} to the - * {@link UserDetails} and automatically prefixes it with "ROLE_". If - * {@link HttpServletRequest#isUserInRole(String)} returns true, the role is - * added to the {@link UserDetails}. This method is the equivalent of - * invoking {@link #mappableAuthorities(Set)}. Multiple invocations of - * {@link #mappableRoles(String...)} will override previous invocations. - * - *

    - * There are no default roles that are mapped. - *

    - * - * @param mappableRoles - * the roles to attempt to map to the {@link UserDetails} (i.e. - * "USER", "ADMIN", etc). - * @return the {@link JeeConfigurer} for further customizations - * @see SimpleMappableAttributesRetriever - * @see #mappableAuthorities(String...) - */ - public JeeConfigurer mappableRoles(String... mappableRoles) { - this.mappableRoles.clear(); - for(String role : mappableRoles) { - this.mappableRoles.add("ROLE_" + role); - } - return this; - } + /** + * Specifies roles to use map from the {@link HttpServletRequest} to the + * {@link UserDetails} and automatically prefixes it with "ROLE_". If + * {@link HttpServletRequest#isUserInRole(String)} returns true, the role is added to + * the {@link UserDetails}. This method is the equivalent of invoking + * {@link #mappableAuthorities(Set)}. Multiple invocations of + * {@link #mappableRoles(String...)} will override previous invocations. + * + *

    + * There are no default roles that are mapped. + *

    + * + * @param mappableRoles the roles to attempt to map to the {@link UserDetails} (i.e. + * "USER", "ADMIN", etc). + * @return the {@link JeeConfigurer} for further customizations + * @see SimpleMappableAttributesRetriever + * @see #mappableAuthorities(String...) + */ + public JeeConfigurer mappableRoles(String... mappableRoles) { + this.mappableRoles.clear(); + for (String role : mappableRoles) { + this.mappableRoles.add("ROLE_" + role); + } + return this; + } - /** - * Specifies roles to use map from the {@link HttpServletRequest} to the - * {@link UserDetails}. If {@link HttpServletRequest#isUserInRole(String)} - * returns true, the role is added to the {@link UserDetails}. This is the - * equivalent of {@link #mappableRoles(String...)}. Multiple invocations of - * {@link #mappableAuthorities(Set)} will override previous invocations. - * - *

    - * There are no default roles that are mapped. - *

    - * - * @param mappableRoles - * the roles to attempt to map to the {@link UserDetails}. - * @return the {@link JeeConfigurer} for further customizations - * @see SimpleMappableAttributesRetriever - */ - public JeeConfigurer mappableAuthorities(Set mappableRoles) { - this.mappableRoles = mappableRoles; - return this; - } + /** + * Specifies roles to use map from the {@link HttpServletRequest} to the + * {@link UserDetails}. If {@link HttpServletRequest#isUserInRole(String)} returns + * true, the role is added to the {@link UserDetails}. This is the equivalent of + * {@link #mappableRoles(String...)}. Multiple invocations of + * {@link #mappableAuthorities(Set)} will override previous invocations. + * + *

    + * There are no default roles that are mapped. + *

    + * + * @param mappableRoles the roles to attempt to map to the {@link UserDetails}. + * @return the {@link JeeConfigurer} for further customizations + * @see SimpleMappableAttributesRetriever + */ + public JeeConfigurer mappableAuthorities(Set mappableRoles) { + this.mappableRoles = mappableRoles; + return this; + } - /** - * Specifies the {@link AuthenticationUserDetailsService} that is used with - * the {@link PreAuthenticatedAuthenticationProvider}. The default is a - * {@link PreAuthenticatedGrantedAuthoritiesUserDetailsService}. - * - * @param authenticatedUserDetailsService the {@link AuthenticationUserDetailsService} to use. - * @return the {@link JeeConfigurer} for further configuration - */ - public JeeConfigurer authenticatedUserDetailsService( - AuthenticationUserDetailsService authenticatedUserDetailsService) { - this.authenticationUserDetailsService = authenticatedUserDetailsService; - return this; - } + /** + * Specifies the {@link AuthenticationUserDetailsService} that is used with the + * {@link PreAuthenticatedAuthenticationProvider}. The default is a + * {@link PreAuthenticatedGrantedAuthoritiesUserDetailsService}. + * + * @param authenticatedUserDetailsService the {@link AuthenticationUserDetailsService} + * to use. + * @return the {@link JeeConfigurer} for further configuration + */ + public JeeConfigurer authenticatedUserDetailsService( + AuthenticationUserDetailsService authenticatedUserDetailsService) { + this.authenticationUserDetailsService = authenticatedUserDetailsService; + return this; + } - /** - * Allows specifying the {@link J2eePreAuthenticatedProcessingFilter} to - * use. If {@link J2eePreAuthenticatedProcessingFilter} is provided, all of its attributes must also be - * configured manually (i.e. all attributes populated in the {@link JeeConfigurer} are not used). - * - * @param j2eePreAuthenticatedProcessingFilter the {@link J2eePreAuthenticatedProcessingFilter} to use. - * @return the {@link JeeConfigurer} for further configuration - */ - public JeeConfigurer j2eePreAuthenticatedProcessingFilter( - J2eePreAuthenticatedProcessingFilter j2eePreAuthenticatedProcessingFilter) { - this.j2eePreAuthenticatedProcessingFilter = j2eePreAuthenticatedProcessingFilter; - return this; - } + /** + * Allows specifying the {@link J2eePreAuthenticatedProcessingFilter} to use. If + * {@link J2eePreAuthenticatedProcessingFilter} is provided, all of its attributes + * must also be configured manually (i.e. all attributes populated in the + * {@link JeeConfigurer} are not used). + * + * @param j2eePreAuthenticatedProcessingFilter the + * {@link J2eePreAuthenticatedProcessingFilter} to use. + * @return the {@link JeeConfigurer} for further configuration + */ + public JeeConfigurer j2eePreAuthenticatedProcessingFilter( + J2eePreAuthenticatedProcessingFilter j2eePreAuthenticatedProcessingFilter) { + this.j2eePreAuthenticatedProcessingFilter = j2eePreAuthenticatedProcessingFilter; + return this; + } - /** - * Populates a {@link PreAuthenticatedAuthenticationProvider} into - * {@link HttpSecurity#authenticationProvider(org.springframework.security.authentication.AuthenticationProvider)} - * and a {@link Http403ForbiddenEntryPoint} into - * {@link HttpSecurity#authenticationEntryPoint(org.springframework.security.web.AuthenticationEntryPoint)} - * - * @see org.springframework.security.config.annotation.SecurityConfigurerAdapter#init(org.springframework.security.config.annotation.SecurityBuilder) - */ - @Override - public void init(H http) throws Exception { - PreAuthenticatedAuthenticationProvider authenticationProvider = new PreAuthenticatedAuthenticationProvider(); - authenticationProvider.setPreAuthenticatedUserDetailsService(getUserDetailsService()); - authenticationProvider = postProcess(authenticationProvider); + /** + * Populates a {@link PreAuthenticatedAuthenticationProvider} into + * {@link HttpSecurity#authenticationProvider(org.springframework.security.authentication.AuthenticationProvider)} + * and a {@link Http403ForbiddenEntryPoint} into + * {@link HttpSecurity#authenticationEntryPoint(org.springframework.security.web.AuthenticationEntryPoint)} + * + * @see org.springframework.security.config.annotation.SecurityConfigurerAdapter#init(org.springframework.security.config.annotation.SecurityBuilder) + */ + @Override + public void init(H http) throws Exception { + PreAuthenticatedAuthenticationProvider authenticationProvider = new PreAuthenticatedAuthenticationProvider(); + authenticationProvider + .setPreAuthenticatedUserDetailsService(getUserDetailsService()); + authenticationProvider = postProcess(authenticationProvider); - http - .authenticationProvider(authenticationProvider) - .setSharedObject(AuthenticationEntryPoint.class,new Http403ForbiddenEntryPoint()); - } + // @formatter:off + http + .authenticationProvider(authenticationProvider) + .setSharedObject(AuthenticationEntryPoint.class,new Http403ForbiddenEntryPoint()); + // @formatter:on + } - @Override - public void configure(H http) throws Exception { - J2eePreAuthenticatedProcessingFilter filter = getFilter(http.getSharedObject(AuthenticationManager.class)); - http.addFilter(filter); - } + @Override + public void configure(H http) throws Exception { + J2eePreAuthenticatedProcessingFilter filter = getFilter(http + .getSharedObject(AuthenticationManager.class)); + http.addFilter(filter); + } - /** - * Gets the {@link J2eePreAuthenticatedProcessingFilter} or creates a default instance using the properties provided. - * @param authenticationManager the {@link AuthenticationManager} to use. - * @return the {@link J2eePreAuthenticatedProcessingFilter} to use. - */ - private J2eePreAuthenticatedProcessingFilter getFilter( - AuthenticationManager authenticationManager) { - if (j2eePreAuthenticatedProcessingFilter == null) { - j2eePreAuthenticatedProcessingFilter = new J2eePreAuthenticatedProcessingFilter(); - j2eePreAuthenticatedProcessingFilter - .setAuthenticationManager(authenticationManager); - j2eePreAuthenticatedProcessingFilter - .setAuthenticationDetailsSource(createWebAuthenticationDetailsSource()); - j2eePreAuthenticatedProcessingFilter = postProcess(j2eePreAuthenticatedProcessingFilter); - } + /** + * Gets the {@link J2eePreAuthenticatedProcessingFilter} or creates a default instance + * using the properties provided. + * @param authenticationManager the {@link AuthenticationManager} to use. + * @return the {@link J2eePreAuthenticatedProcessingFilter} to use. + */ + private J2eePreAuthenticatedProcessingFilter getFilter( + AuthenticationManager authenticationManager) { + if (j2eePreAuthenticatedProcessingFilter == null) { + j2eePreAuthenticatedProcessingFilter = new J2eePreAuthenticatedProcessingFilter(); + j2eePreAuthenticatedProcessingFilter + .setAuthenticationManager(authenticationManager); + j2eePreAuthenticatedProcessingFilter + .setAuthenticationDetailsSource(createWebAuthenticationDetailsSource()); + j2eePreAuthenticatedProcessingFilter = postProcess(j2eePreAuthenticatedProcessingFilter); + } - return j2eePreAuthenticatedProcessingFilter; - } + return j2eePreAuthenticatedProcessingFilter; + } - /** - * Gets the {@link AuthenticationUserDetailsService} that was specified or - * defaults to {@link PreAuthenticatedGrantedAuthoritiesUserDetailsService}. - * - * @return the {@link AuthenticationUserDetailsService} to use - */ - private AuthenticationUserDetailsService getUserDetailsService() { - return authenticationUserDetailsService == null ? new PreAuthenticatedGrantedAuthoritiesUserDetailsService() - : authenticationUserDetailsService; - } + /** + * Gets the {@link AuthenticationUserDetailsService} that was specified or defaults to + * {@link PreAuthenticatedGrantedAuthoritiesUserDetailsService}. + * + * @return the {@link AuthenticationUserDetailsService} to use + */ + private AuthenticationUserDetailsService getUserDetailsService() { + return authenticationUserDetailsService == null ? new PreAuthenticatedGrantedAuthoritiesUserDetailsService() + : authenticationUserDetailsService; + } - /** - * Creates the - * {@link J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource} to set on - * the {@link J2eePreAuthenticatedProcessingFilter}. It is populated with a - * {@link SimpleMappableAttributesRetriever}. - * - * @return the - * {@link J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource} - * to use. - */ - private J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource createWebAuthenticationDetailsSource() { - J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource detailsSource = new J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource(); - SimpleMappableAttributesRetriever rolesRetriever = new SimpleMappableAttributesRetriever(); - rolesRetriever.setMappableAttributes(mappableRoles); - detailsSource.setMappableRolesRetriever(rolesRetriever); + /** + * Creates the {@link J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource} to set + * on the {@link J2eePreAuthenticatedProcessingFilter}. It is populated with a + * {@link SimpleMappableAttributesRetriever}. + * + * @return the {@link J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource} to use. + */ + private J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource createWebAuthenticationDetailsSource() { + J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource detailsSource = new J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource(); + SimpleMappableAttributesRetriever rolesRetriever = new SimpleMappableAttributesRetriever(); + rolesRetriever.setMappableAttributes(mappableRoles); + detailsSource.setMappableRolesRetriever(rolesRetriever); - detailsSource = postProcess(detailsSource); - return detailsSource; - } + detailsSource = postProcess(detailsSource); + return detailsSource; + } } \ No newline at end of file diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/LogoutConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/LogoutConfigurer.java index 6242cd71e9..49e16260b8 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/LogoutConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/LogoutConfigurer.java @@ -35,8 +35,7 @@ import org.springframework.security.web.util.matcher.RequestMatcher; /** * Adds logout support. Other {@link SecurityConfigurer} instances may invoke - * {@link #addLogoutHandler(LogoutHandler)} in the - * {@link #init(HttpSecurity)} phase. + * {@link #addLogoutHandler(LogoutHandler)} in the {@link #init(HttpSecurity)} phase. * *

    Security Filters

    * @@ -59,244 +58,245 @@ import org.springframework.security.web.util.matcher.RequestMatcher; * @since 3.2 * @see RememberMeConfigurer */ -public final class LogoutConfigurer> extends AbstractHttpConfigurer,H> { - private List logoutHandlers = new ArrayList(); - private SecurityContextLogoutHandler contextLogoutHandler = new SecurityContextLogoutHandler(); - private String logoutSuccessUrl = "/login?logout"; - private LogoutSuccessHandler logoutSuccessHandler; - private String logoutUrl = "/logout"; - private RequestMatcher logoutRequestMatcher; - private boolean permitAll; - private boolean customLogoutSuccess; +public final class LogoutConfigurer> extends + AbstractHttpConfigurer, H> { + private List logoutHandlers = new ArrayList(); + private SecurityContextLogoutHandler contextLogoutHandler = new SecurityContextLogoutHandler(); + private String logoutSuccessUrl = "/login?logout"; + private LogoutSuccessHandler logoutSuccessHandler; + private String logoutUrl = "/logout"; + private RequestMatcher logoutRequestMatcher; + private boolean permitAll; + private boolean customLogoutSuccess; - /** - * Creates a new instance - * @see HttpSecurity#logout() - */ - public LogoutConfigurer() { - } + /** + * Creates a new instance + * @see HttpSecurity#logout() + */ + public LogoutConfigurer() { + } - /** - * Adds a {@link LogoutHandler}. The {@link SecurityContextLogoutHandler} is - * added as the last {@link LogoutHandler} by default. - * - * @param logoutHandler the {@link LogoutHandler} to add - * @return the {@link LogoutConfigurer} for further customization - */ - public LogoutConfigurer addLogoutHandler(LogoutHandler logoutHandler) { - this.logoutHandlers.add(logoutHandler); - return this; - } + /** + * Adds a {@link LogoutHandler}. The {@link SecurityContextLogoutHandler} is added as + * the last {@link LogoutHandler} by default. + * + * @param logoutHandler the {@link LogoutHandler} to add + * @return the {@link LogoutConfigurer} for further customization + */ + public LogoutConfigurer addLogoutHandler(LogoutHandler logoutHandler) { + this.logoutHandlers.add(logoutHandler); + return this; + } - /** - * Configures {@link SecurityContextLogoutHandler} to invalidate the {@link HttpSession} at the time of logout. - * @param invalidateHttpSession true if the {@link HttpSession} should be invalidated (default), or false otherwise. - * @return the {@link LogoutConfigurer} for further customization - */ - public LogoutConfigurer invalidateHttpSession(boolean invalidateHttpSession) { - contextLogoutHandler.setInvalidateHttpSession(invalidateHttpSession); - return this; - } + /** + * Configures {@link SecurityContextLogoutHandler} to invalidate the + * {@link HttpSession} at the time of logout. + * @param invalidateHttpSession true if the {@link HttpSession} should be invalidated + * (default), or false otherwise. + * @return the {@link LogoutConfigurer} for further customization + */ + public LogoutConfigurer invalidateHttpSession(boolean invalidateHttpSession) { + contextLogoutHandler.setInvalidateHttpSession(invalidateHttpSession); + return this; + } - /** - * The URL that triggers log out to occur (default is "/logout"). If CSRF - * protection is enabled (default), then the request must also be a POST. - * This means that by default POST "/logout" is required to trigger a log - * out. If CSRF protection is disabled, then any HTTP method is allowed. - * - *

    - * It is considered best practice to use an HTTP POST on any action that - * changes state (i.e. log out) to protect against CSRF - * attacks. If you really want to use an HTTP GET, you can use - * logoutRequestMatcher(new AntPathRequestMatcher(logoutUrl, "GET")); - *

    - * - * @see #logoutRequestMatcher(RequestMatcher) - * @see HttpSecurity#csrf() - * - * @param logoutUrl - * the URL that will invoke logout. - * @return the {@link LogoutConfigurer} for further customization - */ - public LogoutConfigurer logoutUrl(String logoutUrl) { - this.logoutRequestMatcher = null; - this.logoutUrl = logoutUrl; - return this; - } + /** + * The URL that triggers log out to occur (default is "/logout"). If CSRF protection + * is enabled (default), then the request must also be a POST. This means that by + * default POST "/logout" is required to trigger a log out. If CSRF protection is + * disabled, then any HTTP method is allowed. + * + *

    + * It is considered best practice to use an HTTP POST on any action that changes state + * (i.e. log out) to protect against CSRF attacks. If + * you really want to use an HTTP GET, you can use + * logoutRequestMatcher(new AntPathRequestMatcher(logoutUrl, "GET")); + *

    + * + * @see #logoutRequestMatcher(RequestMatcher) + * @see HttpSecurity#csrf() + * + * @param logoutUrl the URL that will invoke logout. + * @return the {@link LogoutConfigurer} for further customization + */ + public LogoutConfigurer logoutUrl(String logoutUrl) { + this.logoutRequestMatcher = null; + this.logoutUrl = logoutUrl; + return this; + } - /** - * The RequestMatcher that triggers log out to occur. In most circumstances - * users will use {@link #logoutUrl(String)} which helps enforce good - * practices. - * - * @see #logoutUrl(String) - * - * @param logoutRequestMatcher - * the RequestMatcher used to determine if logout should occur. - * @return the {@link LogoutConfigurer} for further customization - */ - public LogoutConfigurer logoutRequestMatcher(RequestMatcher logoutRequestMatcher) { - this.logoutRequestMatcher = logoutRequestMatcher; - return this; - } + /** + * The RequestMatcher that triggers log out to occur. In most circumstances users will + * use {@link #logoutUrl(String)} which helps enforce good practices. + * + * @see #logoutUrl(String) + * + * @param logoutRequestMatcher the RequestMatcher used to determine if logout should + * occur. + * @return the {@link LogoutConfigurer} for further customization + */ + public LogoutConfigurer logoutRequestMatcher(RequestMatcher logoutRequestMatcher) { + this.logoutRequestMatcher = logoutRequestMatcher; + return this; + } - /** - * The URL to redirect to after logout has occurred. The default is - * "/login?logout". This is a shortcut for invoking - * {@link #logoutSuccessHandler(LogoutSuccessHandler)} with a - * {@link SimpleUrlLogoutSuccessHandler}. - * - * @param logoutSuccessUrl - * the URL to redirect to after logout occurred - * @return the {@link LogoutConfigurer} for further customization - */ - public LogoutConfigurer logoutSuccessUrl(String logoutSuccessUrl) { - this.customLogoutSuccess = true; - this.logoutSuccessUrl = logoutSuccessUrl; - return this; - } + /** + * The URL to redirect to after logout has occurred. The default is "/login?logout". + * This is a shortcut for invoking {@link #logoutSuccessHandler(LogoutSuccessHandler)} + * with a {@link SimpleUrlLogoutSuccessHandler}. + * + * @param logoutSuccessUrl the URL to redirect to after logout occurred + * @return the {@link LogoutConfigurer} for further customization + */ + public LogoutConfigurer logoutSuccessUrl(String logoutSuccessUrl) { + this.customLogoutSuccess = true; + this.logoutSuccessUrl = logoutSuccessUrl; + return this; + } - /** - * A shortcut for {@link #permitAll(boolean)} with true as an argument. - * @return the {@link LogoutConfigurer} for further customizations - */ - public LogoutConfigurer permitAll() { - return permitAll(true); - } + /** + * A shortcut for {@link #permitAll(boolean)} with true as an argument. + * @return the {@link LogoutConfigurer} for further customizations + */ + public LogoutConfigurer permitAll() { + return permitAll(true); + } - /** - * Allows specifying the names of cookies to be removed on logout success. - * This is a shortcut to easily invoke - * {@link #addLogoutHandler(LogoutHandler)} with a - * {@link CookieClearingLogoutHandler}. - * - * @param cookieNamesToClear the names of cookies to be removed on logout success. - * @return the {@link LogoutConfigurer} for further customization - */ - public LogoutConfigurer deleteCookies(String... cookieNamesToClear) { - return addLogoutHandler(new CookieClearingLogoutHandler(cookieNamesToClear)); - } + /** + * Allows specifying the names of cookies to be removed on logout success. This is a + * shortcut to easily invoke {@link #addLogoutHandler(LogoutHandler)} with a + * {@link CookieClearingLogoutHandler}. + * + * @param cookieNamesToClear the names of cookies to be removed on logout success. + * @return the {@link LogoutConfigurer} for further customization + */ + public LogoutConfigurer deleteCookies(String... cookieNamesToClear) { + return addLogoutHandler(new CookieClearingLogoutHandler(cookieNamesToClear)); + } - /** - * Sets the {@link LogoutSuccessHandler} to use. If this is specified, - * {@link #logoutSuccessUrl(String)} is ignored. - * - * @param logoutSuccessHandler - * the {@link LogoutSuccessHandler} to use after a user has been - * logged out. - * @return the {@link LogoutConfigurer} for further customizations - */ - public LogoutConfigurer logoutSuccessHandler(LogoutSuccessHandler logoutSuccessHandler) { - this.logoutSuccessUrl = null; - this.customLogoutSuccess = true; - this.logoutSuccessHandler = logoutSuccessHandler; - return this; - } + /** + * Sets the {@link LogoutSuccessHandler} to use. If this is specified, + * {@link #logoutSuccessUrl(String)} is ignored. + * + * @param logoutSuccessHandler the {@link LogoutSuccessHandler} to use after a user + * has been logged out. + * @return the {@link LogoutConfigurer} for further customizations + */ + public LogoutConfigurer logoutSuccessHandler( + LogoutSuccessHandler logoutSuccessHandler) { + this.logoutSuccessUrl = null; + this.customLogoutSuccess = true; + this.logoutSuccessHandler = logoutSuccessHandler; + return this; + } - /** - * Grants access to the {@link #logoutSuccessUrl(String)} and the {@link #logoutUrl(String)} for every user. - * - * @param permitAll if true grants access, else nothing is done - * @return the {@link LogoutConfigurer} for further customization. - */ - public LogoutConfigurer permitAll(boolean permitAll) { - this.permitAll = permitAll; - return this; - } + /** + * Grants access to the {@link #logoutSuccessUrl(String)} and the + * {@link #logoutUrl(String)} for every user. + * + * @param permitAll if true grants access, else nothing is done + * @return the {@link LogoutConfigurer} for further customization. + */ + public LogoutConfigurer permitAll(boolean permitAll) { + this.permitAll = permitAll; + return this; + } - /** - * Gets the {@link LogoutSuccessHandler} if not null, otherwise creates a - * new {@link SimpleUrlLogoutSuccessHandler} using the - * {@link #logoutSuccessUrl(String)}. - * - * @return the {@link LogoutSuccessHandler} to use - */ - private LogoutSuccessHandler getLogoutSuccessHandler() { - if(logoutSuccessHandler != null) { - return logoutSuccessHandler; - } - SimpleUrlLogoutSuccessHandler logoutSuccessHandler = new SimpleUrlLogoutSuccessHandler(); - logoutSuccessHandler.setDefaultTargetUrl(logoutSuccessUrl); - return logoutSuccessHandler; - } + /** + * Gets the {@link LogoutSuccessHandler} if not null, otherwise creates a new + * {@link SimpleUrlLogoutSuccessHandler} using the {@link #logoutSuccessUrl(String)}. + * + * @return the {@link LogoutSuccessHandler} to use + */ + private LogoutSuccessHandler getLogoutSuccessHandler() { + if (logoutSuccessHandler != null) { + return logoutSuccessHandler; + } + SimpleUrlLogoutSuccessHandler logoutSuccessHandler = new SimpleUrlLogoutSuccessHandler(); + logoutSuccessHandler.setDefaultTargetUrl(logoutSuccessUrl); + return logoutSuccessHandler; + } - @Override - public void init(H http) throws Exception { - if(permitAll) { - PermitAllSupport.permitAll(http, this.logoutSuccessUrl); - PermitAllSupport.permitAll(http, this.getLogoutRequestMatcher(http)); - } + @Override + public void init(H http) throws Exception { + if (permitAll) { + PermitAllSupport.permitAll(http, this.logoutSuccessUrl); + PermitAllSupport.permitAll(http, this.getLogoutRequestMatcher(http)); + } - DefaultLoginPageGeneratingFilter loginPageGeneratingFilter = http.getSharedObject(DefaultLoginPageGeneratingFilter.class); - if(loginPageGeneratingFilter != null && !isCustomLogoutSuccess()) { - loginPageGeneratingFilter.setLogoutSuccessUrl(getLogoutSuccessUrl()); - } - } + DefaultLoginPageGeneratingFilter loginPageGeneratingFilter = http + .getSharedObject(DefaultLoginPageGeneratingFilter.class); + if (loginPageGeneratingFilter != null && !isCustomLogoutSuccess()) { + loginPageGeneratingFilter.setLogoutSuccessUrl(getLogoutSuccessUrl()); + } + } - @Override - public void configure(H http) throws Exception { - LogoutFilter logoutFilter = createLogoutFilter(http); - http.addFilter(logoutFilter); - } + @Override + public void configure(H http) throws Exception { + LogoutFilter logoutFilter = createLogoutFilter(http); + http.addFilter(logoutFilter); + } - /** - * Returns true if the logout success has been customized via - * {@link #logoutSuccessUrl(String)} or - * {@link #logoutSuccessHandler(LogoutSuccessHandler)}. - * - * @return true if logout success handling has been customized, else false - */ - boolean isCustomLogoutSuccess() { - return customLogoutSuccess; - } + /** + * Returns true if the logout success has been customized via + * {@link #logoutSuccessUrl(String)} or + * {@link #logoutSuccessHandler(LogoutSuccessHandler)}. + * + * @return true if logout success handling has been customized, else false + */ + boolean isCustomLogoutSuccess() { + return customLogoutSuccess; + } - /** - * Gets the logoutSuccesUrl or null if a - * {@link #logoutSuccessHandler(LogoutSuccessHandler)} was configured. - * - * @return the logoutSuccessUrl - */ - private String getLogoutSuccessUrl() { - return logoutSuccessUrl; - } + /** + * Gets the logoutSuccesUrl or null if a + * {@link #logoutSuccessHandler(LogoutSuccessHandler)} was configured. + * + * @return the logoutSuccessUrl + */ + private String getLogoutSuccessUrl() { + return logoutSuccessUrl; + } - /** - * Gets the {@link LogoutHandler} instances that will be used. - * @return the {@link LogoutHandler} instances. Cannot be null. - */ - List getLogoutHandlers() { - return logoutHandlers; - } + /** + * Gets the {@link LogoutHandler} instances that will be used. + * @return the {@link LogoutHandler} instances. Cannot be null. + */ + List getLogoutHandlers() { + return logoutHandlers; + } - /** - * Creates the {@link LogoutFilter} using the {@link LogoutHandler} - * instances, the {@link #logoutSuccessHandler(LogoutSuccessHandler)} and - * the {@link #logoutUrl(String)}. - * - * @param http the builder to use - * @return the {@link LogoutFilter} to use. - * @throws Exception - */ - private LogoutFilter createLogoutFilter(H http) throws Exception { - logoutHandlers.add(contextLogoutHandler); - LogoutHandler[] handlers = logoutHandlers.toArray(new LogoutHandler[logoutHandlers.size()]); - LogoutFilter result = new LogoutFilter(getLogoutSuccessHandler(), handlers); - result.setLogoutRequestMatcher(getLogoutRequestMatcher(http)); - result = postProcess(result); - return result; - } + /** + * Creates the {@link LogoutFilter} using the {@link LogoutHandler} instances, the + * {@link #logoutSuccessHandler(LogoutSuccessHandler)} and the + * {@link #logoutUrl(String)}. + * + * @param http the builder to use + * @return the {@link LogoutFilter} to use. + * @throws Exception + */ + private LogoutFilter createLogoutFilter(H http) throws Exception { + logoutHandlers.add(contextLogoutHandler); + LogoutHandler[] handlers = logoutHandlers + .toArray(new LogoutHandler[logoutHandlers.size()]); + LogoutFilter result = new LogoutFilter(getLogoutSuccessHandler(), handlers); + result.setLogoutRequestMatcher(getLogoutRequestMatcher(http)); + result = postProcess(result); + return result; + } - @SuppressWarnings("unchecked") - private RequestMatcher getLogoutRequestMatcher(H http) { - if(logoutRequestMatcher != null) { - return logoutRequestMatcher; - } - if(http.getConfigurer(CsrfConfigurer.class) != null) { - this.logoutRequestMatcher = new AntPathRequestMatcher(this.logoutUrl, "POST"); - } else { - this.logoutRequestMatcher = new AntPathRequestMatcher(this.logoutUrl); - } - return this.logoutRequestMatcher; - } + @SuppressWarnings("unchecked") + private RequestMatcher getLogoutRequestMatcher(H http) { + if (logoutRequestMatcher != null) { + return logoutRequestMatcher; + } + if (http.getConfigurer(CsrfConfigurer.class) != null) { + this.logoutRequestMatcher = new AntPathRequestMatcher(this.logoutUrl, "POST"); + } + else { + this.logoutRequestMatcher = new AntPathRequestMatcher(this.logoutUrl); + } + return this.logoutRequestMatcher; + } } \ No newline at end of file diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/PermitAllSupport.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/PermitAllSupport.java index 56d15ad55b..265e278231 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/PermitAllSupport.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/PermitAllSupport.java @@ -15,7 +15,6 @@ */ package org.springframework.security.config.annotation.web.configurers; - import javax.servlet.http.HttpServletRequest; import org.springframework.security.access.SecurityConfig; @@ -23,7 +22,6 @@ import org.springframework.security.config.annotation.web.HttpSecurityBuilder; import org.springframework.security.config.annotation.web.configurers.AbstractConfigAttributeRequestMatcherRegistry.UrlMapping; import org.springframework.security.web.util.matcher.RequestMatcher; - /** * Configures non-null URL's to grant access to every URL * @author Rob Winch @@ -31,58 +29,71 @@ import org.springframework.security.web.util.matcher.RequestMatcher; */ final class PermitAllSupport { - public static void permitAll(HttpSecurityBuilder> http, String... urls) { - for(String url : urls) { - if(url != null) { - permitAll(http, new ExactUrlRequestMatcher(url)); - } - } - } + public static void permitAll( + HttpSecurityBuilder> http, String... urls) { + for (String url : urls) { + if (url != null) { + permitAll(http, new ExactUrlRequestMatcher(url)); + } + } + } - @SuppressWarnings("unchecked") - public static void permitAll(HttpSecurityBuilder> http, RequestMatcher... requestMatchers) { - ExpressionUrlAuthorizationConfigurer configurer = http.getConfigurer(ExpressionUrlAuthorizationConfigurer.class); + @SuppressWarnings("unchecked") + public static void permitAll( + HttpSecurityBuilder> http, + RequestMatcher... requestMatchers) { + ExpressionUrlAuthorizationConfigurer configurer = http + .getConfigurer(ExpressionUrlAuthorizationConfigurer.class); - if(configurer == null) { - throw new IllegalStateException("permitAll only works with HttpSecurity.authorizeRequests()"); - } + if (configurer == null) { + throw new IllegalStateException( + "permitAll only works with HttpSecurity.authorizeRequests()"); + } - for(RequestMatcher matcher : requestMatchers) { - if(matcher != null) { - configurer.getRegistry().addMapping(0, new UrlMapping(matcher, SecurityConfig.createList(ExpressionUrlAuthorizationConfigurer.permitAll))); - } - } - } + for (RequestMatcher matcher : requestMatchers) { + if (matcher != null) { + configurer + .getRegistry() + .addMapping( + 0, + new UrlMapping( + matcher, + SecurityConfig + .createList(ExpressionUrlAuthorizationConfigurer.permitAll))); + } + } + } - private final static class ExactUrlRequestMatcher implements RequestMatcher { - private String processUrl; + private final static class ExactUrlRequestMatcher implements RequestMatcher { + private String processUrl; - private ExactUrlRequestMatcher(String processUrl) { - this.processUrl = processUrl; - } + private ExactUrlRequestMatcher(String processUrl) { + this.processUrl = processUrl; + } - public boolean matches(HttpServletRequest request) { - String uri = request.getRequestURI(); - String query = request.getQueryString(); + public boolean matches(HttpServletRequest request) { + String uri = request.getRequestURI(); + String query = request.getQueryString(); - if(query != null) { - uri += "?" + query; - } + if (query != null) { + uri += "?" + query; + } - if ("".equals(request.getContextPath())) { - return uri.equals(processUrl); - } + if ("".equals(request.getContextPath())) { + return uri.equals(processUrl); + } - return uri.equals(request.getContextPath() + processUrl); - } + return uri.equals(request.getContextPath() + processUrl); + } - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("ExactUrl [processUrl='").append(processUrl).append("']"); - return sb.toString(); - } - } + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("ExactUrl [processUrl='").append(processUrl).append("']"); + return sb.toString(); + } + } - private PermitAllSupport() {} + private PermitAllSupport() { + } } \ No newline at end of file diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/PortMapperConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/PortMapperConfigurer.java index 556ec2733e..aa064b8881 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/PortMapperConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/PortMapperConfigurer.java @@ -26,90 +26,91 @@ import org.springframework.security.web.PortMapper; import org.springframework.security.web.PortMapperImpl; /** - * Allows configuring a shared {@link PortMapper} instance used to determine the - * ports when redirecting between HTTP and HTTPS. The {@link PortMapper} can be - * obtained from {@link HttpSecurity#getSharedObject(Class)}. + * Allows configuring a shared {@link PortMapper} instance used to determine the ports + * when redirecting between HTTP and HTTPS. The {@link PortMapper} can be obtained from + * {@link HttpSecurity#getSharedObject(Class)}. * * @author Rob Winch * @since 3.2 */ -public final class PortMapperConfigurer> extends AbstractHttpConfigurer,H> { - private PortMapper portMapper; - private Map httpsPortMappings = new HashMap(); +public final class PortMapperConfigurer> extends + AbstractHttpConfigurer, H> { + private PortMapper portMapper; + private Map httpsPortMappings = new HashMap(); - /** - * Creates a new instance - */ - public PortMapperConfigurer() { - } + /** + * Creates a new instance + */ + public PortMapperConfigurer() { + } - /** - * Allows specifying the {@link PortMapper} instance. - * @param portMapper - * @return - */ - public PortMapperConfigurer portMapper(PortMapper portMapper) { - this.portMapper = portMapper; - return this; - } + /** + * Allows specifying the {@link PortMapper} instance. + * @param portMapper + * @return + */ + public PortMapperConfigurer portMapper(PortMapper portMapper) { + this.portMapper = portMapper; + return this; + } - /** - * Adds a port mapping - * @param httpPort the HTTP port that maps to a specific HTTPS port. - * @return {@link HttpPortMapping} to define the HTTPS port - */ - public HttpPortMapping http(int httpPort) { - return new HttpPortMapping(httpPort); - } + /** + * Adds a port mapping + * @param httpPort the HTTP port that maps to a specific HTTPS port. + * @return {@link HttpPortMapping} to define the HTTPS port + */ + public HttpPortMapping http(int httpPort) { + return new HttpPortMapping(httpPort); + } - @Override - public void init(H http) throws Exception { - http.setSharedObject(PortMapper.class, getPortMapper()); - } + @Override + public void init(H http) throws Exception { + http.setSharedObject(PortMapper.class, getPortMapper()); + } - /** - * Gets the {@link PortMapper} to use. If {@link #portMapper(PortMapper)} - * was not invoked, builds a {@link PortMapperImpl} using the port mappings - * specified with {@link #http(int)}. - * - * @return the {@link PortMapper} to use - */ - private PortMapper getPortMapper() { - if(portMapper == null) { - PortMapperImpl portMapper = new PortMapperImpl(); - portMapper.setPortMappings(httpsPortMappings); - this.portMapper = portMapper; - } - return portMapper; - } + /** + * Gets the {@link PortMapper} to use. If {@link #portMapper(PortMapper)} was not + * invoked, builds a {@link PortMapperImpl} using the port mappings specified with + * {@link #http(int)}. + * + * @return the {@link PortMapper} to use + */ + private PortMapper getPortMapper() { + if (portMapper == null) { + PortMapperImpl portMapper = new PortMapperImpl(); + portMapper.setPortMappings(httpsPortMappings); + this.portMapper = portMapper; + } + return portMapper; + } - /** - * Allows specifying the HTTPS port for a given HTTP port when redirecting - * between HTTP and HTTPS. - * - * @author Rob Winch - * @since 3.2 - */ - public final class HttpPortMapping { - private final int httpPort; + /** + * Allows specifying the HTTPS port for a given HTTP port when redirecting between + * HTTP and HTTPS. + * + * @author Rob Winch + * @since 3.2 + */ + public final class HttpPortMapping { + private final int httpPort; - /** - * Creates a new instance - * @param httpPort - * @see PortMapperConfigurer#http(int) - */ - private HttpPortMapping(int httpPort) { - this.httpPort = httpPort; - } + /** + * Creates a new instance + * @param httpPort + * @see PortMapperConfigurer#http(int) + */ + private HttpPortMapping(int httpPort) { + this.httpPort = httpPort; + } - /** - * Maps the given HTTP port to the provided HTTPS port and vice versa. - * @param httpsPort the HTTPS port to map to - * @return the {@link PortMapperConfigurer} for further customization - */ - public PortMapperConfigurer mapsTo(int httpsPort) { - httpsPortMappings.put(String.valueOf(httpPort), String.valueOf(httpsPort)); - return PortMapperConfigurer.this; - } - } + /** + * Maps the given HTTP port to the provided HTTPS port and vice versa. + * @param httpsPort the HTTPS port to map to + * @return the {@link PortMapperConfigurer} for further customization + */ + public PortMapperConfigurer mapsTo(int httpsPort) { + httpsPortMappings.put(String.valueOf(httpPort), String.valueOf(httpsPort)); + return PortMapperConfigurer.this; + } + } } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/RememberMeConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/RememberMeConfigurer.java index 8a739fdfb5..91988cf741 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/RememberMeConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/RememberMeConfigurer.java @@ -35,9 +35,8 @@ import org.springframework.security.web.authentication.rememberme.TokenBasedReme import org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter; /** - * Configures Remember Me authentication. This typically involves the user - * checking a box when they enter their username and password that states to - * "Remember Me". + * Configures Remember Me authentication. This typically involves the user checking a box + * when they enter their username and password that states to "Remember Me". * *

    Security Filters

    * @@ -56,8 +55,10 @@ import org.springframework.security.web.authentication.ui.DefaultLoginPageGenera *
  • * {@link HttpSecurity#authenticationProvider(org.springframework.security.authentication.AuthenticationProvider)} * is populated with a {@link RememberMeAuthenticationProvider}
  • - *
  • {@link RememberMeServices} is populated as a shared object and available on {@link HttpSecurity#getSharedObject(Class)}
  • - *
  • {@link LogoutConfigurer#addLogoutHandler(LogoutHandler)} is used to add a logout handler to clean up the remember me authentication.
  • + *
  • {@link RememberMeServices} is populated as a shared object and available on + * {@link HttpSecurity#getSharedObject(Class)}
  • + *
  • {@link LogoutConfigurer#addLogoutHandler(LogoutHandler)} is used to add a logout + * handler to clean up the remember me authentication.
  • *
* *

Shared Objects Used

@@ -66,299 +67,307 @@ import org.springframework.security.web.authentication.ui.DefaultLoginPageGenera * *
    *
  • {@link AuthenticationManager}
  • - *
  • {@link UserDetailsService} if no {@link #userDetailsService(UserDetailsService)} was specified.
  • - *
  • {@link DefaultLoginPageGeneratingFilter} - if present will be populated with information from the configuration
  • + *
  • {@link UserDetailsService} if no {@link #userDetailsService(UserDetailsService)} + * was specified.
  • + *
  • {@link DefaultLoginPageGeneratingFilter} - if present will be populated with + * information from the configuration
  • *
* * @author Rob Winch * @since 3.2 */ -public final class RememberMeConfigurer> extends AbstractHttpConfigurer,H> { - private AuthenticationSuccessHandler authenticationSuccessHandler; - private String key; - private RememberMeServices rememberMeServices; - private LogoutHandler logoutHandler; - private String rememberMeParameter = "remember-me"; - private String rememberMeCookieName = "remember-me"; - private PersistentTokenRepository tokenRepository; - private UserDetailsService userDetailsService; - private Integer tokenValiditySeconds; - private Boolean useSecureCookie; +public final class RememberMeConfigurer> extends + AbstractHttpConfigurer, H> { + private AuthenticationSuccessHandler authenticationSuccessHandler; + private String key; + private RememberMeServices rememberMeServices; + private LogoutHandler logoutHandler; + private String rememberMeParameter = "remember-me"; + private String rememberMeCookieName = "remember-me"; + private PersistentTokenRepository tokenRepository; + private UserDetailsService userDetailsService; + private Integer tokenValiditySeconds; + private Boolean useSecureCookie; - /** - * Creates a new instance - */ - public RememberMeConfigurer() { - } + /** + * Creates a new instance + */ + public RememberMeConfigurer() { + } - /** - * Allows specifying how long (in seconds) a token is valid for - * - * @param tokenValiditySeconds - * @return {@link RememberMeConfigurer} for further customization - * @see AbstractRememberMeServices#setTokenValiditySeconds(int) - */ - public RememberMeConfigurer tokenValiditySeconds(int tokenValiditySeconds) { - this.tokenValiditySeconds = tokenValiditySeconds; - return this; - } + /** + * Allows specifying how long (in seconds) a token is valid for + * + * @param tokenValiditySeconds + * @return {@link RememberMeConfigurer} for further customization + * @see AbstractRememberMeServices#setTokenValiditySeconds(int) + */ + public RememberMeConfigurer tokenValiditySeconds(int tokenValiditySeconds) { + this.tokenValiditySeconds = tokenValiditySeconds; + return this; + } - /** - *Whether the cookie should be flagged as secure or not. Secure cookies can only be sent over an HTTPS connection - * and thus cannot be accidentally submitted over HTTP where they could be intercepted. - *

- * By default the cookie will be secure if the request is secure. If you only want to use remember-me over - * HTTPS (recommended) you should set this property to {@code true}. - * - * @param useSecureCookie set to {@code true} to always user secure cookies, {@code false} to disable their use. - * @return the {@link RememberMeConfigurer} for further customization - * @see AbstractRememberMeServices#setUseSecureCookie(boolean) - */ - public RememberMeConfigurer useSecureCookie(boolean useSecureCookie) { - this.useSecureCookie = useSecureCookie; - return this; - } + /** + * Whether the cookie should be flagged as secure or not. Secure cookies can only be + * sent over an HTTPS connection and thus cannot be accidentally submitted over HTTP + * where they could be intercepted. + *

+ * By default the cookie will be secure if the request is secure. If you only want to + * use remember-me over HTTPS (recommended) you should set this property to + * {@code true}. + * + * @param useSecureCookie set to {@code true} to always user secure cookies, + * {@code false} to disable their use. + * @return the {@link RememberMeConfigurer} for further customization + * @see AbstractRememberMeServices#setUseSecureCookie(boolean) + */ + public RememberMeConfigurer useSecureCookie(boolean useSecureCookie) { + this.useSecureCookie = useSecureCookie; + return this; + } - /** - * Specifies the {@link UserDetailsService} used to look up the - * {@link UserDetails} when a remember me token is valid. The default is to - * use the {@link UserDetailsService} found by invoking - * {@link HttpSecurity#getSharedObject(Class)} which is set when using - * {@link WebSecurityConfigurerAdapter#configure(AuthenticationManagerBuilder)}. - * Alternatively, one can populate {@link #rememberMeServices(RememberMeServices)}. - * - * @param userDetailsService - * the {@link UserDetailsService} to configure - * @return the {@link RememberMeConfigurer} for further customization - * @see AbstractRememberMeServices - */ - public RememberMeConfigurer userDetailsService(UserDetailsService userDetailsService) { - this.userDetailsService = userDetailsService; - return this; - } + /** + * Specifies the {@link UserDetailsService} used to look up the {@link UserDetails} + * when a remember me token is valid. The default is to use the + * {@link UserDetailsService} found by invoking + * {@link HttpSecurity#getSharedObject(Class)} which is set when using + * {@link WebSecurityConfigurerAdapter#configure(AuthenticationManagerBuilder)}. + * Alternatively, one can populate {@link #rememberMeServices(RememberMeServices)}. + * + * @param userDetailsService the {@link UserDetailsService} to configure + * @return the {@link RememberMeConfigurer} for further customization + * @see AbstractRememberMeServices + */ + public RememberMeConfigurer userDetailsService( + UserDetailsService userDetailsService) { + this.userDetailsService = userDetailsService; + return this; + } - /** - * Specifies the {@link PersistentTokenRepository} to use. The default is to - * use {@link TokenBasedRememberMeServices} instead. - * - * @param tokenRepository - * the {@link PersistentTokenRepository} to use - * @return the {@link RememberMeConfigurer} for further customization - */ - public RememberMeConfigurer tokenRepository(PersistentTokenRepository tokenRepository) { - this.tokenRepository = tokenRepository; - return this; - } + /** + * Specifies the {@link PersistentTokenRepository} to use. The default is to use + * {@link TokenBasedRememberMeServices} instead. + * + * @param tokenRepository the {@link PersistentTokenRepository} to use + * @return the {@link RememberMeConfigurer} for further customization + */ + public RememberMeConfigurer tokenRepository( + PersistentTokenRepository tokenRepository) { + this.tokenRepository = tokenRepository; + return this; + } - /** - * Sets the key to identify tokens created for remember me authentication. Default is a secure randomly generated - * key. - * - * @param key the key to identify tokens created for remember me authentication - * @return the {@link RememberMeConfigurer} for further customization - */ - public RememberMeConfigurer key(String key) { - this.key = key; - return this; - } + /** + * Sets the key to identify tokens created for remember me authentication. Default is + * a secure randomly generated key. + * + * @param key the key to identify tokens created for remember me authentication + * @return the {@link RememberMeConfigurer} for further customization + */ + public RememberMeConfigurer key(String key) { + this.key = key; + return this; + } - /** - * The HTTP parameter used to indicate to remember the user at time of login. - * - * @param rememberMeParameter the HTTP parameter used to indicate to remember the user - * @return the {@link RememberMeConfigurer} for further customization - */ - public RememberMeConfigurer rememberMeParameter(String rememberMeParameter) { - this.rememberMeParameter = rememberMeParameter; - return this; - } + /** + * The HTTP parameter used to indicate to remember the user at time of login. + * + * @param rememberMeParameter the HTTP parameter used to indicate to remember the user + * @return the {@link RememberMeConfigurer} for further customization + */ + public RememberMeConfigurer rememberMeParameter(String rememberMeParameter) { + this.rememberMeParameter = rememberMeParameter; + return this; + } - /** - * Allows control over the destination a remembered user is sent to when they are successfully authenticated. - * By default, the filter will just allow the current request to proceed, but if an - * {@code AuthenticationSuccessHandler} is set, it will be invoked and the {@code doFilter()} method will return - * immediately, thus allowing the application to redirect the user to a specific URL, regardless of what the original - * request was for. - * - * @param authenticationSuccessHandler the strategy to invoke immediately before returning from {@code doFilter()}. - * @return {@link RememberMeConfigurer} for further customization - * @see RememberMeAuthenticationFilter#setAuthenticationSuccessHandler(AuthenticationSuccessHandler) - */ - public RememberMeConfigurer authenticationSuccessHandler(AuthenticationSuccessHandler authenticationSuccessHandler) { - this.authenticationSuccessHandler = authenticationSuccessHandler; - return this; - } + /** + * Allows control over the destination a remembered user is sent to when they are + * successfully authenticated. By default, the filter will just allow the current + * request to proceed, but if an {@code AuthenticationSuccessHandler} is set, it will + * be invoked and the {@code doFilter()} method will return immediately, thus allowing + * the application to redirect the user to a specific URL, regardless of what the + * original request was for. + * + * @param authenticationSuccessHandler the strategy to invoke immediately before + * returning from {@code doFilter()}. + * @return {@link RememberMeConfigurer} for further customization + * @see RememberMeAuthenticationFilter#setAuthenticationSuccessHandler(AuthenticationSuccessHandler) + */ + public RememberMeConfigurer authenticationSuccessHandler( + AuthenticationSuccessHandler authenticationSuccessHandler) { + this.authenticationSuccessHandler = authenticationSuccessHandler; + return this; + } - /** - * Specify the {@link RememberMeServices} to use. - * @param rememberMeServices the {@link RememberMeServices} to use - * @return the {@link RememberMeConfigurer} for further customizations - * @see RememberMeServices - */ - public RememberMeConfigurer rememberMeServices(RememberMeServices rememberMeServices) { - this.rememberMeServices = rememberMeServices; - return this; - } + /** + * Specify the {@link RememberMeServices} to use. + * @param rememberMeServices the {@link RememberMeServices} to use + * @return the {@link RememberMeConfigurer} for further customizations + * @see RememberMeServices + */ + public RememberMeConfigurer rememberMeServices( + RememberMeServices rememberMeServices) { + this.rememberMeServices = rememberMeServices; + return this; + } - @SuppressWarnings("unchecked") - @Override - public void init(H http) throws Exception { - String key = getKey(); - RememberMeServices rememberMeServices = getRememberMeServices(http, key); - http.setSharedObject(RememberMeServices.class, rememberMeServices); - LogoutConfigurer logoutConfigurer = http.getConfigurer(LogoutConfigurer.class); - if(logoutConfigurer != null) { - logoutConfigurer.addLogoutHandler(logoutHandler); - } + @SuppressWarnings("unchecked") + @Override + public void init(H http) throws Exception { + String key = getKey(); + RememberMeServices rememberMeServices = getRememberMeServices(http, key); + http.setSharedObject(RememberMeServices.class, rememberMeServices); + LogoutConfigurer logoutConfigurer = http.getConfigurer(LogoutConfigurer.class); + if (logoutConfigurer != null) { + logoutConfigurer.addLogoutHandler(logoutHandler); + } - RememberMeAuthenticationProvider authenticationProvider = new RememberMeAuthenticationProvider( - key); - authenticationProvider = postProcess(authenticationProvider); - http.authenticationProvider(authenticationProvider); + RememberMeAuthenticationProvider authenticationProvider = new RememberMeAuthenticationProvider( + key); + authenticationProvider = postProcess(authenticationProvider); + http.authenticationProvider(authenticationProvider); - initDefaultLoginFilter(http); - } + initDefaultLoginFilter(http); + } - @Override - public void configure(H http) throws Exception { - RememberMeAuthenticationFilter rememberMeFilter = new RememberMeAuthenticationFilter( - http.getSharedObject(AuthenticationManager.class), rememberMeServices); - if (authenticationSuccessHandler != null) { - rememberMeFilter - .setAuthenticationSuccessHandler(authenticationSuccessHandler); - } - rememberMeFilter = postProcess(rememberMeFilter); - http.addFilter(rememberMeFilter); - } + @Override + public void configure(H http) throws Exception { + RememberMeAuthenticationFilter rememberMeFilter = new RememberMeAuthenticationFilter( + http.getSharedObject(AuthenticationManager.class), rememberMeServices); + if (authenticationSuccessHandler != null) { + rememberMeFilter + .setAuthenticationSuccessHandler(authenticationSuccessHandler); + } + rememberMeFilter = postProcess(rememberMeFilter); + http.addFilter(rememberMeFilter); + } - /** - * Returns the HTTP parameter used to indicate to remember the user at time of login. - * @return the HTTP parameter used to indicate to remember the user - */ - private String getRememberMeParameter() { - return rememberMeParameter; - } + /** + * Returns the HTTP parameter used to indicate to remember the user at time of login. + * @return the HTTP parameter used to indicate to remember the user + */ + private String getRememberMeParameter() { + return rememberMeParameter; + } - /** - * If available, initializes the {@link DefaultLoginPageGeneratingFilter} shared object. - * - * @param http the {@link HttpSecurityBuilder} to use - */ - private void initDefaultLoginFilter(H http) { - DefaultLoginPageGeneratingFilter loginPageGeneratingFilter = http.getSharedObject(DefaultLoginPageGeneratingFilter.class); - if(loginPageGeneratingFilter != null) { - loginPageGeneratingFilter.setRememberMeParameter(getRememberMeParameter()); - } - } + /** + * If available, initializes the {@link DefaultLoginPageGeneratingFilter} shared + * object. + * + * @param http the {@link HttpSecurityBuilder} to use + */ + private void initDefaultLoginFilter(H http) { + DefaultLoginPageGeneratingFilter loginPageGeneratingFilter = http + .getSharedObject(DefaultLoginPageGeneratingFilter.class); + if (loginPageGeneratingFilter != null) { + loginPageGeneratingFilter.setRememberMeParameter(getRememberMeParameter()); + } + } - /** - * Gets the {@link RememberMeServices} or creates the {@link RememberMeServices}. - * @param http the {@link HttpSecurity} to lookup shared objects - * @param key the {@link #key(String)} - * @return the {@link RememberMeServices} to use - * @throws Exception - */ - private RememberMeServices getRememberMeServices(H http, - String key) throws Exception { - if (rememberMeServices != null) { - if (rememberMeServices instanceof LogoutHandler - && logoutHandler == null) { - this.logoutHandler = (LogoutHandler) rememberMeServices; - } - return rememberMeServices; - } - AbstractRememberMeServices tokenRememberMeServices = createRememberMeServices( - http, key); - tokenRememberMeServices.setParameter(rememberMeParameter); - tokenRememberMeServices.setCookieName(rememberMeCookieName); - if (tokenValiditySeconds != null) { - tokenRememberMeServices - .setTokenValiditySeconds(tokenValiditySeconds); - } - if (useSecureCookie != null) { - tokenRememberMeServices.setUseSecureCookie(useSecureCookie); - } - tokenRememberMeServices.afterPropertiesSet(); - logoutHandler = tokenRememberMeServices; - rememberMeServices = tokenRememberMeServices; - return tokenRememberMeServices; - } + /** + * Gets the {@link RememberMeServices} or creates the {@link RememberMeServices}. + * @param http the {@link HttpSecurity} to lookup shared objects + * @param key the {@link #key(String)} + * @return the {@link RememberMeServices} to use + * @throws Exception + */ + private RememberMeServices getRememberMeServices(H http, String key) throws Exception { + if (rememberMeServices != null) { + if (rememberMeServices instanceof LogoutHandler && logoutHandler == null) { + this.logoutHandler = (LogoutHandler) rememberMeServices; + } + return rememberMeServices; + } + AbstractRememberMeServices tokenRememberMeServices = createRememberMeServices( + http, key); + tokenRememberMeServices.setParameter(rememberMeParameter); + tokenRememberMeServices.setCookieName(rememberMeCookieName); + if (tokenValiditySeconds != null) { + tokenRememberMeServices.setTokenValiditySeconds(tokenValiditySeconds); + } + if (useSecureCookie != null) { + tokenRememberMeServices.setUseSecureCookie(useSecureCookie); + } + tokenRememberMeServices.afterPropertiesSet(); + logoutHandler = tokenRememberMeServices; + rememberMeServices = tokenRememberMeServices; + return tokenRememberMeServices; + } - /** - * Creates the {@link RememberMeServices} to use when none is provided. The - * result is either {@link PersistentTokenRepository} (if a - * {@link PersistentTokenRepository} is specified, else - * {@link TokenBasedRememberMeServices}. - * - * @param http the {@link HttpSecurity} to lookup shared objects - * @param key the {@link #key(String)} - * @return the {@link RememberMeServices} to use - * @throws Exception - */ - private AbstractRememberMeServices createRememberMeServices( - H http, String key) throws Exception { - return tokenRepository == null ? createTokenBasedRememberMeServices( - http, key) : createPersistentRememberMeServices(http, key); - } + /** + * Creates the {@link RememberMeServices} to use when none is provided. The result is + * either {@link PersistentTokenRepository} (if a {@link PersistentTokenRepository} is + * specified, else {@link TokenBasedRememberMeServices}. + * + * @param http the {@link HttpSecurity} to lookup shared objects + * @param key the {@link #key(String)} + * @return the {@link RememberMeServices} to use + * @throws Exception + */ + private AbstractRememberMeServices createRememberMeServices(H http, String key) + throws Exception { + return tokenRepository == null ? createTokenBasedRememberMeServices(http, key) + : createPersistentRememberMeServices(http, key); + } - /** - * Creates {@link TokenBasedRememberMeServices} - * - * @param http the {@link HttpSecurity} to lookup shared objects - * @param key the {@link #key(String)} - * @return the {@link TokenBasedRememberMeServices} - */ - private AbstractRememberMeServices createTokenBasedRememberMeServices( - H http, String key) { - UserDetailsService userDetailsService = getUserDetailsService(http); - return new TokenBasedRememberMeServices(key, userDetailsService); - } + /** + * Creates {@link TokenBasedRememberMeServices} + * + * @param http the {@link HttpSecurity} to lookup shared objects + * @param key the {@link #key(String)} + * @return the {@link TokenBasedRememberMeServices} + */ + private AbstractRememberMeServices createTokenBasedRememberMeServices(H http, + String key) { + UserDetailsService userDetailsService = getUserDetailsService(http); + return new TokenBasedRememberMeServices(key, userDetailsService); + } - /** - * Creates {@link PersistentTokenBasedRememberMeServices} - * - * @param http the {@link HttpSecurity} to lookup shared objects - * @param key the {@link #key(String)} - * @return the {@link PersistentTokenBasedRememberMeServices} - */ - private AbstractRememberMeServices createPersistentRememberMeServices( - H http, String key) { - UserDetailsService userDetailsService = getUserDetailsService(http); - return new PersistentTokenBasedRememberMeServices(key, - userDetailsService, tokenRepository); - } + /** + * Creates {@link PersistentTokenBasedRememberMeServices} + * + * @param http the {@link HttpSecurity} to lookup shared objects + * @param key the {@link #key(String)} + * @return the {@link PersistentTokenBasedRememberMeServices} + */ + private AbstractRememberMeServices createPersistentRememberMeServices(H http, + String key) { + UserDetailsService userDetailsService = getUserDetailsService(http); + return new PersistentTokenBasedRememberMeServices(key, userDetailsService, + tokenRepository); + } - /** - * Gets the {@link UserDetailsService} to use. Either the explicitly - * configure {@link UserDetailsService} from - * {@link #userDetailsService(UserDetailsService)} or a shared object from - * {@link HttpSecurity#getSharedObject(Class)}. - * - * @param http {@link HttpSecurity} to get the shared {@link UserDetailsService} - * @return the {@link UserDetailsService} to use - */ - private UserDetailsService getUserDetailsService(H http) { - if(userDetailsService == null) { - userDetailsService = http.getSharedObject(UserDetailsService.class); - } - if(userDetailsService == null) { - throw new IllegalStateException("userDetailsService cannot be null. Invoke " - + RememberMeConfigurer.class.getSimpleName() + "#userDetailsService(UserDetailsService) or see its javadoc for alternative approaches."); - } - return userDetailsService; - } + /** + * Gets the {@link UserDetailsService} to use. Either the explicitly configure + * {@link UserDetailsService} from {@link #userDetailsService(UserDetailsService)} or + * a shared object from {@link HttpSecurity#getSharedObject(Class)}. + * + * @param http {@link HttpSecurity} to get the shared {@link UserDetailsService} + * @return the {@link UserDetailsService} to use + */ + private UserDetailsService getUserDetailsService(H http) { + if (userDetailsService == null) { + userDetailsService = http.getSharedObject(UserDetailsService.class); + } + if (userDetailsService == null) { + throw new IllegalStateException( + "userDetailsService cannot be null. Invoke " + + RememberMeConfigurer.class.getSimpleName() + + "#userDetailsService(UserDetailsService) or see its javadoc for alternative approaches."); + } + return userDetailsService; + } - /** - * Gets the key to use for validating remember me tokens. Either the value - * passed into {@link #key(String)}, or a secure random string if none was - * specified. - * - * @return the remember me key to use - */ - private String getKey() { - if (key == null) { - key = UUID.randomUUID().toString(); - } - return key; - } + /** + * Gets the key to use for validating remember me tokens. Either the value passed into + * {@link #key(String)}, or a secure random string if none was specified. + * + * @return the remember me key to use + */ + private String getKey() { + if (key == null) { + key = UUID.randomUUID().toString(); + } + return key; + } } \ No newline at end of file diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/RequestCacheConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/RequestCacheConfigurer.java index e6c252dfbf..b83c91af3f 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/RequestCacheConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/RequestCacheConfigurer.java @@ -35,11 +35,11 @@ import org.springframework.web.accept.ContentNegotiationStrategy; import org.springframework.web.accept.HeaderContentNegotiationStrategy; /** - * Adds request cache for Spring Security. Specifically this ensures that - * requests that are saved (i.e. after authentication is required) are later - * replayed. All properties have reasonable defaults, so no additional - * configuration is required other than applying this - * {@link org.springframework.security.config.annotation.SecurityConfigurer}. + * Adds request cache for Spring Security. Specifically this ensures that requests that + * are saved (i.e. after authentication is required) are later replayed. All properties + * have reasonable defaults, so no additional configuration is required other than + * applying this {@link org.springframework.security.config.annotation.SecurityConfigurer} + * . * *

Security Filters

* @@ -58,90 +58,96 @@ import org.springframework.web.accept.HeaderContentNegotiationStrategy; * The following shared objects are used: * *
    - *
  • If no explicit {@link RequestCache}, is provided a {@link RequestCache} - * shared object is used to replay the request after authentication is - * successful
  • + *
  • If no explicit {@link RequestCache}, is provided a {@link RequestCache} shared + * object is used to replay the request after authentication is successful
  • *
* * @author Rob Winch * @since 3.2 * @see RequestCache */ -public final class RequestCacheConfigurer> extends AbstractHttpConfigurer,H> { +public final class RequestCacheConfigurer> extends + AbstractHttpConfigurer, H> { - public RequestCacheConfigurer() { - } + public RequestCacheConfigurer() { + } - /** - * Allows explicit configuration of the {@link RequestCache} to be used. Defaults to try finding a - * {@link RequestCache} as a shared object. Then falls back to a {@link HttpSessionRequestCache}. - * - * @param requestCache the explicit {@link RequestCache} to use - * @return the {@link RequestCacheConfigurer} for further customization - */ - public RequestCacheConfigurer requestCache(RequestCache requestCache) { - getBuilder().setSharedObject(RequestCache.class, requestCache); - return this; - } + /** + * Allows explicit configuration of the {@link RequestCache} to be used. Defaults to + * try finding a {@link RequestCache} as a shared object. Then falls back to a + * {@link HttpSessionRequestCache}. + * + * @param requestCache the explicit {@link RequestCache} to use + * @return the {@link RequestCacheConfigurer} for further customization + */ + public RequestCacheConfigurer requestCache(RequestCache requestCache) { + getBuilder().setSharedObject(RequestCache.class, requestCache); + return this; + } - @Override - public void init(H http) throws Exception { - http.setSharedObject(RequestCache.class, getRequestCache(http)); - } + @Override + public void init(H http) throws Exception { + http.setSharedObject(RequestCache.class, getRequestCache(http)); + } - @Override - public void configure(H http) throws Exception { - RequestCache requestCache = getRequestCache(http); - RequestCacheAwareFilter requestCacheFilter = new RequestCacheAwareFilter(requestCache); - requestCacheFilter = postProcess(requestCacheFilter); - http.addFilter(requestCacheFilter); - } + @Override + public void configure(H http) throws Exception { + RequestCache requestCache = getRequestCache(http); + RequestCacheAwareFilter requestCacheFilter = new RequestCacheAwareFilter( + requestCache); + requestCacheFilter = postProcess(requestCacheFilter); + http.addFilter(requestCacheFilter); + } - /** - * Gets the {@link RequestCache} to use. If one is defined using - * {@link #requestCache(org.springframework.security.web.savedrequest.RequestCache)}, then it is used. Otherwise, an - * attempt to find a {@link RequestCache} shared object is made. If that fails, an {@link HttpSessionRequestCache} - * is used - * - * @param http the {@link HttpSecurity} to attempt to fined the shared object - * @return the {@link RequestCache} to use - */ - private RequestCache getRequestCache(H http) { - RequestCache result = http.getSharedObject(RequestCache.class); - if(result != null) { - return result; - } - HttpSessionRequestCache defaultCache = new HttpSessionRequestCache(); - defaultCache.setRequestMatcher(createDefaultSavedRequestMatcher(http)); - return defaultCache; - } + /** + * Gets the {@link RequestCache} to use. If one is defined using + * {@link #requestCache(org.springframework.security.web.savedrequest.RequestCache)}, + * then it is used. Otherwise, an attempt to find a {@link RequestCache} shared object + * is made. If that fails, an {@link HttpSessionRequestCache} is used + * + * @param http the {@link HttpSecurity} to attempt to fined the shared object + * @return the {@link RequestCache} to use + */ + private RequestCache getRequestCache(H http) { + RequestCache result = http.getSharedObject(RequestCache.class); + if (result != null) { + return result; + } + HttpSessionRequestCache defaultCache = new HttpSessionRequestCache(); + defaultCache.setRequestMatcher(createDefaultSavedRequestMatcher(http)); + return defaultCache; + } - @SuppressWarnings("unchecked") - private RequestMatcher createDefaultSavedRequestMatcher(H http) { - ContentNegotiationStrategy contentNegotiationStrategy = http.getSharedObject(ContentNegotiationStrategy.class); - if(contentNegotiationStrategy == null) { - contentNegotiationStrategy = new HeaderContentNegotiationStrategy(); - } + @SuppressWarnings("unchecked") + private RequestMatcher createDefaultSavedRequestMatcher(H http) { + ContentNegotiationStrategy contentNegotiationStrategy = http + .getSharedObject(ContentNegotiationStrategy.class); + if (contentNegotiationStrategy == null) { + contentNegotiationStrategy = new HeaderContentNegotiationStrategy(); + } - RequestMatcher notFavIcon = new NegatedRequestMatcher(new AntPathRequestMatcher("/**/favicon.ico")); + RequestMatcher notFavIcon = new NegatedRequestMatcher(new AntPathRequestMatcher( + "/**/favicon.ico")); - MediaTypeRequestMatcher jsonRequest = new MediaTypeRequestMatcher(contentNegotiationStrategy, MediaType.APPLICATION_JSON); - jsonRequest.setIgnoredMediaTypes(Collections.singleton(MediaType.ALL)); - RequestMatcher notJson = new NegatedRequestMatcher(jsonRequest); + MediaTypeRequestMatcher jsonRequest = new MediaTypeRequestMatcher( + contentNegotiationStrategy, MediaType.APPLICATION_JSON); + jsonRequest.setIgnoredMediaTypes(Collections.singleton(MediaType.ALL)); + RequestMatcher notJson = new NegatedRequestMatcher(jsonRequest); - RequestMatcher notXRequestedWith = new NegatedRequestMatcher(new RequestHeaderRequestMatcher("X-Requested-With","XMLHttpRequest")); + RequestMatcher notXRequestedWith = new NegatedRequestMatcher( + new RequestHeaderRequestMatcher("X-Requested-With", "XMLHttpRequest")); - boolean isCsrfEnabled = http.getConfigurer(CsrfConfigurer.class) != null; + boolean isCsrfEnabled = http.getConfigurer(CsrfConfigurer.class) != null; - List matchers = new ArrayList(); - if(isCsrfEnabled) { - RequestMatcher getRequests = new AntPathRequestMatcher("/**", "GET"); - matchers.add(0, getRequests); - } - matchers.add(notFavIcon); - matchers.add(notJson); - matchers.add(notXRequestedWith); + List matchers = new ArrayList(); + if (isCsrfEnabled) { + RequestMatcher getRequests = new AntPathRequestMatcher("/**", "GET"); + matchers.add(0, getRequests); + } + matchers.add(notFavIcon); + matchers.add(notJson); + matchers.add(notXRequestedWith); - return new AndRequestMatcher(matchers); - } + return new AndRequestMatcher(matchers); + } } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/SecurityContextConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/SecurityContextConfigurer.java index 483a6e995c..e90832fb44 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/SecurityContextConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/SecurityContextConfigurer.java @@ -26,8 +26,8 @@ import org.springframework.security.web.context.SecurityContextRepository; /** * Allows persisting and restoring of the {@link SecurityContext} found on the * {@link SecurityContextHolder} for each request by configuring the - * {@link SecurityContextPersistenceFilter}. All properties have reasonable - * defaults, so no additional configuration is required other than applying this + * {@link SecurityContextPersistenceFilter}. All properties have reasonable defaults, so + * no additional configuration is required other than applying this * {@link org.springframework.security.config.annotation.SecurityConfigurer}. * *

Security Filters

@@ -47,10 +47,9 @@ import org.springframework.security.web.context.SecurityContextRepository; * The following shared objects are used: * *
    - *
  • If {@link SessionManagementConfigurer}, is provided and set to always, - * then the - * {@link SecurityContextPersistenceFilter#setForceEagerSessionCreation(boolean)} - * will be set to true.
  • + *
  • If {@link SessionManagementConfigurer}, is provided and set to always, then the + * {@link SecurityContextPersistenceFilter#setForceEagerSessionCreation(boolean)} will be + * set to true.
  • *
  • {@link SecurityContextRepository} must be set and is used on * {@link SecurityContextPersistenceFilter}.
  • *
@@ -58,39 +57,44 @@ import org.springframework.security.web.context.SecurityContextRepository; * @author Rob Winch * @since 3.2 */ -public final class SecurityContextConfigurer> extends AbstractHttpConfigurer,H> { +public final class SecurityContextConfigurer> extends + AbstractHttpConfigurer, H> { - /** - * Creates a new instance - * @see HttpSecurity#securityContext() - */ - public SecurityContextConfigurer() { - } + /** + * Creates a new instance + * @see HttpSecurity#securityContext() + */ + public SecurityContextConfigurer() { + } - /** - * Specifies the shared {@link SecurityContextRepository} that is to be used - * @param securityContextRepository the {@link SecurityContextRepository} to use - * @return the {@link HttpSecurity} for further customizations - */ - public SecurityContextConfigurer securityContextRepository(SecurityContextRepository securityContextRepository) { - getBuilder().setSharedObject(SecurityContextRepository.class, securityContextRepository); - return this; - } + /** + * Specifies the shared {@link SecurityContextRepository} that is to be used + * @param securityContextRepository the {@link SecurityContextRepository} to use + * @return the {@link HttpSecurity} for further customizations + */ + public SecurityContextConfigurer securityContextRepository( + SecurityContextRepository securityContextRepository) { + getBuilder().setSharedObject(SecurityContextRepository.class, + securityContextRepository); + return this; + } - @Override - @SuppressWarnings("unchecked") - public void configure(H http) throws Exception { + @Override + @SuppressWarnings("unchecked") + public void configure(H http) throws Exception { - SecurityContextRepository securityContextRepository = http.getSharedObject(SecurityContextRepository.class); - SecurityContextPersistenceFilter securityContextFilter = new SecurityContextPersistenceFilter( - securityContextRepository); - SessionManagementConfigurer sessionManagement = http.getConfigurer(SessionManagementConfigurer.class); - SessionCreationPolicy sessionCreationPolicy = sessionManagement == null ? null - : sessionManagement.getSessionCreationPolicy(); - if (SessionCreationPolicy.ALWAYS == sessionCreationPolicy) { - securityContextFilter.setForceEagerSessionCreation(true); - } - securityContextFilter = postProcess(securityContextFilter); - http.addFilter(securityContextFilter); - } + SecurityContextRepository securityContextRepository = http + .getSharedObject(SecurityContextRepository.class); + SecurityContextPersistenceFilter securityContextFilter = new SecurityContextPersistenceFilter( + securityContextRepository); + SessionManagementConfigurer sessionManagement = http + .getConfigurer(SessionManagementConfigurer.class); + SessionCreationPolicy sessionCreationPolicy = sessionManagement == null ? null + : sessionManagement.getSessionCreationPolicy(); + if (SessionCreationPolicy.ALWAYS == sessionCreationPolicy) { + securityContextFilter.setForceEagerSessionCreation(true); + } + securityContextFilter = postProcess(securityContextFilter); + http.addFilter(securityContextFilter); + } } \ No newline at end of file diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/ServletApiConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/ServletApiConfigurer.java index 9ffcd7b570..9dc3abf13e 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/ServletApiConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/ServletApiConfigurer.java @@ -30,7 +30,8 @@ import org.springframework.security.web.authentication.logout.LogoutHandler; import org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter; /** - * Implements select methods from the {@link HttpServletRequest} using the {@link SecurityContext} from the {@link SecurityContextHolder}. + * Implements select methods from the {@link HttpServletRequest} using the + * {@link SecurityContext} from the {@link SecurityContextHolder}. * *

Security Filters

* @@ -47,42 +48,50 @@ import org.springframework.security.web.servletapi.SecurityContextHolderAwareReq *

Shared Objects Used

* *
    - *
  • {@link AuthenticationTrustResolver} is optionally used to populate the {@link SecurityContextHolderAwareRequestFilter}
  • + *
  • {@link AuthenticationTrustResolver} is optionally used to populate the + * {@link SecurityContextHolderAwareRequestFilter}
  • *
* * @author Rob Winch * @since 3.2 */ -public final class ServletApiConfigurer> extends AbstractHttpConfigurer,H> { - private SecurityContextHolderAwareRequestFilter securityContextRequestFilter = new SecurityContextHolderAwareRequestFilter(); +public final class ServletApiConfigurer> extends + AbstractHttpConfigurer, H> { + private SecurityContextHolderAwareRequestFilter securityContextRequestFilter = new SecurityContextHolderAwareRequestFilter(); - /** - * Creates a new instance - * @see HttpSecurity#servletApi() - */ - public ServletApiConfigurer() { - } + /** + * Creates a new instance + * @see HttpSecurity#servletApi() + */ + public ServletApiConfigurer() { + } - public ServletApiConfigurer rolePrefix(String rolePrefix) { - securityContextRequestFilter.setRolePrefix(rolePrefix); - return this; - } + public ServletApiConfigurer rolePrefix(String rolePrefix) { + securityContextRequestFilter.setRolePrefix(rolePrefix); + return this; + } - @Override - @SuppressWarnings("unchecked") - public void configure(H http) throws Exception { - securityContextRequestFilter.setAuthenticationManager(http.getSharedObject(AuthenticationManager.class)); - ExceptionHandlingConfigurer exceptionConf = http.getConfigurer(ExceptionHandlingConfigurer.class); - AuthenticationEntryPoint authenticationEntryPoint = exceptionConf == null ? null : exceptionConf.getAuthenticationEntryPoint(http); - securityContextRequestFilter.setAuthenticationEntryPoint(authenticationEntryPoint); - LogoutConfigurer logoutConf = http.getConfigurer(LogoutConfigurer.class); - List logoutHandlers = logoutConf == null ? null : logoutConf.getLogoutHandlers(); - securityContextRequestFilter.setLogoutHandlers(logoutHandlers); - AuthenticationTrustResolver trustResolver = http.getSharedObject(AuthenticationTrustResolver.class); - if(trustResolver != null) { - securityContextRequestFilter.setTrustResolver(trustResolver); - } - securityContextRequestFilter = postProcess(securityContextRequestFilter); - http.addFilter(securityContextRequestFilter); - } + @Override + @SuppressWarnings("unchecked") + public void configure(H http) throws Exception { + securityContextRequestFilter.setAuthenticationManager(http + .getSharedObject(AuthenticationManager.class)); + ExceptionHandlingConfigurer exceptionConf = http + .getConfigurer(ExceptionHandlingConfigurer.class); + AuthenticationEntryPoint authenticationEntryPoint = exceptionConf == null ? null + : exceptionConf.getAuthenticationEntryPoint(http); + securityContextRequestFilter + .setAuthenticationEntryPoint(authenticationEntryPoint); + LogoutConfigurer logoutConf = http.getConfigurer(LogoutConfigurer.class); + List logoutHandlers = logoutConf == null ? null : logoutConf + .getLogoutHandlers(); + securityContextRequestFilter.setLogoutHandlers(logoutHandlers); + AuthenticationTrustResolver trustResolver = http + .getSharedObject(AuthenticationTrustResolver.class); + if (trustResolver != null) { + securityContextRequestFilter.setTrustResolver(trustResolver); + } + securityContextRequestFilter = postProcess(securityContextRequestFilter); + http.addFilter(securityContextRequestFilter); + } } \ No newline at end of file diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurer.java index 7098eb2d79..a711ac7f81 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurer.java @@ -61,7 +61,8 @@ import org.springframework.util.Assert; * *
    *
  • {@link SessionManagementFilter}
  • - *
  • {@link ConcurrentSessionFilter} if there are restrictions on how many concurrent sessions a user can have
  • + *
  • {@link ConcurrentSessionFilter} if there are restrictions on how many concurrent + * sessions a user can have
  • *
* *

Shared Objects Created

@@ -79,7 +80,8 @@ import org.springframework.util.Assert; * *
    *
  • {@link SecurityContextRepository}
  • - *
  • {@link AuthenticationTrustResolver} is optionally used to populate the {@link HttpSessionSecurityContextRepository} and {@link SessionManagementFilter}
  • + *
  • {@link AuthenticationTrustResolver} is optionally used to populate the + * {@link HttpSessionSecurityContextRepository} and {@link SessionManagementFilter}
  • *
* * @author Rob Winch @@ -87,430 +89,459 @@ import org.springframework.util.Assert; * @see SessionManagementFilter * @see ConcurrentSessionFilter */ -public final class SessionManagementConfigurer> extends AbstractHttpConfigurer,H> { - private SessionAuthenticationStrategy sessionFixationAuthenticationStrategy = createDefaultSessionFixationProtectionStrategy(); - private SessionAuthenticationStrategy sessionAuthenticationStrategy; - private InvalidSessionStrategy invalidSessionStrategy; - private List sessionAuthenticationStrategies = new ArrayList(); - private SessionRegistry sessionRegistry; - private Integer maximumSessions; - private String expiredUrl; - private boolean maxSessionsPreventsLogin; - private SessionCreationPolicy sessionPolicy = SessionCreationPolicy.IF_REQUIRED; - private boolean enableSessionUrlRewriting; - private String invalidSessionUrl; - private String sessionAuthenticationErrorUrl; +public final class SessionManagementConfigurer> extends + AbstractHttpConfigurer, H> { + private SessionAuthenticationStrategy sessionFixationAuthenticationStrategy = createDefaultSessionFixationProtectionStrategy(); + private SessionAuthenticationStrategy sessionAuthenticationStrategy; + private InvalidSessionStrategy invalidSessionStrategy; + private List sessionAuthenticationStrategies = new ArrayList(); + private SessionRegistry sessionRegistry; + private Integer maximumSessions; + private String expiredUrl; + private boolean maxSessionsPreventsLogin; + private SessionCreationPolicy sessionPolicy = SessionCreationPolicy.IF_REQUIRED; + private boolean enableSessionUrlRewriting; + private String invalidSessionUrl; + private String sessionAuthenticationErrorUrl; - /** - * Creates a new instance - * @see HttpSecurity#sessionManagement() - */ - public SessionManagementConfigurer() { - } + /** + * Creates a new instance + * @see HttpSecurity#sessionManagement() + */ + public SessionManagementConfigurer() { + } - /** - * Setting this attribute will inject the {@link SessionManagementFilter} with a - * {@link SimpleRedirectInvalidSessionStrategy} configured with the attribute value. - * When an invalid session ID is submitted, the strategy will be invoked, - * redirecting to the configured URL. - * - * @param invalidSessionUrl the URL to redirect to when an invalid session is detected - * @return the {@link SessionManagementConfigurer} for further customization - */ - public SessionManagementConfigurer invalidSessionUrl(String invalidSessionUrl) { - this.invalidSessionUrl = invalidSessionUrl; - return this; - } + /** + * Setting this attribute will inject the {@link SessionManagementFilter} with a + * {@link SimpleRedirectInvalidSessionStrategy} configured with the attribute value. + * When an invalid session ID is submitted, the strategy will be invoked, redirecting + * to the configured URL. + * + * @param invalidSessionUrl the URL to redirect to when an invalid session is detected + * @return the {@link SessionManagementConfigurer} for further customization + */ + public SessionManagementConfigurer invalidSessionUrl(String invalidSessionUrl) { + this.invalidSessionUrl = invalidSessionUrl; + return this; + } - /** - * Defines the URL of the error page which should be shown when the - * SessionAuthenticationStrategy raises an exception. If not set, an - * unauthorized (402) error code will be returned to the client. Note that - * this attribute doesn't apply if the error occurs during a form-based - * login, where the URL for authentication failure will take precedence. - * - * @param sessionAuthenticationErrorUrl - * the URL to redirect to - * @return the {@link SessionManagementConfigurer} for further customization - */ - public SessionManagementConfigurer sessionAuthenticationErrorUrl(String sessionAuthenticationErrorUrl) { - this.sessionAuthenticationErrorUrl = sessionAuthenticationErrorUrl; - return this; - } + /** + * Defines the URL of the error page which should be shown when the + * SessionAuthenticationStrategy raises an exception. If not set, an unauthorized + * (402) error code will be returned to the client. Note that this attribute doesn't + * apply if the error occurs during a form-based login, where the URL for + * authentication failure will take precedence. + * + * @param sessionAuthenticationErrorUrl the URL to redirect to + * @return the {@link SessionManagementConfigurer} for further customization + */ + public SessionManagementConfigurer sessionAuthenticationErrorUrl( + String sessionAuthenticationErrorUrl) { + this.sessionAuthenticationErrorUrl = sessionAuthenticationErrorUrl; + return this; + } - /** - * If set to true, allows HTTP sessions to be rewritten in the URLs when - * using {@link HttpServletResponse#encodeRedirectURL(String)} or - * {@link HttpServletResponse#encodeURL(String)}, otherwise disallows HTTP - * sessions to be included in the URL. This prevents leaking information to - * external domains. - * - * @param enableSessionUrlRewriting true if should allow the JSESSIONID to be rewritten into the URLs, else false (default) - * @return the {@link SessionManagementConfigurer} for further customization - * @see HttpSessionSecurityContextRepository#setDisableUrlRewriting(boolean) - */ - public SessionManagementConfigurer enableSessionUrlRewriting(boolean enableSessionUrlRewriting) { - this.enableSessionUrlRewriting = enableSessionUrlRewriting; - return this; - } + /** + * If set to true, allows HTTP sessions to be rewritten in the URLs when using + * {@link HttpServletResponse#encodeRedirectURL(String)} or + * {@link HttpServletResponse#encodeURL(String)}, otherwise disallows HTTP sessions to + * be included in the URL. This prevents leaking information to external domains. + * + * @param enableSessionUrlRewriting true if should allow the JSESSIONID to be + * rewritten into the URLs, else false (default) + * @return the {@link SessionManagementConfigurer} for further customization + * @see HttpSessionSecurityContextRepository#setDisableUrlRewriting(boolean) + */ + public SessionManagementConfigurer enableSessionUrlRewriting( + boolean enableSessionUrlRewriting) { + this.enableSessionUrlRewriting = enableSessionUrlRewriting; + return this; + } - /** - * Allows specifying the {@link SessionCreationPolicy} - * @param sessionCreationPolicy the {@link SessionCreationPolicy} to use. Cannot be null. - * @return the {@link SessionManagementConfigurer} for further customizations - * @see SessionCreationPolicy - * @throws IllegalArgumentException if {@link SessionCreationPolicy} is null. - */ - public SessionManagementConfigurer sessionCreationPolicy(SessionCreationPolicy sessionCreationPolicy) { - Assert.notNull(sessionCreationPolicy, "sessionCreationPolicy cannot be null"); - this.sessionPolicy = sessionCreationPolicy; - return this; - } + /** + * Allows specifying the {@link SessionCreationPolicy} + * @param sessionCreationPolicy the {@link SessionCreationPolicy} to use. Cannot be + * null. + * @return the {@link SessionManagementConfigurer} for further customizations + * @see SessionCreationPolicy + * @throws IllegalArgumentException if {@link SessionCreationPolicy} is null. + */ + public SessionManagementConfigurer sessionCreationPolicy( + SessionCreationPolicy sessionCreationPolicy) { + Assert.notNull(sessionCreationPolicy, "sessionCreationPolicy cannot be null"); + this.sessionPolicy = sessionCreationPolicy; + return this; + } - /** - * Allows explicitly specifying the {@link SessionAuthenticationStrategy}. - * The default is to use {@link SessionFixationProtectionStrategy}. If - * restricting the maximum number of sessions is configured, then - * {@link CompositeSessionAuthenticationStrategy} delegating to - * {@link ConcurrentSessionControlAuthenticationStrategy}, - * {@link SessionFixationProtectionStrategy} (optional), and - * {@link RegisterSessionAuthenticationStrategy} will be used. - * - * @param sessionAuthenticationStrategy - * @return the {@link SessionManagementConfigurer} for further - * customizations - */ - public SessionManagementConfigurer sessionAuthenticationStrategy(SessionAuthenticationStrategy sessionAuthenticationStrategy) { - this.sessionFixationAuthenticationStrategy = sessionAuthenticationStrategy; - return this; - } + /** + * Allows explicitly specifying the {@link SessionAuthenticationStrategy}. The default + * is to use {@link SessionFixationProtectionStrategy}. If restricting the maximum + * number of sessions is configured, then + * {@link CompositeSessionAuthenticationStrategy} delegating to + * {@link ConcurrentSessionControlAuthenticationStrategy}, + * {@link SessionFixationProtectionStrategy} (optional), and + * {@link RegisterSessionAuthenticationStrategy} will be used. + * + * @param sessionAuthenticationStrategy + * @return the {@link SessionManagementConfigurer} for further customizations + */ + public SessionManagementConfigurer sessionAuthenticationStrategy( + SessionAuthenticationStrategy sessionAuthenticationStrategy) { + this.sessionFixationAuthenticationStrategy = sessionAuthenticationStrategy; + return this; + } - /** - * Adds an additional {@link SessionAuthenticationStrategy} to be used within the {@link CompositeSessionAuthenticationStrategy}. - * - * @param sessionAuthenticationStrategy - * @return the {@link SessionManagementConfigurer} for further - * customizations - */ - SessionManagementConfigurer addSessionAuthenticationStrategy(SessionAuthenticationStrategy sessionAuthenticationStrategy) { - this.sessionAuthenticationStrategies.add(sessionAuthenticationStrategy); - return this; - } + /** + * Adds an additional {@link SessionAuthenticationStrategy} to be used within the + * {@link CompositeSessionAuthenticationStrategy}. + * + * @param sessionAuthenticationStrategy + * @return the {@link SessionManagementConfigurer} for further customizations + */ + SessionManagementConfigurer addSessionAuthenticationStrategy( + SessionAuthenticationStrategy sessionAuthenticationStrategy) { + this.sessionAuthenticationStrategies.add(sessionAuthenticationStrategy); + return this; + } - public SessionFixationConfigurer sessionFixation() { - return new SessionFixationConfigurer(); - } + public SessionFixationConfigurer sessionFixation() { + return new SessionFixationConfigurer(); + } - /** - * Controls the maximum number of sessions for a user. The default is to allow any number of users. - * @param maximumSessions the maximum number of sessions for a user - * @return the {@link SessionManagementConfigurer} for further customizations - */ - public ConcurrencyControlConfigurer maximumSessions(int maximumSessions) { - this.maximumSessions = maximumSessions; - return new ConcurrencyControlConfigurer(); - } + /** + * Controls the maximum number of sessions for a user. The default is to allow any + * number of users. + * @param maximumSessions the maximum number of sessions for a user + * @return the {@link SessionManagementConfigurer} for further customizations + */ + public ConcurrencyControlConfigurer maximumSessions(int maximumSessions) { + this.maximumSessions = maximumSessions; + return new ConcurrencyControlConfigurer(); + } - /** - * Invokes {@link #postProcess(Object)} and sets the {@link SessionAuthenticationStrategy} for session fixation. - * @param sessionFixationAuthenticationStrategy - */ - private void setSessionFixationAuthenticationStrategy(SessionAuthenticationStrategy sessionFixationAuthenticationStrategy) { - this.sessionFixationAuthenticationStrategy = postProcess(sessionFixationAuthenticationStrategy); - } + /** + * Invokes {@link #postProcess(Object)} and sets the + * {@link SessionAuthenticationStrategy} for session fixation. + * @param sessionFixationAuthenticationStrategy + */ + private void setSessionFixationAuthenticationStrategy( + SessionAuthenticationStrategy sessionFixationAuthenticationStrategy) { + this.sessionFixationAuthenticationStrategy = postProcess(sessionFixationAuthenticationStrategy); + } - /** - * Allows configuring SessionFixation protection - * - * @author Rob Winch - */ - public final class SessionFixationConfigurer { - /** - * Specifies that a new session should be created, but the session - * attributes from the original {@link HttpSession} should not be - * retained. - * - * @return the {@link SessionManagementConfigurer} for further customizations - */ - public SessionManagementConfigurer newSession() { - SessionFixationProtectionStrategy sessionFixationProtectionStrategy = new SessionFixationProtectionStrategy(); - sessionFixationProtectionStrategy.setMigrateSessionAttributes(false); - setSessionFixationAuthenticationStrategy(sessionFixationProtectionStrategy); - return SessionManagementConfigurer.this; - } + /** + * Allows configuring SessionFixation protection + * + * @author Rob Winch + */ + public final class SessionFixationConfigurer { + /** + * Specifies that a new session should be created, but the session attributes from + * the original {@link HttpSession} should not be retained. + * + * @return the {@link SessionManagementConfigurer} for further customizations + */ + public SessionManagementConfigurer newSession() { + SessionFixationProtectionStrategy sessionFixationProtectionStrategy = new SessionFixationProtectionStrategy(); + sessionFixationProtectionStrategy.setMigrateSessionAttributes(false); + setSessionFixationAuthenticationStrategy(sessionFixationProtectionStrategy); + return SessionManagementConfigurer.this; + } - /** - * Specifies that a new session should be created and the session - * attributes from the original {@link HttpSession} should be - * retained. - * - * @return the {@link SessionManagementConfigurer} for further customizations - */ - public SessionManagementConfigurer migrateSession() { - setSessionFixationAuthenticationStrategy(new SessionFixationProtectionStrategy()); - return SessionManagementConfigurer.this; - } + /** + * Specifies that a new session should be created and the session attributes from + * the original {@link HttpSession} should be retained. + * + * @return the {@link SessionManagementConfigurer} for further customizations + */ + public SessionManagementConfigurer migrateSession() { + setSessionFixationAuthenticationStrategy(new SessionFixationProtectionStrategy()); + return SessionManagementConfigurer.this; + } - /** - * Specifies that the Servlet container-provided session fixation - * protection should be used. When a session authenticates, the - * Servlet 3.1 method {@code HttpServletRequest#changeSessionId()} is - * called to change the session ID and retain all session attributes. - * Using this option in a Servlet 3.0 or older container results in an - * {@link IllegalStateException}. - * - * @return the {@link SessionManagementConfigurer} for further - * customizations - * @throws IllegalStateException if the container is not Servlet 3.1 or - * newer. - */ - public SessionManagementConfigurer changeSessionId() { - setSessionFixationAuthenticationStrategy(new ChangeSessionIdAuthenticationStrategy()); - return SessionManagementConfigurer.this; - } + /** + * Specifies that the Servlet container-provided session fixation protection + * should be used. When a session authenticates, the Servlet 3.1 method + * {@code HttpServletRequest#changeSessionId()} is called to change the session ID + * and retain all session attributes. Using this option in a Servlet 3.0 or older + * container results in an {@link IllegalStateException}. + * + * @return the {@link SessionManagementConfigurer} for further customizations + * @throws IllegalStateException if the container is not Servlet 3.1 or newer. + */ + public SessionManagementConfigurer changeSessionId() { + setSessionFixationAuthenticationStrategy(new ChangeSessionIdAuthenticationStrategy()); + return SessionManagementConfigurer.this; + } - /** - * Specifies that no session fixation protection should be enabled. This - * may be useful when utilizing other mechanisms for protecting against - * session fixation. For example, if application container session - * fixation protection is already in use. Otherwise, this option is not - * recommended. - * - * @return the {@link SessionManagementConfigurer} for further - * customizations - */ - public SessionManagementConfigurer none() { - setSessionFixationAuthenticationStrategy(new NullAuthenticatedSessionStrategy()); - return SessionManagementConfigurer.this; - } - } + /** + * Specifies that no session fixation protection should be enabled. This may be + * useful when utilizing other mechanisms for protecting against session fixation. + * For example, if application container session fixation protection is already in + * use. Otherwise, this option is not recommended. + * + * @return the {@link SessionManagementConfigurer} for further customizations + */ + public SessionManagementConfigurer none() { + setSessionFixationAuthenticationStrategy(new NullAuthenticatedSessionStrategy()); + return SessionManagementConfigurer.this; + } + } - /** - * Allows configuring controlling of multiple sessions. - * - * @author Rob Winch - */ - public final class ConcurrencyControlConfigurer { + /** + * Allows configuring controlling of multiple sessions. + * + * @author Rob Winch + */ + public final class ConcurrencyControlConfigurer { - /** - * The URL to redirect to if a user tries to access a resource and their - * session has been expired due to too many sessions for the current user. - * The default is to write a simple error message to the response. - * - * @param expiredUrl the URL to redirect to - * @return the {@link ConcurrencyControlConfigurer} for further customizations - */ - public ConcurrencyControlConfigurer expiredUrl(String expiredUrl) { - SessionManagementConfigurer.this.expiredUrl = expiredUrl; - return this; - } + /** + * The URL to redirect to if a user tries to access a resource and their session + * has been expired due to too many sessions for the current user. The default is + * to write a simple error message to the response. + * + * @param expiredUrl the URL to redirect to + * @return the {@link ConcurrencyControlConfigurer} for further customizations + */ + public ConcurrencyControlConfigurer expiredUrl(String expiredUrl) { + SessionManagementConfigurer.this.expiredUrl = expiredUrl; + return this; + } - /** - * If true, prevents a user from authenticating when the - * {@link #maximumSessions(int)} has been reached. Otherwise (default), the user who - * authenticates is allowed access and an existing user's session is - * expired. The user's who's session is forcibly expired is sent to - * {@link #expiredUrl(String)}. The advantage of this approach is if a user - * accidentally does not log out, there is no need for an administrator to - * intervene or wait till their session expires. - * - * @param maxSessionsPreventsLogin true to have an error at time of authentication, else false (default) - * @return the {@link ConcurrencyControlConfigurer} for further customizations - */ - public ConcurrencyControlConfigurer maxSessionsPreventsLogin(boolean maxSessionsPreventsLogin) { - SessionManagementConfigurer.this.maxSessionsPreventsLogin = maxSessionsPreventsLogin; - return this; - } + /** + * If true, prevents a user from authenticating when the + * {@link #maximumSessions(int)} has been reached. Otherwise (default), the user + * who authenticates is allowed access and an existing user's session is expired. + * The user's who's session is forcibly expired is sent to + * {@link #expiredUrl(String)}. The advantage of this approach is if a user + * accidentally does not log out, there is no need for an administrator to + * intervene or wait till their session expires. + * + * @param maxSessionsPreventsLogin true to have an error at time of + * authentication, else false (default) + * @return the {@link ConcurrencyControlConfigurer} for further customizations + */ + public ConcurrencyControlConfigurer maxSessionsPreventsLogin( + boolean maxSessionsPreventsLogin) { + SessionManagementConfigurer.this.maxSessionsPreventsLogin = maxSessionsPreventsLogin; + return this; + } - /** - * Controls the {@link SessionRegistry} implementation used. The default - * is {@link SessionRegistryImpl} which is an in memory implementation. - * - * @param sessionRegistry the {@link SessionRegistry} to use - * @return the {@link ConcurrencyControlConfigurer} for further customizations - */ - public ConcurrencyControlConfigurer sessionRegistry(SessionRegistry sessionRegistry) { - SessionManagementConfigurer.this.sessionRegistry = sessionRegistry; - return this; - } + /** + * Controls the {@link SessionRegistry} implementation used. The default is + * {@link SessionRegistryImpl} which is an in memory implementation. + * + * @param sessionRegistry the {@link SessionRegistry} to use + * @return the {@link ConcurrencyControlConfigurer} for further customizations + */ + public ConcurrencyControlConfigurer sessionRegistry( + SessionRegistry sessionRegistry) { + SessionManagementConfigurer.this.sessionRegistry = sessionRegistry; + return this; + } - /** - * Used to chain back to the {@link SessionManagementConfigurer} - * - * @return the {@link SessionManagementConfigurer} for further customizations - */ - public SessionManagementConfigurer and() { - return SessionManagementConfigurer.this; - } + /** + * Used to chain back to the {@link SessionManagementConfigurer} + * + * @return the {@link SessionManagementConfigurer} for further customizations + */ + public SessionManagementConfigurer and() { + return SessionManagementConfigurer.this; + } - private ConcurrencyControlConfigurer() {} - } + private ConcurrencyControlConfigurer() { + } + } - @Override - public void init(H http) throws Exception { - SecurityContextRepository securityContextRepository = http.getSharedObject(SecurityContextRepository.class); - boolean stateless = isStateless(); + @Override + public void init(H http) throws Exception { + SecurityContextRepository securityContextRepository = http + .getSharedObject(SecurityContextRepository.class); + boolean stateless = isStateless(); - if(securityContextRepository == null) { - if(stateless) { - http.setSharedObject(SecurityContextRepository.class, new NullSecurityContextRepository()); - } else { - HttpSessionSecurityContextRepository httpSecurityRepository = new HttpSessionSecurityContextRepository(); - httpSecurityRepository.setDisableUrlRewriting(!enableSessionUrlRewriting); - httpSecurityRepository.setAllowSessionCreation(isAllowSessionCreation()); - AuthenticationTrustResolver trustResolver = http.getSharedObject(AuthenticationTrustResolver.class); - if(trustResolver != null) { - httpSecurityRepository.setTrustResolver(trustResolver); - } - http.setSharedObject(SecurityContextRepository.class, httpSecurityRepository); - } - } + if (securityContextRepository == null) { + if (stateless) { + http.setSharedObject(SecurityContextRepository.class, + new NullSecurityContextRepository()); + } + else { + HttpSessionSecurityContextRepository httpSecurityRepository = new HttpSessionSecurityContextRepository(); + httpSecurityRepository.setDisableUrlRewriting(!enableSessionUrlRewriting); + httpSecurityRepository.setAllowSessionCreation(isAllowSessionCreation()); + AuthenticationTrustResolver trustResolver = http + .getSharedObject(AuthenticationTrustResolver.class); + if (trustResolver != null) { + httpSecurityRepository.setTrustResolver(trustResolver); + } + http.setSharedObject(SecurityContextRepository.class, + httpSecurityRepository); + } + } - RequestCache requestCache = http.getSharedObject(RequestCache.class); - if(requestCache == null) { - if(stateless) { - http.setSharedObject(RequestCache.class, new NullRequestCache()); - } - } - http.setSharedObject(SessionAuthenticationStrategy.class, getSessionAuthenticationStrategy(http)); - http.setSharedObject(InvalidSessionStrategy.class, getInvalidSessionStrategy()); - } + RequestCache requestCache = http.getSharedObject(RequestCache.class); + if (requestCache == null) { + if (stateless) { + http.setSharedObject(RequestCache.class, new NullRequestCache()); + } + } + http.setSharedObject(SessionAuthenticationStrategy.class, + getSessionAuthenticationStrategy(http)); + http.setSharedObject(InvalidSessionStrategy.class, getInvalidSessionStrategy()); + } - @Override - public void configure(H http) throws Exception { - SecurityContextRepository securityContextRepository = http.getSharedObject(SecurityContextRepository.class); - SessionManagementFilter sessionManagementFilter = new SessionManagementFilter(securityContextRepository, getSessionAuthenticationStrategy(http)); - if(sessionAuthenticationErrorUrl != null) { - sessionManagementFilter.setAuthenticationFailureHandler(new SimpleUrlAuthenticationFailureHandler(sessionAuthenticationErrorUrl)); - } - if(invalidSessionUrl != null) { - sessionManagementFilter.setInvalidSessionStrategy(getInvalidSessionStrategy()); - } - AuthenticationTrustResolver trustResolver = http.getSharedObject(AuthenticationTrustResolver.class); - if(trustResolver != null) { - sessionManagementFilter.setTrustResolver(trustResolver); - } - sessionManagementFilter = postProcess(sessionManagementFilter); + @Override + public void configure(H http) throws Exception { + SecurityContextRepository securityContextRepository = http + .getSharedObject(SecurityContextRepository.class); + SessionManagementFilter sessionManagementFilter = new SessionManagementFilter( + securityContextRepository, getSessionAuthenticationStrategy(http)); + if (sessionAuthenticationErrorUrl != null) { + sessionManagementFilter + .setAuthenticationFailureHandler(new SimpleUrlAuthenticationFailureHandler( + sessionAuthenticationErrorUrl)); + } + if (invalidSessionUrl != null) { + sessionManagementFilter + .setInvalidSessionStrategy(getInvalidSessionStrategy()); + } + AuthenticationTrustResolver trustResolver = http + .getSharedObject(AuthenticationTrustResolver.class); + if (trustResolver != null) { + sessionManagementFilter.setTrustResolver(trustResolver); + } + sessionManagementFilter = postProcess(sessionManagementFilter); - http.addFilter(sessionManagementFilter); - if(isConcurrentSessionControlEnabled()) { - ConcurrentSessionFilter concurrentSessionFilter = new ConcurrentSessionFilter(getSessionRegistry(http), expiredUrl); - concurrentSessionFilter = postProcess(concurrentSessionFilter); - http.addFilter(concurrentSessionFilter); - } - } + http.addFilter(sessionManagementFilter); + if (isConcurrentSessionControlEnabled()) { + ConcurrentSessionFilter concurrentSessionFilter = new ConcurrentSessionFilter( + getSessionRegistry(http), expiredUrl); + concurrentSessionFilter = postProcess(concurrentSessionFilter); + http.addFilter(concurrentSessionFilter); + } + } - /** - * Gets the {@link InvalidSessionStrategy} to use. If - * {@link #invalidSessionUrl} is null, returns null otherwise - * {@link SimpleRedirectInvalidSessionStrategy} is used. - * - * @return the {@link InvalidSessionStrategy} to use - */ - InvalidSessionStrategy getInvalidSessionStrategy() { - if(invalidSessionUrl == null) { - return null; - } - if(invalidSessionStrategy == null) { - invalidSessionStrategy = new SimpleRedirectInvalidSessionStrategy(invalidSessionUrl); - } - return invalidSessionStrategy; - } + /** + * Gets the {@link InvalidSessionStrategy} to use. If {@link #invalidSessionUrl} is + * null, returns null otherwise {@link SimpleRedirectInvalidSessionStrategy} is used. + * + * @return the {@link InvalidSessionStrategy} to use + */ + InvalidSessionStrategy getInvalidSessionStrategy() { + if (invalidSessionUrl == null) { + return null; + } + if (invalidSessionStrategy == null) { + invalidSessionStrategy = new SimpleRedirectInvalidSessionStrategy( + invalidSessionUrl); + } + return invalidSessionStrategy; + } - /** - * Gets the {@link SessionCreationPolicy}. Can not be null. - * @return the {@link SessionCreationPolicy} - */ - SessionCreationPolicy getSessionCreationPolicy() { - return sessionPolicy; - } + /** + * Gets the {@link SessionCreationPolicy}. Can not be null. + * @return the {@link SessionCreationPolicy} + */ + SessionCreationPolicy getSessionCreationPolicy() { + return sessionPolicy; + } - /** - * Returns true if the {@link SessionCreationPolicy} allows session creation, else false - * @return true if the {@link SessionCreationPolicy} allows session creation - */ - private boolean isAllowSessionCreation() { - return SessionCreationPolicy.ALWAYS == sessionPolicy || SessionCreationPolicy.IF_REQUIRED == sessionPolicy; - } + /** + * Returns true if the {@link SessionCreationPolicy} allows session creation, else + * false + * @return true if the {@link SessionCreationPolicy} allows session creation + */ + private boolean isAllowSessionCreation() { + return SessionCreationPolicy.ALWAYS == sessionPolicy + || SessionCreationPolicy.IF_REQUIRED == sessionPolicy; + } - /** - * Returns true if the {@link SessionCreationPolicy} is stateless - * @return - */ - private boolean isStateless() { - return SessionCreationPolicy.STATELESS == sessionPolicy; - } + /** + * Returns true if the {@link SessionCreationPolicy} is stateless + * @return + */ + private boolean isStateless() { + return SessionCreationPolicy.STATELESS == sessionPolicy; + } - /** - * Gets the customized {@link SessionAuthenticationStrategy} if - * {@link #sessionAuthenticationStrategy(SessionAuthenticationStrategy)} was - * specified. Otherwise creates a default - * {@link SessionAuthenticationStrategy}. - * - * @return the {@link SessionAuthenticationStrategy} to use - */ - private SessionAuthenticationStrategy getSessionAuthenticationStrategy(H http) { - if(sessionAuthenticationStrategy != null) { - return sessionAuthenticationStrategy; - } - List delegateStrategies = sessionAuthenticationStrategies; - if(isConcurrentSessionControlEnabled()) { - SessionRegistry sessionRegistry = getSessionRegistry(http); - ConcurrentSessionControlAuthenticationStrategy concurrentSessionControlStrategy = new ConcurrentSessionControlAuthenticationStrategy(sessionRegistry); - concurrentSessionControlStrategy.setMaximumSessions(maximumSessions); - concurrentSessionControlStrategy.setExceptionIfMaximumExceeded(maxSessionsPreventsLogin); - concurrentSessionControlStrategy = postProcess(concurrentSessionControlStrategy); + /** + * Gets the customized {@link SessionAuthenticationStrategy} if + * {@link #sessionAuthenticationStrategy(SessionAuthenticationStrategy)} was + * specified. Otherwise creates a default {@link SessionAuthenticationStrategy}. + * + * @return the {@link SessionAuthenticationStrategy} to use + */ + private SessionAuthenticationStrategy getSessionAuthenticationStrategy(H http) { + if (sessionAuthenticationStrategy != null) { + return sessionAuthenticationStrategy; + } + List delegateStrategies = sessionAuthenticationStrategies; + if (isConcurrentSessionControlEnabled()) { + SessionRegistry sessionRegistry = getSessionRegistry(http); + ConcurrentSessionControlAuthenticationStrategy concurrentSessionControlStrategy = new ConcurrentSessionControlAuthenticationStrategy( + sessionRegistry); + concurrentSessionControlStrategy.setMaximumSessions(maximumSessions); + concurrentSessionControlStrategy + .setExceptionIfMaximumExceeded(maxSessionsPreventsLogin); + concurrentSessionControlStrategy = postProcess(concurrentSessionControlStrategy); - RegisterSessionAuthenticationStrategy registerSessionStrategy = new RegisterSessionAuthenticationStrategy(sessionRegistry); - registerSessionStrategy = postProcess(registerSessionStrategy); + RegisterSessionAuthenticationStrategy registerSessionStrategy = new RegisterSessionAuthenticationStrategy( + sessionRegistry); + registerSessionStrategy = postProcess(registerSessionStrategy); - delegateStrategies.addAll(Arrays.asList(concurrentSessionControlStrategy, sessionFixationAuthenticationStrategy, registerSessionStrategy)); - } else { - delegateStrategies.add(sessionFixationAuthenticationStrategy); - } - sessionAuthenticationStrategy = postProcess(new CompositeSessionAuthenticationStrategy(delegateStrategies)); - return sessionAuthenticationStrategy; - } + delegateStrategies.addAll(Arrays.asList(concurrentSessionControlStrategy, + sessionFixationAuthenticationStrategy, registerSessionStrategy)); + } + else { + delegateStrategies.add(sessionFixationAuthenticationStrategy); + } + sessionAuthenticationStrategy = postProcess(new CompositeSessionAuthenticationStrategy( + delegateStrategies)); + return sessionAuthenticationStrategy; + } - private SessionRegistry getSessionRegistry(H http) { - if(sessionRegistry == null) { - SessionRegistryImpl sessionRegistry = new SessionRegistryImpl(); - registerDelegateApplicationListener(http, sessionRegistry); - this.sessionRegistry = sessionRegistry; - } - return sessionRegistry; - } + private SessionRegistry getSessionRegistry(H http) { + if (sessionRegistry == null) { + SessionRegistryImpl sessionRegistry = new SessionRegistryImpl(); + registerDelegateApplicationListener(http, sessionRegistry); + this.sessionRegistry = sessionRegistry; + } + return sessionRegistry; + } - private void registerDelegateApplicationListener(H http, ApplicationListener delegate) { - ApplicationContext context = http.getSharedObject(ApplicationContext.class); - if(context == null) { - return; - } - if(context.getBeansOfType(DelegatingApplicationListener.class).isEmpty()) { - return; - } - DelegatingApplicationListener delegating = context.getBean(DelegatingApplicationListener.class); - SmartApplicationListener smartListener = new GenericApplicationListenerAdapter(delegate); - delegating.addListener(smartListener); - } + private void registerDelegateApplicationListener(H http, + ApplicationListener delegate) { + ApplicationContext context = http.getSharedObject(ApplicationContext.class); + if (context == null) { + return; + } + if (context.getBeansOfType(DelegatingApplicationListener.class).isEmpty()) { + return; + } + DelegatingApplicationListener delegating = context + .getBean(DelegatingApplicationListener.class); + SmartApplicationListener smartListener = new GenericApplicationListenerAdapter( + delegate); + delegating.addListener(smartListener); + } - /** - * Returns true if the number of concurrent sessions per user should be restricted. - * @return - */ - private boolean isConcurrentSessionControlEnabled() { - return maximumSessions != null; - } + /** + * Returns true if the number of concurrent sessions per user should be restricted. + * @return + */ + private boolean isConcurrentSessionControlEnabled() { + return maximumSessions != null; + } - /** - * Creates the default {@link SessionAuthenticationStrategy} for session fixation - * @return the default {@link SessionAuthenticationStrategy} for session fixation - */ - private static SessionAuthenticationStrategy createDefaultSessionFixationProtectionStrategy() { - try { - return new ChangeSessionIdAuthenticationStrategy(); - } catch(IllegalStateException e) { - return new SessionFixationProtectionStrategy(); - } - } + /** + * Creates the default {@link SessionAuthenticationStrategy} for session fixation + * @return the default {@link SessionAuthenticationStrategy} for session fixation + */ + private static SessionAuthenticationStrategy createDefaultSessionFixationProtectionStrategy() { + try { + return new ChangeSessionIdAuthenticationStrategy(); + } + catch (IllegalStateException e) { + return new SessionFixationProtectionStrategy(); + } + } } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/UrlAuthorizationConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/UrlAuthorizationConfigurer.java index dee4b374f8..8805ab44b9 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/UrlAuthorizationConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/UrlAuthorizationConfigurer.java @@ -33,26 +33,23 @@ import org.springframework.security.web.access.intercept.FilterInvocationSecurit import org.springframework.security.web.util.matcher.RequestMatcher; import org.springframework.util.Assert; - /** * Adds URL based authorization using * {@link DefaultFilterInvocationSecurityMetadataSource}. At least one - * {@link org.springframework.web.bind.annotation.RequestMapping} needs to be - * mapped to {@link ConfigAttribute}'s for this - * {@link SecurityContextConfigurer} to have meaning.

Security Filters

+ * {@link org.springframework.web.bind.annotation.RequestMapping} needs to be mapped to + * {@link ConfigAttribute}'s for this {@link SecurityContextConfigurer} to have meaning. + *

Security Filters

* *

- * Usage includes applying the {@link UrlAuthorizationConfigurer} and then - * modifying the StandardInterceptUrlRegistry. For example: + * Usage includes applying the {@link UrlAuthorizationConfigurer} and then modifying the + * StandardInterceptUrlRegistry. For example: *

* *
  * protected void configure(HttpSecurity http) throws Exception {
- *     http
- *          .apply(new UrlAuthorizationConfigurer()).getRegistry()
- *              .antMatchers("/users**","/sessions/**").hasRole("USER")
- *              .antMatchers("/signup").hasRole("ANONYMOUS")
- *              .anyRequest().hasRole("USER");
+ * 	http.apply(new UrlAuthorizationConfigurer<HttpSecurity>()).getRegistry()
+ * 			.antMatchers("/users**", "/sessions/**").hasRole("USER")
+ * 			.antMatchers("/signup").hasRole("ANONYMOUS").anyRequest().hasRole("USER");
  * }
  * 
* @@ -60,19 +57,17 @@ import org.springframework.util.Assert; * *
    *
  • - * {@link org.springframework.security.web.access.intercept.FilterSecurityInterceptor} - *
  • + * {@link org.springframework.security.web.access.intercept.FilterSecurityInterceptor} *
* *

Shared Objects Created

* * The following shared objects are populated to allow other - * {@link org.springframework.security.config.annotation.SecurityConfigurer}'s - * to customize: + * {@link org.springframework.security.config.annotation.SecurityConfigurer}'s to + * customize: *
    *
  • - * {@link org.springframework.security.web.access.intercept.FilterSecurityInterceptor} - *
  • + * {@link org.springframework.security.web.access.intercept.FilterSecurityInterceptor} *
* *

Shared Objects Used

@@ -81,226 +76,236 @@ import org.springframework.util.Assert; * *
    *
  • - * AuthenticationManager - *
  • + * AuthenticationManager *
* - * @param - * the type of {@link HttpSecurityBuilder} that is being configured + * @param the type of {@link HttpSecurityBuilder} that is being configured * * @author Rob Winch * @since 3.2 * @see ExpressionUrlAuthorizationConfigurer */ -public final class UrlAuthorizationConfigurer> extends AbstractInterceptUrlConfigurer,H> { - private final StandardInterceptUrlRegistry REGISTRY = new StandardInterceptUrlRegistry(); +public final class UrlAuthorizationConfigurer> extends + AbstractInterceptUrlConfigurer, H> { + private final StandardInterceptUrlRegistry REGISTRY = new StandardInterceptUrlRegistry(); - /** - * The StandardInterceptUrlRegistry is what users will interact with after - * applying the {@link UrlAuthorizationConfigurer}. - * - * @return - */ - public StandardInterceptUrlRegistry getRegistry() { - return REGISTRY; - } + /** + * The StandardInterceptUrlRegistry is what users will interact with after applying + * the {@link UrlAuthorizationConfigurer}. + * + * @return + */ + public StandardInterceptUrlRegistry getRegistry() { + return REGISTRY; + } - /** - * Adds an {@link ObjectPostProcessor} for this class. - * - * @param objectPostProcessor - * @return the {@link UrlAuthorizationConfigurer} for further customizations - */ - public UrlAuthorizationConfigurer withObjectPostProcessor(ObjectPostProcessor objectPostProcessor) { - addObjectPostProcessor(objectPostProcessor); - return this; - } + /** + * Adds an {@link ObjectPostProcessor} for this class. + * + * @param objectPostProcessor + * @return the {@link UrlAuthorizationConfigurer} for further customizations + */ + public UrlAuthorizationConfigurer withObjectPostProcessor( + ObjectPostProcessor objectPostProcessor) { + addObjectPostProcessor(objectPostProcessor); + return this; + } - public class StandardInterceptUrlRegistry extends ExpressionUrlAuthorizationConfigurer.AbstractInterceptUrlRegistry { + public class StandardInterceptUrlRegistry + extends + ExpressionUrlAuthorizationConfigurer.AbstractInterceptUrlRegistry { - @Override - protected final AuthorizedUrl chainRequestMatchersInternal(List requestMatchers) { - return new AuthorizedUrl(requestMatchers); - } + @Override + protected final AuthorizedUrl chainRequestMatchersInternal( + List requestMatchers) { + return new AuthorizedUrl(requestMatchers); + } - /** - * Adds an {@link ObjectPostProcessor} for this class. - * - * @param objectPostProcessor - * @return the {@link ExpressionUrlAuthorizationConfigurer} for further customizations - */ - public StandardInterceptUrlRegistry withObjectPostProcessor(ObjectPostProcessor objectPostProcessor) { - addObjectPostProcessor(objectPostProcessor); - return this; - } + /** + * Adds an {@link ObjectPostProcessor} for this class. + * + * @param objectPostProcessor + * @return the {@link ExpressionUrlAuthorizationConfigurer} for further + * customizations + */ + public StandardInterceptUrlRegistry withObjectPostProcessor( + ObjectPostProcessor objectPostProcessor) { + addObjectPostProcessor(objectPostProcessor); + return this; + } - public H and() { - return UrlAuthorizationConfigurer.this.and(); - } + public H and() { + return UrlAuthorizationConfigurer.this.and(); + } - } + } - /** - * Creates the default {@link AccessDecisionVoter} instances used if an - * {@link AccessDecisionManager} was not specified. - * - * @param http the builder to use - */ - @Override - @SuppressWarnings("rawtypes") - final List> getDecisionVoters(H http) { - List> decisionVoters = new ArrayList>(); - decisionVoters.add(new RoleVoter()); - decisionVoters.add(new AuthenticatedVoter()); - return decisionVoters; - } + /** + * Creates the default {@link AccessDecisionVoter} instances used if an + * {@link AccessDecisionManager} was not specified. + * + * @param http the builder to use + */ + @Override + @SuppressWarnings("rawtypes") + final List> getDecisionVoters(H http) { + List> decisionVoters = new ArrayList>(); + decisionVoters.add(new RoleVoter()); + decisionVoters.add(new AuthenticatedVoter()); + return decisionVoters; + } - /** - * Creates the {@link FilterInvocationSecurityMetadataSource} to use. The - * implementation is a {@link DefaultFilterInvocationSecurityMetadataSource}. - * - * @param http the builder to use - */ - @Override - FilterInvocationSecurityMetadataSource createMetadataSource(H http) { - return new DefaultFilterInvocationSecurityMetadataSource(REGISTRY.createRequestMap()); - } + /** + * Creates the {@link FilterInvocationSecurityMetadataSource} to use. The + * implementation is a {@link DefaultFilterInvocationSecurityMetadataSource}. + * + * @param http the builder to use + */ + @Override + FilterInvocationSecurityMetadataSource createMetadataSource(H http) { + return new DefaultFilterInvocationSecurityMetadataSource( + REGISTRY.createRequestMap()); + } - /** - * Adds a mapping of the {@link RequestMatcher} instances to the {@link ConfigAttribute} instances. - * @param requestMatchers the {@link RequestMatcher} instances that should map to the provided {@link ConfigAttribute} instances - * @param configAttributes the {@link ConfigAttribute} instances that should be mapped by the {@link RequestMatcher} instances - * @return the {@link UrlAuthorizationConfigurer} for further customizations - */ - private StandardInterceptUrlRegistry addMapping(Iterable requestMatchers, Collection configAttributes) { - for(RequestMatcher requestMatcher : requestMatchers) { - REGISTRY.addMapping(new AbstractConfigAttributeRequestMatcherRegistry.UrlMapping(requestMatcher, configAttributes)); - } - return REGISTRY; - } + /** + * Adds a mapping of the {@link RequestMatcher} instances to the + * {@link ConfigAttribute} instances. + * @param requestMatchers the {@link RequestMatcher} instances that should map to the + * provided {@link ConfigAttribute} instances + * @param configAttributes the {@link ConfigAttribute} instances that should be mapped + * by the {@link RequestMatcher} instances + * @return the {@link UrlAuthorizationConfigurer} for further customizations + */ + private StandardInterceptUrlRegistry addMapping( + Iterable requestMatchers, + Collection configAttributes) { + for (RequestMatcher requestMatcher : requestMatchers) { + REGISTRY.addMapping(new AbstractConfigAttributeRequestMatcherRegistry.UrlMapping( + requestMatcher, configAttributes)); + } + return REGISTRY; + } - /** - * Creates a String for specifying a user requires a role. - * - * @param role - * the role that should be required which is prepended with ROLE_ - * automatically (i.e. USER, ADMIN, etc). It should not start - * with ROLE_ - * @return the {@link ConfigAttribute} expressed as a String - */ - private static String hasRole(String role) { - Assert.isTrue( - !role.startsWith("ROLE_"), - role - + " should not start with ROLE_ since ROLE_ is automatically prepended when using hasRole. Consider using hasAuthority or access instead."); - return "ROLE_" + role; - } + /** + * Creates a String for specifying a user requires a role. + * + * @param role the role that should be required which is prepended with ROLE_ + * automatically (i.e. USER, ADMIN, etc). It should not start with ROLE_ + * @return the {@link ConfigAttribute} expressed as a String + */ + private static String hasRole(String role) { + Assert.isTrue( + !role.startsWith("ROLE_"), + role + + " should not start with ROLE_ since ROLE_ is automatically prepended when using hasRole. Consider using hasAuthority or access instead."); + return "ROLE_" + role; + } - /** - * Creates a String for specifying that a user requires one of many roles. - * - * @param roles - * the roles that the user should have at least one of (i.e. - * ADMIN, USER, etc). Each role should not start with ROLE_ since - * it is automatically prepended already. - * @return the {@link ConfigAttribute} expressed as a String - */ - private static String[] hasAnyRole(String... roles) { - for(int i=0;i requestMatchers; + /** + * Maps the specified {@link RequestMatcher} instances to {@link ConfigAttribute} + * instances. + * + * @author Rob Winch + * @since 3.2 + */ + public final class AuthorizedUrl { + private final List requestMatchers; - /** - * Creates a new instance - * @param requestMatchers the {@link RequestMatcher} instances to map to some {@link ConfigAttribute} instances. - */ - private AuthorizedUrl(List requestMatchers) { - Assert.notEmpty(requestMatchers, "requestMatchers must contain at least one value"); - this.requestMatchers = requestMatchers; - } + /** + * Creates a new instance + * @param requestMatchers the {@link RequestMatcher} instances to map to some + * {@link ConfigAttribute} instances. + */ + private AuthorizedUrl(List requestMatchers) { + Assert.notEmpty(requestMatchers, + "requestMatchers must contain at least one value"); + this.requestMatchers = requestMatchers; + } - /** - * Specifies a user requires a role. - * - * @param role - * the role that should be required which is prepended with ROLE_ - * automatically (i.e. USER, ADMIN, etc). It should not start - * with ROLE_ - * the {@link UrlAuthorizationConfigurer} for further customization - */ - public StandardInterceptUrlRegistry hasRole(String role) { - return access(UrlAuthorizationConfigurer.hasRole(role)); - } + /** + * Specifies a user requires a role. + * + * @param role the role that should be required which is prepended with ROLE_ + * automatically (i.e. USER, ADMIN, etc). It should not start with ROLE_ the + * {@link UrlAuthorizationConfigurer} for further customization + */ + public StandardInterceptUrlRegistry hasRole(String role) { + return access(UrlAuthorizationConfigurer.hasRole(role)); + } - /** - * Specifies that a user requires one of many roles. - * - * @param roles - * the roles that the user should have at least one of (i.e. - * ADMIN, USER, etc). Each role should not start with ROLE_ since - * it is automatically prepended already. - * @return the {@link UrlAuthorizationConfigurer} for further customization - */ - public StandardInterceptUrlRegistry hasAnyRole(String... roles) { - return access(UrlAuthorizationConfigurer.hasAnyRole(roles)); - } + /** + * Specifies that a user requires one of many roles. + * + * @param roles the roles that the user should have at least one of (i.e. ADMIN, + * USER, etc). Each role should not start with ROLE_ since it is automatically + * prepended already. + * @return the {@link UrlAuthorizationConfigurer} for further customization + */ + public StandardInterceptUrlRegistry hasAnyRole(String... roles) { + return access(UrlAuthorizationConfigurer.hasAnyRole(roles)); + } - /** - * Specifies a user requires an authority. - * - * @param authority - * the authority that should be required - * @return the {@link UrlAuthorizationConfigurer} for further customization - */ - public StandardInterceptUrlRegistry hasAuthority(String authority) { - return access(authority); - } + /** + * Specifies a user requires an authority. + * + * @param authority the authority that should be required + * @return the {@link UrlAuthorizationConfigurer} for further customization + */ + public StandardInterceptUrlRegistry hasAuthority(String authority) { + return access(authority); + } - /** - * Specifies that a user requires one of many authorities - * @param authorities the authorities that the user should have at least one of (i.e. ROLE_USER, ROLE_ADMIN, etc). - * @return the {@link UrlAuthorizationConfigurer} for further customization - */ - public StandardInterceptUrlRegistry hasAnyAuthority(String... authorities) { - return access(UrlAuthorizationConfigurer.hasAnyAuthority(authorities)); - } + /** + * Specifies that a user requires one of many authorities + * @param authorities the authorities that the user should have at least one of + * (i.e. ROLE_USER, ROLE_ADMIN, etc). + * @return the {@link UrlAuthorizationConfigurer} for further customization + */ + public StandardInterceptUrlRegistry hasAnyAuthority(String... authorities) { + return access(UrlAuthorizationConfigurer.hasAnyAuthority(authorities)); + } - /** - * Specifies that an anonymous user is allowed access - * @return the {@link UrlAuthorizationConfigurer} for further customization - */ - public StandardInterceptUrlRegistry anonymous() { - return hasRole("ROLE_ANONYMOUS"); - } + /** + * Specifies that an anonymous user is allowed access + * @return the {@link UrlAuthorizationConfigurer} for further customization + */ + public StandardInterceptUrlRegistry anonymous() { + return hasRole("ROLE_ANONYMOUS"); + } - /** - * Specifies that the user must have the specified {@link ConfigAttribute}'s - * @param attributes the {@link ConfigAttribute}'s that restrict access to a URL - * @return the {@link UrlAuthorizationConfigurer} for further customization - */ - public StandardInterceptUrlRegistry access(String... attributes) { - addMapping(requestMatchers, SecurityConfig.createList(attributes)); - return UrlAuthorizationConfigurer.this.REGISTRY; - } - } + /** + * Specifies that the user must have the specified {@link ConfigAttribute}'s + * @param attributes the {@link ConfigAttribute}'s that restrict access to a URL + * @return the {@link UrlAuthorizationConfigurer} for further customization + */ + public StandardInterceptUrlRegistry access(String... attributes) { + addMapping(requestMatchers, SecurityConfig.createList(attributes)); + return UrlAuthorizationConfigurer.this.REGISTRY; + } + } } \ No newline at end of file diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/X509Configurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/X509Configurer.java index 45eb3e23a5..5f7f896b03 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/X509Configurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/X509Configurer.java @@ -34,10 +34,10 @@ import org.springframework.security.web.authentication.preauth.x509.SubjectDnX50 import org.springframework.security.web.authentication.preauth.x509.X509AuthenticationFilter; /** - * Adds X509 based pre authentication to an application. Since validating the - * certificate happens when the client connects, the requesting and validation - * of the client certificate should be performed by the container. Spring Security - * will then use the certificate to look up the {@link Authentication} for the user. + * Adds X509 based pre authentication to an application. Since validating the certificate + * happens when the client connects, the requesting and validation of the client + * certificate should be performed by the container. Spring Security will then use the + * certificate to look up the {@link Authentication} for the user. * *

Security Filters

* @@ -53,8 +53,8 @@ import org.springframework.security.web.authentication.preauth.x509.X509Authenti * *