Polish spring-security-config main code
Manually polish `spring-security-config` following the formatting and checkstyle fixes. Issue gh-8945
This commit is contained in:
parent
4e5aa6c9d3
commit
7bf6008efe
|
@ -35,7 +35,9 @@ public abstract class BeanIds {
|
|||
*/
|
||||
public static final String AUTHENTICATION_MANAGER = PREFIX + "authenticationManager";
|
||||
|
||||
/** External alias for FilterChainProxy bean, for use in web.xml files */
|
||||
/**
|
||||
* 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";
|
||||
|
|
|
@ -33,7 +33,6 @@ public class DebugBeanDefinitionParser implements BeanDefinitionParser {
|
|||
public BeanDefinition parse(Element element, ParserContext parserContext) {
|
||||
RootBeanDefinition debugPP = new RootBeanDefinition(SecurityDebugBeanFactoryPostProcessor.class);
|
||||
parserContext.getReaderContext().registerWithGeneratedName(debugPP);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -75,17 +75,13 @@ public final class SecurityNamespaceHandler implements NamespaceHandler {
|
|||
|
||||
public SecurityNamespaceHandler() {
|
||||
String coreVersion = SpringSecurityCoreVersion.getVersion();
|
||||
|
||||
Package pkg = SpringSecurityCoreVersion.class.getPackage();
|
||||
|
||||
if (pkg == null || coreVersion == null) {
|
||||
this.logger.info("Couldn't determine package version information.");
|
||||
return;
|
||||
}
|
||||
|
||||
String version = pkg.getImplementationVersion();
|
||||
this.logger.info("Spring Security 'config' module version is " + version);
|
||||
|
||||
if (version.compareTo(coreVersion) != 0) {
|
||||
this.logger.error(
|
||||
"You are running with different versions of the Spring Security 'core' and 'config' modules");
|
||||
|
@ -95,44 +91,37 @@ public final class SecurityNamespaceHandler implements NamespaceHandler {
|
|||
@Override
|
||||
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 or spring-security-3.2.xsd schema or spring-security-4.0.xsd schema "
|
||||
+ "with Spring Security 5.4. Please update your schema declarations to the 5.4 schema.",
|
||||
element);
|
||||
pc.getReaderContext().fatal("You cannot use a spring-security-2.0.xsd or spring-security-3.0.xsd or "
|
||||
+ "spring-security-3.1.xsd schema or spring-security-3.2.xsd schema or spring-security-4.0.xsd schema "
|
||||
+ "with Spring Security 5.4. Please update your schema declarations to the 5.4 schema.", element);
|
||||
}
|
||||
String name = pc.getDelegate().getLocalName(element);
|
||||
BeanDefinitionParser parser = this.parsers.get(name);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
return null;
|
||||
if (parser != null) {
|
||||
return parser.parse(element, pc);
|
||||
}
|
||||
|
||||
return parser.parse(element, pc);
|
||||
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;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder definition, ParserContext pc) {
|
||||
String name = pc.getDelegate().getLocalName(node);
|
||||
|
||||
// We only handle elements
|
||||
if (node instanceof Element) {
|
||||
// We only handle elements
|
||||
if (Elements.INTERCEPT_METHODS.equals(name)) {
|
||||
return this.interceptMethodsBDD.decorate(node, definition, pc);
|
||||
}
|
||||
|
||||
if (Elements.FILTER_CHAIN_MAP.equals(name)) {
|
||||
if (this.filterChainMapBDD == null) {
|
||||
loadParsers();
|
||||
|
@ -143,9 +132,7 @@ public final class SecurityNamespaceHandler implements NamespaceHandler {
|
|||
return this.filterChainMapBDD.decorate(node, definition, pc);
|
||||
}
|
||||
}
|
||||
|
||||
reportUnsupportedNodeType(name, pc, node);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -162,9 +149,9 @@ public final class SecurityNamespaceHandler implements NamespaceHandler {
|
|||
// no details available
|
||||
pc.getReaderContext().fatal(errorMessage, node);
|
||||
}
|
||||
catch (Throwable cause) {
|
||||
catch (Throwable ex) {
|
||||
// provide details on why it could not be loaded
|
||||
pc.getReaderContext().fatal(errorMessage, node, cause);
|
||||
pc.getReaderContext().fatal(errorMessage, node, ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -185,25 +172,28 @@ public final class SecurityNamespaceHandler implements NamespaceHandler {
|
|||
this.parsers.put(Elements.AUTHENTICATION_MANAGER, new AuthenticationManagerBeanDefinitionParser());
|
||||
this.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())) {
|
||||
this.parsers.put(Elements.DEBUG, new DebugBeanDefinitionParser());
|
||||
this.parsers.put(Elements.HTTP, new HttpSecurityBeanDefinitionParser());
|
||||
this.parsers.put(Elements.HTTP_FIREWALL, new HttpFirewallBeanDefinitionParser());
|
||||
this.parsers.put(Elements.FILTER_SECURITY_METADATA_SOURCE,
|
||||
new FilterInvocationSecurityMetadataSourceParser());
|
||||
this.parsers.put(Elements.FILTER_CHAIN, new FilterChainBeanDefinitionParser());
|
||||
this.filterChainMapBDD = new FilterChainMapBeanDefinitionDecorator();
|
||||
this.parsers.put(Elements.CLIENT_REGISTRATIONS, new ClientRegistrationsBeanDefinitionParser());
|
||||
loadWebParsers();
|
||||
}
|
||||
|
||||
if (ClassUtils.isPresent(MESSAGE_CLASSNAME, getClass().getClassLoader())) {
|
||||
this.parsers.put(Elements.WEBSOCKET_MESSAGE_BROKER,
|
||||
new WebSocketMessageBrokerSecurityBeanDefinitionParser());
|
||||
loadWebSocketParsers();
|
||||
}
|
||||
}
|
||||
|
||||
private void loadWebParsers() {
|
||||
this.parsers.put(Elements.DEBUG, new DebugBeanDefinitionParser());
|
||||
this.parsers.put(Elements.HTTP, new HttpSecurityBeanDefinitionParser());
|
||||
this.parsers.put(Elements.HTTP_FIREWALL, new HttpFirewallBeanDefinitionParser());
|
||||
this.parsers.put(Elements.FILTER_SECURITY_METADATA_SOURCE, new FilterInvocationSecurityMetadataSourceParser());
|
||||
this.parsers.put(Elements.FILTER_CHAIN, new FilterChainBeanDefinitionParser());
|
||||
this.filterChainMapBDD = new FilterChainMapBeanDefinitionDecorator();
|
||||
this.parsers.put(Elements.CLIENT_REGISTRATIONS, new ClientRegistrationsBeanDefinitionParser());
|
||||
}
|
||||
|
||||
private void loadWebSocketParsers() {
|
||||
this.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,
|
||||
|
|
|
@ -99,18 +99,16 @@ public abstract class AbstractConfiguredSecurityBuilder<O, B extends SecurityBui
|
|||
* while building, returns null.
|
||||
*/
|
||||
public O getOrBuild() {
|
||||
if (isUnbuilt()) {
|
||||
try {
|
||||
return build();
|
||||
}
|
||||
catch (Exception ex) {
|
||||
this.logger.debug("Failed to perform build. Returning null", ex);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!isUnbuilt()) {
|
||||
return getObject();
|
||||
}
|
||||
try {
|
||||
return build();
|
||||
}
|
||||
catch (Exception ex) {
|
||||
this.logger.debug("Failed to perform build. Returning null", ex);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -177,18 +175,17 @@ public abstract class AbstractConfiguredSecurityBuilder<O, B extends SecurityBui
|
|||
@SuppressWarnings("unchecked")
|
||||
private <C extends SecurityConfigurer<O, B>> void add(C configurer) {
|
||||
Assert.notNull(configurer, "configurer cannot be null");
|
||||
|
||||
Class<? extends SecurityConfigurer<O, B>> clazz = (Class<? extends SecurityConfigurer<O, B>>) configurer
|
||||
.getClass();
|
||||
synchronized (this.configurers) {
|
||||
if (this.buildState.isConfigured()) {
|
||||
throw new IllegalStateException("Cannot apply " + configurer + " to already built object");
|
||||
}
|
||||
List<SecurityConfigurer<O, B>> configs = this.allowConfigurersOfSameType ? this.configurers.get(clazz)
|
||||
: null;
|
||||
if (configs == null) {
|
||||
configs = new ArrayList<>(1);
|
||||
List<SecurityConfigurer<O, B>> configs = null;
|
||||
if (this.allowConfigurersOfSameType) {
|
||||
configs = this.configurers.get(clazz);
|
||||
}
|
||||
configs = (configs != null) ? configs : new ArrayList<>(1);
|
||||
configs.add(configurer);
|
||||
this.configurers.put(clazz, configs);
|
||||
if (this.buildState.isInitializing()) {
|
||||
|
@ -239,9 +236,8 @@ public abstract class AbstractConfiguredSecurityBuilder<O, B extends SecurityBui
|
|||
if (configs == null) {
|
||||
return null;
|
||||
}
|
||||
if (configs.size() != 1) {
|
||||
throw new IllegalStateException("Only one configurer expected for type " + clazz + ", but got " + configs);
|
||||
}
|
||||
Assert.state(configs.size() == 1,
|
||||
() -> "Only one configurer expected for type " + clazz + ", but got " + configs);
|
||||
return (C) configs.get(0);
|
||||
}
|
||||
|
||||
|
@ -257,9 +253,8 @@ public abstract class AbstractConfiguredSecurityBuilder<O, B extends SecurityBui
|
|||
if (configs == null) {
|
||||
return null;
|
||||
}
|
||||
if (configs.size() != 1) {
|
||||
throw new IllegalStateException("Only one configurer expected for type " + clazz + ", but got " + configs);
|
||||
}
|
||||
Assert.state(configs.size() == 1,
|
||||
() -> "Only one configurer expected for type " + clazz + ", but got " + configs);
|
||||
return (C) configs.get(0);
|
||||
}
|
||||
|
||||
|
@ -301,21 +296,14 @@ public abstract class AbstractConfiguredSecurityBuilder<O, B extends SecurityBui
|
|||
protected final O doBuild() throws Exception {
|
||||
synchronized (this.configurers) {
|
||||
this.buildState = BuildState.INITIALIZING;
|
||||
|
||||
beforeInit();
|
||||
init();
|
||||
|
||||
this.buildState = BuildState.CONFIGURING;
|
||||
|
||||
beforeConfigure();
|
||||
configure();
|
||||
|
||||
this.buildState = BuildState.BUILDING;
|
||||
|
||||
O result = performBuild();
|
||||
|
||||
this.buildState = BuildState.BUILT;
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@ -346,11 +334,9 @@ public abstract class AbstractConfiguredSecurityBuilder<O, B extends SecurityBui
|
|||
@SuppressWarnings("unchecked")
|
||||
private void init() throws Exception {
|
||||
Collection<SecurityConfigurer<O, B>> configurers = getConfigurers();
|
||||
|
||||
for (SecurityConfigurer<O, B> configurer : configurers) {
|
||||
configurer.init((B) this);
|
||||
}
|
||||
|
||||
for (SecurityConfigurer<O, B> configurer : this.configurersAddedInInitializing) {
|
||||
configurer.init((B) this);
|
||||
}
|
||||
|
@ -359,7 +345,6 @@ public abstract class AbstractConfiguredSecurityBuilder<O, B extends SecurityBui
|
|||
@SuppressWarnings("unchecked")
|
||||
private void configure() throws Exception {
|
||||
Collection<SecurityConfigurer<O, B>> configurers = getConfigurers();
|
||||
|
||||
for (SecurityConfigurer<O, B> configurer : configurers) {
|
||||
configurer.configure((B) this);
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ import java.util.List;
|
|||
|
||||
import org.springframework.core.GenericTypeResolver;
|
||||
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A base class for {@link SecurityConfigurer} that allows subclasses to only implement
|
||||
|
@ -63,9 +64,7 @@ public abstract class SecurityConfigurerAdapter<O, B extends SecurityBuilder<O>>
|
|||
* @throws IllegalStateException if {@link SecurityBuilder} is null
|
||||
*/
|
||||
protected final B getBuilder() {
|
||||
if (this.securityBuilder == null) {
|
||||
throw new IllegalStateException("securityBuilder cannot be null");
|
||||
}
|
||||
Assert.state(this.securityBuilder != null, "securityBuilder cannot be null");
|
||||
return this.securityBuilder;
|
||||
}
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@ import org.springframework.context.annotation.Bean;
|
|||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
|
||||
import org.springframework.core.log.LogMessage;
|
||||
import org.springframework.security.authentication.AuthenticationEventPublisher;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.config.annotation.ObjectPostProcessor;
|
||||
|
@ -80,7 +81,6 @@ public class AuthenticationConfiguration {
|
|||
LazyPasswordEncoder defaultPasswordEncoder = new LazyPasswordEncoder(context);
|
||||
AuthenticationEventPublisher authenticationEventPublisher = getBeanOrNull(context,
|
||||
AuthenticationEventPublisher.class);
|
||||
|
||||
DefaultPasswordEncoderAuthenticationManagerBuilder result = new DefaultPasswordEncoderAuthenticationManagerBuilder(
|
||||
objectPostProcessor, defaultPasswordEncoder);
|
||||
if (authenticationEventPublisher != null) {
|
||||
|
@ -115,17 +115,13 @@ public class AuthenticationConfiguration {
|
|||
if (this.buildingAuthenticationManager.getAndSet(true)) {
|
||||
return new AuthenticationManagerDelegator(authBuilder);
|
||||
}
|
||||
|
||||
for (GlobalAuthenticationConfigurerAdapter config : this.globalAuthConfigurers) {
|
||||
authBuilder.apply(config);
|
||||
}
|
||||
|
||||
this.authenticationManager = authBuilder.build();
|
||||
|
||||
if (this.authenticationManager == null) {
|
||||
this.authenticationManager = getAuthenticationManagerBean();
|
||||
}
|
||||
|
||||
this.authenticationManagerInitialized = true;
|
||||
return this.authenticationManager;
|
||||
}
|
||||
|
@ -154,20 +150,7 @@ public class AuthenticationConfiguration {
|
|||
if (beanNamesForType.length == 0) {
|
||||
return null;
|
||||
}
|
||||
String beanName;
|
||||
if (beanNamesForType.length > 1) {
|
||||
List<String> primaryBeanNames = getPrimaryBeanNames(beanNamesForType);
|
||||
|
||||
Assert.isTrue(primaryBeanNames.size() != 0, () -> "Found " + beanNamesForType.length + " beans for type "
|
||||
+ interfaceName + ", but none marked as primary");
|
||||
Assert.isTrue(primaryBeanNames.size() == 1, () -> "Found " + primaryBeanNames.size() + " beans for type "
|
||||
+ interfaceName + " marked as primary");
|
||||
beanName = primaryBeanNames.get(0);
|
||||
}
|
||||
else {
|
||||
beanName = beanNamesForType[0];
|
||||
}
|
||||
|
||||
String beanName = getBeanName(interfaceName, beanNamesForType);
|
||||
lazyTargetSource.setTargetBeanName(beanName);
|
||||
lazyTargetSource.setBeanFactory(this.applicationContext);
|
||||
ProxyFactoryBean proxyFactory = new ProxyFactoryBean();
|
||||
|
@ -176,6 +159,18 @@ public class AuthenticationConfiguration {
|
|||
return (T) proxyFactory.getObject();
|
||||
}
|
||||
|
||||
private <T> String getBeanName(Class<T> interfaceName, String[] beanNamesForType) {
|
||||
if (beanNamesForType.length == 1) {
|
||||
return beanNamesForType[0];
|
||||
}
|
||||
List<String> primaryBeanNames = getPrimaryBeanNames(beanNamesForType);
|
||||
Assert.isTrue(primaryBeanNames.size() != 0, () -> "Found " + beanNamesForType.length + " beans for type "
|
||||
+ interfaceName + ", but none marked as primary");
|
||||
Assert.isTrue(primaryBeanNames.size() == 1,
|
||||
() -> "Found " + primaryBeanNames.size() + " beans for type " + interfaceName + " marked as primary");
|
||||
return primaryBeanNames.get(0);
|
||||
}
|
||||
|
||||
private List<String> getPrimaryBeanNames(String[] beanNamesForType) {
|
||||
List<String> list = new ArrayList<>();
|
||||
if (!(this.applicationContext instanceof ConfigurableApplicationContext)) {
|
||||
|
@ -217,9 +212,7 @@ public class AuthenticationConfiguration {
|
|||
public void init(AuthenticationManagerBuilder auth) {
|
||||
Map<String, Object> beansWithAnnotation = this.context
|
||||
.getBeansWithAnnotation(EnableGlobalAuthentication.class);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Eagerly initializing " + beansWithAnnotation);
|
||||
}
|
||||
logger.debug(LogMessage.format("Eagerly initializing %s", beansWithAnnotation));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -249,14 +242,12 @@ public class AuthenticationConfiguration {
|
|||
if (this.delegate != null) {
|
||||
return this.delegate.authenticate(authentication);
|
||||
}
|
||||
|
||||
synchronized (this.delegateMonitor) {
|
||||
if (this.delegate == null) {
|
||||
this.delegate = this.delegateBuilder.getObject();
|
||||
this.delegateBuilder = null;
|
||||
}
|
||||
}
|
||||
|
||||
return this.delegate.authenticate(authentication);
|
||||
}
|
||||
|
||||
|
|
|
@ -58,7 +58,6 @@ class InitializeAuthenticationProviderBeanManagerConfigurer extends GlobalAuthen
|
|||
if (authenticationProvider == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
auth.authenticationProvider(authenticationProvider);
|
||||
}
|
||||
|
||||
|
@ -72,7 +71,6 @@ class InitializeAuthenticationProviderBeanManagerConfigurer extends GlobalAuthen
|
|||
if (beanNames.length != 1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return InitializeAuthenticationProviderBeanManagerConfigurer.this.context.getBean(beanNames[0], type);
|
||||
}
|
||||
|
||||
|
|
|
@ -63,10 +63,8 @@ class InitializeUserDetailsBeanManagerConfigurer extends GlobalAuthenticationCon
|
|||
if (userDetailsService == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
PasswordEncoder passwordEncoder = getBeanOrNull(PasswordEncoder.class);
|
||||
UserDetailsPasswordService passwordManager = getBeanOrNull(UserDetailsPasswordService.class);
|
||||
|
||||
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
|
||||
provider.setUserDetailsService(userDetailsService);
|
||||
if (passwordEncoder != null) {
|
||||
|
@ -76,7 +74,6 @@ class InitializeUserDetailsBeanManagerConfigurer extends GlobalAuthenticationCon
|
|||
provider.setUserDetailsPasswordService(passwordManager);
|
||||
}
|
||||
provider.afterPropertiesSet();
|
||||
|
||||
auth.authenticationProvider(provider);
|
||||
}
|
||||
|
||||
|
@ -89,7 +86,6 @@ class InitializeUserDetailsBeanManagerConfigurer extends GlobalAuthenticationCon
|
|||
if (beanNames.length != 1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return InitializeUserDetailsBeanManagerConfigurer.this.context.getBean(beanNames[0], type);
|
||||
}
|
||||
|
||||
|
|
|
@ -93,9 +93,7 @@ public class LdapAuthenticationProviderConfigurer<B extends ProviderManagerBuild
|
|||
private LdapAuthenticationProvider build() throws Exception {
|
||||
BaseLdapPathContextSource contextSource = getContextSource();
|
||||
LdapAuthenticator ldapAuthenticator = createLdapAuthenticator(contextSource);
|
||||
|
||||
LdapAuthoritiesPopulator authoritiesPopulator = getLdapAuthoritiesPopulator();
|
||||
|
||||
LdapAuthenticationProvider ldapAuthenticationProvider = new LdapAuthenticationProvider(ldapAuthenticator,
|
||||
authoritiesPopulator);
|
||||
ldapAuthenticationProvider.setAuthoritiesMapper(getAuthoritiesMapper());
|
||||
|
@ -136,14 +134,12 @@ public class LdapAuthenticationProviderConfigurer<B extends ProviderManagerBuild
|
|||
if (this.ldapAuthoritiesPopulator != null) {
|
||||
return this.ldapAuthoritiesPopulator;
|
||||
}
|
||||
|
||||
DefaultLdapAuthoritiesPopulator defaultAuthoritiesPopulator = new DefaultLdapAuthoritiesPopulator(
|
||||
this.contextSource, this.groupSearchBase);
|
||||
defaultAuthoritiesPopulator.setGroupRoleAttribute(this.groupRoleAttribute);
|
||||
defaultAuthoritiesPopulator.setGroupSearchFilter(this.groupSearchFilter);
|
||||
defaultAuthoritiesPopulator.setSearchSubtree(this.groupSearchSubtree);
|
||||
defaultAuthoritiesPopulator.setRolePrefix(this.rolePrefix);
|
||||
|
||||
this.ldapAuthoritiesPopulator = defaultAuthoritiesPopulator;
|
||||
return defaultAuthoritiesPopulator;
|
||||
}
|
||||
|
@ -173,7 +169,6 @@ public class LdapAuthenticationProviderConfigurer<B extends ProviderManagerBuild
|
|||
if (this.authoritiesMapper != null) {
|
||||
return this.authoritiesMapper;
|
||||
}
|
||||
|
||||
SimpleAuthorityMapper simpleAuthorityMapper = new SimpleAuthorityMapper();
|
||||
simpleAuthorityMapper.setPrefix(this.rolePrefix);
|
||||
simpleAuthorityMapper.afterPropertiesSet();
|
||||
|
@ -554,7 +549,6 @@ public class LdapAuthenticationProviderConfigurer<B extends ProviderManagerBuild
|
|||
if (this.url == null) {
|
||||
startEmbeddedLdapServer();
|
||||
}
|
||||
|
||||
DefaultSpringSecurityContextSource contextSource = new DefaultSpringSecurityContextSource(getProviderUrl());
|
||||
if (this.managerDn != null) {
|
||||
contextSource.setUserDn(this.managerDn);
|
||||
|
|
|
@ -45,7 +45,6 @@ public class UserDetailsServiceConfigurer<B extends ProviderManagerBuilder<B>, C
|
|||
@Override
|
||||
public void configure(B builder) throws Exception {
|
||||
initUserDetailsService();
|
||||
|
||||
super.configure(builder);
|
||||
}
|
||||
|
||||
|
|
|
@ -91,8 +91,8 @@ final class AutowireBeanFactoryObjectPostProcessor
|
|||
try {
|
||||
disposable.destroy();
|
||||
}
|
||||
catch (Exception error) {
|
||||
this.logger.error(error);
|
||||
catch (Exception ex) {
|
||||
this.logger.error(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,15 +46,12 @@ class GlobalMethodSecurityAspectJAutoProxyRegistrar implements ImportBeanDefinit
|
|||
*/
|
||||
@Override
|
||||
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
|
||||
|
||||
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);
|
||||
|
||||
registry.registerBeanDefinition("annotationSecurityAspect$0", aspect.getBeanDefinition());
|
||||
}
|
||||
|
||||
|
|
|
@ -92,11 +92,13 @@ public class GlobalMethodSecurityConfiguration implements ImportAware, SmartInit
|
|||
private static final Log logger = LogFactory.getLog(GlobalMethodSecurityConfiguration.class);
|
||||
|
||||
private ObjectPostProcessor<Object> objectPostProcessor = new ObjectPostProcessor<Object>() {
|
||||
|
||||
@Override
|
||||
public <T> 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();
|
||||
|
@ -145,7 +147,6 @@ public class GlobalMethodSecurityConfiguration implements ImportAware, SmartInit
|
|||
if (runAsManager != null) {
|
||||
this.methodSecurityInterceptor.setRunAsManager(runAsManager);
|
||||
}
|
||||
|
||||
return this.methodSecurityInterceptor;
|
||||
}
|
||||
|
||||
|
@ -157,22 +158,18 @@ public class GlobalMethodSecurityConfiguration implements ImportAware, SmartInit
|
|||
catch (Exception ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
|
||||
PermissionEvaluator permissionEvaluator = getSingleBeanOrNull(PermissionEvaluator.class);
|
||||
if (permissionEvaluator != null) {
|
||||
this.defaultMethodExpressionHandler.setPermissionEvaluator(permissionEvaluator);
|
||||
}
|
||||
|
||||
RoleHierarchy roleHierarchy = getSingleBeanOrNull(RoleHierarchy.class);
|
||||
if (roleHierarchy != null) {
|
||||
this.defaultMethodExpressionHandler.setRoleHierarchy(roleHierarchy);
|
||||
}
|
||||
|
||||
AuthenticationTrustResolver trustResolver = getSingleBeanOrNull(AuthenticationTrustResolver.class);
|
||||
if (trustResolver != null) {
|
||||
this.defaultMethodExpressionHandler.setTrustResolver(trustResolver);
|
||||
}
|
||||
|
||||
GrantedAuthorityDefaults grantedAuthorityDefaults = getSingleBeanOrNull(GrantedAuthorityDefaults.class);
|
||||
if (grantedAuthorityDefaults != null) {
|
||||
this.defaultMethodExpressionHandler.setDefaultRolePrefix(grantedAuthorityDefaults.getRolePrefix());
|
||||
|
@ -315,12 +312,8 @@ public class GlobalMethodSecurityConfiguration implements ImportAware, SmartInit
|
|||
this.auth = new AuthenticationManagerBuilder(this.objectPostProcessor);
|
||||
this.auth.authenticationEventPublisher(eventPublisher);
|
||||
configure(this.auth);
|
||||
if (this.disableAuthenticationRegistry) {
|
||||
this.authenticationManager = getAuthenticationConfiguration().getAuthenticationManager();
|
||||
}
|
||||
else {
|
||||
this.authenticationManager = this.auth.build();
|
||||
}
|
||||
this.authenticationManager = (this.disableAuthenticationRegistry)
|
||||
? getAuthenticationConfiguration().getAuthenticationManager() : this.auth.build();
|
||||
}
|
||||
return this.authenticationManager;
|
||||
}
|
||||
|
@ -353,17 +346,13 @@ public class GlobalMethodSecurityConfiguration implements ImportAware, SmartInit
|
|||
if (customMethodSecurityMetadataSource != null) {
|
||||
sources.add(customMethodSecurityMetadataSource);
|
||||
}
|
||||
|
||||
boolean hasCustom = customMethodSecurityMetadataSource != null;
|
||||
boolean isPrePostEnabled = prePostEnabled();
|
||||
boolean isSecuredEnabled = securedEnabled();
|
||||
boolean isJsr250Enabled = jsr250Enabled();
|
||||
|
||||
if (!isPrePostEnabled && !isSecuredEnabled && !isJsr250Enabled && !hasCustom) {
|
||||
throw new IllegalStateException("In the composition of all global method configuration, "
|
||||
+ "no annotation support was actually activated");
|
||||
}
|
||||
|
||||
Assert.state(isPrePostEnabled || isSecuredEnabled || isJsr250Enabled || hasCustom,
|
||||
"In the composition of all global method configuration, "
|
||||
+ "no annotation support was actually activated");
|
||||
if (isPrePostEnabled) {
|
||||
sources.add(new PrePostAnnotationSecurityMetadataSource(attributeFactory));
|
||||
}
|
||||
|
@ -441,10 +430,6 @@ public class GlobalMethodSecurityConfiguration implements ImportAware, SmartInit
|
|||
return enableMethodSecurity().getBoolean("jsr250Enabled");
|
||||
}
|
||||
|
||||
private int order() {
|
||||
return (Integer) enableMethodSecurity().get("order");
|
||||
}
|
||||
|
||||
private boolean isAspectJ() {
|
||||
return enableMethodSecurity().getEnum("mode") == AdviceMode.ASPECTJ;
|
||||
}
|
||||
|
|
|
@ -45,35 +45,27 @@ final class GlobalMethodSecuritySelector implements ImportSelector {
|
|||
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);
|
||||
|
||||
AdviceMode mode = attributes.getEnum("mode");
|
||||
boolean isProxy = AdviceMode.PROXY == mode;
|
||||
String autoProxyClassName = isProxy ? AutoProxyRegistrar.class.getName()
|
||||
: GlobalMethodSecurityAspectJAutoProxyRegistrar.class.getName();
|
||||
|
||||
boolean jsr250Enabled = attributes.getBoolean("jsr250Enabled");
|
||||
|
||||
List<String> classNames = new ArrayList<>(4);
|
||||
if (isProxy) {
|
||||
classNames.add(MethodSecurityMetadataSourceAdvisorRegistrar.class.getName());
|
||||
}
|
||||
|
||||
classNames.add(autoProxyClassName);
|
||||
|
||||
if (!skipMethodSecurityConfiguration) {
|
||||
classNames.add(GlobalMethodSecurityConfiguration.class.getName());
|
||||
}
|
||||
|
||||
if (jsr250Enabled) {
|
||||
classNames.add(Jsr250MetadataSourceConfiguration.class.getName());
|
||||
}
|
||||
|
||||
return classNames.toArray(new String[0]);
|
||||
}
|
||||
|
||||
|
|
|
@ -42,21 +42,18 @@ class MethodSecurityMetadataSourceAdvisorRegistrar implements ImportBeanDefiniti
|
|||
*/
|
||||
@Override
|
||||
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
|
||||
|
||||
BeanDefinitionBuilder advisor = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(MethodSecurityMetadataSourceAdvisor.class);
|
||||
advisor.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
advisor.addConstructorArgValue("methodSecurityInterceptor");
|
||||
advisor.addConstructorArgReference("methodSecurityMetadataSource");
|
||||
advisor.addConstructorArgValue("methodSecurityMetadataSource");
|
||||
|
||||
MultiValueMap<String, Object> attributes = importingClassMetadata
|
||||
.getAllAnnotationAttributes(EnableGlobalMethodSecurity.class.getName());
|
||||
Integer order = (Integer) attributes.getFirst("order");
|
||||
if (order != null) {
|
||||
advisor.addPropertyValue("order", order);
|
||||
}
|
||||
|
||||
registry.registerBeanDefinition("metaDataSourceAdvisor", advisor.getBeanDefinition());
|
||||
}
|
||||
|
||||
|
|
|
@ -72,11 +72,9 @@ class ReactiveMethodSecurityConfiguration implements ImportAware {
|
|||
@Bean
|
||||
PrePostAdviceReactiveMethodInterceptor securityMethodInterceptor(AbstractMethodSecurityMetadataSource source,
|
||||
MethodSecurityExpressionHandler handler) {
|
||||
|
||||
ExpressionBasedPostInvocationAdvice postAdvice = new ExpressionBasedPostInvocationAdvice(handler);
|
||||
ExpressionBasedPreInvocationAdvice preAdvice = new ExpressionBasedPreInvocationAdvice();
|
||||
preAdvice.setExpressionHandler(handler);
|
||||
|
||||
return new PrePostAdviceReactiveMethodInterceptor(source, preAdvice, postAdvice);
|
||||
}
|
||||
|
||||
|
|
|
@ -31,12 +31,10 @@ class ReactiveMethodSecuritySelector extends AdviceModeImportSelector<EnableReac
|
|||
|
||||
@Override
|
||||
protected String[] selectImports(AdviceMode adviceMode) {
|
||||
switch (adviceMode) {
|
||||
case PROXY:
|
||||
if (adviceMode == AdviceMode.PROXY) {
|
||||
return getProxyImports();
|
||||
default:
|
||||
throw new IllegalStateException("AdviceMode " + adviceMode + " is not supported");
|
||||
}
|
||||
throw new IllegalStateException("AdviceMode " + adviceMode + " is not supported");
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -202,7 +202,6 @@ public class RSocketSecurity {
|
|||
|
||||
private List<PayloadInterceptor> payloadInterceptors() {
|
||||
List<PayloadInterceptor> result = new ArrayList<>(this.payloadInterceptors);
|
||||
|
||||
if (this.basicAuthSpec != null) {
|
||||
result.add(this.basicAuthSpec.build());
|
||||
}
|
||||
|
@ -213,7 +212,6 @@ public class RSocketSecurity {
|
|||
result.addAll(this.jwtSpec.build());
|
||||
}
|
||||
result.add(anonymous());
|
||||
|
||||
if (this.authorizePayload != null) {
|
||||
result.add(this.authorizePayload.build());
|
||||
}
|
||||
|
@ -260,6 +258,9 @@ public class RSocketSecurity {
|
|||
|
||||
private ReactiveAuthenticationManager authenticationManager;
|
||||
|
||||
private SimpleAuthenticationSpec() {
|
||||
}
|
||||
|
||||
public SimpleAuthenticationSpec authenticationManager(ReactiveAuthenticationManager authenticationManager) {
|
||||
this.authenticationManager = authenticationManager;
|
||||
return this;
|
||||
|
@ -280,15 +281,15 @@ public class RSocketSecurity {
|
|||
return result;
|
||||
}
|
||||
|
||||
private SimpleAuthenticationSpec() {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public final class BasicAuthenticationSpec {
|
||||
|
||||
private ReactiveAuthenticationManager authenticationManager;
|
||||
|
||||
private BasicAuthenticationSpec() {
|
||||
}
|
||||
|
||||
public BasicAuthenticationSpec authenticationManager(ReactiveAuthenticationManager authenticationManager) {
|
||||
this.authenticationManager = authenticationManager;
|
||||
return this;
|
||||
|
@ -308,15 +309,15 @@ public class RSocketSecurity {
|
|||
return result;
|
||||
}
|
||||
|
||||
private BasicAuthenticationSpec() {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public final class JwtSpec {
|
||||
|
||||
private ReactiveAuthenticationManager authenticationManager;
|
||||
|
||||
private JwtSpec() {
|
||||
}
|
||||
|
||||
public JwtSpec authenticationManager(ReactiveAuthenticationManager authenticationManager) {
|
||||
this.authenticationManager = authenticationManager;
|
||||
return this;
|
||||
|
@ -339,17 +340,12 @@ public class RSocketSecurity {
|
|||
AuthenticationPayloadInterceptor legacy = new AuthenticationPayloadInterceptor(manager);
|
||||
legacy.setAuthenticationConverter(new BearerPayloadExchangeConverter());
|
||||
legacy.setOrder(PayloadInterceptorOrder.AUTHENTICATION.getOrder());
|
||||
|
||||
AuthenticationPayloadInterceptor standard = new AuthenticationPayloadInterceptor(manager);
|
||||
standard.setAuthenticationConverter(new AuthenticationPayloadExchangeConverter());
|
||||
standard.setOrder(PayloadInterceptorOrder.AUTHENTICATION.getOrder());
|
||||
|
||||
return Arrays.asList(standard, legacy);
|
||||
}
|
||||
|
||||
private JwtSpec() {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class AuthorizePayloadsSpec {
|
||||
|
|
|
@ -170,7 +170,6 @@ public abstract class AbstractRequestMatcherRegistry<C> {
|
|||
for (String mvcPattern : mvcPatterns) {
|
||||
MvcRequestMatcher matcher = new MvcRequestMatcher(introspector, mvcPattern);
|
||||
opp.postProcess(matcher);
|
||||
|
||||
if (method != null) {
|
||||
matcher.setMethod(method);
|
||||
}
|
||||
|
|
|
@ -46,6 +46,7 @@ import org.springframework.security.web.savedrequest.RequestCacheAwareFilter;
|
|||
import org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter;
|
||||
import org.springframework.security.web.session.ConcurrentSessionFilter;
|
||||
import org.springframework.security.web.session.SessionManagementFilter;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.filter.CorsFilter;
|
||||
|
||||
/**
|
||||
|
@ -138,10 +139,7 @@ final class FilterComparator implements Comparator<Filter>, Serializable {
|
|||
*/
|
||||
void registerAfter(Class<? extends Filter> filter, Class<? extends Filter> afterFilter) {
|
||||
Integer position = getOrder(afterFilter);
|
||||
if (position == null) {
|
||||
throw new IllegalArgumentException("Cannot register after unregistered Filter " + afterFilter);
|
||||
}
|
||||
|
||||
Assert.notNull(position, () -> "Cannot register after unregistered Filter " + afterFilter);
|
||||
put(filter, position + 1);
|
||||
}
|
||||
|
||||
|
@ -153,10 +151,7 @@ final class FilterComparator implements Comparator<Filter>, Serializable {
|
|||
*/
|
||||
void registerAt(Class<? extends Filter> filter, Class<? extends Filter> atFilter) {
|
||||
Integer position = getOrder(atFilter);
|
||||
if (position == null) {
|
||||
throw new IllegalArgumentException("Cannot register after unregistered Filter " + atFilter);
|
||||
}
|
||||
|
||||
Assert.notNull(position, () -> "Cannot register after unregistered Filter " + atFilter);
|
||||
put(filter, position);
|
||||
}
|
||||
|
||||
|
@ -169,10 +164,7 @@ final class FilterComparator implements Comparator<Filter>, Serializable {
|
|||
*/
|
||||
void registerBefore(Class<? extends Filter> filter, Class<? extends Filter> beforeFilter) {
|
||||
Integer position = getOrder(beforeFilter);
|
||||
if (position == null) {
|
||||
throw new IllegalArgumentException("Cannot register after unregistered Filter " + beforeFilter);
|
||||
}
|
||||
|
||||
Assert.notNull(position, () -> "Cannot register after unregistered Filter " + beforeFilter);
|
||||
put(filter, position - 1);
|
||||
}
|
||||
|
||||
|
|
|
@ -308,20 +308,17 @@ public final class WebSecurity extends AbstractConfiguredSecurityBuilder<Filter,
|
|||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
this.defaultWebSecurityExpressionHandler.setApplicationContext(applicationContext);
|
||||
|
||||
try {
|
||||
this.defaultWebSecurityExpressionHandler.setRoleHierarchy(applicationContext.getBean(RoleHierarchy.class));
|
||||
}
|
||||
catch (NoSuchBeanDefinitionException ex) {
|
||||
}
|
||||
|
||||
try {
|
||||
this.defaultWebSecurityExpressionHandler
|
||||
.setPermissionEvaluator(applicationContext.getBean(PermissionEvaluator.class));
|
||||
}
|
||||
catch (NoSuchBeanDefinitionException ex) {
|
||||
}
|
||||
|
||||
this.ignoredRequestRegistry = new IgnoredRequestConfigurer(applicationContext);
|
||||
try {
|
||||
this.httpFirewall = applicationContext.getBean(HttpFirewall.class);
|
||||
|
|
|
@ -80,27 +80,27 @@ class HttpSecurityConfiguration {
|
|||
HttpSecurity httpSecurity() throws Exception {
|
||||
WebSecurityConfigurerAdapter.LazyPasswordEncoder passwordEncoder = new WebSecurityConfigurerAdapter.LazyPasswordEncoder(
|
||||
this.context);
|
||||
|
||||
AuthenticationManagerBuilder authenticationBuilder = new WebSecurityConfigurerAdapter.DefaultPasswordEncoderAuthenticationManagerBuilder(
|
||||
this.objectPostProcessor, passwordEncoder);
|
||||
authenticationBuilder.parentAuthenticationManager(authenticationManager());
|
||||
|
||||
HttpSecurity http = new HttpSecurity(this.objectPostProcessor, authenticationBuilder, createSharedObjects());
|
||||
http.csrf(withDefaults()).addFilter(new WebAsyncManagerIntegrationFilter()).exceptionHandling(withDefaults())
|
||||
.headers(withDefaults()).sessionManagement(withDefaults()).securityContext(withDefaults())
|
||||
.requestCache(withDefaults()).anonymous(withDefaults()).servletApi(withDefaults())
|
||||
.logout(withDefaults()).apply(new DefaultLoginPageConfigurer<>());
|
||||
|
||||
http.csrf(withDefaults());
|
||||
http.addFilter(new WebAsyncManagerIntegrationFilter());
|
||||
http.exceptionHandling(withDefaults());
|
||||
http.headers(withDefaults());
|
||||
http.sessionManagement(withDefaults());
|
||||
http.securityContext(withDefaults());
|
||||
http.requestCache(withDefaults());
|
||||
http.anonymous(withDefaults());
|
||||
http.servletApi(withDefaults());
|
||||
http.logout(withDefaults());
|
||||
http.apply(new DefaultLoginPageConfigurer<>());
|
||||
return http;
|
||||
}
|
||||
|
||||
private AuthenticationManager authenticationManager() throws Exception {
|
||||
if (this.authenticationManager != null) {
|
||||
return this.authenticationManager;
|
||||
}
|
||||
else {
|
||||
return this.authenticationConfiguration.getAuthenticationManager();
|
||||
}
|
||||
return (this.authenticationManager != null) ? this.authenticationManager
|
||||
: this.authenticationConfiguration.getAuthenticationManager();
|
||||
}
|
||||
|
||||
private Map<Class<?>, Object> createSharedObjects() {
|
||||
|
|
|
@ -54,12 +54,12 @@ final class OAuth2ClientConfiguration {
|
|||
|
||||
@Override
|
||||
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.OAuth2ClientConfiguration.OAuth2ClientWebMvcSecurityConfiguration" }
|
||||
: new String[] {};
|
||||
if (!ClassUtils.isPresent("org.springframework.web.servlet.DispatcherServlet",
|
||||
getClass().getClassLoader())) {
|
||||
return new String[0];
|
||||
}
|
||||
return new String[] { "org.springframework.security.config.annotation.web.configuration."
|
||||
+ "OAuth2ClientConfiguration.OAuth2ClientWebMvcSecurityConfiguration" };
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -114,7 +114,6 @@ final class OAuth2ClientConfiguration {
|
|||
if (this.authorizedClientManager != null) {
|
||||
return this.authorizedClientManager;
|
||||
}
|
||||
|
||||
OAuth2AuthorizedClientManager authorizedClientManager = null;
|
||||
if (this.clientRegistrationRepository != null && this.authorizedClientRepository != null) {
|
||||
if (this.accessTokenResponseClient != null) {
|
||||
|
|
|
@ -22,6 +22,7 @@ import java.util.Set;
|
|||
import org.springframework.context.annotation.ImportSelector;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Used by {@link EnableWebSecurity} to conditionally import:
|
||||
|
@ -45,29 +46,25 @@ final class OAuth2ImportSelector implements ImportSelector {
|
|||
@Override
|
||||
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
|
||||
Set<String> imports = new LinkedHashSet<>();
|
||||
|
||||
boolean oauth2ClientPresent = ClassUtils.isPresent(
|
||||
"org.springframework.security.oauth2.client.registration.ClientRegistration",
|
||||
getClass().getClassLoader());
|
||||
ClassLoader classLoader = getClass().getClassLoader();
|
||||
boolean oauth2ClientPresent = ClassUtils
|
||||
.isPresent("org.springframework.security.oauth2.client.registration.ClientRegistration", classLoader);
|
||||
boolean webfluxPresent = ClassUtils
|
||||
.isPresent("org.springframework.web.reactive.function.client.ExchangeFilterFunction", classLoader);
|
||||
boolean oauth2ResourceServerPresent = ClassUtils
|
||||
.isPresent("org.springframework.security.oauth2.server.resource.BearerTokenError", classLoader);
|
||||
if (oauth2ClientPresent) {
|
||||
imports.add("org.springframework.security.config.annotation.web.configuration.OAuth2ClientConfiguration");
|
||||
}
|
||||
|
||||
boolean webfluxPresent = ClassUtils.isPresent(
|
||||
"org.springframework.web.reactive.function.client.ExchangeFilterFunction", getClass().getClassLoader());
|
||||
if (webfluxPresent && oauth2ClientPresent) {
|
||||
imports.add(
|
||||
"org.springframework.security.config.annotation.web.configuration.SecurityReactorContextConfiguration");
|
||||
}
|
||||
|
||||
boolean oauth2ResourceServerPresent = ClassUtils.isPresent(
|
||||
"org.springframework.security.oauth2.server.resource.BearerTokenError", getClass().getClassLoader());
|
||||
if (webfluxPresent && oauth2ResourceServerPresent) {
|
||||
imports.add(
|
||||
"org.springframework.security.config.annotation.web.configuration.SecurityReactorContextConfiguration");
|
||||
}
|
||||
|
||||
return imports.toArray(new String[0]);
|
||||
return StringUtils.toStringArray(imports);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -71,7 +71,6 @@ class SecurityReactorContextConfiguration {
|
|||
public void afterPropertiesSet() throws Exception {
|
||||
Function<? super Publisher<Object>, ? extends Publisher<Object>> lifter = Operators
|
||||
.liftPublisher((pub, sub) -> createSubscriberIfNecessary(sub));
|
||||
|
||||
Hooks.onLastOperator(SECURITY_REACTOR_CONTEXT_OPERATOR_KEY, (pub) -> {
|
||||
if (!contextAttributesAvailable()) {
|
||||
// No need to decorate so return original Publisher
|
||||
|
@ -112,7 +111,6 @@ class SecurityReactorContextConfiguration {
|
|||
if (authentication == null && servletRequest == null) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
Map<Object, Object> contextAttributes = new HashMap<>();
|
||||
if (servletRequest != null) {
|
||||
contextAttributes.put(HttpServletRequest.class, servletRequest);
|
||||
|
@ -139,17 +137,17 @@ class SecurityReactorContextConfiguration {
|
|||
|
||||
SecurityReactorContextSubscriber(CoreSubscriber<T> delegate, Map<Object, Object> attributes) {
|
||||
this.delegate = delegate;
|
||||
Context currentContext = this.delegate.currentContext();
|
||||
Context context;
|
||||
if (currentContext.hasKey(SECURITY_CONTEXT_ATTRIBUTES)) {
|
||||
context = currentContext;
|
||||
}
|
||||
else {
|
||||
context = currentContext.put(SECURITY_CONTEXT_ATTRIBUTES, attributes);
|
||||
}
|
||||
Context context = getOrPutContext(attributes, this.delegate.currentContext());
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
private Context getOrPutContext(Map<Object, Object> attributes, Context currentContext) {
|
||||
if (currentContext.hasKey(SECURITY_CONTEXT_ATTRIBUTES)) {
|
||||
return currentContext;
|
||||
}
|
||||
return currentContext.put(SECURITY_CONTEXT_ATTRIBUTES, attributes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Context currentContext() {
|
||||
return this.context;
|
||||
|
|
|
@ -32,12 +32,11 @@ class SpringWebMvcImportSelector implements ImportSelector {
|
|||
|
||||
@Override
|
||||
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[] {};
|
||||
if (!ClassUtils.isPresent("org.springframework.web.servlet.DispatcherServlet", getClass().getClassLoader())) {
|
||||
return new String[0];
|
||||
}
|
||||
return new String[] {
|
||||
"org.springframework.security.config.annotation.web.configuration.WebMvcSecurityConfiguration" };
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -58,7 +58,6 @@ class WebMvcSecurityConfiguration implements WebMvcConfigurer, ApplicationContex
|
|||
argumentResolvers.add(authenticationPrincipalResolver);
|
||||
argumentResolvers
|
||||
.add(new org.springframework.security.web.bind.support.AuthenticationPrincipalArgumentResolver());
|
||||
|
||||
CurrentSecurityContextArgumentResolver currentSecurityContextArgumentResolver = new CurrentSecurityContextArgumentResolver();
|
||||
currentSecurityContextArgumentResolver.setBeanResolver(this.beanResolver);
|
||||
argumentResolvers.add(currentSecurityContextArgumentResolver);
|
||||
|
|
|
@ -50,6 +50,7 @@ import org.springframework.security.web.SecurityFilterChain;
|
|||
import org.springframework.security.web.access.WebInvocationPrivilegeEvaluator;
|
||||
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
|
||||
import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Uses a {@link WebSecurity} to create the {@link FilterChainProxy} that performs the web
|
||||
|
@ -101,10 +102,8 @@ public class WebSecurityConfiguration implements ImportAware, BeanClassLoaderAwa
|
|||
public Filter springSecurityFilterChain() throws Exception {
|
||||
boolean hasConfigurers = this.webSecurityConfigurers != null && !this.webSecurityConfigurers.isEmpty();
|
||||
boolean hasFilterChain = !this.securityFilterChains.isEmpty();
|
||||
if (hasConfigurers && hasFilterChain) {
|
||||
throw new IllegalStateException(
|
||||
"Found WebSecurityConfigurerAdapter as well as SecurityFilterChain." + "Please select just one.");
|
||||
}
|
||||
Assert.state(!(hasConfigurers && hasFilterChain),
|
||||
"Found WebSecurityConfigurerAdapter as well as SecurityFilterChain. Please select just one.");
|
||||
if (!hasConfigurers && !hasFilterChain) {
|
||||
WebSecurityConfigurerAdapter adapter = this.objectObjectPostProcessor
|
||||
.postProcess(new WebSecurityConfigurerAdapter() {
|
||||
|
@ -152,9 +151,7 @@ public class WebSecurityConfiguration implements ImportAware, BeanClassLoaderAwa
|
|||
if (this.debugEnabled != null) {
|
||||
this.webSecurity.debug(this.debugEnabled);
|
||||
}
|
||||
|
||||
webSecurityConfigurers.sort(AnnotationAwareOrderComparator.INSTANCE);
|
||||
|
||||
Integer previousOrder = null;
|
||||
Object previousConfig = null;
|
||||
for (SecurityConfigurer<Filter, WebSecurity> config : webSecurityConfigurers) {
|
||||
|
|
|
@ -18,7 +18,6 @@ package org.springframework.security.config.annotation.web.configuration;
|
|||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
@ -200,34 +199,17 @@ public abstract class WebSecurityConfigurerAdapter implements WebSecurityConfigu
|
|||
if (this.http != null) {
|
||||
return this.http;
|
||||
}
|
||||
|
||||
AuthenticationEventPublisher eventPublisher = getAuthenticationEventPublisher();
|
||||
this.localConfigureAuthenticationBldr.authenticationEventPublisher(eventPublisher);
|
||||
|
||||
AuthenticationManager authenticationManager = authenticationManager();
|
||||
this.authenticationBuilder.parentAuthenticationManager(authenticationManager);
|
||||
Map<Class<?>, Object> sharedObjects = createSharedObjects();
|
||||
|
||||
this.http = new HttpSecurity(this.objectPostProcessor, this.authenticationBuilder, sharedObjects);
|
||||
if (!this.disableDefaults) {
|
||||
// @formatter:off
|
||||
this.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
|
||||
applyDefaultConfiguration(this.http);
|
||||
ClassLoader classLoader = this.context.getClassLoader();
|
||||
List<AbstractHttpConfigurer> defaultHttpConfigurers = SpringFactoriesLoader
|
||||
.loadFactories(AbstractHttpConfigurer.class, classLoader);
|
||||
|
||||
for (AbstractHttpConfigurer configurer : defaultHttpConfigurers) {
|
||||
this.http.apply(configurer);
|
||||
}
|
||||
|
@ -236,6 +218,20 @@ public abstract class WebSecurityConfigurerAdapter implements WebSecurityConfigu
|
|||
return this.http;
|
||||
}
|
||||
|
||||
private void applyDefaultConfiguration(HttpSecurity http) throws Exception {
|
||||
http.csrf();
|
||||
http.addFilter(new WebAsyncManagerIntegrationFilter());
|
||||
http.exceptionHandling();
|
||||
http.headers();
|
||||
http.sessionManagement();
|
||||
http.securityContext();
|
||||
http.requestCache();
|
||||
http.anonymous();
|
||||
http.servletApi();
|
||||
http.apply(new DefaultLoginPageConfigurer<>());
|
||||
http.logout();
|
||||
}
|
||||
|
||||
/**
|
||||
* Override this method to expose the {@link AuthenticationManager} from
|
||||
* {@link #configure(AuthenticationManagerBuilder)} to be exposed as a Bean. For
|
||||
|
@ -315,8 +311,8 @@ public abstract class WebSecurityConfigurerAdapter implements WebSecurityConfigu
|
|||
}
|
||||
|
||||
@Override
|
||||
public void init(final WebSecurity web) throws Exception {
|
||||
final HttpSecurity http = getHttp();
|
||||
public void init(WebSecurity web) throws Exception {
|
||||
HttpSecurity http = getHttp();
|
||||
web.addSecurityFilterChainBuilder(http).postBuildAction(() -> {
|
||||
FilterSecurityInterceptor securityInterceptor = http.getSharedObject(FilterSecurityInterceptor.class);
|
||||
web.securityInterceptor(securityInterceptor);
|
||||
|
@ -354,17 +350,11 @@ public abstract class WebSecurityConfigurerAdapter implements WebSecurityConfigu
|
|||
* @throws Exception if an error occurs
|
||||
*/
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
this.logger.debug(
|
||||
"Using default configure(HttpSecurity). If subclassed this will potentially override subclass configure(HttpSecurity).");
|
||||
|
||||
// @formatter:off
|
||||
http
|
||||
.authorizeRequests()
|
||||
.anyRequest().authenticated()
|
||||
.and()
|
||||
.formLogin().and()
|
||||
.httpBasic();
|
||||
// @formatter:on
|
||||
this.logger.debug("Using default configure(HttpSecurity). "
|
||||
+ "If subclassed this will potentially override subclass configure(HttpSecurity).");
|
||||
http.authorizeRequests((requests) -> requests.anyRequest().authenticated());
|
||||
http.formLogin();
|
||||
http.httpBasic();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -378,14 +368,13 @@ public abstract class WebSecurityConfigurerAdapter implements WebSecurityConfigu
|
|||
@Autowired
|
||||
public void setApplicationContext(ApplicationContext context) {
|
||||
this.context = context;
|
||||
|
||||
ObjectPostProcessor<Object> objectPostProcessor = context.getBean(ObjectPostProcessor.class);
|
||||
LazyPasswordEncoder passwordEncoder = new LazyPasswordEncoder(context);
|
||||
|
||||
this.authenticationBuilder = new DefaultPasswordEncoderAuthenticationManagerBuilder(objectPostProcessor,
|
||||
passwordEncoder);
|
||||
this.localConfigureAuthenticationBldr = new DefaultPasswordEncoderAuthenticationManagerBuilder(
|
||||
objectPostProcessor, passwordEncoder) {
|
||||
|
||||
@Override
|
||||
public AuthenticationManagerBuilder eraseCredentials(boolean eraseCredentials) {
|
||||
WebSecurityConfigurerAdapter.this.authenticationBuilder.eraseCredentials(eraseCredentials);
|
||||
|
@ -398,6 +387,7 @@ public abstract class WebSecurityConfigurerAdapter implements WebSecurityConfigu
|
|||
WebSecurityConfigurerAdapter.this.authenticationBuilder.authenticationEventPublisher(eventPublisher);
|
||||
return super.authenticationEventPublisher(eventPublisher);
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -458,10 +448,8 @@ public abstract class WebSecurityConfigurerAdapter implements WebSecurityConfigu
|
|||
private final Object delegateMonitor = new Object();
|
||||
|
||||
UserDetailsServiceDelegator(List<AuthenticationManagerBuilder> delegateBuilders) {
|
||||
if (delegateBuilders.contains(null)) {
|
||||
throw new IllegalArgumentException(
|
||||
"delegateBuilders cannot contain null values. Got " + delegateBuilders);
|
||||
}
|
||||
Assert.isTrue(!delegateBuilders.contains(null),
|
||||
() -> "delegateBuilders cannot contain null values. Got " + delegateBuilders);
|
||||
this.delegateBuilders = delegateBuilders;
|
||||
}
|
||||
|
||||
|
@ -470,7 +458,6 @@ public abstract class WebSecurityConfigurerAdapter implements WebSecurityConfigu
|
|||
if (this.delegate != null) {
|
||||
return this.delegate.loadUserByUsername(username);
|
||||
}
|
||||
|
||||
synchronized (this.delegateMonitor) {
|
||||
if (this.delegate == null) {
|
||||
for (AuthenticationManagerBuilder delegateBuilder : this.delegateBuilders) {
|
||||
|
@ -479,14 +466,12 @@ public abstract class WebSecurityConfigurerAdapter implements WebSecurityConfigu
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.delegate == null) {
|
||||
throw new IllegalStateException("UserDetailsService is required.");
|
||||
}
|
||||
this.delegateBuilders = null;
|
||||
}
|
||||
}
|
||||
|
||||
return this.delegate.loadUserByUsername(username);
|
||||
}
|
||||
|
||||
|
@ -524,14 +509,12 @@ public abstract class WebSecurityConfigurerAdapter implements WebSecurityConfigu
|
|||
if (this.delegate != null) {
|
||||
return this.delegate.authenticate(authentication);
|
||||
}
|
||||
|
||||
synchronized (this.delegateMonitor) {
|
||||
if (this.delegate == null) {
|
||||
this.delegate = this.delegateBuilder.getObject();
|
||||
this.delegateBuilder = null;
|
||||
}
|
||||
}
|
||||
|
||||
return this.delegate.authenticate(authentication);
|
||||
}
|
||||
|
||||
|
@ -542,19 +525,18 @@ public abstract class WebSecurityConfigurerAdapter implements WebSecurityConfigu
|
|||
}
|
||||
|
||||
private static void validateBeanCycle(Object auth, Set<String> 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();
|
||||
if (auth == null || beanNames.isEmpty() || !(auth instanceof Advised)) {
|
||||
return;
|
||||
}
|
||||
TargetSource targetSource = ((Advised) auth).getTargetSource();
|
||||
if (!(targetSource instanceof LazyInitTargetSource)) {
|
||||
return;
|
||||
}
|
||||
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.");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -634,7 +616,7 @@ public abstract class WebSecurityConfigurerAdapter implements WebSecurityConfigu
|
|||
try {
|
||||
return this.applicationContext.getBean(type);
|
||||
}
|
||||
catch (NoSuchBeanDefinitionException notFound) {
|
||||
catch (NoSuchBeanDefinitionException ex) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -253,15 +253,12 @@ public abstract class AbstractAuthenticationFilterConfigurer<B extends HttpSecur
|
|||
if (contentNegotiationStrategy == null) {
|
||||
contentNegotiationStrategy = new HeaderContentNegotiationStrategy();
|
||||
}
|
||||
|
||||
MediaTypeRequestMatcher mediaMatcher = new MediaTypeRequestMatcher(contentNegotiationStrategy,
|
||||
MediaType.APPLICATION_XHTML_XML, new MediaType("image", "*"), MediaType.TEXT_HTML,
|
||||
MediaType.TEXT_PLAIN);
|
||||
mediaMatcher.setIgnoredMediaTypes(Collections.singleton(MediaType.ALL));
|
||||
|
||||
RequestMatcher notXRequestedWith = new NegatedRequestMatcher(
|
||||
new RequestHeaderRequestMatcher("X-Requested-With", "XMLHttpRequest"));
|
||||
|
||||
return new AndRequestMatcher(Arrays.asList(notXRequestedWith, mediaMatcher));
|
||||
}
|
||||
|
||||
|
@ -271,12 +268,10 @@ public abstract class AbstractAuthenticationFilterConfigurer<B extends HttpSecur
|
|||
if (portMapper != null) {
|
||||
this.authenticationEntryPoint.setPortMapper(portMapper);
|
||||
}
|
||||
|
||||
RequestCache requestCache = http.getSharedObject(RequestCache.class);
|
||||
if (requestCache != null) {
|
||||
this.defaultSuccessHandler.setRequestCache(requestCache);
|
||||
}
|
||||
|
||||
this.authFilter.setAuthenticationManager(http.getSharedObject(AuthenticationManager.class));
|
||||
this.authFilter.setAuthenticationSuccessHandler(this.successHandler);
|
||||
this.authFilter.setAuthenticationFailureHandler(this.failureHandler);
|
||||
|
@ -383,8 +378,7 @@ public abstract class AbstractAuthenticationFilterConfigurer<B extends HttpSecur
|
|||
if (this.failureHandler == null) {
|
||||
failureUrl(this.loginPage + "?error");
|
||||
}
|
||||
|
||||
final LogoutConfigurer<B> logoutConfigurer = getBuilder().getConfigurer(LogoutConfigurer.class);
|
||||
LogoutConfigurer<B> logoutConfigurer = getBuilder().getConfigurer(LogoutConfigurer.class);
|
||||
if (logoutConfigurer != null && !logoutConfigurer.isCustomLogoutSuccess()) {
|
||||
logoutConfigurer.logoutSuccessUrl(this.loginPage + "?logout");
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ import java.util.List;
|
|||
import org.springframework.security.access.ConfigAttribute;
|
||||
import org.springframework.security.config.annotation.web.AbstractRequestMatcherRegistry;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A base class for registering {@link RequestMatcher}'s. For example, it might allow for
|
||||
|
@ -102,11 +103,8 @@ public abstract class AbstractConfigAttributeRequestMatcherRegistry<C> extends A
|
|||
* {@link ConfigAttribute} instances. Cannot be null.
|
||||
*/
|
||||
final LinkedHashMap<RequestMatcher, Collection<ConfigAttribute>> createRequestMap() {
|
||||
if (this.unmappedMatchers != null) {
|
||||
throw new IllegalStateException("An incomplete mapping was found for " + this.unmappedMatchers
|
||||
+ ". Try completing it with something like requestUrls().<something>.hasRole('USER')");
|
||||
}
|
||||
|
||||
Assert.state(this.unmappedMatchers == null, () -> "An incomplete mapping was found for " + this.unmappedMatchers
|
||||
+ ". Try completing it with something like requestUrls().<something>.hasRole('USER')");
|
||||
LinkedHashMap<RequestMatcher, Collection<ConfigAttribute>> requestMap = new LinkedHashMap<>();
|
||||
for (UrlMapping mapping : getUrlMappings()) {
|
||||
RequestMatcher matcher = mapping.getRequestMatcher();
|
||||
|
|
|
@ -28,7 +28,6 @@ import org.springframework.security.web.DefaultSecurityFilterChain;
|
|||
* {@link HttpSecurity}.
|
||||
*
|
||||
* @author Rob Winch
|
||||
*
|
||||
*/
|
||||
public abstract class AbstractHttpConfigurer<T extends AbstractHttpConfigurer<T, B>, B extends HttpSecurityBuilder<B>>
|
||||
extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, B> {
|
||||
|
|
|
@ -105,13 +105,10 @@ public final class ChannelSecurityConfigurer<H extends HttpSecurityBuilder<H>>
|
|||
ChannelDecisionManagerImpl channelDecisionManager = new ChannelDecisionManagerImpl();
|
||||
channelDecisionManager.setChannelProcessors(getChannelProcessors(http));
|
||||
channelDecisionManager = postProcess(channelDecisionManager);
|
||||
|
||||
this.channelFilter.setChannelDecisionManager(channelDecisionManager);
|
||||
|
||||
DefaultFilterInvocationSecurityMetadataSource filterInvocationSecurityMetadataSource = new DefaultFilterInvocationSecurityMetadataSource(
|
||||
this.requestMap);
|
||||
this.channelFilter.setSecurityMetadataSource(filterInvocationSecurityMetadataSource);
|
||||
|
||||
this.channelFilter = postProcess(this.channelFilter);
|
||||
http.addFilter(this.channelFilter);
|
||||
}
|
||||
|
@ -120,28 +117,25 @@ public final class ChannelSecurityConfigurer<H extends HttpSecurityBuilder<H>>
|
|||
if (this.channelProcessors != null) {
|
||||
return this.channelProcessors;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
RetryWithHttpsEntryPoint httpsEntryPoint = new RetryWithHttpsEntryPoint();
|
||||
httpsEntryPoint.setPortMapper(portMapper);
|
||||
secureChannelProcessor.setEntryPoint(httpsEntryPoint);
|
||||
}
|
||||
insecureChannelProcessor = postProcess(insecureChannelProcessor);
|
||||
secureChannelProcessor = postProcess(secureChannelProcessor);
|
||||
return Arrays.<ChannelProcessor>asList(insecureChannelProcessor, secureChannelProcessor);
|
||||
return Arrays.asList(insecureChannelProcessor, secureChannelProcessor);
|
||||
}
|
||||
|
||||
private ChannelRequestMatcherRegistry addAttribute(String attribute, List<? extends RequestMatcher> matchers) {
|
||||
for (RequestMatcher matcher : matchers) {
|
||||
Collection<ConfigAttribute> attrs = Arrays.<ConfigAttribute>asList(new SecurityConfig(attribute));
|
||||
Collection<ConfigAttribute> attrs = Arrays.asList(new SecurityConfig(attribute));
|
||||
this.requestMap.put(matcher, attrs);
|
||||
}
|
||||
return this.REGISTRY;
|
||||
|
|
|
@ -20,6 +20,7 @@ import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
|||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.web.cors.CorsConfiguration;
|
||||
import org.springframework.web.cors.CorsConfigurationSource;
|
||||
|
@ -63,12 +64,9 @@ public class CorsConfigurer<H extends HttpSecurityBuilder<H>> extends AbstractHt
|
|||
@Override
|
||||
public void configure(H http) {
|
||||
ApplicationContext context = http.getSharedObject(ApplicationContext.class);
|
||||
|
||||
CorsFilter corsFilter = getCorsFilter(context);
|
||||
if (corsFilter == null) {
|
||||
throw new IllegalStateException("Please configure either a " + CORS_FILTER_BEAN_NAME + " bean or a "
|
||||
+ CORS_CONFIGURATION_SOURCE_BEAN_NAME + "bean.");
|
||||
}
|
||||
Assert.state(corsFilter != null, () -> "Please configure either a " + CORS_FILTER_BEAN_NAME + " bean or a "
|
||||
+ CORS_CONFIGURATION_SOURCE_BEAN_NAME + "bean.");
|
||||
http.addFilter(corsFilter);
|
||||
}
|
||||
|
||||
|
@ -76,19 +74,16 @@ public class CorsConfigurer<H extends HttpSecurityBuilder<H>> extends AbstractHt
|
|||
if (this.configurationSource != null) {
|
||||
return new CorsFilter(this.configurationSource);
|
||||
}
|
||||
|
||||
boolean containsCorsFilter = context.containsBeanDefinition(CORS_FILTER_BEAN_NAME);
|
||||
if (containsCorsFilter) {
|
||||
return context.getBean(CORS_FILTER_BEAN_NAME, CorsFilter.class);
|
||||
}
|
||||
|
||||
boolean containsCorsSource = context.containsBean(CORS_CONFIGURATION_SOURCE_BEAN_NAME);
|
||||
if (containsCorsSource) {
|
||||
CorsConfigurationSource configurationSource = context.getBean(CORS_CONFIGURATION_SOURCE_BEAN_NAME,
|
||||
CorsConfigurationSource.class);
|
||||
return new CorsFilter(configurationSource);
|
||||
}
|
||||
|
||||
boolean mvcPresent = ClassUtils.isPresent(HANDLER_MAPPING_INTROSPECTOR, context.getClassLoader());
|
||||
if (mvcPresent) {
|
||||
return MvcCorsFilter.getMvcCorsFilter(context);
|
||||
|
|
|
@ -289,7 +289,6 @@ public final class CsrfConfigurer<H extends HttpSecurityBuilder<H>>
|
|||
if (invalidSessionStrategy == null) {
|
||||
return defaultAccessDeniedHandler;
|
||||
}
|
||||
|
||||
InvalidSessionAccessDeniedHandler invalidSessionDeniedHandler = new InvalidSessionAccessDeniedHandler(
|
||||
invalidSessionStrategy);
|
||||
LinkedHashMap<Class<? extends AccessDeniedException>, AccessDeniedHandler> handlers = new LinkedHashMap<>();
|
||||
|
@ -307,9 +306,7 @@ public final class CsrfConfigurer<H extends HttpSecurityBuilder<H>>
|
|||
if (this.sessionAuthenticationStrategy != null) {
|
||||
return this.sessionAuthenticationStrategy;
|
||||
}
|
||||
else {
|
||||
return new CsrfAuthenticationStrategy(this.csrfTokenRepository);
|
||||
}
|
||||
return new CsrfAuthenticationStrategy(this.csrfTokenRepository);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -18,7 +18,6 @@ package org.springframework.security.config.annotation.web.configurers;
|
|||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
|
@ -76,18 +75,17 @@ public final class DefaultLoginPageConfigurer<H extends HttpSecurityBuilder<H>>
|
|||
|
||||
@Override
|
||||
public void init(H http) {
|
||||
Function<HttpServletRequest, Map<String, String>> hiddenInputs = (request) -> {
|
||||
CsrfToken token = (CsrfToken) request.getAttribute(CsrfToken.class.getName());
|
||||
if (token == null) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
return Collections.singletonMap(token.getParameterName(), token.getToken());
|
||||
};
|
||||
this.loginPageGeneratingFilter.setResolveHiddenInputs(hiddenInputs);
|
||||
this.logoutPageGeneratingFilter.setResolveHiddenInputs(hiddenInputs);
|
||||
this.loginPageGeneratingFilter.setResolveHiddenInputs(DefaultLoginPageConfigurer.this::hiddenInputs);
|
||||
this.logoutPageGeneratingFilter.setResolveHiddenInputs(DefaultLoginPageConfigurer.this::hiddenInputs);
|
||||
http.setSharedObject(DefaultLoginPageGeneratingFilter.class, this.loginPageGeneratingFilter);
|
||||
}
|
||||
|
||||
private Map<String, String> hiddenInputs(HttpServletRequest request) {
|
||||
CsrfToken token = (CsrfToken) request.getAttribute(CsrfToken.class.getName());
|
||||
return (token != null) ? Collections.singletonMap(token.getParameterName(), token.getToken())
|
||||
: Collections.emptyMap();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void configure(H http) {
|
||||
|
@ -96,7 +94,6 @@ public final class DefaultLoginPageConfigurer<H extends HttpSecurityBuilder<H>>
|
|||
if (exceptionConf != null) {
|
||||
authenticationEntryPoint = exceptionConf.getAuthenticationEntryPoint();
|
||||
}
|
||||
|
||||
if (this.loginPageGeneratingFilter.isEnabled() && authenticationEntryPoint == null) {
|
||||
this.loginPageGeneratingFilter = postProcess(this.loginPageGeneratingFilter);
|
||||
http.addFilter(this.loginPageGeneratingFilter);
|
||||
|
|
|
@ -139,44 +139,40 @@ public final class ExpressionUrlAuthorizationConfigurer<H extends HttpSecurityBu
|
|||
@Override
|
||||
ExpressionBasedFilterInvocationSecurityMetadataSource createMetadataSource(H http) {
|
||||
LinkedHashMap<RequestMatcher, Collection<ConfigAttribute>> requestMap = this.REGISTRY.createRequestMap();
|
||||
if (requestMap.isEmpty()) {
|
||||
throw new IllegalStateException(
|
||||
"At least one mapping is required (i.e. authorizeRequests().anyRequest().authenticated())");
|
||||
}
|
||||
Assert.state(!requestMap.isEmpty(),
|
||||
"At least one mapping is required (i.e. authorizeRequests().anyRequest().authenticated())");
|
||||
return new ExpressionBasedFilterInvocationSecurityMetadataSource(requestMap, getExpressionHandler(http));
|
||||
}
|
||||
|
||||
private SecurityExpressionHandler<FilterInvocation> getExpressionHandler(H http) {
|
||||
if (this.expressionHandler == null) {
|
||||
DefaultWebSecurityExpressionHandler defaultHandler = new DefaultWebSecurityExpressionHandler();
|
||||
AuthenticationTrustResolver trustResolver = http.getSharedObject(AuthenticationTrustResolver.class);
|
||||
if (trustResolver != null) {
|
||||
defaultHandler.setTrustResolver(trustResolver);
|
||||
}
|
||||
ApplicationContext context = http.getSharedObject(ApplicationContext.class);
|
||||
if (context != null) {
|
||||
String[] roleHiearchyBeanNames = context.getBeanNamesForType(RoleHierarchy.class);
|
||||
if (roleHiearchyBeanNames.length == 1) {
|
||||
defaultHandler.setRoleHierarchy(context.getBean(roleHiearchyBeanNames[0], RoleHierarchy.class));
|
||||
}
|
||||
String[] grantedAuthorityDefaultsBeanNames = context
|
||||
.getBeanNamesForType(GrantedAuthorityDefaults.class);
|
||||
if (grantedAuthorityDefaultsBeanNames.length == 1) {
|
||||
GrantedAuthorityDefaults grantedAuthorityDefaults = context
|
||||
.getBean(grantedAuthorityDefaultsBeanNames[0], GrantedAuthorityDefaults.class);
|
||||
defaultHandler.setDefaultRolePrefix(grantedAuthorityDefaults.getRolePrefix());
|
||||
}
|
||||
String[] permissionEvaluatorBeanNames = context.getBeanNamesForType(PermissionEvaluator.class);
|
||||
if (permissionEvaluatorBeanNames.length == 1) {
|
||||
PermissionEvaluator permissionEvaluator = context.getBean(permissionEvaluatorBeanNames[0],
|
||||
PermissionEvaluator.class);
|
||||
defaultHandler.setPermissionEvaluator(permissionEvaluator);
|
||||
}
|
||||
}
|
||||
|
||||
this.expressionHandler = postProcess(defaultHandler);
|
||||
if (this.expressionHandler != null) {
|
||||
return this.expressionHandler;
|
||||
}
|
||||
|
||||
DefaultWebSecurityExpressionHandler defaultHandler = new DefaultWebSecurityExpressionHandler();
|
||||
AuthenticationTrustResolver trustResolver = http.getSharedObject(AuthenticationTrustResolver.class);
|
||||
if (trustResolver != null) {
|
||||
defaultHandler.setTrustResolver(trustResolver);
|
||||
}
|
||||
ApplicationContext context = http.getSharedObject(ApplicationContext.class);
|
||||
if (context != null) {
|
||||
String[] roleHiearchyBeanNames = context.getBeanNamesForType(RoleHierarchy.class);
|
||||
if (roleHiearchyBeanNames.length == 1) {
|
||||
defaultHandler.setRoleHierarchy(context.getBean(roleHiearchyBeanNames[0], RoleHierarchy.class));
|
||||
}
|
||||
String[] grantedAuthorityDefaultsBeanNames = context.getBeanNamesForType(GrantedAuthorityDefaults.class);
|
||||
if (grantedAuthorityDefaultsBeanNames.length == 1) {
|
||||
GrantedAuthorityDefaults grantedAuthorityDefaults = context
|
||||
.getBean(grantedAuthorityDefaultsBeanNames[0], GrantedAuthorityDefaults.class);
|
||||
defaultHandler.setDefaultRolePrefix(grantedAuthorityDefaults.getRolePrefix());
|
||||
}
|
||||
String[] permissionEvaluatorBeanNames = context.getBeanNamesForType(PermissionEvaluator.class);
|
||||
if (permissionEvaluatorBeanNames.length == 1) {
|
||||
PermissionEvaluator permissionEvaluator = context.getBean(permissionEvaluatorBeanNames[0],
|
||||
PermissionEvaluator.class);
|
||||
defaultHandler.setPermissionEvaluator(permissionEvaluator);
|
||||
}
|
||||
}
|
||||
this.expressionHandler = postProcess(defaultHandler);
|
||||
return this.expressionHandler;
|
||||
}
|
||||
|
||||
|
@ -187,10 +183,8 @@ public final class ExpressionUrlAuthorizationConfigurer<H extends HttpSecurityBu
|
|||
|
||||
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 + "'");
|
||||
}
|
||||
Assert.isTrue(!role.startsWith("ROLE_"),
|
||||
() -> "role should not start with 'ROLE_' since it is automatically inserted. Got '" + role + "'");
|
||||
return "hasRole('ROLE_" + role + "')";
|
||||
}
|
||||
|
||||
|
@ -210,9 +204,6 @@ public final class ExpressionUrlAuthorizationConfigurer<H extends HttpSecurityBu
|
|||
public final class ExpressionInterceptUrlRegistry extends
|
||||
ExpressionUrlAuthorizationConfigurer<H>.AbstractInterceptUrlRegistry<ExpressionInterceptUrlRegistry, AuthorizedUrl> {
|
||||
|
||||
/**
|
||||
* @param context
|
||||
*/
|
||||
private ExpressionInterceptUrlRegistry(ApplicationContext context) {
|
||||
setApplicationContext(context);
|
||||
}
|
||||
|
|
|
@ -329,7 +329,6 @@ public class HeadersConfigurer<H extends HttpSecurityBuilder<H>>
|
|||
Customizer<ContentSecurityPolicyConfig> contentSecurityCustomizer) {
|
||||
this.contentSecurityPolicy.writer = new ContentSecurityPolicyHeaderWriter();
|
||||
contentSecurityCustomizer.customize(this.contentSecurityPolicy);
|
||||
|
||||
return HeadersConfigurer.this;
|
||||
}
|
||||
|
||||
|
|
|
@ -97,10 +97,8 @@ public final class HttpBasicConfigurer<B extends HttpSecurityBuilder<B>>
|
|||
*/
|
||||
public HttpBasicConfigurer() {
|
||||
realmName(DEFAULT_REALM);
|
||||
|
||||
LinkedHashMap<RequestMatcher, AuthenticationEntryPoint> entryPoints = new LinkedHashMap<>();
|
||||
entryPoints.put(X_REQUESTED_WITH, new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED));
|
||||
|
||||
DelegatingAuthenticationEntryPoint defaultEntryPoint = new DelegatingAuthenticationEntryPoint(entryPoints);
|
||||
defaultEntryPoint.setDefaultEntryPoint(this.basicAuthEntryPoint);
|
||||
this.authenticationEntryPoint = defaultEntryPoint;
|
||||
|
@ -154,24 +152,19 @@ public final class HttpBasicConfigurer<B extends HttpSecurityBuilder<B>>
|
|||
if (contentNegotiationStrategy == null) {
|
||||
contentNegotiationStrategy = new HeaderContentNegotiationStrategy();
|
||||
}
|
||||
|
||||
MediaTypeRequestMatcher restMatcher = 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);
|
||||
restMatcher.setIgnoredMediaTypes(Collections.singleton(MediaType.ALL));
|
||||
|
||||
MediaTypeRequestMatcher allMatcher = new MediaTypeRequestMatcher(contentNegotiationStrategy, MediaType.ALL);
|
||||
allMatcher.setUseEquals(true);
|
||||
|
||||
RequestMatcher notHtmlMatcher = new NegatedRequestMatcher(
|
||||
new MediaTypeRequestMatcher(contentNegotiationStrategy, MediaType.TEXT_HTML));
|
||||
RequestMatcher restNotHtmlMatcher = new AndRequestMatcher(
|
||||
Arrays.<RequestMatcher>asList(notHtmlMatcher, restMatcher));
|
||||
|
||||
RequestMatcher preferredMatcher = new OrRequestMatcher(
|
||||
Arrays.asList(X_REQUESTED_WITH, restNotHtmlMatcher, allMatcher));
|
||||
|
||||
registerDefaultEntryPoint(http, preferredMatcher);
|
||||
registerDefaultLogoutSuccessHandler(http, preferredMatcher);
|
||||
}
|
||||
|
|
|
@ -192,12 +192,8 @@ public final class JeeConfigurer<H extends HttpSecurityBuilder<H>> extends Abstr
|
|||
PreAuthenticatedAuthenticationProvider authenticationProvider = new PreAuthenticatedAuthenticationProvider();
|
||||
authenticationProvider.setPreAuthenticatedUserDetailsService(getUserDetailsService());
|
||||
authenticationProvider = postProcess(authenticationProvider);
|
||||
|
||||
// @formatter:off
|
||||
http
|
||||
.authenticationProvider(authenticationProvider)
|
||||
.setSharedObject(AuthenticationEntryPoint.class, new Http403ForbiddenEntryPoint());
|
||||
// @formatter:on
|
||||
http.authenticationProvider(authenticationProvider).setSharedObject(AuthenticationEntryPoint.class,
|
||||
new Http403ForbiddenEntryPoint());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -245,7 +241,6 @@ public final class JeeConfigurer<H extends HttpSecurityBuilder<H>> extends Abstr
|
|||
SimpleMappableAttributesRetriever rolesRetriever = new SimpleMappableAttributesRetriever();
|
||||
rolesRetriever.setMappableAttributes(this.mappableRoles);
|
||||
detailsSource.setMappableRolesRetriever(rolesRetriever);
|
||||
|
||||
detailsSource = postProcess(detailsSource);
|
||||
return detailsSource;
|
||||
}
|
||||
|
|
|
@ -276,7 +276,6 @@ public final class LogoutConfigurer<H extends HttpSecurityBuilder<H>>
|
|||
PermitAllSupport.permitAll(http, this.logoutSuccessUrl);
|
||||
PermitAllSupport.permitAll(http, this.getLogoutRequestMatcher(http));
|
||||
}
|
||||
|
||||
DefaultLoginPageGeneratingFilter loginPageGeneratingFilter = http
|
||||
.getSharedObject(DefaultLoginPageGeneratingFilter.class);
|
||||
if (loginPageGeneratingFilter != null && !isCustomLogoutSuccess()) {
|
||||
|
@ -334,20 +333,28 @@ public final class LogoutConfigurer<H extends HttpSecurityBuilder<H>>
|
|||
return result;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private RequestMatcher getLogoutRequestMatcher(H http) {
|
||||
if (this.logoutRequestMatcher != null) {
|
||||
return this.logoutRequestMatcher;
|
||||
}
|
||||
if (http.getConfigurer(CsrfConfigurer.class) != null) {
|
||||
this.logoutRequestMatcher = new AntPathRequestMatcher(this.logoutUrl, "POST");
|
||||
}
|
||||
else {
|
||||
this.logoutRequestMatcher = new OrRequestMatcher(new AntPathRequestMatcher(this.logoutUrl, "GET"),
|
||||
new AntPathRequestMatcher(this.logoutUrl, "POST"), new AntPathRequestMatcher(this.logoutUrl, "PUT"),
|
||||
new AntPathRequestMatcher(this.logoutUrl, "DELETE"));
|
||||
}
|
||||
this.logoutRequestMatcher = createLogoutRequestMatcher(http);
|
||||
return this.logoutRequestMatcher;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private RequestMatcher createLogoutRequestMatcher(H http) {
|
||||
RequestMatcher post = createLogoutRequestMatcher("POST");
|
||||
if (http.getConfigurer(CsrfConfigurer.class) != null) {
|
||||
return post;
|
||||
}
|
||||
RequestMatcher get = createLogoutRequestMatcher("GET");
|
||||
RequestMatcher put = createLogoutRequestMatcher("PUT");
|
||||
RequestMatcher delete = createLogoutRequestMatcher("DELETE");
|
||||
return new OrRequestMatcher(get, post, put, delete);
|
||||
}
|
||||
|
||||
private RequestMatcher createLogoutRequestMatcher(String httpMethod) {
|
||||
return new AntPathRequestMatcher(this.logoutUrl, httpMethod);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ import org.springframework.security.access.SecurityConfig;
|
|||
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;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Configures non-null URL's to grant access to every URL
|
||||
|
@ -47,11 +48,7 @@ final class PermitAllSupport {
|
|||
RequestMatcher... requestMatchers) {
|
||||
ExpressionUrlAuthorizationConfigurer<?> configurer = http
|
||||
.getConfigurer(ExpressionUrlAuthorizationConfigurer.class);
|
||||
|
||||
if (configurer == null) {
|
||||
throw new IllegalStateException("permitAll only works with HttpSecurity.authorizeRequests()");
|
||||
}
|
||||
|
||||
Assert.state(configurer != null, "permitAll only works with HttpSecurity.authorizeRequests()");
|
||||
for (RequestMatcher matcher : requestMatchers) {
|
||||
if (matcher != null) {
|
||||
configurer.getRegistry().addMapping(0, new UrlMapping(matcher,
|
||||
|
@ -72,15 +69,12 @@ final class PermitAllSupport {
|
|||
public boolean matches(HttpServletRequest request) {
|
||||
String uri = request.getRequestURI();
|
||||
String query = request.getQueryString();
|
||||
|
||||
if (query != null) {
|
||||
uri += "?" + query;
|
||||
}
|
||||
|
||||
if ("".equals(request.getContextPath())) {
|
||||
return uri.equals(this.processUrl);
|
||||
}
|
||||
|
||||
return uri.equals(request.getContextPath() + this.processUrl);
|
||||
}
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@ import org.springframework.security.web.authentication.rememberme.PersistentToke
|
|||
import org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter;
|
||||
import org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices;
|
||||
import org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Configures Remember Me authentication. This typically involves the user checking a box
|
||||
|
@ -275,11 +276,9 @@ public final class RememberMeConfigurer<H extends HttpSecurityBuilder<H>>
|
|||
if (logoutConfigurer != null && this.logoutHandler != null) {
|
||||
logoutConfigurer.addLogoutHandler(this.logoutHandler);
|
||||
}
|
||||
|
||||
RememberMeAuthenticationProvider authenticationProvider = new RememberMeAuthenticationProvider(key);
|
||||
authenticationProvider = postProcess(authenticationProvider);
|
||||
http.authenticationProvider(authenticationProvider);
|
||||
|
||||
initDefaultLoginFilter(http);
|
||||
}
|
||||
|
||||
|
@ -299,8 +298,8 @@ public final class RememberMeConfigurer<H extends HttpSecurityBuilder<H>>
|
|||
* time.
|
||||
*/
|
||||
private void validateInput() {
|
||||
if (this.rememberMeServices != null && this.rememberMeCookieName != DEFAULT_REMEMBER_ME_NAME) {
|
||||
throw new IllegalArgumentException("Can not set rememberMeCookieName " + "and custom rememberMeServices.");
|
||||
if (this.rememberMeServices != null && !DEFAULT_REMEMBER_ME_NAME.equals(this.rememberMeCookieName)) {
|
||||
throw new IllegalArgumentException("Can not set rememberMeCookieName and custom rememberMeServices.");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -406,11 +405,9 @@ public final class RememberMeConfigurer<H extends HttpSecurityBuilder<H>>
|
|||
if (this.userDetailsService == null) {
|
||||
this.userDetailsService = http.getSharedObject(UserDetailsService.class);
|
||||
}
|
||||
if (this.userDetailsService == null) {
|
||||
throw new IllegalStateException(
|
||||
"userDetailsService cannot be null. Invoke " + RememberMeConfigurer.class.getSimpleName()
|
||||
+ "#userDetailsService(UserDetailsService) or see its javadoc for alternative approaches.");
|
||||
}
|
||||
Assert.state(this.userDetailsService != null,
|
||||
() -> "userDetailsService cannot be null. Invoke " + RememberMeConfigurer.class.getSimpleName()
|
||||
+ "#userDetailsService(UserDetailsService) or see its javadoc for alternative approaches.");
|
||||
return this.userDetailsService;
|
||||
}
|
||||
|
||||
|
|
|
@ -145,12 +145,9 @@ public final class RequestCacheConfigurer<H extends HttpSecurityBuilder<H>>
|
|||
@SuppressWarnings("unchecked")
|
||||
private RequestMatcher createDefaultSavedRequestMatcher(H http) {
|
||||
RequestMatcher notFavIcon = new NegatedRequestMatcher(new AntPathRequestMatcher("/**/favicon.*"));
|
||||
|
||||
RequestMatcher notXRequestedWith = new NegatedRequestMatcher(
|
||||
new RequestHeaderRequestMatcher("X-Requested-With", "XMLHttpRequest"));
|
||||
|
||||
boolean isCsrfEnabled = http.getConfigurer(CsrfConfigurer.class) != null;
|
||||
|
||||
List<RequestMatcher> matchers = new ArrayList<>();
|
||||
if (isCsrfEnabled) {
|
||||
RequestMatcher getRequests = new AntPathRequestMatcher("/**", "GET");
|
||||
|
@ -161,7 +158,6 @@ public final class RequestCacheConfigurer<H extends HttpSecurityBuilder<H>>
|
|||
matchers.add(notXRequestedWith);
|
||||
matchers.add(notMatchingMediaType(http, MediaType.MULTIPART_FORM_DATA));
|
||||
matchers.add(notMatchingMediaType(http, MediaType.TEXT_EVENT_STREAM));
|
||||
|
||||
return new AndRequestMatcher(matchers);
|
||||
}
|
||||
|
||||
|
@ -170,7 +166,6 @@ public final class RequestCacheConfigurer<H extends HttpSecurityBuilder<H>>
|
|||
if (contentNegotiationStrategy == null) {
|
||||
contentNegotiationStrategy = new HeaderContentNegotiationStrategy();
|
||||
}
|
||||
|
||||
MediaTypeRequestMatcher mediaRequest = new MediaTypeRequestMatcher(contentNegotiationStrategy, mediaType);
|
||||
mediaRequest.setIgnoredMediaTypes(Collections.singleton(MediaType.ALL));
|
||||
return new NegatedRequestMatcher(mediaRequest);
|
||||
|
|
|
@ -82,7 +82,6 @@ public final class SecurityContextConfigurer<H extends HttpSecurityBuilder<H>>
|
|||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void configure(H http) {
|
||||
|
||||
SecurityContextRepository securityContextRepository = http.getSharedObject(SecurityContextRepository.class);
|
||||
if (securityContextRepository == null) {
|
||||
securityContextRepository = new HttpSessionSecurityContextRepository();
|
||||
|
|
|
@ -316,7 +316,6 @@ public final class SessionManagementConfigurer<H extends HttpSecurityBuilder<H>>
|
|||
public void init(H http) {
|
||||
SecurityContextRepository securityContextRepository = http.getSharedObject(SecurityContextRepository.class);
|
||||
boolean stateless = isStateless();
|
||||
|
||||
if (securityContextRepository == null) {
|
||||
if (stateless) {
|
||||
http.setSharedObject(SecurityContextRepository.class, new NullSecurityContextRepository());
|
||||
|
@ -332,7 +331,6 @@ public final class SessionManagementConfigurer<H extends HttpSecurityBuilder<H>>
|
|||
http.setSharedObject(SecurityContextRepository.class, httpSecurityRepository);
|
||||
}
|
||||
}
|
||||
|
||||
RequestCache requestCache = http.getSharedObject(RequestCache.class);
|
||||
if (requestCache == null) {
|
||||
if (stateless) {
|
||||
|
@ -365,7 +363,6 @@ public final class SessionManagementConfigurer<H extends HttpSecurityBuilder<H>>
|
|||
sessionManagementFilter.setTrustResolver(trustResolver);
|
||||
}
|
||||
sessionManagementFilter = postProcess(sessionManagementFilter);
|
||||
|
||||
http.addFilter(sessionManagementFilter);
|
||||
if (isConcurrentSessionControlEnabled()) {
|
||||
ConcurrentSessionFilter concurrentSessionFilter = createConcurrencyFilter(http);
|
||||
|
@ -378,13 +375,9 @@ public final class SessionManagementConfigurer<H extends HttpSecurityBuilder<H>>
|
|||
private ConcurrentSessionFilter createConcurrencyFilter(H http) {
|
||||
SessionInformationExpiredStrategy expireStrategy = getExpiredSessionStrategy();
|
||||
SessionRegistry sessionRegistry = getSessionRegistry(http);
|
||||
ConcurrentSessionFilter concurrentSessionFilter;
|
||||
if (expireStrategy == null) {
|
||||
concurrentSessionFilter = new ConcurrentSessionFilter(sessionRegistry);
|
||||
}
|
||||
else {
|
||||
concurrentSessionFilter = new ConcurrentSessionFilter(sessionRegistry, expireStrategy);
|
||||
}
|
||||
ConcurrentSessionFilter concurrentSessionFilter = (expireStrategy != null)
|
||||
? new ConcurrentSessionFilter(sessionRegistry, expireStrategy)
|
||||
: new ConcurrentSessionFilter(sessionRegistry);
|
||||
LogoutConfigurer<H> logoutConfigurer = http.getConfigurer(LogoutConfigurer.class);
|
||||
if (logoutConfigurer != null) {
|
||||
List<LogoutHandler> logoutHandlers = logoutConfigurer.getLogoutHandlers();
|
||||
|
@ -405,11 +398,9 @@ public final class SessionManagementConfigurer<H extends HttpSecurityBuilder<H>>
|
|||
if (this.invalidSessionStrategy != null) {
|
||||
return this.invalidSessionStrategy;
|
||||
}
|
||||
|
||||
if (this.invalidSessionUrl == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
this.invalidSessionStrategy = new SimpleRedirectInvalidSessionStrategy(this.invalidSessionUrl);
|
||||
return this.invalidSessionStrategy;
|
||||
}
|
||||
|
@ -418,11 +409,9 @@ public final class SessionManagementConfigurer<H extends HttpSecurityBuilder<H>>
|
|||
if (this.expiredSessionStrategy != null) {
|
||||
return this.expiredSessionStrategy;
|
||||
}
|
||||
|
||||
if (this.expiredUrl == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
this.expiredSessionStrategy = new SimpleRedirectSessionInformationExpiredStrategy(this.expiredUrl);
|
||||
return this.expiredSessionStrategy;
|
||||
}
|
||||
|
@ -431,11 +420,9 @@ public final class SessionManagementConfigurer<H extends HttpSecurityBuilder<H>>
|
|||
if (this.sessionAuthenticationFailureHandler != null) {
|
||||
return this.sessionAuthenticationFailureHandler;
|
||||
}
|
||||
|
||||
if (this.sessionAuthenticationErrorUrl == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
this.sessionAuthenticationFailureHandler = new SimpleUrlAuthenticationFailureHandler(
|
||||
this.sessionAuthenticationErrorUrl);
|
||||
return this.sessionAuthenticationFailureHandler;
|
||||
|
@ -449,7 +436,6 @@ public final class SessionManagementConfigurer<H extends HttpSecurityBuilder<H>>
|
|||
if (this.sessionPolicy != null) {
|
||||
return this.sessionPolicy;
|
||||
}
|
||||
|
||||
SessionCreationPolicy sessionPolicy = getBuilder().getSharedObject(SessionCreationPolicy.class);
|
||||
return (sessionPolicy != null) ? sessionPolicy : SessionCreationPolicy.IF_REQUIRED;
|
||||
}
|
||||
|
@ -628,6 +614,9 @@ public final class SessionManagementConfigurer<H extends HttpSecurityBuilder<H>>
|
|||
*/
|
||||
public final class ConcurrencyControlConfigurer {
|
||||
|
||||
private ConcurrencyControlConfigurer() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Controls the maximum number of sessions for a user. The default is to allow any
|
||||
* number of users.
|
||||
|
@ -699,9 +688,6 @@ public final class SessionManagementConfigurer<H extends HttpSecurityBuilder<H>>
|
|||
return SessionManagementConfigurer.this;
|
||||
}
|
||||
|
||||
private ConcurrencyControlConfigurer() {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -89,10 +89,10 @@ import org.springframework.util.Assert;
|
|||
public final class UrlAuthorizationConfigurer<H extends HttpSecurityBuilder<H>>
|
||||
extends AbstractInterceptUrlConfigurer<UrlAuthorizationConfigurer<H>, H> {
|
||||
|
||||
private final StandardInterceptUrlRegistry REGISTRY;
|
||||
private final StandardInterceptUrlRegistry registry;
|
||||
|
||||
public UrlAuthorizationConfigurer(ApplicationContext context) {
|
||||
this.REGISTRY = new StandardInterceptUrlRegistry(context);
|
||||
this.registry = new StandardInterceptUrlRegistry(context);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -101,7 +101,7 @@ public final class UrlAuthorizationConfigurer<H extends HttpSecurityBuilder<H>>
|
|||
* @return the {@link ExpressionUrlAuthorizationConfigurer} for further customizations
|
||||
*/
|
||||
public StandardInterceptUrlRegistry getRegistry() {
|
||||
return this.REGISTRY;
|
||||
return this.registry;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -136,7 +136,7 @@ public final class UrlAuthorizationConfigurer<H extends HttpSecurityBuilder<H>>
|
|||
*/
|
||||
@Override
|
||||
FilterInvocationSecurityMetadataSource createMetadataSource(H http) {
|
||||
return new DefaultFilterInvocationSecurityMetadataSource(this.REGISTRY.createRequestMap());
|
||||
return new DefaultFilterInvocationSecurityMetadataSource(this.registry.createRequestMap());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -151,10 +151,10 @@ public final class UrlAuthorizationConfigurer<H extends HttpSecurityBuilder<H>>
|
|||
private StandardInterceptUrlRegistry addMapping(Iterable<? extends RequestMatcher> requestMatchers,
|
||||
Collection<ConfigAttribute> configAttributes) {
|
||||
for (RequestMatcher requestMatcher : requestMatchers) {
|
||||
this.REGISTRY.addMapping(
|
||||
this.registry.addMapping(
|
||||
new AbstractConfigAttributeRequestMatcherRegistry.UrlMapping(requestMatcher, configAttributes));
|
||||
}
|
||||
return this.REGISTRY;
|
||||
return this.registry;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -196,9 +196,6 @@ public final class UrlAuthorizationConfigurer<H extends HttpSecurityBuilder<H>>
|
|||
public final class StandardInterceptUrlRegistry extends
|
||||
ExpressionUrlAuthorizationConfigurer<H>.AbstractInterceptUrlRegistry<StandardInterceptUrlRegistry, AuthorizedUrl> {
|
||||
|
||||
/**
|
||||
* @param context
|
||||
*/
|
||||
private StandardInterceptUrlRegistry(ApplicationContext context) {
|
||||
setApplicationContext(context);
|
||||
}
|
||||
|
@ -337,7 +334,7 @@ public final class UrlAuthorizationConfigurer<H extends HttpSecurityBuilder<H>>
|
|||
*/
|
||||
public StandardInterceptUrlRegistry access(String... attributes) {
|
||||
addMapping(this.requestMatchers, SecurityConfig.createList(attributes));
|
||||
return UrlAuthorizationConfigurer.this.REGISTRY;
|
||||
return UrlAuthorizationConfigurer.this.registry;
|
||||
}
|
||||
|
||||
protected List<? extends RequestMatcher> getMatchers() {
|
||||
|
|
|
@ -171,12 +171,8 @@ public final class X509Configurer<H extends HttpSecurityBuilder<H>>
|
|||
public void init(H http) {
|
||||
PreAuthenticatedAuthenticationProvider authenticationProvider = new PreAuthenticatedAuthenticationProvider();
|
||||
authenticationProvider.setPreAuthenticatedUserDetailsService(getAuthenticationUserDetailsService(http));
|
||||
|
||||
// @formatter:off
|
||||
http
|
||||
.authenticationProvider(authenticationProvider)
|
||||
.setSharedObject(AuthenticationEntryPoint.class, new Http403ForbiddenEntryPoint());
|
||||
// @formatter:on
|
||||
http.authenticationProvider(authenticationProvider).setSharedObject(AuthenticationEntryPoint.class,
|
||||
new Http403ForbiddenEntryPoint());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -197,7 +197,6 @@ public final class OAuth2ClientConfigurer<B extends HttpSecurityBuilder<B>>
|
|||
*/
|
||||
public AuthorizationCodeGrantConfigurer authorizationRequestRepository(
|
||||
AuthorizationRequestRepository<OAuth2AuthorizationRequest> authorizationRequestRepository) {
|
||||
|
||||
Assert.notNull(authorizationRequestRepository, "authorizationRequestRepository cannot be null");
|
||||
this.authorizationRequestRepository = authorizationRequestRepository;
|
||||
return this;
|
||||
|
@ -212,7 +211,6 @@ public final class OAuth2ClientConfigurer<B extends HttpSecurityBuilder<B>>
|
|||
*/
|
||||
public AuthorizationCodeGrantConfigurer accessTokenResponseClient(
|
||||
OAuth2AccessTokenResponseClient<OAuth2AuthorizationCodeGrantRequest> accessTokenResponseClient) {
|
||||
|
||||
Assert.notNull(accessTokenResponseClient, "accessTokenResponseClient cannot be null");
|
||||
this.accessTokenResponseClient = accessTokenResponseClient;
|
||||
return this;
|
||||
|
@ -245,7 +243,6 @@ public final class OAuth2ClientConfigurer<B extends HttpSecurityBuilder<B>>
|
|||
OAuth2AuthorizationRequestResolver resolver = getAuthorizationRequestResolver();
|
||||
OAuth2AuthorizationRequestRedirectFilter authorizationRequestRedirectFilter = new OAuth2AuthorizationRequestRedirectFilter(
|
||||
resolver);
|
||||
|
||||
if (this.authorizationRequestRepository != null) {
|
||||
authorizationRequestRedirectFilter
|
||||
.setAuthorizationRequestRepository(this.authorizationRequestRepository);
|
||||
|
@ -272,7 +269,6 @@ public final class OAuth2ClientConfigurer<B extends HttpSecurityBuilder<B>>
|
|||
OAuth2AuthorizationCodeGrantFilter authorizationCodeGrantFilter = new OAuth2AuthorizationCodeGrantFilter(
|
||||
OAuth2ClientConfigurerUtils.getClientRegistrationRepository(builder),
|
||||
OAuth2ClientConfigurerUtils.getAuthorizedClientRepository(builder), authenticationManager);
|
||||
|
||||
if (this.authorizationRequestRepository != null) {
|
||||
authorizationCodeGrantFilter.setAuthorizationRequestRepository(this.authorizationRequestRepository);
|
||||
}
|
||||
|
|
|
@ -291,7 +291,6 @@ public final class OAuth2LoginConfigurer<B extends HttpSecurityBuilder<B>>
|
|||
OAuth2ClientConfigurerUtils.getAuthorizedClientRepository(this.getBuilder()), this.loginProcessingUrl);
|
||||
this.setAuthenticationFilter(authenticationFilter);
|
||||
super.loginProcessingUrl(this.loginProcessingUrl);
|
||||
|
||||
if (this.loginPage != null) {
|
||||
// Set custom login page
|
||||
super.loginPage(this.loginPage);
|
||||
|
@ -311,12 +310,10 @@ public final class OAuth2LoginConfigurer<B extends HttpSecurityBuilder<B>>
|
|||
super.init(http);
|
||||
}
|
||||
}
|
||||
|
||||
OAuth2AccessTokenResponseClient<OAuth2AuthorizationCodeGrantRequest> accessTokenResponseClient = this.tokenEndpointConfig.accessTokenResponseClient;
|
||||
if (accessTokenResponseClient == null) {
|
||||
accessTokenResponseClient = new DefaultAuthorizationCodeTokenResponseClient();
|
||||
}
|
||||
|
||||
OAuth2UserService<OAuth2UserRequest, OAuth2User> oauth2UserService = getOAuth2UserService();
|
||||
OAuth2LoginAuthenticationProvider oauth2LoginAuthenticationProvider = new OAuth2LoginAuthenticationProvider(
|
||||
accessTokenResponseClient, oauth2UserService);
|
||||
|
@ -325,10 +322,8 @@ public final class OAuth2LoginConfigurer<B extends HttpSecurityBuilder<B>>
|
|||
oauth2LoginAuthenticationProvider.setAuthoritiesMapper(userAuthoritiesMapper);
|
||||
}
|
||||
http.authenticationProvider(this.postProcess(oauth2LoginAuthenticationProvider));
|
||||
|
||||
boolean oidcAuthenticationProviderEnabled = ClassUtils
|
||||
.isPresent("org.springframework.security.oauth2.jwt.JwtDecoder", this.getClass().getClassLoader());
|
||||
|
||||
if (oidcAuthenticationProviderEnabled) {
|
||||
OAuth2UserService<OidcUserRequest, OidcUser> oidcUserService = getOidcUserService();
|
||||
OidcAuthorizationCodeAuthenticationProvider oidcAuthorizationCodeAuthenticationProvider = new OidcAuthorizationCodeAuthenticationProvider(
|
||||
|
@ -345,14 +340,12 @@ public final class OAuth2LoginConfigurer<B extends HttpSecurityBuilder<B>>
|
|||
else {
|
||||
http.authenticationProvider(new OidcAuthenticationRequestChecker());
|
||||
}
|
||||
|
||||
this.initDefaultLoginFilter(http);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(B http) throws Exception {
|
||||
OAuth2AuthorizationRequestRedirectFilter authorizationRequestFilter;
|
||||
|
||||
if (this.authorizationEndpointConfig.authorizationRequestResolver != null) {
|
||||
authorizationRequestFilter = new OAuth2AuthorizationRequestRedirectFilter(
|
||||
this.authorizationEndpointConfig.authorizationRequestResolver);
|
||||
|
@ -366,7 +359,6 @@ public final class OAuth2LoginConfigurer<B extends HttpSecurityBuilder<B>>
|
|||
OAuth2ClientConfigurerUtils.getClientRegistrationRepository(this.getBuilder()),
|
||||
authorizationRequestBaseUri);
|
||||
}
|
||||
|
||||
if (this.authorizationEndpointConfig.authorizationRequestRepository != null) {
|
||||
authorizationRequestFilter
|
||||
.setAuthorizationRequestRepository(this.authorizationEndpointConfig.authorizationRequestRepository);
|
||||
|
@ -376,7 +368,6 @@ public final class OAuth2LoginConfigurer<B extends HttpSecurityBuilder<B>>
|
|||
authorizationRequestFilter.setRequestCache(requestCache);
|
||||
}
|
||||
http.addFilter(this.postProcess(authorizationRequestFilter));
|
||||
|
||||
OAuth2LoginAuthenticationFilter authenticationFilter = this.getAuthenticationFilter();
|
||||
if (this.redirectionEndpointConfig.authorizationResponseBaseUri != null) {
|
||||
authenticationFilter.setFilterProcessesUrl(this.redirectionEndpointConfig.authorizationResponseBaseUri);
|
||||
|
@ -433,11 +424,7 @@ public final class OAuth2LoginConfigurer<B extends HttpSecurityBuilder<B>>
|
|||
ResolvableType type = ResolvableType.forClassWithGenerics(OAuth2UserService.class, OidcUserRequest.class,
|
||||
OidcUser.class);
|
||||
OAuth2UserService<OidcUserRequest, OidcUser> bean = getBeanOrNull(type);
|
||||
if (bean == null) {
|
||||
return new OidcUserService();
|
||||
}
|
||||
|
||||
return bean;
|
||||
return (bean != null) ? bean : new OidcUserService();
|
||||
}
|
||||
|
||||
private OAuth2UserService<OAuth2UserRequest, OAuth2User> getOAuth2UserService() {
|
||||
|
@ -447,29 +434,25 @@ public final class OAuth2LoginConfigurer<B extends HttpSecurityBuilder<B>>
|
|||
ResolvableType type = ResolvableType.forClassWithGenerics(OAuth2UserService.class, OAuth2UserRequest.class,
|
||||
OAuth2User.class);
|
||||
OAuth2UserService<OAuth2UserRequest, OAuth2User> bean = getBeanOrNull(type);
|
||||
if (bean == null) {
|
||||
if (!this.userInfoEndpointConfig.customUserTypes.isEmpty()) {
|
||||
List<OAuth2UserService<OAuth2UserRequest, OAuth2User>> userServices = new ArrayList<>();
|
||||
userServices.add(new CustomUserTypesOAuth2UserService(this.userInfoEndpointConfig.customUserTypes));
|
||||
userServices.add(new DefaultOAuth2UserService());
|
||||
return new DelegatingOAuth2UserService<>(userServices);
|
||||
}
|
||||
else {
|
||||
return new DefaultOAuth2UserService();
|
||||
}
|
||||
if (bean != null) {
|
||||
return bean;
|
||||
}
|
||||
|
||||
return bean;
|
||||
if (this.userInfoEndpointConfig.customUserTypes.isEmpty()) {
|
||||
return new DefaultOAuth2UserService();
|
||||
}
|
||||
List<OAuth2UserService<OAuth2UserRequest, OAuth2User>> userServices = new ArrayList<>();
|
||||
userServices.add(new CustomUserTypesOAuth2UserService(this.userInfoEndpointConfig.customUserTypes));
|
||||
userServices.add(new DefaultOAuth2UserService());
|
||||
return new DelegatingOAuth2UserService<>(userServices);
|
||||
}
|
||||
|
||||
private <T> T getBeanOrNull(ResolvableType type) {
|
||||
ApplicationContext context = getBuilder().getSharedObject(ApplicationContext.class);
|
||||
if (context == null) {
|
||||
return null;
|
||||
}
|
||||
String[] names = context.getBeanNamesForType(type);
|
||||
if (names.length == 1) {
|
||||
return (T) context.getBean(names[0]);
|
||||
if (context != null) {
|
||||
String[] names = context.getBeanNamesForType(type);
|
||||
if (names.length == 1) {
|
||||
return (T) context.getBean(names[0]);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -480,7 +463,6 @@ public final class OAuth2LoginConfigurer<B extends HttpSecurityBuilder<B>>
|
|||
if (loginPageGeneratingFilter == null || this.isCustomLoginPage()) {
|
||||
return;
|
||||
}
|
||||
|
||||
loginPageGeneratingFilter.setOauth2LoginEnabled(true);
|
||||
loginPageGeneratingFilter.setOauth2AuthenticationUrlToClientName(this.getLoginLinks());
|
||||
loginPageGeneratingFilter.setLoginPageUrl(this.getLoginPage());
|
||||
|
@ -499,14 +481,12 @@ public final class OAuth2LoginConfigurer<B extends HttpSecurityBuilder<B>>
|
|||
if (clientRegistrations == null) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
String authorizationRequestBaseUri = (this.authorizationEndpointConfig.authorizationRequestBaseUri != null)
|
||||
? this.authorizationEndpointConfig.authorizationRequestBaseUri
|
||||
: OAuth2AuthorizationRequestRedirectFilter.DEFAULT_AUTHORIZATION_REQUEST_BASE_URI;
|
||||
Map<String, String> loginUrlToClientName = new HashMap<>();
|
||||
clientRegistrations.forEach((registration) -> loginUrlToClientName.put(
|
||||
authorizationRequestBaseUri + "/" + registration.getRegistrationId(), registration.getClientName()));
|
||||
|
||||
return loginUrlToClientName;
|
||||
}
|
||||
|
||||
|
@ -516,17 +496,13 @@ public final class OAuth2LoginConfigurer<B extends HttpSecurityBuilder<B>>
|
|||
RequestMatcher defaultEntryPointMatcher = this.getAuthenticationEntryPointMatcher(http);
|
||||
RequestMatcher defaultLoginPageMatcher = new AndRequestMatcher(
|
||||
new OrRequestMatcher(loginPageMatcher, faviconMatcher), defaultEntryPointMatcher);
|
||||
|
||||
RequestMatcher notXRequestedWith = new NegatedRequestMatcher(
|
||||
new RequestHeaderRequestMatcher("X-Requested-With", "XMLHttpRequest"));
|
||||
|
||||
LinkedHashMap<RequestMatcher, AuthenticationEntryPoint> entryPoints = new LinkedHashMap<>();
|
||||
entryPoints.put(new AndRequestMatcher(notXRequestedWith, new NegatedRequestMatcher(defaultLoginPageMatcher)),
|
||||
new LoginUrlAuthenticationEntryPoint(providerLoginPage));
|
||||
|
||||
DelegatingAuthenticationEntryPoint loginEntryPoint = new DelegatingAuthenticationEntryPoint(entryPoints);
|
||||
loginEntryPoint.setDefaultEntryPoint(this.getAuthenticationEntryPoint());
|
||||
|
||||
return loginEntryPoint;
|
||||
}
|
||||
|
||||
|
@ -612,7 +588,6 @@ public final class OAuth2LoginConfigurer<B extends HttpSecurityBuilder<B>>
|
|||
*/
|
||||
public TokenEndpointConfig accessTokenResponseClient(
|
||||
OAuth2AccessTokenResponseClient<OAuth2AuthorizationCodeGrantRequest> accessTokenResponseClient) {
|
||||
|
||||
Assert.notNull(accessTokenResponseClient, "accessTokenResponseClient cannot be null");
|
||||
this.accessTokenResponseClient = accessTokenResponseClient;
|
||||
return this;
|
||||
|
@ -746,21 +721,19 @@ public final class OAuth2LoginConfigurer<B extends HttpSecurityBuilder<B>>
|
|||
@Override
|
||||
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
|
||||
OAuth2LoginAuthenticationToken authorizationCodeAuthentication = (OAuth2LoginAuthenticationToken) authentication;
|
||||
|
||||
// Section 3.1.2.1 Authentication Request -
|
||||
// https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest
|
||||
// scope
|
||||
// REQUIRED. OpenID Connect requests MUST contain the "openid" scope value.
|
||||
if (authorizationCodeAuthentication.getAuthorizationExchange().getAuthorizationRequest().getScopes()
|
||||
.contains(OidcScopes.OPENID)) {
|
||||
|
||||
OAuth2AuthorizationRequest authorizationRequest = authorizationCodeAuthentication.getAuthorizationExchange()
|
||||
.getAuthorizationRequest();
|
||||
if (authorizationRequest.getScopes().contains(OidcScopes.OPENID)) {
|
||||
// Section 3.1.2.1 Authentication Request -
|
||||
// https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest scope
|
||||
// REQUIRED. OpenID Connect requests MUST contain the "openid" scope
|
||||
// value.
|
||||
OAuth2Error oauth2Error = new OAuth2Error("oidc_provider_not_configured",
|
||||
"An OpenID Connect Authentication Provider has not been configured. "
|
||||
+ "Check to ensure you include the dependency 'spring-security-oauth2-jose'.",
|
||||
null);
|
||||
throw new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -180,7 +180,6 @@ public final class OAuth2ResourceServerConfigurer<H extends HttpSecurityBuilder<
|
|||
if (this.jwtConfigurer == null) {
|
||||
this.jwtConfigurer = new JwtConfigurer(this.context);
|
||||
}
|
||||
|
||||
return this.jwtConfigurer;
|
||||
}
|
||||
|
||||
|
@ -202,7 +201,6 @@ public final class OAuth2ResourceServerConfigurer<H extends HttpSecurityBuilder<
|
|||
if (this.opaqueTokenConfigurer == null) {
|
||||
this.opaqueTokenConfigurer = new OpaqueTokenConfigurer(this.context);
|
||||
}
|
||||
|
||||
return this.opaqueTokenConfigurer;
|
||||
}
|
||||
|
||||
|
@ -223,11 +221,9 @@ public final class OAuth2ResourceServerConfigurer<H extends HttpSecurityBuilder<
|
|||
@Override
|
||||
public void init(H http) {
|
||||
validateConfiguration();
|
||||
|
||||
registerDefaultAccessDeniedHandler(http);
|
||||
registerDefaultEntryPoint(http);
|
||||
registerDefaultCsrfOverride(http);
|
||||
|
||||
AuthenticationProvider authenticationProvider = getAuthenticationProvider();
|
||||
if (authenticationProvider != null) {
|
||||
http.authenticationProvider(authenticationProvider);
|
||||
|
@ -238,79 +234,63 @@ public final class OAuth2ResourceServerConfigurer<H extends HttpSecurityBuilder<
|
|||
public void configure(H http) {
|
||||
BearerTokenResolver bearerTokenResolver = getBearerTokenResolver();
|
||||
this.requestMatcher.setBearerTokenResolver(bearerTokenResolver);
|
||||
|
||||
AuthenticationManagerResolver resolver = this.authenticationManagerResolver;
|
||||
if (resolver == null) {
|
||||
AuthenticationManager authenticationManager = getAuthenticationManager(http);
|
||||
resolver = (request) -> authenticationManager;
|
||||
}
|
||||
|
||||
BearerTokenAuthenticationFilter filter = new BearerTokenAuthenticationFilter(resolver);
|
||||
filter.setBearerTokenResolver(bearerTokenResolver);
|
||||
filter.setAuthenticationEntryPoint(this.authenticationEntryPoint);
|
||||
filter = postProcess(filter);
|
||||
|
||||
http.addFilter(filter);
|
||||
}
|
||||
|
||||
private void validateConfiguration() {
|
||||
if (this.authenticationManagerResolver == null) {
|
||||
if (this.jwtConfigurer == null && this.opaqueTokenConfigurer == null) {
|
||||
throw new IllegalStateException("Jwt and Opaque Token are the only supported formats for bearer tokens "
|
||||
+ "in Spring Security and neither was found. Make sure to configure JWT "
|
||||
+ "via http.oauth2ResourceServer().jwt() or Opaque Tokens via "
|
||||
+ "http.oauth2ResourceServer().opaqueToken().");
|
||||
}
|
||||
|
||||
if (this.jwtConfigurer != null && this.opaqueTokenConfigurer != null) {
|
||||
throw new IllegalStateException(
|
||||
"Spring Security only supports JWTs or Opaque Tokens, not both at the " + "same time.");
|
||||
}
|
||||
Assert.state(this.jwtConfigurer != null || this.opaqueTokenConfigurer != null,
|
||||
"Jwt and Opaque Token are the only supported formats for bearer tokens "
|
||||
+ "in Spring Security and neither was found. Make sure to configure JWT "
|
||||
+ "via http.oauth2ResourceServer().jwt() or Opaque Tokens via "
|
||||
+ "http.oauth2ResourceServer().opaqueToken().");
|
||||
Assert.state(this.jwtConfigurer == null || this.opaqueTokenConfigurer == null,
|
||||
"Spring Security only supports JWTs or Opaque Tokens, not both at the " + "same time.");
|
||||
}
|
||||
else {
|
||||
if (this.jwtConfigurer != null || this.opaqueTokenConfigurer != null) {
|
||||
throw new IllegalStateException("If an authenticationManagerResolver() is configured, then it takes "
|
||||
+ "precedence over any jwt() or opaqueToken() configuration.");
|
||||
}
|
||||
Assert.state(this.jwtConfigurer == null && this.opaqueTokenConfigurer == null,
|
||||
"If an authenticationManagerResolver() is configured, then it takes "
|
||||
+ "precedence over any jwt() or opaqueToken() configuration.");
|
||||
}
|
||||
}
|
||||
|
||||
private void registerDefaultAccessDeniedHandler(H http) {
|
||||
ExceptionHandlingConfigurer<H> exceptionHandling = http.getConfigurer(ExceptionHandlingConfigurer.class);
|
||||
if (exceptionHandling == null) {
|
||||
return;
|
||||
if (exceptionHandling != null) {
|
||||
exceptionHandling.defaultAccessDeniedHandlerFor(this.accessDeniedHandler, this.requestMatcher);
|
||||
}
|
||||
|
||||
exceptionHandling.defaultAccessDeniedHandlerFor(this.accessDeniedHandler, this.requestMatcher);
|
||||
}
|
||||
|
||||
private void registerDefaultEntryPoint(H http) {
|
||||
ExceptionHandlingConfigurer<H> exceptionHandling = http.getConfigurer(ExceptionHandlingConfigurer.class);
|
||||
if (exceptionHandling == null) {
|
||||
return;
|
||||
if (exceptionHandling != null) {
|
||||
exceptionHandling.defaultAuthenticationEntryPointFor(this.authenticationEntryPoint, this.requestMatcher);
|
||||
}
|
||||
|
||||
exceptionHandling.defaultAuthenticationEntryPointFor(this.authenticationEntryPoint, this.requestMatcher);
|
||||
}
|
||||
|
||||
private void registerDefaultCsrfOverride(H http) {
|
||||
CsrfConfigurer<H> csrf = http.getConfigurer(CsrfConfigurer.class);
|
||||
if (csrf == null) {
|
||||
return;
|
||||
if (csrf != null) {
|
||||
csrf.ignoringRequestMatchers(this.requestMatcher);
|
||||
}
|
||||
|
||||
csrf.ignoringRequestMatchers(this.requestMatcher);
|
||||
}
|
||||
|
||||
AuthenticationProvider getAuthenticationProvider() {
|
||||
if (this.jwtConfigurer != null) {
|
||||
return this.jwtConfigurer.getAuthenticationProvider();
|
||||
}
|
||||
|
||||
if (this.opaqueTokenConfigurer != null) {
|
||||
return this.opaqueTokenConfigurer.getAuthenticationProvider();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -318,11 +298,9 @@ public final class OAuth2ResourceServerConfigurer<H extends HttpSecurityBuilder<
|
|||
if (this.jwtConfigurer != null) {
|
||||
return this.jwtConfigurer.getAuthenticationManager(http);
|
||||
}
|
||||
|
||||
if (this.opaqueTokenConfigurer != null) {
|
||||
return this.opaqueTokenConfigurer.getAuthenticationManager(http);
|
||||
}
|
||||
|
||||
return http.getSharedObject(AuthenticationManager.class);
|
||||
}
|
||||
|
||||
|
@ -335,7 +313,6 @@ public final class OAuth2ResourceServerConfigurer<H extends HttpSecurityBuilder<
|
|||
this.bearerTokenResolver = new DefaultBearerTokenResolver();
|
||||
}
|
||||
}
|
||||
|
||||
return this.bearerTokenResolver;
|
||||
}
|
||||
|
||||
|
@ -371,7 +348,6 @@ public final class OAuth2ResourceServerConfigurer<H extends HttpSecurityBuilder<
|
|||
|
||||
public JwtConfigurer jwtAuthenticationConverter(
|
||||
Converter<Jwt, ? extends AbstractAuthenticationToken> jwtAuthenticationConverter) {
|
||||
|
||||
this.jwtAuthenticationConverter = jwtAuthenticationConverter;
|
||||
return this;
|
||||
}
|
||||
|
@ -389,7 +365,6 @@ public final class OAuth2ResourceServerConfigurer<H extends HttpSecurityBuilder<
|
|||
this.jwtAuthenticationConverter = new JwtAuthenticationConverter();
|
||||
}
|
||||
}
|
||||
|
||||
return this.jwtAuthenticationConverter;
|
||||
}
|
||||
|
||||
|
@ -397,7 +372,6 @@ public final class OAuth2ResourceServerConfigurer<H extends HttpSecurityBuilder<
|
|||
if (this.decoder == null) {
|
||||
return this.context.getBean(JwtDecoder.class);
|
||||
}
|
||||
|
||||
return this.decoder;
|
||||
}
|
||||
|
||||
|
@ -405,10 +379,8 @@ public final class OAuth2ResourceServerConfigurer<H extends HttpSecurityBuilder<
|
|||
if (this.authenticationManager != null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
JwtDecoder decoder = getJwtDecoder();
|
||||
Converter<Jwt, ? extends AbstractAuthenticationToken> jwtAuthenticationConverter = getJwtAuthenticationConverter();
|
||||
|
||||
JwtAuthenticationProvider provider = new JwtAuthenticationProvider(decoder);
|
||||
provider.setJwtAuthenticationConverter(jwtAuthenticationConverter);
|
||||
return postProcess(provider);
|
||||
|
@ -418,7 +390,6 @@ public final class OAuth2ResourceServerConfigurer<H extends HttpSecurityBuilder<
|
|||
if (this.authenticationManager != null) {
|
||||
return this.authenticationManager;
|
||||
}
|
||||
|
||||
return http.getSharedObject(AuthenticationManager.class);
|
||||
}
|
||||
|
||||
|
@ -491,7 +462,6 @@ public final class OAuth2ResourceServerConfigurer<H extends HttpSecurityBuilder<
|
|||
if (this.authenticationManager != null) {
|
||||
return this.authenticationManager;
|
||||
}
|
||||
|
||||
return http.getSharedObject(AuthenticationManager.class);
|
||||
}
|
||||
|
||||
|
|
|
@ -280,12 +280,10 @@ public final class OpenIDLoginConfigurer<H extends HttpSecurityBuilder<H>>
|
|||
@Override
|
||||
public void init(H http) throws Exception {
|
||||
super.init(http);
|
||||
|
||||
OpenIDAuthenticationProvider authenticationProvider = new OpenIDAuthenticationProvider();
|
||||
authenticationProvider.setAuthenticationUserDetailsService(getAuthenticationUserDetailsService(http));
|
||||
authenticationProvider = postProcess(authenticationProvider);
|
||||
http.authenticationProvider(authenticationProvider);
|
||||
|
||||
initDefaultLoginFilter(http);
|
||||
}
|
||||
|
||||
|
|
|
@ -160,9 +160,6 @@ public final class Saml2LoginConfigurer<B extends HttpSecurityBuilder<B>>
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Saml2LoginConfigurer<B> loginPage(String loginPage) {
|
||||
Assert.hasText(loginPage, "loginPage cannot be empty");
|
||||
|
@ -170,9 +167,6 @@ public final class Saml2LoginConfigurer<B extends HttpSecurityBuilder<B>>
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Saml2LoginConfigurer<B> loginProcessingUrl(String loginProcessingUrl) {
|
||||
Assert.hasText(loginProcessingUrl, "loginProcessingUrl cannot be empty");
|
||||
|
@ -181,9 +175,6 @@ public final class Saml2LoginConfigurer<B extends HttpSecurityBuilder<B>>
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
protected RequestMatcher createLoginProcessingUrlMatcher(String loginProcessingUrl) {
|
||||
return new AntPathRequestMatcher(loginProcessingUrl);
|
||||
|
@ -208,28 +199,24 @@ public final class Saml2LoginConfigurer<B extends HttpSecurityBuilder<B>>
|
|||
if (this.relyingPartyRegistrationRepository == null) {
|
||||
this.relyingPartyRegistrationRepository = getSharedOrBean(http, RelyingPartyRegistrationRepository.class);
|
||||
}
|
||||
|
||||
this.saml2WebSsoAuthenticationFilter = new Saml2WebSsoAuthenticationFilter(getAuthenticationConverter(http),
|
||||
this.loginProcessingUrl);
|
||||
setAuthenticationFilter(this.saml2WebSsoAuthenticationFilter);
|
||||
super.loginProcessingUrl(this.loginProcessingUrl);
|
||||
|
||||
if (StringUtils.hasText(this.loginPage)) {
|
||||
// Set custom login page
|
||||
super.loginPage(this.loginPage);
|
||||
super.init(http);
|
||||
}
|
||||
else {
|
||||
final Map<String, String> providerUrlMap = getIdentityProviderUrlMap(
|
||||
Map<String, String> providerUrlMap = getIdentityProviderUrlMap(
|
||||
this.authenticationRequestEndpoint.filterProcessingUrl, this.relyingPartyRegistrationRepository);
|
||||
|
||||
boolean singleProvider = providerUrlMap.size() == 1;
|
||||
if (singleProvider) {
|
||||
// Setup auto-redirect to provider login page
|
||||
// when only 1 IDP is configured
|
||||
this.updateAuthenticationDefaults();
|
||||
this.updateAccessDefaults(http);
|
||||
|
||||
String loginUrl = providerUrlMap.entrySet().iterator().next().getKey();
|
||||
final LoginUrlAuthenticationEntryPoint entryPoint = new LoginUrlAuthenticationEntryPoint(loginUrl);
|
||||
registerAuthenticationEntryPoint(http, entryPoint);
|
||||
|
@ -238,7 +225,6 @@ public final class Saml2LoginConfigurer<B extends HttpSecurityBuilder<B>>
|
|||
super.init(http);
|
||||
}
|
||||
}
|
||||
|
||||
this.initDefaultLoginFilter(http);
|
||||
}
|
||||
|
||||
|
@ -279,7 +265,6 @@ public final class Saml2LoginConfigurer<B extends HttpSecurityBuilder<B>>
|
|||
if (csrf == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
csrf.ignoringRequestMatchers(new AntPathRequestMatcher(this.loginProcessingUrl));
|
||||
}
|
||||
|
||||
|
@ -289,7 +274,6 @@ public final class Saml2LoginConfigurer<B extends HttpSecurityBuilder<B>>
|
|||
if (loginPageGeneratingFilter == null || this.isCustomLoginPage()) {
|
||||
return;
|
||||
}
|
||||
|
||||
loginPageGeneratingFilter.setSaml2LoginEnabled(true);
|
||||
loginPageGeneratingFilter.setSaml2AuthenticationUrlToProviderName(this.getIdentityProviderUrlMap(
|
||||
this.authenticationRequestEndpoint.filterProcessingUrl, this.relyingPartyRegistrationRepository));
|
||||
|
@ -326,8 +310,8 @@ public final class Saml2LoginConfigurer<B extends HttpSecurityBuilder<B>>
|
|||
return context.getBean(clazz);
|
||||
}
|
||||
catch (NoSuchBeanDefinitionException ex) {
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private <C> void setSharedObject(B http, Class<C> clazz, C object) {
|
||||
|
@ -346,7 +330,6 @@ public final class Saml2LoginConfigurer<B extends HttpSecurityBuilder<B>>
|
|||
private Filter build(B http) {
|
||||
Saml2AuthenticationRequestFactory authenticationRequestResolver = getResolver(http);
|
||||
Saml2AuthenticationRequestContextResolver contextResolver = getContextResolver(http);
|
||||
|
||||
return postProcess(
|
||||
new Saml2WebSsoAuthenticationRequestFilter(contextResolver, authenticationRequestResolver));
|
||||
}
|
||||
|
|
|
@ -442,11 +442,11 @@ public class MessageSecurityMetadataSourceRegistry {
|
|||
return new SimpDestinationMessageMatcher(this.pattern,
|
||||
MessageSecurityMetadataSourceRegistry.this.pathMatcher);
|
||||
}
|
||||
else if (SimpMessageType.MESSAGE == this.type) {
|
||||
if (SimpMessageType.MESSAGE == this.type) {
|
||||
return SimpDestinationMessageMatcher.createMessageMatcher(this.pattern,
|
||||
MessageSecurityMetadataSourceRegistry.this.pathMatcher);
|
||||
}
|
||||
else if (SimpMessageType.SUBSCRIBE == this.type) {
|
||||
if (SimpMessageType.SUBSCRIBE == this.type) {
|
||||
return SimpDestinationMessageMatcher.createSubscribeMatcher(this.pattern,
|
||||
MessageSecurityMetadataSourceRegistry.this.pathMatcher);
|
||||
}
|
||||
|
|
|
@ -47,13 +47,12 @@ final class ReactiveOAuth2ClientImportSelector implements ImportSelector {
|
|||
|
||||
@Override
|
||||
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
|
||||
boolean oauth2ClientPresent = ClassUtils.isPresent(
|
||||
"org.springframework.security.oauth2.client.registration.ClientRegistration",
|
||||
getClass().getClassLoader());
|
||||
|
||||
return oauth2ClientPresent ? new String[] {
|
||||
"org.springframework.security.config.annotation.web.reactive.ReactiveOAuth2ClientImportSelector$OAuth2ClientWebFluxSecurityConfiguration" }
|
||||
: new String[] {};
|
||||
if (!ClassUtils.isPresent("org.springframework.security.oauth2.client.registration.ClientRegistration",
|
||||
getClass().getClassLoader())) {
|
||||
return new String[0];
|
||||
}
|
||||
return new String[] { "org.springframework.security.config.annotation.web.reactive."
|
||||
+ "ReactiveOAuth2ClientImportSelector$OAuth2ClientWebFluxSecurityConfiguration" };
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
|
|
|
@ -98,23 +98,14 @@ class WebFluxSecurityConfiguration {
|
|||
* @return
|
||||
*/
|
||||
private SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
|
||||
// @formatter:off
|
||||
http
|
||||
.authorizeExchange()
|
||||
.anyExchange().authenticated();
|
||||
// @formatter:on
|
||||
|
||||
http.authorizeExchange().anyExchange().authenticated();
|
||||
if (isOAuth2Present && OAuth2ClasspathGuard.shouldConfigure(this.context)) {
|
||||
OAuth2ClasspathGuard.configure(this.context, http);
|
||||
}
|
||||
else {
|
||||
// @formatter:off
|
||||
http
|
||||
.httpBasic().and()
|
||||
.formLogin();
|
||||
// @formatter:on
|
||||
http.httpBasic();
|
||||
http.formLogin();
|
||||
}
|
||||
|
||||
SecurityWebFilterChain result = http.build();
|
||||
return result;
|
||||
}
|
||||
|
@ -122,11 +113,8 @@ class WebFluxSecurityConfiguration {
|
|||
private static class OAuth2ClasspathGuard {
|
||||
|
||||
static void configure(ApplicationContext context, ServerHttpSecurity http) {
|
||||
// @formatter:off
|
||||
http
|
||||
.oauth2Login().and()
|
||||
.oauth2Client();
|
||||
// @formatter:on
|
||||
http.oauth2Login();
|
||||
http.oauth2Client();
|
||||
}
|
||||
|
||||
static boolean shouldConfigure(ApplicationContext context) {
|
||||
|
|
|
@ -47,6 +47,7 @@ import org.springframework.security.messaging.context.SecurityContextChannelInte
|
|||
import org.springframework.security.messaging.web.csrf.CsrfChannelInterceptor;
|
||||
import org.springframework.security.messaging.web.socket.server.CsrfTokenHandshakeInterceptor;
|
||||
import org.springframework.util.AntPathMatcher;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.PathMatcher;
|
||||
import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping;
|
||||
import org.springframework.web.socket.config.annotation.AbstractWebSocketMessageBrokerConfigurer;
|
||||
|
@ -160,10 +161,8 @@ public abstract class AbstractSecurityWebSocketMessageBrokerConfigurer extends A
|
|||
messageSecurityMetadataSource);
|
||||
MessageExpressionVoter<Object> voter = new MessageExpressionVoter<>();
|
||||
voter.setExpressionHandler(getMessageExpressionHandler());
|
||||
|
||||
List<AccessDecisionVoter<?>> voters = new ArrayList<>();
|
||||
voters.add(voter);
|
||||
|
||||
AffirmativeBased manager = new AffirmativeBased(voters);
|
||||
channelSecurityInterceptor.setAccessDecisionManager(manager);
|
||||
return channelSecurityInterceptor;
|
||||
|
@ -221,50 +220,47 @@ public abstract class AbstractSecurityWebSocketMessageBrokerConfigurer extends A
|
|||
if (sameOriginDisabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
String beanName = "stompWebSocketHandlerMapping";
|
||||
SimpleUrlHandlerMapping mapping = this.context.getBean(beanName, SimpleUrlHandlerMapping.class);
|
||||
Map<String, Object> mappings = mapping.getHandlerMap();
|
||||
for (Object object : mappings.values()) {
|
||||
if (object instanceof SockJsHttpRequestHandler) {
|
||||
SockJsHttpRequestHandler sockjsHandler = (SockJsHttpRequestHandler) object;
|
||||
SockJsService sockJsService = sockjsHandler.getSockJsService();
|
||||
if (!(sockJsService instanceof TransportHandlingSockJsService)) {
|
||||
throw new IllegalStateException(
|
||||
"sockJsService must be instance of TransportHandlingSockJsService got " + sockJsService);
|
||||
}
|
||||
|
||||
TransportHandlingSockJsService transportHandlingSockJsService = (TransportHandlingSockJsService) sockJsService;
|
||||
List<HandshakeInterceptor> handshakeInterceptors = transportHandlingSockJsService
|
||||
.getHandshakeInterceptors();
|
||||
List<HandshakeInterceptor> interceptorsToSet = new ArrayList<>(handshakeInterceptors.size() + 1);
|
||||
interceptorsToSet.add(new CsrfTokenHandshakeInterceptor());
|
||||
interceptorsToSet.addAll(handshakeInterceptors);
|
||||
|
||||
transportHandlingSockJsService.setHandshakeInterceptors(interceptorsToSet);
|
||||
setHandshakeInterceptors((SockJsHttpRequestHandler) object);
|
||||
}
|
||||
else if (object instanceof WebSocketHttpRequestHandler) {
|
||||
WebSocketHttpRequestHandler handler = (WebSocketHttpRequestHandler) object;
|
||||
List<HandshakeInterceptor> handshakeInterceptors = handler.getHandshakeInterceptors();
|
||||
List<HandshakeInterceptor> interceptorsToSet = new ArrayList<>(handshakeInterceptors.size() + 1);
|
||||
interceptorsToSet.add(new CsrfTokenHandshakeInterceptor());
|
||||
interceptorsToSet.addAll(handshakeInterceptors);
|
||||
|
||||
handler.setHandshakeInterceptors(interceptorsToSet);
|
||||
setHandshakeInterceptors((WebSocketHttpRequestHandler) object);
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException("Bean " + beanName
|
||||
+ " is expected to contain mappings to either a SockJsHttpRequestHandler or a WebSocketHttpRequestHandler but got "
|
||||
+ object);
|
||||
throw new IllegalStateException("Bean " + beanName + " is expected to contain mappings to either a "
|
||||
+ "SockJsHttpRequestHandler or a WebSocketHttpRequestHandler but got " + object);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.inboundRegistry.containsMapping() && !this.inboundRegistry.isSimpDestPathMatcherConfigured()) {
|
||||
PathMatcher pathMatcher = getDefaultPathMatcher();
|
||||
this.inboundRegistry.simpDestPathMatcher(pathMatcher);
|
||||
}
|
||||
}
|
||||
|
||||
private void setHandshakeInterceptors(SockJsHttpRequestHandler handler) {
|
||||
SockJsService sockJsService = handler.getSockJsService();
|
||||
Assert.state(sockJsService instanceof TransportHandlingSockJsService,
|
||||
() -> "sockJsService must be instance of TransportHandlingSockJsService got " + sockJsService);
|
||||
TransportHandlingSockJsService transportHandlingSockJsService = (TransportHandlingSockJsService) sockJsService;
|
||||
List<HandshakeInterceptor> handshakeInterceptors = transportHandlingSockJsService.getHandshakeInterceptors();
|
||||
List<HandshakeInterceptor> interceptorsToSet = new ArrayList<>(handshakeInterceptors.size() + 1);
|
||||
interceptorsToSet.add(new CsrfTokenHandshakeInterceptor());
|
||||
interceptorsToSet.addAll(handshakeInterceptors);
|
||||
transportHandlingSockJsService.setHandshakeInterceptors(interceptorsToSet);
|
||||
}
|
||||
|
||||
private void setHandshakeInterceptors(WebSocketHttpRequestHandler handler) {
|
||||
List<HandshakeInterceptor> handshakeInterceptors = handler.getHandshakeInterceptors();
|
||||
List<HandshakeInterceptor> interceptorsToSet = new ArrayList<>(handshakeInterceptors.size() + 1);
|
||||
interceptorsToSet.add(new CsrfTokenHandshakeInterceptor());
|
||||
interceptorsToSet.addAll(handshakeInterceptors);
|
||||
handler.setHandshakeInterceptors(interceptorsToSet);
|
||||
}
|
||||
|
||||
private static class WebSocketMessageSecurityMetadataSourceRegistry extends MessageSecurityMetadataSourceRegistry {
|
||||
|
||||
@Override
|
||||
|
|
|
@ -47,36 +47,27 @@ public abstract class AbstractUserDetailsServiceBeanDefinitionParser implements
|
|||
@Override
|
||||
public BeanDefinition parse(Element element, ParserContext parserContext) {
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(getBeanClassName(element));
|
||||
|
||||
doParse(element, parserContext, builder);
|
||||
|
||||
RootBeanDefinition userService = (RootBeanDefinition) builder.getBeanDefinition();
|
||||
final String beanId = resolveId(element, userService, parserContext);
|
||||
|
||||
String beanId = resolveId(element, userService, parserContext);
|
||||
parserContext.registerBeanComponent(new BeanComponentDefinition(userService, beanId));
|
||||
|
||||
String cacheRef = element.getAttribute(CACHE_REF);
|
||||
|
||||
// Register a caching version of the user service if there's a cache-ref
|
||||
if (StringUtils.hasText(cacheRef)) {
|
||||
BeanDefinitionBuilder cachingUSBuilder = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(CachingUserDetailsService.class);
|
||||
cachingUSBuilder.addConstructorArgReference(beanId);
|
||||
|
||||
cachingUSBuilder.addPropertyValue("userCache", new RuntimeBeanReference(cacheRef));
|
||||
BeanDefinition cachingUserService = cachingUSBuilder.getBeanDefinition();
|
||||
parserContext
|
||||
.registerBeanComponent(new BeanComponentDefinition(cachingUserService, beanId + CACHING_SUFFIX));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private String resolveId(Element element, AbstractBeanDefinition definition, ParserContext pc)
|
||||
throws BeanDefinitionStoreException {
|
||||
|
||||
String id = element.getAttribute("id");
|
||||
|
||||
if (pc.isNested()) {
|
||||
// We're inside an <authentication-provider> element
|
||||
if (!StringUtils.hasText(id)) {
|
||||
|
@ -85,17 +76,14 @@ public abstract class AbstractUserDetailsServiceBeanDefinitionParser implements
|
|||
BeanDefinition container = pc.getContainingBeanDefinition();
|
||||
container.getPropertyValues().add("userDetailsService", new RuntimeBeanReference(id));
|
||||
}
|
||||
|
||||
if (StringUtils.hasText(id)) {
|
||||
return id;
|
||||
}
|
||||
|
||||
// If top level, use the default name or throw an exception if already used
|
||||
if (pc.getRegistry().containsBeanDefinition(BeanIds.USER_DETAILS_SERVICE)) {
|
||||
throw new BeanDefinitionStoreException(
|
||||
"No id supplied and another " + "bean is already registered as " + BeanIds.USER_DETAILS_SERVICE);
|
||||
"No id supplied and another bean is already registered as " + BeanIds.USER_DETAILS_SERVICE);
|
||||
}
|
||||
|
||||
return BeanIds.USER_DETAILS_SERVICE;
|
||||
}
|
||||
|
||||
|
|
|
@ -60,7 +60,6 @@ public class AuthenticationManagerBeanDefinitionParser implements BeanDefinition
|
|||
@Override
|
||||
public BeanDefinition parse(Element element, ParserContext pc) {
|
||||
String id = element.getAttribute("id");
|
||||
|
||||
if (!StringUtils.hasText(id)) {
|
||||
if (pc.getRegistry().containsBeanDefinition(BeanIds.AUTHENTICATION_MANAGER)) {
|
||||
pc.getReaderContext().warning("Overriding globally registered AuthenticationManager",
|
||||
|
@ -69,65 +68,30 @@ public class AuthenticationManagerBeanDefinitionParser implements BeanDefinition
|
|||
id = BeanIds.AUTHENTICATION_MANAGER;
|
||||
}
|
||||
pc.pushContainingComponent(new CompositeComponentDefinition(element.getTagName(), pc.extractSource(element)));
|
||||
|
||||
BeanDefinitionBuilder providerManagerBldr = BeanDefinitionBuilder.rootBeanDefinition(ProviderManager.class);
|
||||
|
||||
String alias = element.getAttribute(ATT_ALIAS);
|
||||
|
||||
List<BeanMetadataElement> providers = new ManagedList<>();
|
||||
NamespaceHandlerResolver resolver = pc.getReaderContext().getNamespaceHandlerResolver();
|
||||
|
||||
NodeList children = element.getChildNodes();
|
||||
|
||||
for (int i = 0; i < children.getLength(); i++) {
|
||||
Node node = children.item(i);
|
||||
if (node instanceof Element) {
|
||||
Element providerElt = (Element) node;
|
||||
if (StringUtils.hasText(providerElt.getAttribute(ATT_REF))) {
|
||||
if (providerElt.getAttributes().getLength() > 1) {
|
||||
pc.getReaderContext()
|
||||
.error("authentication-provider element cannot be used with other attributes "
|
||||
+ "when using 'ref' attribute", pc.extractSource(element));
|
||||
}
|
||||
NodeList providerChildren = providerElt.getChildNodes();
|
||||
for (int j = 0; j < providerChildren.getLength(); j++) {
|
||||
if (providerChildren.item(j) instanceof Element) {
|
||||
pc.getReaderContext()
|
||||
.error("authentication-provider element cannot have child elements when used "
|
||||
+ "with 'ref' attribute", pc.extractSource(element));
|
||||
}
|
||||
}
|
||||
providers.add(new RuntimeBeanReference(providerElt.getAttribute(ATT_REF)));
|
||||
}
|
||||
else {
|
||||
BeanDefinition provider = resolver.resolve(providerElt.getNamespaceURI()).parse(providerElt, pc);
|
||||
Assert.notNull(provider,
|
||||
() -> "Parser for " + providerElt.getNodeName() + " returned a null bean definition");
|
||||
String providerId = pc.getReaderContext().generateBeanName(provider);
|
||||
pc.registerBeanComponent(new BeanComponentDefinition(provider, providerId));
|
||||
providers.add(new RuntimeBeanReference(providerId));
|
||||
}
|
||||
providers.add(extracted(element, pc, resolver, (Element) node));
|
||||
}
|
||||
}
|
||||
|
||||
if (providers.isEmpty()) {
|
||||
providers.add(new RootBeanDefinition(NullAuthenticationProvider.class));
|
||||
}
|
||||
|
||||
providerManagerBldr.addConstructorArgValue(providers);
|
||||
|
||||
if ("false".equals(element.getAttribute(ATT_ERASE_CREDENTIALS))) {
|
||||
providerManagerBldr.addPropertyValue("eraseCredentialsAfterAuthentication", false);
|
||||
}
|
||||
|
||||
// Add the default event publisher
|
||||
BeanDefinition publisher = new RootBeanDefinition(DefaultAuthenticationEventPublisher.class);
|
||||
String pubId = pc.getReaderContext().generateBeanName(publisher);
|
||||
pc.registerBeanComponent(new BeanComponentDefinition(publisher, pubId));
|
||||
providerManagerBldr.addPropertyReference("authenticationEventPublisher", pubId);
|
||||
|
||||
pc.registerBeanComponent(new BeanComponentDefinition(providerManagerBldr.getBeanDefinition(), id));
|
||||
|
||||
if (StringUtils.hasText(alias)) {
|
||||
pc.getRegistry().registerAlias(id, alias);
|
||||
pc.getReaderContext().fireAliasRegistered(id, alias, pc.extractSource(element));
|
||||
|
@ -136,12 +100,35 @@ public class AuthenticationManagerBeanDefinitionParser implements BeanDefinition
|
|||
pc.getRegistry().registerAlias(id, BeanIds.AUTHENTICATION_MANAGER);
|
||||
pc.getReaderContext().fireAliasRegistered(id, BeanIds.AUTHENTICATION_MANAGER, pc.extractSource(element));
|
||||
}
|
||||
|
||||
pc.popAndRegisterContainingComponent();
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private BeanMetadataElement extracted(Element element, ParserContext pc, NamespaceHandlerResolver resolver,
|
||||
Element providerElement) {
|
||||
String ref = providerElement.getAttribute(ATT_REF);
|
||||
if (!StringUtils.hasText(ref)) {
|
||||
BeanDefinition provider = resolver.resolve(providerElement.getNamespaceURI()).parse(providerElement, pc);
|
||||
Assert.notNull(provider,
|
||||
() -> "Parser for " + providerElement.getNodeName() + " returned a null bean definition");
|
||||
String providerId = pc.getReaderContext().generateBeanName(provider);
|
||||
pc.registerBeanComponent(new BeanComponentDefinition(provider, providerId));
|
||||
return new RuntimeBeanReference(providerId);
|
||||
}
|
||||
if (providerElement.getAttributes().getLength() > 1) {
|
||||
pc.getReaderContext().error("authentication-provider element cannot be used with other attributes "
|
||||
+ "when using 'ref' attribute", pc.extractSource(element));
|
||||
}
|
||||
NodeList providerChildren = providerElement.getChildNodes();
|
||||
for (int i = 0; i < providerChildren.getLength(); i++) {
|
||||
if (providerChildren.item(i) instanceof Element) {
|
||||
pc.getReaderContext().error("authentication-provider element cannot have child elements when used "
|
||||
+ "with 'ref' attribute", pc.extractSource(element));
|
||||
}
|
||||
}
|
||||
return new RuntimeBeanReference(ref);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provider which doesn't provide any service. Only used to prevent a configuration
|
||||
* exception if the provider list is empty (usually because a child ProviderManager
|
||||
|
|
|
@ -56,12 +56,10 @@ public class AuthenticationManagerFactoryBean implements FactoryBean<Authenticat
|
|||
if (!BeanIds.AUTHENTICATION_MANAGER.equals(ex.getBeanName())) {
|
||||
throw ex;
|
||||
}
|
||||
|
||||
UserDetailsService uds = getBeanOrNull(UserDetailsService.class);
|
||||
if (uds == null) {
|
||||
throw new NoSuchBeanDefinitionException(BeanIds.AUTHENTICATION_MANAGER, MISSING_BEAN_ERROR_MESSAGE);
|
||||
}
|
||||
|
||||
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
|
||||
provider.setUserDetailsService(uds);
|
||||
PasswordEncoder passwordEncoder = getBeanOrNull(PasswordEncoder.class);
|
||||
|
|
|
@ -43,15 +43,12 @@ public class AuthenticationProviderBeanDefinitionParser implements BeanDefinitio
|
|||
public BeanDefinition parse(Element element, ParserContext pc) {
|
||||
RootBeanDefinition authProvider = new RootBeanDefinition(DaoAuthenticationProvider.class);
|
||||
authProvider.setSource(pc.extractSource(element));
|
||||
|
||||
Element passwordEncoderElt = DomUtils.getChildElementByTagName(element, Elements.PASSWORD_ENCODER);
|
||||
|
||||
PasswordEncoderParser pep = new PasswordEncoderParser(passwordEncoderElt, pc);
|
||||
BeanMetadataElement passwordEncoder = pep.getPasswordEncoder();
|
||||
if (passwordEncoder != null) {
|
||||
authProvider.getPropertyValues().addPropertyValue("passwordEncoder", passwordEncoder);
|
||||
}
|
||||
|
||||
Element userServiceElt = DomUtils.getChildElementByTagName(element, Elements.USER_SERVICE);
|
||||
if (userServiceElt == null) {
|
||||
userServiceElt = DomUtils.getChildElementByTagName(element, Elements.JDBC_USER_SERVICE);
|
||||
|
@ -59,9 +56,7 @@ public class AuthenticationProviderBeanDefinitionParser implements BeanDefinitio
|
|||
if (userServiceElt == null) {
|
||||
userServiceElt = DomUtils.getChildElementByTagName(element, Elements.LDAP_USER_SERVICE);
|
||||
}
|
||||
|
||||
String ref = element.getAttribute(ATT_USER_DETAILS_REF);
|
||||
|
||||
if (StringUtils.hasText(ref)) {
|
||||
if (userServiceElt != null) {
|
||||
pc.getReaderContext()
|
||||
|
@ -69,7 +64,6 @@ public class AuthenticationProviderBeanDefinitionParser implements BeanDefinitio
|
|||
+ "elements '" + Elements.USER_SERVICE + "', '" + Elements.JDBC_USER_SERVICE + "' or '"
|
||||
+ Elements.LDAP_USER_SERVICE + "'", element);
|
||||
}
|
||||
|
||||
authProvider.getPropertyValues().add("userDetailsService", new RuntimeBeanReference(ref));
|
||||
}
|
||||
else {
|
||||
|
@ -80,7 +74,6 @@ public class AuthenticationProviderBeanDefinitionParser implements BeanDefinitio
|
|||
else {
|
||||
pc.getReaderContext().error("A user-service is required", element);
|
||||
}
|
||||
|
||||
// Pinch the cache-ref from the UserDetailService element, if set.
|
||||
String cacheRef = userServiceElt.getAttribute(AbstractUserDetailsServiceBeanDefinitionParser.CACHE_REF);
|
||||
|
||||
|
@ -88,7 +81,6 @@ public class AuthenticationProviderBeanDefinitionParser implements BeanDefinitio
|
|||
authProvider.getPropertyValues().addPropertyValue("userCache", new RuntimeBeanReference(cacheRef));
|
||||
}
|
||||
}
|
||||
|
||||
return authProvider;
|
||||
}
|
||||
|
||||
|
|
|
@ -42,7 +42,6 @@ public class JdbcUserServiceBeanDefinitionParser extends AbstractUserDetailsServ
|
|||
@Override
|
||||
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
|
||||
String dataSource = element.getAttribute(ATT_DATA_SOURCE);
|
||||
|
||||
if (dataSource != null) {
|
||||
builder.addPropertyReference("dataSource", dataSource);
|
||||
}
|
||||
|
@ -50,24 +49,19 @@ public class JdbcUserServiceBeanDefinitionParser extends AbstractUserDetailsServ
|
|||
parserContext.getReaderContext().error(ATT_DATA_SOURCE + " is required for " + Elements.JDBC_USER_SERVICE,
|
||||
parserContext.extractSource(element));
|
||||
}
|
||||
|
||||
String usersQuery = element.getAttribute(ATT_USERS_BY_USERNAME_QUERY);
|
||||
String authoritiesQuery = element.getAttribute(ATT_AUTHORITIES_BY_USERNAME_QUERY);
|
||||
String groupAuthoritiesQuery = element.getAttribute(ATT_GROUP_AUTHORITIES_QUERY);
|
||||
String rolePrefix = element.getAttribute(ATT_ROLE_PREFIX);
|
||||
|
||||
if (StringUtils.hasText(rolePrefix)) {
|
||||
builder.addPropertyValue("rolePrefix", rolePrefix);
|
||||
}
|
||||
|
||||
if (StringUtils.hasText(usersQuery)) {
|
||||
builder.addPropertyValue("usersByUsernameQuery", usersQuery);
|
||||
}
|
||||
|
||||
if (StringUtils.hasText(authoritiesQuery)) {
|
||||
builder.addPropertyValue("authoritiesByUsernameQuery", authoritiesQuery);
|
||||
}
|
||||
|
||||
if (StringUtils.hasText(groupAuthoritiesQuery)) {
|
||||
builder.addPropertyValue("enableGroups", Boolean.TRUE);
|
||||
builder.addPropertyValue("groupAuthoritiesByUsernameQuery", groupAuthoritiesQuery);
|
||||
|
|
|
@ -16,11 +16,9 @@
|
|||
|
||||
package org.springframework.security.config.authentication;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import org.springframework.beans.BeanMetadataElement;
|
||||
|
@ -42,17 +40,13 @@ public class PasswordEncoderParser {
|
|||
static final String ATT_REF = "ref";
|
||||
|
||||
public static final String ATT_HASH = "hash";
|
||||
|
||||
static final String ATT_BASE_64 = "base64";
|
||||
|
||||
static final String OPT_HASH_BCRYPT = "bcrypt";
|
||||
|
||||
private static final Map<String, Class<?>> ENCODER_CLASSES;
|
||||
|
||||
static {
|
||||
ENCODER_CLASSES = new HashMap<>();
|
||||
ENCODER_CLASSES.put(OPT_HASH_BCRYPT, BCryptPasswordEncoder.class);
|
||||
}
|
||||
|
||||
private static final Log logger = LogFactory.getLog(PasswordEncoderParser.class);
|
||||
private static final Map<String, Class<?>> ENCODER_CLASSES = Collections.singletonMap(OPT_HASH_BCRYPT,
|
||||
BCryptPasswordEncoder.class);
|
||||
|
||||
private BeanMetadataElement passwordEncoder;
|
||||
|
||||
|
@ -68,14 +62,9 @@ public class PasswordEncoderParser {
|
|||
return;
|
||||
}
|
||||
String hash = element.getAttribute(ATT_HASH);
|
||||
boolean useBase64 = false;
|
||||
|
||||
if (StringUtils.hasText(element.getAttribute(ATT_BASE_64))) {
|
||||
useBase64 = Boolean.parseBoolean(element.getAttribute(ATT_BASE_64));
|
||||
}
|
||||
|
||||
boolean useBase64 = StringUtils.hasText(element.getAttribute(ATT_BASE_64))
|
||||
&& Boolean.parseBoolean(element.getAttribute(ATT_BASE_64));
|
||||
String ref = element.getAttribute(ATT_REF);
|
||||
|
||||
if (StringUtils.hasText(ref)) {
|
||||
this.passwordEncoder = new RuntimeBeanReference(ref);
|
||||
}
|
||||
|
|
|
@ -62,43 +62,33 @@ public class UserServiceBeanDefinitionParser extends AbstractUserDetailsServiceB
|
|||
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
|
||||
String userProperties = element.getAttribute(ATT_PROPERTIES);
|
||||
List<Element> userElts = DomUtils.getChildElementsByTagName(element, ELT_USER);
|
||||
|
||||
if (StringUtils.hasText(userProperties)) {
|
||||
|
||||
if (!CollectionUtils.isEmpty(userElts)) {
|
||||
throw new BeanDefinitionStoreException(
|
||||
"Use of a properties file and user elements are mutually exclusive");
|
||||
}
|
||||
|
||||
BeanDefinition bd = new RootBeanDefinition(PropertiesFactoryBean.class);
|
||||
bd.getPropertyValues().addPropertyValue("location", userProperties);
|
||||
builder.addConstructorArgValue(bd);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (CollectionUtils.isEmpty(userElts)) {
|
||||
throw new BeanDefinitionStoreException("You must supply user definitions, either with <" + ELT_USER
|
||||
+ "> child elements or a " + "properties file (using the '" + ATT_PROPERTIES + "' attribute)");
|
||||
}
|
||||
|
||||
ManagedList<BeanDefinition> users = new ManagedList<>();
|
||||
|
||||
for (Object elt : userElts) {
|
||||
Element userElt = (Element) elt;
|
||||
String userName = userElt.getAttribute(ATT_NAME);
|
||||
String password = userElt.getAttribute(ATT_PASSWORD);
|
||||
|
||||
if (!StringUtils.hasLength(password)) {
|
||||
password = generateRandomPassword();
|
||||
}
|
||||
|
||||
boolean locked = "true".equals(userElt.getAttribute(ATT_LOCKED));
|
||||
boolean disabled = "true".equals(userElt.getAttribute(ATT_DISABLED));
|
||||
BeanDefinitionBuilder authorities = BeanDefinitionBuilder.rootBeanDefinition(AuthorityUtils.class);
|
||||
authorities.addConstructorArgValue(userElt.getAttribute(ATT_AUTHORITIES));
|
||||
authorities.setFactoryMethod("commaSeparatedStringToAuthorityList");
|
||||
|
||||
BeanDefinitionBuilder user = BeanDefinitionBuilder.rootBeanDefinition(User.class);
|
||||
user.addConstructorArgValue(userName);
|
||||
user.addConstructorArgValue(password);
|
||||
|
@ -107,10 +97,8 @@ public class UserServiceBeanDefinitionParser extends AbstractUserDetailsServiceB
|
|||
user.addConstructorArgValue(true);
|
||||
user.addConstructorArgValue(!locked);
|
||||
user.addConstructorArgValue(authorities.getBeanDefinition());
|
||||
|
||||
users.add(user.getBeanDefinition());
|
||||
}
|
||||
|
||||
builder.addConstructorArgValue(users);
|
||||
}
|
||||
|
||||
|
|
|
@ -18,9 +18,11 @@ package org.springframework.security.config.core.userdetails;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.User;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.memory.UserAttribute;
|
||||
|
@ -58,27 +60,19 @@ public class UserDetailsMapFactoryBean implements FactoryBean<Collection<UserDet
|
|||
@Override
|
||||
public Collection<UserDetails> getObject() {
|
||||
Collection<UserDetails> users = new ArrayList<>(this.userProperties.size());
|
||||
|
||||
UserAttributeEditor editor = new UserAttributeEditor();
|
||||
for (Map.Entry<String, String> entry : this.userProperties.entrySet()) {
|
||||
String name = entry.getKey();
|
||||
String property = entry.getValue();
|
||||
this.userProperties.forEach((name, property) -> {
|
||||
editor.setAsText(property);
|
||||
UserAttribute attr = (UserAttribute) editor.getValue();
|
||||
if (attr == null) {
|
||||
throw new IllegalStateException("The entry with username '" + name + "' and value '" + property
|
||||
+ "' could not be converted to a UserDetails.");
|
||||
}
|
||||
// @formatter:off
|
||||
UserDetails user = User.withUsername(name)
|
||||
.password(attr.getPassword())
|
||||
.disabled(!attr.isEnabled())
|
||||
.authorities(attr.getAuthorities())
|
||||
.build();
|
||||
users.add(user);
|
||||
// @formatter:on
|
||||
}
|
||||
Assert.state(attr != null, () -> "The entry with username '" + name + "' and value '" + property
|
||||
+ "' could not be converted to a UserDetails.");
|
||||
String password = attr.getPassword();
|
||||
boolean disabled = !attr.isEnabled();
|
||||
List<GrantedAuthority> authorities = attr.getAuthorities();
|
||||
users.add(User.withUsername(name).password(password).disabled(disabled).authorities(authorities).build());
|
||||
});
|
||||
return users;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -57,18 +57,13 @@ public class RsaKeyConversionServicePostProcessor implements BeanFactoryPostProc
|
|||
this.resourceLoader = resourceLoader;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
|
||||
if (hasUserDefinedConversionService(beanFactory)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Converter<String, RSAPrivateKey> pkcs8 = pkcs8();
|
||||
Converter<String, RSAPublicKey> x509 = x509();
|
||||
|
||||
ConversionService service = beanFactory.getConversionService();
|
||||
if (service instanceof ConverterRegistry) {
|
||||
ConverterRegistry registry = (ConverterRegistry) service;
|
||||
|
|
|
@ -86,12 +86,15 @@ final class AuthenticationConfigBuilder {
|
|||
private static final String DEF_REALM = "Realm";
|
||||
|
||||
static final String OPEN_ID_AUTHENTICATION_PROCESSING_FILTER_CLASS = "org.springframework.security.openid.OpenIDAuthenticationFilter";
|
||||
|
||||
static final String OPEN_ID_AUTHENTICATION_PROVIDER_CLASS = "org.springframework.security.openid.OpenIDAuthenticationProvider";
|
||||
|
||||
private static final String OPEN_ID_CONSUMER_CLASS = "org.springframework.security.openid.OpenID4JavaConsumer";
|
||||
|
||||
static final String OPEN_ID_ATTRIBUTE_CLASS = "org.springframework.security.openid.OpenIDAttribute";
|
||||
|
||||
private static final String OPEN_ID_ATTRIBUTE_FACTORY_CLASS = "org.springframework.security.openid.RegexBasedAxFetchListFactory";
|
||||
|
||||
static final String AUTHENTICATION_PROCESSING_FILTER_CLASS = "org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter";
|
||||
|
||||
static final String ATT_AUTH_DETAILS_SOURCE_REF = "authentication-details-source-ref";
|
||||
|
@ -106,6 +109,8 @@ final class AuthenticationConfigBuilder {
|
|||
|
||||
private static final String ATT_KEY = "key";
|
||||
|
||||
private static final String ATT_MAPPABLE_ROLES = "mappable-roles";
|
||||
|
||||
private final Element httpElt;
|
||||
|
||||
private final ParserContext pc;
|
||||
|
@ -226,7 +231,6 @@ final class AuthenticationConfigBuilder {
|
|||
this.portMapper = portMapper;
|
||||
this.portResolver = portResolver;
|
||||
this.csrfLogoutHandler = csrfLogoutHandler;
|
||||
|
||||
createAnonymousFilter();
|
||||
createRememberMeFilter(authenticationManager);
|
||||
createBasicFilter(authenticationManager);
|
||||
|
@ -243,18 +247,14 @@ final class AuthenticationConfigBuilder {
|
|||
}
|
||||
|
||||
void createRememberMeFilter(BeanReference authenticationManager) {
|
||||
|
||||
// Parse remember me before logout as RememberMeServices is also a LogoutHandler
|
||||
// implementation.
|
||||
Element rememberMeElt = DomUtils.getChildElementByTagName(this.httpElt, Elements.REMEMBER_ME);
|
||||
|
||||
if (rememberMeElt != null) {
|
||||
String key = rememberMeElt.getAttribute(ATT_KEY);
|
||||
|
||||
if (!StringUtils.hasText(key)) {
|
||||
key = createKey();
|
||||
}
|
||||
|
||||
RememberMeBeanDefinitionParser rememberMeParser = new RememberMeBeanDefinitionParser(key,
|
||||
authenticationManager);
|
||||
this.rememberMeFilter = rememberMeParser.parse(rememberMeElt, this.pc);
|
||||
|
@ -266,36 +266,28 @@ final class AuthenticationConfigBuilder {
|
|||
private void createRememberMeProvider(String key) {
|
||||
RootBeanDefinition provider = new RootBeanDefinition(RememberMeAuthenticationProvider.class);
|
||||
provider.setSource(this.rememberMeFilter.getSource());
|
||||
|
||||
provider.getConstructorArgumentValues().addGenericArgumentValue(key);
|
||||
|
||||
String id = this.pc.getReaderContext().generateBeanName(provider);
|
||||
this.pc.registerBeanComponent(new BeanComponentDefinition(provider, id));
|
||||
|
||||
this.rememberMeProviderRef = new RuntimeBeanReference(id);
|
||||
}
|
||||
|
||||
void createFormLoginFilter(BeanReference sessionStrategy, BeanReference authManager) {
|
||||
|
||||
Element formLoginElt = DomUtils.getChildElementByTagName(this.httpElt, Elements.FORM_LOGIN);
|
||||
RootBeanDefinition formFilter = null;
|
||||
|
||||
if (formLoginElt != null || this.autoConfig) {
|
||||
FormLoginBeanDefinitionParser parser = new FormLoginBeanDefinitionParser("/login", "POST",
|
||||
AUTHENTICATION_PROCESSING_FILTER_CLASS, this.requestCache, sessionStrategy,
|
||||
this.allowSessionCreation, this.portMapper, this.portResolver);
|
||||
|
||||
parser.parse(formLoginElt, this.pc);
|
||||
formFilter = parser.getFilterBean();
|
||||
this.formEntryPoint = parser.getEntryPointBean();
|
||||
this.loginProcessingUrl = parser.getLoginProcessingUrl();
|
||||
this.formLoginPage = parser.getLoginPage();
|
||||
}
|
||||
|
||||
if (formFilter != null) {
|
||||
formFilter.getPropertyValues().addPropertyValue("allowSessionCreation", this.allowSessionCreation);
|
||||
formFilter.getPropertyValues().addPropertyValue("authenticationManager", authManager);
|
||||
|
||||
// Id is required by login page filter
|
||||
this.formFilterId = this.pc.getReaderContext().generateBeanName(formFilter);
|
||||
this.pc.registerBeanComponent(new BeanComponentDefinition(formFilter, this.formFilterId));
|
||||
|
@ -316,14 +308,11 @@ final class AuthenticationConfigBuilder {
|
|||
return;
|
||||
}
|
||||
this.oauth2LoginEnabled = true;
|
||||
|
||||
OAuth2LoginBeanDefinitionParser parser = new OAuth2LoginBeanDefinitionParser(this.requestCache, this.portMapper,
|
||||
this.portResolver, sessionStrategy, this.allowSessionCreation);
|
||||
BeanDefinition oauth2LoginFilterBean = parser.parse(oauth2LoginElt, this.pc);
|
||||
|
||||
BeanDefinition defaultAuthorizedClientRepository = parser.getDefaultAuthorizedClientRepository();
|
||||
registerDefaultAuthorizedClientRepositoryIfNecessary(defaultAuthorizedClientRepository);
|
||||
|
||||
oauth2LoginFilterBean.getPropertyValues().addPropertyValue("authenticationManager", authManager);
|
||||
|
||||
// retrieve the other bean result
|
||||
|
@ -360,26 +349,21 @@ final class AuthenticationConfigBuilder {
|
|||
return;
|
||||
}
|
||||
this.oauth2ClientEnabled = true;
|
||||
|
||||
OAuth2ClientBeanDefinitionParser parser = new OAuth2ClientBeanDefinitionParser(requestCache,
|
||||
authenticationManager);
|
||||
parser.parse(oauth2ClientElt, this.pc);
|
||||
|
||||
BeanDefinition defaultAuthorizedClientRepository = parser.getDefaultAuthorizedClientRepository();
|
||||
registerDefaultAuthorizedClientRepositoryIfNecessary(defaultAuthorizedClientRepository);
|
||||
|
||||
this.authorizationRequestRedirectFilter = parser.getAuthorizationRequestRedirectFilter();
|
||||
String authorizationRequestRedirectFilterId = this.pc.getReaderContext()
|
||||
.generateBeanName(this.authorizationRequestRedirectFilter);
|
||||
this.pc.registerBeanComponent(new BeanComponentDefinition(this.authorizationRequestRedirectFilter,
|
||||
authorizationRequestRedirectFilterId));
|
||||
|
||||
this.authorizationCodeGrantFilter = parser.getAuthorizationCodeGrantFilter();
|
||||
String authorizationCodeGrantFilterId = this.pc.getReaderContext()
|
||||
.generateBeanName(this.authorizationCodeGrantFilter);
|
||||
this.pc.registerBeanComponent(
|
||||
new BeanComponentDefinition(this.authorizationCodeGrantFilter, authorizationCodeGrantFilterId));
|
||||
|
||||
BeanDefinition authorizationCodeAuthenticationProvider = parser.getAuthorizationCodeAuthenticationProvider();
|
||||
String authorizationCodeAuthenticationProviderId = this.pc.getReaderContext()
|
||||
.generateBeanName(authorizationCodeAuthenticationProvider);
|
||||
|
@ -403,7 +387,6 @@ final class AuthenticationConfigBuilder {
|
|||
if (!this.oauth2LoginEnabled && !this.oauth2ClientEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
boolean webmvcPresent = ClassUtils.isPresent("org.springframework.web.servlet.DispatcherServlet",
|
||||
getClass().getClassLoader());
|
||||
if (webmvcPresent) {
|
||||
|
@ -415,11 +398,9 @@ final class AuthenticationConfigBuilder {
|
|||
void createOpenIDLoginFilter(BeanReference sessionStrategy, BeanReference authManager) {
|
||||
Element openIDLoginElt = DomUtils.getChildElementByTagName(this.httpElt, Elements.OPENID_LOGIN);
|
||||
RootBeanDefinition openIDFilter = null;
|
||||
|
||||
if (openIDLoginElt != null) {
|
||||
openIDFilter = parseOpenIDFilter(sessionStrategy, openIDLoginElt);
|
||||
}
|
||||
|
||||
if (openIDFilter != null) {
|
||||
openIDFilter.getPropertyValues().addPropertyValue("allowSessionCreation", this.allowSessionCreation);
|
||||
openIDFilter.getPropertyValues().addPropertyValue("authenticationManager", authManager);
|
||||
|
@ -427,7 +408,6 @@ final class AuthenticationConfigBuilder {
|
|||
this.openIDFilterId = this.pc.getReaderContext().generateBeanName(openIDFilter);
|
||||
this.pc.registerBeanComponent(new BeanComponentDefinition(openIDFilter, this.openIDFilterId));
|
||||
injectRememberMeServicesRef(openIDFilter, this.rememberMeServicesId);
|
||||
|
||||
createOpenIDProvider();
|
||||
}
|
||||
}
|
||||
|
@ -454,19 +434,15 @@ final class AuthenticationConfigBuilder {
|
|||
this.openIDEntryPoint = parser.getEntryPointBean();
|
||||
this.openidLoginProcessingUrl = parser.getLoginProcessingUrl();
|
||||
this.openIDLoginPage = parser.getLoginPage();
|
||||
|
||||
List<Element> attrExElts = DomUtils.getChildElementsByTagName(openIDLoginElt,
|
||||
Elements.OPENID_ATTRIBUTE_EXCHANGE);
|
||||
|
||||
if (!attrExElts.isEmpty()) {
|
||||
// Set up the consumer with the required attribute list
|
||||
BeanDefinitionBuilder consumerBldr = BeanDefinitionBuilder.rootBeanDefinition(OPEN_ID_CONSUMER_CLASS);
|
||||
BeanDefinitionBuilder axFactory = BeanDefinitionBuilder.rootBeanDefinition(OPEN_ID_ATTRIBUTE_FACTORY_CLASS);
|
||||
ManagedMap<String, ManagedList<BeanDefinition>> axMap = new ManagedMap<>();
|
||||
|
||||
for (Element attrExElt : attrExElts) {
|
||||
String identifierMatch = attrExElt.getAttribute("identifier-match");
|
||||
|
||||
if (!StringUtils.hasText(identifierMatch)) {
|
||||
if (attrExElts.size() > 1) {
|
||||
this.pc.getReaderContext().error("You must supply an identifier-match attribute if using more"
|
||||
|
@ -475,11 +451,9 @@ final class AuthenticationConfigBuilder {
|
|||
// Match anything
|
||||
identifierMatch = ".*";
|
||||
}
|
||||
|
||||
axMap.put(identifierMatch, parseOpenIDAttributes(attrExElt));
|
||||
}
|
||||
axFactory.addConstructorArgValue(axMap);
|
||||
|
||||
consumerBldr.addConstructorArgValue(axFactory.getBeanDefinition());
|
||||
openIDFilter.getPropertyValues().addPropertyValue("consumer", consumerBldr.getBeanDefinition());
|
||||
}
|
||||
|
@ -499,13 +473,11 @@ final class AuthenticationConfigBuilder {
|
|||
if (StringUtils.hasLength(required)) {
|
||||
attrBldr.addPropertyValue("required", Boolean.valueOf(required));
|
||||
}
|
||||
|
||||
if (StringUtils.hasLength(count)) {
|
||||
attrBldr.addPropertyValue("count", Integer.parseInt(count));
|
||||
}
|
||||
attributes.add(attrBldr.getBeanDefinition());
|
||||
}
|
||||
|
||||
return attributes;
|
||||
}
|
||||
|
||||
|
@ -513,14 +485,11 @@ final class AuthenticationConfigBuilder {
|
|||
Element openIDLoginElt = DomUtils.getChildElementByTagName(this.httpElt, Elements.OPENID_LOGIN);
|
||||
BeanDefinitionBuilder openIDProviderBuilder = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(OPEN_ID_AUTHENTICATION_PROVIDER_CLASS);
|
||||
|
||||
RootBeanDefinition uds = new RootBeanDefinition();
|
||||
uds.setFactoryBeanName(BeanIds.USER_DETAILS_SERVICE_FACTORY);
|
||||
uds.setFactoryMethodName("authenticationUserDetailsService");
|
||||
uds.getConstructorArgumentValues().addGenericArgumentValue(openIDLoginElt.getAttribute(ATT_USER_SERVICE_REF));
|
||||
|
||||
openIDProviderBuilder.addPropertyValue("authenticationUserDetailsService", uds);
|
||||
|
||||
BeanDefinition openIDProvider = openIDProviderBuilder.getBeanDefinition();
|
||||
this.openIDProviderRef = new RuntimeBeanReference(
|
||||
this.pc.getReaderContext().registerWithGeneratedName(openIDProvider));
|
||||
|
@ -535,30 +504,22 @@ final class AuthenticationConfigBuilder {
|
|||
|
||||
void createBasicFilter(BeanReference authManager) {
|
||||
Element basicAuthElt = DomUtils.getChildElementByTagName(this.httpElt, Elements.BASIC_AUTH);
|
||||
|
||||
if (basicAuthElt == null && !this.autoConfig) {
|
||||
// No basic auth, do nothing
|
||||
return;
|
||||
}
|
||||
|
||||
String realm = this.httpElt.getAttribute(ATT_REALM);
|
||||
if (!StringUtils.hasText(realm)) {
|
||||
realm = DEF_REALM;
|
||||
}
|
||||
|
||||
BeanDefinitionBuilder filterBuilder = BeanDefinitionBuilder.rootBeanDefinition(BasicAuthenticationFilter.class);
|
||||
|
||||
String entryPointId;
|
||||
|
||||
if (basicAuthElt != null) {
|
||||
if (StringUtils.hasText(basicAuthElt.getAttribute(ATT_ENTRY_POINT_REF))) {
|
||||
this.basicEntryPoint = new RuntimeBeanReference(basicAuthElt.getAttribute(ATT_ENTRY_POINT_REF));
|
||||
}
|
||||
|
||||
injectAuthenticationDetailsSource(basicAuthElt, filterBuilder);
|
||||
|
||||
}
|
||||
|
||||
if (this.basicEntryPoint == null) {
|
||||
RootBeanDefinition entryPoint = new RootBeanDefinition(BasicAuthenticationEntryPoint.class);
|
||||
entryPoint.setSource(this.pc.extractSource(this.httpElt));
|
||||
|
@ -567,7 +528,6 @@ final class AuthenticationConfigBuilder {
|
|||
this.pc.registerBeanComponent(new BeanComponentDefinition(entryPoint, entryPointId));
|
||||
this.basicEntryPoint = new RuntimeBeanReference(entryPointId);
|
||||
}
|
||||
|
||||
filterBuilder.addConstructorArgValue(authManager);
|
||||
filterBuilder.addConstructorArgValue(this.basicEntryPoint);
|
||||
this.basicFilter = filterBuilder.getBeanDefinition();
|
||||
|
@ -575,12 +535,10 @@ final class AuthenticationConfigBuilder {
|
|||
|
||||
void createBearerTokenAuthenticationFilter(BeanReference authManager) {
|
||||
Element resourceServerElt = DomUtils.getChildElementByTagName(this.httpElt, Elements.OAUTH2_RESOURCE_SERVER);
|
||||
|
||||
if (resourceServerElt == null) {
|
||||
// No resource server, do nothing
|
||||
return;
|
||||
}
|
||||
|
||||
OAuth2ResourceServerBeanDefinitionParser resourceServerBuilder = new OAuth2ResourceServerBeanDefinitionParser(
|
||||
authManager, this.authenticationProviders, this.defaultEntryPointMappings,
|
||||
this.defaultDeniedHandlerMappings, this.csrfIgnoreRequestMatchers);
|
||||
|
@ -590,37 +548,28 @@ final class AuthenticationConfigBuilder {
|
|||
void createX509Filter(BeanReference authManager) {
|
||||
Element x509Elt = DomUtils.getChildElementByTagName(this.httpElt, Elements.X509);
|
||||
RootBeanDefinition filter = null;
|
||||
|
||||
if (x509Elt != null) {
|
||||
BeanDefinitionBuilder filterBuilder = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(X509AuthenticationFilter.class);
|
||||
filterBuilder.getRawBeanDefinition().setSource(this.pc.extractSource(x509Elt));
|
||||
filterBuilder.addPropertyValue("authenticationManager", authManager);
|
||||
|
||||
String regex = x509Elt.getAttribute("subject-principal-regex");
|
||||
|
||||
if (StringUtils.hasText(regex)) {
|
||||
BeanDefinitionBuilder extractor = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(SubjectDnX509PrincipalExtractor.class);
|
||||
extractor.addPropertyValue("subjectDnRegex", regex);
|
||||
|
||||
filterBuilder.addPropertyValue("principalExtractor", extractor.getBeanDefinition());
|
||||
}
|
||||
|
||||
injectAuthenticationDetailsSource(x509Elt, filterBuilder);
|
||||
|
||||
filter = (RootBeanDefinition) filterBuilder.getBeanDefinition();
|
||||
createPrauthEntryPoint(x509Elt);
|
||||
|
||||
createX509Provider();
|
||||
}
|
||||
|
||||
this.x509Filter = filter;
|
||||
}
|
||||
|
||||
private void injectAuthenticationDetailsSource(Element elt, BeanDefinitionBuilder filterBuilder) {
|
||||
String authDetailsSourceRef = elt.getAttribute(AuthenticationConfigBuilder.ATT_AUTH_DETAILS_SOURCE_REF);
|
||||
|
||||
if (StringUtils.hasText(authDetailsSourceRef)) {
|
||||
filterBuilder.addPropertyReference("authenticationDetailsSource", authDetailsSourceRef);
|
||||
}
|
||||
|
@ -629,14 +578,11 @@ final class AuthenticationConfigBuilder {
|
|||
private void createX509Provider() {
|
||||
Element x509Elt = DomUtils.getChildElementByTagName(this.httpElt, Elements.X509);
|
||||
BeanDefinition provider = new RootBeanDefinition(PreAuthenticatedAuthenticationProvider.class);
|
||||
|
||||
RootBeanDefinition uds = new RootBeanDefinition();
|
||||
uds.setFactoryBeanName(BeanIds.USER_DETAILS_SERVICE_FACTORY);
|
||||
uds.setFactoryMethodName("authenticationUserDetailsService");
|
||||
uds.getConstructorArgumentValues().addGenericArgumentValue(x509Elt.getAttribute(ATT_USER_SERVICE_REF));
|
||||
|
||||
provider.getPropertyValues().addPropertyValue("preAuthenticatedUserDetailsService", uds);
|
||||
|
||||
this.x509ProviderRef = new RuntimeBeanReference(this.pc.getReaderContext().registerWithGeneratedName(provider));
|
||||
}
|
||||
|
||||
|
@ -648,47 +594,37 @@ final class AuthenticationConfigBuilder {
|
|||
}
|
||||
|
||||
void createJeeFilter(BeanReference authManager) {
|
||||
final String ATT_MAPPABLE_ROLES = "mappable-roles";
|
||||
|
||||
Element jeeElt = DomUtils.getChildElementByTagName(this.httpElt, Elements.JEE);
|
||||
RootBeanDefinition filter = null;
|
||||
|
||||
if (jeeElt != null) {
|
||||
BeanDefinitionBuilder filterBuilder = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(J2eePreAuthenticatedProcessingFilter.class);
|
||||
filterBuilder.getRawBeanDefinition().setSource(this.pc.extractSource(jeeElt));
|
||||
filterBuilder.addPropertyValue("authenticationManager", authManager);
|
||||
|
||||
BeanDefinitionBuilder adsBldr = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource.class);
|
||||
adsBldr.addPropertyValue("userRoles2GrantedAuthoritiesMapper",
|
||||
new RootBeanDefinition(SimpleAttributes2GrantedAuthoritiesMapper.class));
|
||||
|
||||
String roles = jeeElt.getAttribute(ATT_MAPPABLE_ROLES);
|
||||
Assert.hasLength(roles, "roles is expected to have length");
|
||||
BeanDefinitionBuilder rolesBuilder = BeanDefinitionBuilder.rootBeanDefinition(StringUtils.class);
|
||||
rolesBuilder.addConstructorArgValue(roles);
|
||||
rolesBuilder.setFactoryMethod("commaDelimitedListToSet");
|
||||
|
||||
RootBeanDefinition mappableRolesRetriever = new RootBeanDefinition(SimpleMappableAttributesRetriever.class);
|
||||
mappableRolesRetriever.getPropertyValues().addPropertyValue("mappableAttributes",
|
||||
rolesBuilder.getBeanDefinition());
|
||||
adsBldr.addPropertyValue("mappableRolesRetriever", mappableRolesRetriever);
|
||||
filterBuilder.addPropertyValue("authenticationDetailsSource", adsBldr.getBeanDefinition());
|
||||
|
||||
filter = (RootBeanDefinition) filterBuilder.getBeanDefinition();
|
||||
|
||||
createPrauthEntryPoint(jeeElt);
|
||||
createJeeProvider();
|
||||
}
|
||||
|
||||
this.jeeFilter = filter;
|
||||
}
|
||||
|
||||
private void createJeeProvider() {
|
||||
Element jeeElt = DomUtils.getChildElementByTagName(this.httpElt, Elements.JEE);
|
||||
BeanDefinition provider = new RootBeanDefinition(PreAuthenticatedAuthenticationProvider.class);
|
||||
|
||||
RootBeanDefinition uds;
|
||||
if (StringUtils.hasText(jeeElt.getAttribute(ATT_USER_SERVICE_REF))) {
|
||||
uds = new RootBeanDefinition();
|
||||
|
@ -699,16 +635,13 @@ final class AuthenticationConfigBuilder {
|
|||
else {
|
||||
uds = new RootBeanDefinition(PreAuthenticatedGrantedAuthoritiesUserDetailsService.class);
|
||||
}
|
||||
|
||||
provider.getPropertyValues().addPropertyValue("preAuthenticatedUserDetailsService", uds);
|
||||
|
||||
this.jeeProviderRef = new RuntimeBeanReference(this.pc.getReaderContext().registerWithGeneratedName(provider));
|
||||
}
|
||||
|
||||
void createLoginPageFilterIfNeeded() {
|
||||
boolean needLoginPage = this.formFilterId != null || this.openIDFilterId != null
|
||||
|| this.oauth2LoginFilterId != null;
|
||||
|
||||
// If no login page has been defined, add in the default page generator.
|
||||
if (needLoginPage && this.formLoginPage == null && this.openIDLoginPage == null) {
|
||||
this.logger.info("No login page configured. The default internal one will be used. Use the '"
|
||||
|
@ -720,23 +653,19 @@ final class AuthenticationConfigBuilder {
|
|||
BeanDefinitionBuilder logoutPageFilter = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(DefaultLogoutPageGeneratingFilter.class);
|
||||
logoutPageFilter.addPropertyValue("resolveHiddenInputs", new CsrfTokenHiddenInputFunction());
|
||||
|
||||
if (this.formFilterId != null) {
|
||||
loginPageFilter.addConstructorArgReference(this.formFilterId);
|
||||
loginPageFilter.addPropertyValue("authenticationUrl", this.loginProcessingUrl);
|
||||
}
|
||||
|
||||
if (this.openIDFilterId != null) {
|
||||
loginPageFilter.addConstructorArgReference(this.openIDFilterId);
|
||||
loginPageFilter.addPropertyValue("openIDauthenticationUrl", this.openidLoginProcessingUrl);
|
||||
}
|
||||
|
||||
if (this.oauth2LoginFilterId != null) {
|
||||
loginPageFilter.addConstructorArgReference(this.oauth2LoginFilterId);
|
||||
loginPageFilter.addPropertyValue("Oauth2LoginEnabled", true);
|
||||
loginPageFilter.addPropertyValue("Oauth2AuthenticationUrlToClientName", this.oauth2LoginLinks);
|
||||
}
|
||||
|
||||
this.loginPageGenerationFilter = loginPageFilter.getBeanDefinition();
|
||||
this.logoutPageGenerationFilter = logoutPageFilter.getBeanDefinition();
|
||||
}
|
||||
|
@ -784,51 +713,41 @@ final class AuthenticationConfigBuilder {
|
|||
|
||||
void createAnonymousFilter() {
|
||||
Element anonymousElt = DomUtils.getChildElementByTagName(this.httpElt, Elements.ANONYMOUS);
|
||||
|
||||
if (anonymousElt != null && "false".equals(anonymousElt.getAttribute("enabled"))) {
|
||||
return;
|
||||
}
|
||||
|
||||
String grantedAuthority = null;
|
||||
String username = null;
|
||||
String key = null;
|
||||
Object source = this.pc.extractSource(this.httpElt);
|
||||
|
||||
if (anonymousElt != null) {
|
||||
grantedAuthority = anonymousElt.getAttribute("granted-authority");
|
||||
username = anonymousElt.getAttribute("username");
|
||||
key = anonymousElt.getAttribute(ATT_KEY);
|
||||
source = this.pc.extractSource(anonymousElt);
|
||||
}
|
||||
|
||||
if (!StringUtils.hasText(grantedAuthority)) {
|
||||
grantedAuthority = "ROLE_ANONYMOUS";
|
||||
}
|
||||
|
||||
if (!StringUtils.hasText(username)) {
|
||||
username = "anonymousUser";
|
||||
}
|
||||
|
||||
if (!StringUtils.hasText(key)) {
|
||||
// Generate a random key for the Anonymous provider
|
||||
key = createKey();
|
||||
}
|
||||
|
||||
this.anonymousFilter = new RootBeanDefinition(AnonymousAuthenticationFilter.class);
|
||||
this.anonymousFilter.getConstructorArgumentValues().addIndexedArgumentValue(0, key);
|
||||
this.anonymousFilter.getConstructorArgumentValues().addIndexedArgumentValue(1, username);
|
||||
this.anonymousFilter.getConstructorArgumentValues().addIndexedArgumentValue(2,
|
||||
AuthorityUtils.commaSeparatedStringToAuthorityList(grantedAuthority));
|
||||
this.anonymousFilter.setSource(source);
|
||||
|
||||
RootBeanDefinition anonymousProviderBean = new RootBeanDefinition(AnonymousAuthenticationProvider.class);
|
||||
anonymousProviderBean.getConstructorArgumentValues().addIndexedArgumentValue(0, key);
|
||||
anonymousProviderBean.setSource(this.anonymousFilter.getSource());
|
||||
String id = this.pc.getReaderContext().generateBeanName(anonymousProviderBean);
|
||||
this.pc.registerBeanComponent(new BeanComponentDefinition(anonymousProviderBean, id));
|
||||
|
||||
this.anonymousProviderRef = new RuntimeBeanReference(id);
|
||||
|
||||
}
|
||||
|
||||
private String createKey() {
|
||||
|
@ -840,11 +759,10 @@ final class AuthenticationConfigBuilder {
|
|||
BeanDefinitionBuilder etfBuilder = BeanDefinitionBuilder.rootBeanDefinition(ExceptionTranslationFilter.class);
|
||||
this.accessDeniedHandler = createAccessDeniedHandler(this.httpElt, this.pc);
|
||||
etfBuilder.addPropertyValue("accessDeniedHandler", this.accessDeniedHandler);
|
||||
assert this.requestCache != null;
|
||||
Assert.state(this.requestCache != null, "No request cache found");
|
||||
this.mainEntryPoint = selectEntryPoint();
|
||||
etfBuilder.addConstructorArgValue(this.mainEntryPoint);
|
||||
etfBuilder.addConstructorArgValue(this.requestCache);
|
||||
|
||||
this.etf = etfBuilder.getBeanDefinition();
|
||||
}
|
||||
|
||||
|
@ -852,11 +770,9 @@ final class AuthenticationConfigBuilder {
|
|||
Element accessDeniedElt = DomUtils.getChildElementByTagName(element, Elements.ACCESS_DENIED_HANDLER);
|
||||
BeanDefinitionBuilder accessDeniedHandler = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(AccessDeniedHandlerImpl.class);
|
||||
|
||||
if (accessDeniedElt != null) {
|
||||
String errorPage = accessDeniedElt.getAttribute("error-page");
|
||||
String ref = accessDeniedElt.getAttribute("ref");
|
||||
|
||||
if (StringUtils.hasText(errorPage)) {
|
||||
if (StringUtils.hasText(ref)) {
|
||||
pc.getReaderContext()
|
||||
|
@ -868,25 +784,21 @@ final class AuthenticationConfigBuilder {
|
|||
accessDeniedHandler.addPropertyValue("errorPage", errorPage);
|
||||
return accessDeniedHandler.getBeanDefinition();
|
||||
}
|
||||
else if (StringUtils.hasText(ref)) {
|
||||
if (StringUtils.hasText(ref)) {
|
||||
return new RuntimeBeanReference(ref);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (this.defaultDeniedHandlerMappings.isEmpty()) {
|
||||
return accessDeniedHandler.getBeanDefinition();
|
||||
}
|
||||
if (this.defaultDeniedHandlerMappings.size() == 1) {
|
||||
return this.defaultDeniedHandlerMappings.values().iterator().next();
|
||||
}
|
||||
|
||||
accessDeniedHandler = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(RequestMatcherDelegatingAccessDeniedHandler.class);
|
||||
accessDeniedHandler.addConstructorArgValue(this.defaultDeniedHandlerMappings);
|
||||
accessDeniedHandler
|
||||
.addConstructorArgValue(BeanDefinitionBuilder.rootBeanDefinition(AccessDeniedHandlerImpl.class));
|
||||
|
||||
return accessDeniedHandler.getBeanDefinition();
|
||||
}
|
||||
|
||||
|
@ -894,11 +806,9 @@ final class AuthenticationConfigBuilder {
|
|||
// We need to establish the main entry point.
|
||||
// First check if a custom entry point bean is set
|
||||
String customEntryPoint = this.httpElt.getAttribute(ATT_ENTRY_POINT_REF);
|
||||
|
||||
if (StringUtils.hasText(customEntryPoint)) {
|
||||
return new RuntimeBeanReference(customEntryPoint);
|
||||
}
|
||||
|
||||
if (!this.defaultEntryPointMappings.isEmpty()) {
|
||||
if (this.defaultEntryPointMappings.size() == 1) {
|
||||
return this.defaultEntryPointMappings.values().iterator().next();
|
||||
|
@ -908,7 +818,6 @@ final class AuthenticationConfigBuilder {
|
|||
delegatingEntryPoint.addConstructorArgValue(this.defaultEntryPointMappings);
|
||||
return delegatingEntryPoint.getBeanDefinition();
|
||||
}
|
||||
|
||||
Element basicAuthElt = DomUtils.getChildElementByTagName(this.httpElt, Elements.BASIC_AUTH);
|
||||
Element formLoginElt = DomUtils.getChildElementByTagName(this.httpElt, Elements.FORM_LOGIN);
|
||||
Element openIDLoginElt = DomUtils.getChildElementByTagName(this.httpElt, Elements.OPENID_LOGIN);
|
||||
|
@ -917,21 +826,17 @@ final class AuthenticationConfigBuilder {
|
|||
&& this.oauth2LoginEntryPoint == null) {
|
||||
return this.basicEntryPoint;
|
||||
}
|
||||
|
||||
// If formLogin has been enabled either through an element or auto-config, then it
|
||||
// is used if no openID login page
|
||||
// has been set.
|
||||
|
||||
if (this.formLoginPage != null && this.openIDLoginPage != null) {
|
||||
this.pc.getReaderContext().error(
|
||||
"Only one login-page can be defined, either for OpenID or form-login, " + "but not both.",
|
||||
this.pc.extractSource(openIDLoginElt));
|
||||
}
|
||||
|
||||
if (this.formFilterId != null && this.openIDLoginPage == null) {
|
||||
// gh-6802
|
||||
// If form login was enabled through element and Oauth2 login was enabled from
|
||||
// element then use form login
|
||||
// element then use form login (gh-6802)
|
||||
if (formLoginElt != null && this.oauth2LoginEntryPoint != null) {
|
||||
return this.formEntryPoint;
|
||||
}
|
||||
|
@ -941,22 +846,18 @@ final class AuthenticationConfigBuilder {
|
|||
return this.formEntryPoint;
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise use OpenID if enabled
|
||||
if (this.openIDFilterId != null) {
|
||||
return this.openIDEntryPoint;
|
||||
}
|
||||
|
||||
// If X.509 or JEE have been enabled, use the preauth entry point.
|
||||
if (this.preAuthEntryPoint != null) {
|
||||
return this.preAuthEntryPoint;
|
||||
}
|
||||
|
||||
// OAuth2 entry point will not be null if only 1 client registration
|
||||
if (this.oauth2LoginEntryPoint != null) {
|
||||
return this.oauth2LoginEntryPoint;
|
||||
}
|
||||
|
||||
this.pc.getReaderContext().error("No AuthenticationEntryPoint could be established. Please "
|
||||
+ "make sure you have a login mechanism configured through the namespace (such as form-login) or "
|
||||
+ "specify a custom AuthenticationEntryPoint with the '" + ATT_ENTRY_POINT_REF + "' attribute ",
|
||||
|
@ -976,107 +877,83 @@ final class AuthenticationConfigBuilder {
|
|||
|
||||
List<OrderDecorator> getFilters() {
|
||||
List<OrderDecorator> filters = new ArrayList<>();
|
||||
|
||||
if (this.anonymousFilter != null) {
|
||||
filters.add(new OrderDecorator(this.anonymousFilter, SecurityFilters.ANONYMOUS_FILTER));
|
||||
}
|
||||
|
||||
if (this.rememberMeFilter != null) {
|
||||
filters.add(new OrderDecorator(this.rememberMeFilter, SecurityFilters.REMEMBER_ME_FILTER));
|
||||
}
|
||||
|
||||
if (this.logoutFilter != null) {
|
||||
filters.add(new OrderDecorator(this.logoutFilter, SecurityFilters.LOGOUT_FILTER));
|
||||
}
|
||||
|
||||
if (this.x509Filter != null) {
|
||||
filters.add(new OrderDecorator(this.x509Filter, SecurityFilters.X509_FILTER));
|
||||
}
|
||||
|
||||
if (this.jeeFilter != null) {
|
||||
filters.add(new OrderDecorator(this.jeeFilter, SecurityFilters.PRE_AUTH_FILTER));
|
||||
}
|
||||
|
||||
if (this.formFilterId != null) {
|
||||
filters.add(
|
||||
new OrderDecorator(new RuntimeBeanReference(this.formFilterId), SecurityFilters.FORM_LOGIN_FILTER));
|
||||
}
|
||||
|
||||
if (this.oauth2LoginFilterId != null) {
|
||||
filters.add(new OrderDecorator(new RuntimeBeanReference(this.oauth2LoginFilterId),
|
||||
SecurityFilters.OAUTH2_LOGIN_FILTER));
|
||||
filters.add(new OrderDecorator(this.oauth2AuthorizationRequestRedirectFilter,
|
||||
SecurityFilters.OAUTH2_AUTHORIZATION_REQUEST_FILTER));
|
||||
}
|
||||
|
||||
if (this.openIDFilterId != null) {
|
||||
filters.add(
|
||||
new OrderDecorator(new RuntimeBeanReference(this.openIDFilterId), SecurityFilters.OPENID_FILTER));
|
||||
}
|
||||
|
||||
if (this.loginPageGenerationFilter != null) {
|
||||
filters.add(new OrderDecorator(this.loginPageGenerationFilter, SecurityFilters.LOGIN_PAGE_FILTER));
|
||||
filters.add(new OrderDecorator(this.logoutPageGenerationFilter, SecurityFilters.LOGOUT_PAGE_FILTER));
|
||||
}
|
||||
|
||||
if (this.basicFilter != null) {
|
||||
filters.add(new OrderDecorator(this.basicFilter, SecurityFilters.BASIC_AUTH_FILTER));
|
||||
}
|
||||
|
||||
if (this.bearerTokenAuthenticationFilter != null) {
|
||||
filters.add(
|
||||
new OrderDecorator(this.bearerTokenAuthenticationFilter, SecurityFilters.BEARER_TOKEN_AUTH_FILTER));
|
||||
}
|
||||
|
||||
if (this.authorizationCodeGrantFilter != null) {
|
||||
filters.add(new OrderDecorator(this.authorizationRequestRedirectFilter,
|
||||
SecurityFilters.OAUTH2_AUTHORIZATION_REQUEST_FILTER.getOrder() + 1));
|
||||
filters.add(new OrderDecorator(this.authorizationCodeGrantFilter,
|
||||
SecurityFilters.OAUTH2_AUTHORIZATION_CODE_GRANT_FILTER));
|
||||
}
|
||||
|
||||
filters.add(new OrderDecorator(this.etf, SecurityFilters.EXCEPTION_TRANSLATION_FILTER));
|
||||
|
||||
return filters;
|
||||
}
|
||||
|
||||
List<BeanReference> getProviders() {
|
||||
List<BeanReference> providers = new ArrayList<>();
|
||||
|
||||
if (this.anonymousProviderRef != null) {
|
||||
providers.add(this.anonymousProviderRef);
|
||||
}
|
||||
|
||||
if (this.rememberMeProviderRef != null) {
|
||||
providers.add(this.rememberMeProviderRef);
|
||||
}
|
||||
|
||||
if (this.openIDProviderRef != null) {
|
||||
providers.add(this.openIDProviderRef);
|
||||
}
|
||||
|
||||
if (this.x509ProviderRef != null) {
|
||||
providers.add(this.x509ProviderRef);
|
||||
}
|
||||
|
||||
if (this.jeeProviderRef != null) {
|
||||
providers.add(this.jeeProviderRef);
|
||||
}
|
||||
|
||||
if (this.oauth2LoginAuthenticationProviderRef != null) {
|
||||
providers.add(this.oauth2LoginAuthenticationProviderRef);
|
||||
}
|
||||
|
||||
if (this.oauth2LoginOidcAuthenticationProviderRef != null) {
|
||||
providers.add(this.oauth2LoginOidcAuthenticationProviderRef);
|
||||
}
|
||||
|
||||
if (this.authorizationCodeAuthenticationProviderRef != null) {
|
||||
providers.add(this.authorizationCodeAuthenticationProviderRef);
|
||||
}
|
||||
|
||||
providers.addAll(this.authenticationProviders);
|
||||
|
||||
return providers;
|
||||
}
|
||||
|
||||
|
|
|
@ -43,7 +43,6 @@ public final class ChannelAttributeFactory {
|
|||
|
||||
public static List<ConfigAttribute> createChannelAttributes(String requiredChannel) {
|
||||
String channelConfigAttribute;
|
||||
|
||||
if (requiredChannel.equals(OPT_REQUIRES_HTTPS)) {
|
||||
channelConfigAttribute = "REQUIRES_SECURE_CHANNEL";
|
||||
}
|
||||
|
@ -56,7 +55,6 @@ public final class ChannelAttributeFactory {
|
|||
else {
|
||||
throw new BeanCreationException("Unknown channel attribute " + requiredChannel);
|
||||
}
|
||||
|
||||
return SecurityConfig.createList(channelConfigAttribute);
|
||||
}
|
||||
|
||||
|
|
|
@ -46,17 +46,14 @@ public class CorsBeanDefinitionParser {
|
|||
if (element == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String filterRef = element.getAttribute(ATT_REF);
|
||||
if (StringUtils.hasText(filterRef)) {
|
||||
return new RuntimeBeanReference(filterRef);
|
||||
}
|
||||
|
||||
BeanMetadataElement configurationSource = getSource(element, parserContext);
|
||||
if (configurationSource == null) {
|
||||
throw new BeanCreationException("Could not create CorsFilter");
|
||||
}
|
||||
|
||||
BeanDefinitionBuilder filterBldr = BeanDefinitionBuilder.rootBeanDefinition(CorsFilter.class);
|
||||
filterBldr.addConstructorArgValue(configurationSource);
|
||||
return filterBldr.getBeanDefinition();
|
||||
|
@ -67,12 +64,10 @@ public class CorsBeanDefinitionParser {
|
|||
if (StringUtils.hasText(configurationSourceRef)) {
|
||||
return new RuntimeBeanReference(configurationSourceRef);
|
||||
}
|
||||
|
||||
boolean mvcPresent = ClassUtils.isPresent(HANDLER_MAPPING_INTROSPECTOR, getClass().getClassLoader());
|
||||
if (!mvcPresent) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new RootBeanDefinition(HandlerMappingIntrospectorFactoryBean.class);
|
||||
}
|
||||
|
||||
|
|
|
@ -92,14 +92,11 @@ public class CsrfBeanDefinitionParser implements BeanDefinitionParser {
|
|||
pc.registerBeanComponent(componentDefinition);
|
||||
}
|
||||
}
|
||||
|
||||
if (element != null) {
|
||||
this.csrfRepositoryRef = element.getAttribute(ATT_REPOSITORY);
|
||||
this.requestMatcherRef = element.getAttribute(ATT_MATCHER);
|
||||
}
|
||||
|
||||
if (!StringUtils.hasText(this.csrfRepositoryRef)) {
|
||||
|
||||
RootBeanDefinition csrfTokenRepository = new RootBeanDefinition(HttpSessionCsrfTokenRepository.class);
|
||||
BeanDefinitionBuilder lazyTokenRepository = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(LazyCsrfTokenRepository.class);
|
||||
|
@ -108,14 +105,11 @@ public class CsrfBeanDefinitionParser implements BeanDefinitionParser {
|
|||
pc.registerBeanComponent(
|
||||
new BeanComponentDefinition(lazyTokenRepository.getBeanDefinition(), this.csrfRepositoryRef));
|
||||
}
|
||||
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(CsrfFilter.class);
|
||||
builder.addConstructorArgReference(this.csrfRepositoryRef);
|
||||
|
||||
if (StringUtils.hasText(this.requestMatcherRef)) {
|
||||
builder.addPropertyReference("requireCsrfProtectionMatcher", this.requestMatcherRef);
|
||||
}
|
||||
|
||||
this.csrfFilter = builder.getBeanDefinition();
|
||||
return this.csrfFilter;
|
||||
}
|
||||
|
@ -155,12 +149,10 @@ public class CsrfBeanDefinitionParser implements BeanDefinitionParser {
|
|||
.rootBeanDefinition(InvalidSessionAccessDeniedHandler.class);
|
||||
invalidSessionHandlerBldr.addConstructorArgValue(invalidSessionStrategy);
|
||||
handlers.put(MissingCsrfTokenException.class, invalidSessionHandlerBldr.getBeanDefinition());
|
||||
|
||||
BeanDefinitionBuilder deniedBldr = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(DelegatingAccessDeniedHandler.class);
|
||||
deniedBldr.addConstructorArgValue(handlers);
|
||||
deniedBldr.addConstructorArgValue(defaultDeniedHandler);
|
||||
|
||||
return deniedBldr.getBeanDefinition();
|
||||
}
|
||||
|
||||
|
@ -180,13 +172,9 @@ public class CsrfBeanDefinitionParser implements BeanDefinitionParser {
|
|||
|
||||
void setIgnoreCsrfRequestMatchers(List<BeanDefinition> requestMatchers) {
|
||||
if (!requestMatchers.isEmpty()) {
|
||||
BeanMetadataElement requestMatcher;
|
||||
if (StringUtils.hasText(this.requestMatcherRef)) {
|
||||
requestMatcher = new RuntimeBeanReference(this.requestMatcherRef);
|
||||
}
|
||||
else {
|
||||
requestMatcher = new RootBeanDefinition(DefaultRequiresCsrfMatcher.class);
|
||||
}
|
||||
BeanMetadataElement requestMatcher = (!StringUtils.hasText(this.requestMatcherRef))
|
||||
? new RootBeanDefinition(DefaultRequiresCsrfMatcher.class)
|
||||
: new RuntimeBeanReference(this.requestMatcherRef);
|
||||
BeanDefinitionBuilder and = BeanDefinitionBuilder.rootBeanDefinition(AndRequestMatcher.class);
|
||||
BeanDefinitionBuilder negated = BeanDefinitionBuilder.rootBeanDefinition(NegatedRequestMatcher.class);
|
||||
BeanDefinitionBuilder or = BeanDefinitionBuilder.rootBeanDefinition(OrRequestMatcher.class);
|
||||
|
|
|
@ -58,7 +58,6 @@ public class DefaultFilterChainValidator implements FilterChainProxy.FilterChain
|
|||
checkLoginPageIsntProtected(fcp, filterChain.getFilters());
|
||||
checkFilterStack(filterChain.getFilters());
|
||||
}
|
||||
|
||||
checkPathOrder(new ArrayList<>(fcp.getFilterChains()));
|
||||
checkForDuplicateMatchers(new ArrayList<>(fcp.getFilterChains()));
|
||||
}
|
||||
|
@ -66,7 +65,6 @@ public class DefaultFilterChainValidator implements FilterChainProxy.FilterChain
|
|||
private void checkPathOrder(List<SecurityFilterChain> filterChains) {
|
||||
// Check that the universal pattern is listed at the end, if at all
|
||||
Iterator<SecurityFilterChain> chains = filterChains.iterator();
|
||||
|
||||
while (chains.hasNext()) {
|
||||
RequestMatcher matcher = ((DefaultSecurityFilterChain) chains.next()).getRequestMatcher();
|
||||
if (AnyRequestMatcher.INSTANCE.equals(matcher) && chains.hasNext()) {
|
||||
|
@ -78,10 +76,8 @@ public class DefaultFilterChainValidator implements FilterChainProxy.FilterChain
|
|||
}
|
||||
|
||||
private void checkForDuplicateMatchers(List<SecurityFilterChain> chains) {
|
||||
|
||||
while (chains.size() > 1) {
|
||||
DefaultSecurityFilterChain chain = (DefaultSecurityFilterChain) chains.remove(0);
|
||||
|
||||
for (SecurityFilterChain test : chains) {
|
||||
if (chain.getRequestMatcher().equals(((DefaultSecurityFilterChain) test).getRequestMatcher())) {
|
||||
throw new IllegalArgumentException("The FilterChainProxy contains two filter chains using the"
|
||||
|
@ -99,7 +95,6 @@ public class DefaultFilterChainValidator implements FilterChainProxy.FilterChain
|
|||
return (F) f;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -140,16 +135,13 @@ public class DefaultFilterChainValidator implements FilterChainProxy.FilterChain
|
|||
*/
|
||||
private void checkLoginPageIsntProtected(FilterChainProxy fcp, List<Filter> filterStack) {
|
||||
ExceptionTranslationFilter etf = getFilter(ExceptionTranslationFilter.class, filterStack);
|
||||
|
||||
if (etf == null || !(etf.getAuthenticationEntryPoint() instanceof LoginUrlAuthenticationEntryPoint)) {
|
||||
return;
|
||||
}
|
||||
|
||||
String loginPage = ((LoginUrlAuthenticationEntryPoint) etf.getAuthenticationEntryPoint()).getLoginFormUrl();
|
||||
this.logger.info("Checking whether login URL '" + loginPage + "' is accessible with your configuration");
|
||||
FilterInvocation loginRequest = new FilterInvocation(loginPage, "POST");
|
||||
List<Filter> filters = null;
|
||||
|
||||
try {
|
||||
filters = fcp.getFilters(loginPage);
|
||||
}
|
||||
|
@ -159,22 +151,17 @@ public class DefaultFilterChainValidator implements FilterChainProxy.FilterChain
|
|||
// by the dummy request used when creating the filter invocation.
|
||||
this.logger.info("Failed to obtain filter chain information for the login page. Unable to complete check.");
|
||||
}
|
||||
|
||||
if (filters == null || filters.isEmpty()) {
|
||||
this.logger.debug("Filter chain is empty for the login page");
|
||||
return;
|
||||
}
|
||||
|
||||
if (getFilter(DefaultLoginPageGeneratingFilter.class, filters) != null) {
|
||||
this.logger.debug("Default generated login page is in use");
|
||||
return;
|
||||
}
|
||||
|
||||
FilterSecurityInterceptor fsi = getFilter(FilterSecurityInterceptor.class, filters);
|
||||
FilterInvocationSecurityMetadataSource fids = fsi.getSecurityMetadataSource();
|
||||
|
||||
Collection<ConfigAttribute> attributes = fids.getAttributes(loginRequest);
|
||||
|
||||
if (attributes == null) {
|
||||
this.logger.debug("No access attributes defined for login page URL");
|
||||
if (fsi.isRejectPublicInvocations()) {
|
||||
|
@ -183,14 +170,12 @@ public class DefaultFilterChainValidator implements FilterChainProxy.FilterChain
|
|||
}
|
||||
return;
|
||||
}
|
||||
|
||||
AnonymousAuthenticationFilter anonPF = getFilter(AnonymousAuthenticationFilter.class, filters);
|
||||
if (anonPF == null) {
|
||||
this.logger.warn("The login page is being protected by the filter chain, but you don't appear to have"
|
||||
+ " anonymous authentication enabled. This is almost certainly an error.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Simulate an anonymous access with the supplied attributes.
|
||||
AnonymousAuthenticationToken token = new AnonymousAuthenticationToken("key", anonPF.getPrincipal(),
|
||||
anonPF.getAuthorities());
|
||||
|
@ -198,18 +183,16 @@ public class DefaultFilterChainValidator implements FilterChainProxy.FilterChain
|
|||
fsi.getAccessDecisionManager().decide(token, loginRequest, attributes);
|
||||
}
|
||||
catch (AccessDeniedException ex) {
|
||||
this.logger
|
||||
.warn("Anonymous access to the login page doesn't appear to be enabled. This is almost certainly "
|
||||
+ "an error. Please check your configuration allows unauthenticated access to the configured "
|
||||
+ "login page. (Simulated access was rejected: " + ex + ")");
|
||||
this.logger.warn("Anonymous access to the login page doesn't appear to be enabled. "
|
||||
+ "This is almost certainly an error. Please check your configuration allows unauthenticated "
|
||||
+ "access to the configured login page. (Simulated access was rejected: " + ex + ")");
|
||||
}
|
||||
catch (Exception ex) {
|
||||
// May happen legitimately if a filter-chain request matcher requires more
|
||||
// request data than that provided
|
||||
// by the dummy request used when creating the filter invocation. See SEC-1878
|
||||
this.logger.info(
|
||||
"Unable to check access to the login page to determine if anonymous access is allowed. This might be an error, but can happen under normal circumstances.",
|
||||
ex);
|
||||
this.logger.info("Unable to check access to the login page to determine if anonymous access is allowed. "
|
||||
+ "This might be an error, but can happen under normal circumstances.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -43,9 +43,7 @@ public class FilterChainBeanDefinitionParser implements BeanDefinitionParser {
|
|||
String path = elt.getAttribute(HttpSecurityBeanDefinitionParser.ATT_PATH_PATTERN);
|
||||
String requestMatcher = elt.getAttribute(ATT_REQUEST_MATCHER_REF);
|
||||
String filters = elt.getAttribute(HttpSecurityBeanDefinitionParser.ATT_FILTERS);
|
||||
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(DefaultSecurityFilterChain.class);
|
||||
|
||||
if (StringUtils.hasText(path)) {
|
||||
Assert.isTrue(!StringUtils.hasText(requestMatcher), "");
|
||||
builder.addConstructorArgValue(matcherType.createMatcher(pc, path, null));
|
||||
|
@ -54,21 +52,17 @@ public class FilterChainBeanDefinitionParser implements BeanDefinitionParser {
|
|||
Assert.isTrue(StringUtils.hasText(requestMatcher), "");
|
||||
builder.addConstructorArgReference(requestMatcher);
|
||||
}
|
||||
|
||||
if (filters.equals(HttpSecurityBeanDefinitionParser.OPT_FILTERS_NONE)) {
|
||||
builder.addConstructorArgValue(Collections.EMPTY_LIST);
|
||||
}
|
||||
else {
|
||||
String[] filterBeanNames = StringUtils.tokenizeToStringArray(filters, ",");
|
||||
ManagedList<RuntimeBeanReference> filterChain = new ManagedList<>(filterBeanNames.length);
|
||||
|
||||
for (String name : filterBeanNames) {
|
||||
filterChain.add(new RuntimeBeanReference(name));
|
||||
}
|
||||
|
||||
builder.addConstructorArgValue(filterChain);
|
||||
}
|
||||
|
||||
return builder.getBeanDefinition();
|
||||
}
|
||||
|
||||
|
|
|
@ -45,48 +45,36 @@ public class FilterChainMapBeanDefinitionDecorator implements BeanDefinitionDeco
|
|||
@SuppressWarnings("unchecked")
|
||||
public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder holder, ParserContext parserContext) {
|
||||
BeanDefinition filterChainProxy = holder.getBeanDefinition();
|
||||
|
||||
ManagedList<BeanMetadataElement> securityFilterChains = new ManagedList<>();
|
||||
Element elt = (Element) node;
|
||||
|
||||
MatcherType matcherType = MatcherType.fromElement(elt);
|
||||
|
||||
List<Element> filterChainElts = DomUtils.getChildElementsByTagName(elt, Elements.FILTER_CHAIN);
|
||||
|
||||
for (Element chain : filterChainElts) {
|
||||
String path = chain.getAttribute(HttpSecurityBeanDefinitionParser.ATT_PATH_PATTERN);
|
||||
String filters = chain.getAttribute(HttpSecurityBeanDefinitionParser.ATT_FILTERS);
|
||||
|
||||
if (!StringUtils.hasText(path)) {
|
||||
parserContext.getReaderContext().error(
|
||||
"The attribute '" + HttpSecurityBeanDefinitionParser.ATT_PATH_PATTERN + "' must not be empty",
|
||||
elt);
|
||||
}
|
||||
|
||||
if (!StringUtils.hasText(filters)) {
|
||||
parserContext.getReaderContext().error(
|
||||
"The attribute '" + HttpSecurityBeanDefinitionParser.ATT_FILTERS + "'must not be empty", elt);
|
||||
}
|
||||
|
||||
BeanDefinition matcher = matcherType.createMatcher(parserContext, path, null);
|
||||
|
||||
if (filters.equals(HttpSecurityBeanDefinitionParser.OPT_FILTERS_NONE)) {
|
||||
securityFilterChains.add(createSecurityFilterChain(matcher, new ManagedList(0)));
|
||||
}
|
||||
else {
|
||||
String[] filterBeanNames = StringUtils.tokenizeToStringArray(filters, ",");
|
||||
ManagedList filterChain = new ManagedList(filterBeanNames.length);
|
||||
|
||||
for (String name : filterBeanNames) {
|
||||
filterChain.add(new RuntimeBeanReference(name));
|
||||
}
|
||||
|
||||
securityFilterChains.add(createSecurityFilterChain(matcher, filterChain));
|
||||
}
|
||||
}
|
||||
|
||||
filterChainProxy.getConstructorArgumentValues().addGenericArgumentValue(securityFilterChains);
|
||||
|
||||
return holder;
|
||||
}
|
||||
|
||||
|
|
|
@ -64,35 +64,28 @@ public class FilterInvocationSecurityMetadataSourceParser implements BeanDefinit
|
|||
@Override
|
||||
public BeanDefinition parse(Element element, ParserContext parserContext) {
|
||||
List<Element> interceptUrls = DomUtils.getChildElementsByTagName(element, Elements.INTERCEPT_URL);
|
||||
|
||||
// Check for attributes that aren't allowed in this context
|
||||
for (Element elt : interceptUrls) {
|
||||
if (StringUtils.hasLength(elt.getAttribute(HttpSecurityBeanDefinitionParser.ATT_REQUIRES_CHANNEL))) {
|
||||
parserContext.getReaderContext().error("The attribute '"
|
||||
+ HttpSecurityBeanDefinitionParser.ATT_REQUIRES_CHANNEL + "' isn't allowed here.", elt);
|
||||
}
|
||||
|
||||
if (StringUtils.hasLength(elt.getAttribute(HttpSecurityBeanDefinitionParser.ATT_FILTERS))) {
|
||||
parserContext.getReaderContext().error(
|
||||
"The attribute '" + HttpSecurityBeanDefinitionParser.ATT_FILTERS + "' isn't allowed here.",
|
||||
elt);
|
||||
}
|
||||
|
||||
if (StringUtils.hasLength(elt.getAttribute(ATT_SERVLET_PATH))) {
|
||||
parserContext.getReaderContext().error("The attribute '" + ATT_SERVLET_PATH + "' isn't allowed here.",
|
||||
elt);
|
||||
}
|
||||
}
|
||||
|
||||
BeanDefinition mds = createSecurityMetadataSource(interceptUrls, false, element, parserContext);
|
||||
|
||||
String id = element.getAttribute(AbstractBeanDefinitionParser.ID_ATTRIBUTE);
|
||||
|
||||
if (StringUtils.hasText(id)) {
|
||||
parserContext.registerComponent(new BeanComponentDefinition(mds, id));
|
||||
parserContext.getRegistry().registerBeanDefinition(id, mds);
|
||||
}
|
||||
|
||||
return mds;
|
||||
}
|
||||
|
||||
|
@ -100,24 +93,20 @@ public class FilterInvocationSecurityMetadataSourceParser implements BeanDefinit
|
|||
Element httpElt, ParserContext pc) {
|
||||
MatcherType matcherType = MatcherType.fromElement(httpElt);
|
||||
boolean useExpressions = isUseExpressions(httpElt);
|
||||
|
||||
ManagedMap<BeanMetadataElement, BeanDefinition> requestToAttributesMap = parseInterceptUrlsForFilterInvocationRequestMap(
|
||||
matcherType, interceptUrls, useExpressions, addAllAuth, pc);
|
||||
BeanDefinitionBuilder fidsBuilder;
|
||||
|
||||
if (useExpressions) {
|
||||
Element expressionHandlerElt = DomUtils.getChildElementByTagName(httpElt, Elements.EXPRESSION_HANDLER);
|
||||
String expressionHandlerRef = (expressionHandlerElt != null) ? expressionHandlerElt.getAttribute("ref")
|
||||
: null;
|
||||
|
||||
if (StringUtils.hasText(expressionHandlerRef)) {
|
||||
logger.info(
|
||||
"Using bean '" + expressionHandlerRef + "' as web SecurityExpressionHandler implementation");
|
||||
logger.info("Using bean '" + expressionHandlerRef + "' as web "
|
||||
+ "SecurityExpressionHandler implementation");
|
||||
}
|
||||
else {
|
||||
expressionHandlerRef = registerDefaultExpressionHandler(pc);
|
||||
}
|
||||
|
||||
fidsBuilder = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(ExpressionBasedFilterInvocationSecurityMetadataSource.class);
|
||||
fidsBuilder.addConstructorArgValue(requestToAttributesMap);
|
||||
|
@ -127,9 +116,7 @@ public class FilterInvocationSecurityMetadataSourceParser implements BeanDefinit
|
|||
fidsBuilder = BeanDefinitionBuilder.rootBeanDefinition(DefaultFilterInvocationSecurityMetadataSource.class);
|
||||
fidsBuilder.addConstructorArgValue(requestToAttributesMap);
|
||||
}
|
||||
|
||||
fidsBuilder.getRawBeanDefinition().setSource(pc.extractSource(httpElt));
|
||||
|
||||
return (RootBeanDefinition) fidsBuilder.getBeanDefinition();
|
||||
}
|
||||
|
||||
|
@ -138,7 +125,6 @@ public class FilterInvocationSecurityMetadataSourceParser implements BeanDefinit
|
|||
DefaultWebSecurityExpressionHandlerBeanFactory.class);
|
||||
String expressionHandlerRef = pc.getReaderContext().generateBeanName(expressionHandler);
|
||||
pc.registerBeanComponent(new BeanComponentDefinition(expressionHandler, expressionHandlerRef));
|
||||
|
||||
return expressionHandlerRef;
|
||||
}
|
||||
|
||||
|
@ -150,28 +136,22 @@ public class FilterInvocationSecurityMetadataSourceParser implements BeanDefinit
|
|||
private static ManagedMap<BeanMetadataElement, BeanDefinition> parseInterceptUrlsForFilterInvocationRequestMap(
|
||||
MatcherType matcherType, List<Element> urlElts, boolean useExpressions, boolean addAuthenticatedAll,
|
||||
ParserContext parserContext) {
|
||||
|
||||
ManagedMap<BeanMetadataElement, BeanDefinition> filterInvocationDefinitionMap = new ManagedMap<>();
|
||||
|
||||
for (Element urlElt : urlElts) {
|
||||
String access = urlElt.getAttribute(ATT_ACCESS);
|
||||
if (!StringUtils.hasText(access)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String path = urlElt.getAttribute(ATT_PATTERN);
|
||||
String matcherRef = urlElt.getAttribute(HttpSecurityBeanDefinitionParser.ATT_REQUEST_MATCHER_REF);
|
||||
boolean hasMatcherRef = StringUtils.hasText(matcherRef);
|
||||
|
||||
if (!hasMatcherRef && !StringUtils.hasText(path)) {
|
||||
parserContext.getReaderContext().error("path attribute cannot be empty or null", urlElt);
|
||||
}
|
||||
|
||||
String method = urlElt.getAttribute(ATT_HTTP_METHOD);
|
||||
if (!StringUtils.hasText(method)) {
|
||||
method = null;
|
||||
}
|
||||
|
||||
String servletPath = urlElt.getAttribute(ATT_SERVLET_PATH);
|
||||
if (!StringUtils.hasText(servletPath)) {
|
||||
servletPath = null;
|
||||
|
@ -181,11 +161,9 @@ public class FilterInvocationSecurityMetadataSourceParser implements BeanDefinit
|
|||
ATT_SERVLET_PATH + " is not applicable for request-matcher: '" + matcherType.name() + "'",
|
||||
urlElt);
|
||||
}
|
||||
|
||||
BeanMetadataElement matcher = hasMatcherRef ? new RuntimeBeanReference(matcherRef)
|
||||
: matcherType.createMatcher(parserContext, path, method, servletPath);
|
||||
BeanDefinitionBuilder attributeBuilder = BeanDefinitionBuilder.rootBeanDefinition(SecurityConfig.class);
|
||||
|
||||
if (useExpressions) {
|
||||
logger.info("Creating access control expression attribute '" + access + "' for " + path);
|
||||
// The single expression will be parsed later by the
|
||||
|
@ -198,23 +176,18 @@ public class FilterInvocationSecurityMetadataSourceParser implements BeanDefinit
|
|||
attributeBuilder.addConstructorArgValue(access);
|
||||
attributeBuilder.setFactoryMethod("createListFromCommaDelimitedString");
|
||||
}
|
||||
|
||||
if (filterInvocationDefinitionMap.containsKey(matcher)) {
|
||||
logger.warn("Duplicate URL defined: " + path + ". The original attribute values will be overwritten");
|
||||
}
|
||||
|
||||
filterInvocationDefinitionMap.put(matcher, attributeBuilder.getBeanDefinition());
|
||||
}
|
||||
|
||||
if (addAuthenticatedAll && filterInvocationDefinitionMap.isEmpty()) {
|
||||
|
||||
BeanDefinition matcher = matcherType.createMatcher(parserContext, "/**", null);
|
||||
BeanDefinitionBuilder attributeBuilder = BeanDefinitionBuilder.rootBeanDefinition(SecurityConfig.class);
|
||||
attributeBuilder.addConstructorArgValue(new String[] { "authenticated" });
|
||||
attributeBuilder.setFactoryMethod("createList");
|
||||
filterInvocationDefinitionMap.put(matcher, attributeBuilder.getBeanDefinition());
|
||||
}
|
||||
|
||||
return filterInvocationDefinitionMap;
|
||||
}
|
||||
|
||||
|
|
|
@ -123,9 +123,7 @@ public class FormLoginBeanDefinitionParser {
|
|||
String authDetailsSourceRef = null;
|
||||
String authenticationFailureForwardUrl = null;
|
||||
String authenticationSuccessForwardUrl = null;
|
||||
|
||||
Object source = null;
|
||||
|
||||
if (elt != null) {
|
||||
source = pc.extractSource(elt);
|
||||
loginUrl = elt.getAttribute(ATT_LOGIN_URL);
|
||||
|
@ -143,7 +141,6 @@ public class FormLoginBeanDefinitionParser {
|
|||
WebConfigUtils.validateHttpRedirect(authenticationFailureForwardUrl, pc, source);
|
||||
authenticationSuccessForwardUrl = elt.getAttribute(ATT_FORM_LOGIN_AUTHENTICATION_SUCCESS_FORWARD_URL);
|
||||
WebConfigUtils.validateHttpRedirect(authenticationSuccessForwardUrl, pc, source);
|
||||
|
||||
if (!StringUtils.hasText(this.loginPage)) {
|
||||
this.loginPage = null;
|
||||
}
|
||||
|
@ -151,20 +148,16 @@ public class FormLoginBeanDefinitionParser {
|
|||
usernameParameter = elt.getAttribute(ATT_USERNAME_PARAMETER);
|
||||
passwordParameter = elt.getAttribute(ATT_PASSWORD_PARAMETER);
|
||||
}
|
||||
|
||||
this.filterBean = createFilterBean(loginUrl, defaultTargetUrl, alwaysUseDefault, this.loginPage,
|
||||
authenticationFailureUrl, successHandlerRef, failureHandlerRef, authDetailsSourceRef,
|
||||
authenticationFailureForwardUrl, authenticationSuccessForwardUrl);
|
||||
|
||||
if (StringUtils.hasText(usernameParameter)) {
|
||||
this.filterBean.getPropertyValues().addPropertyValue("usernameParameter", usernameParameter);
|
||||
}
|
||||
if (StringUtils.hasText(passwordParameter)) {
|
||||
this.filterBean.getPropertyValues().addPropertyValue("passwordParameter", passwordParameter);
|
||||
}
|
||||
|
||||
this.filterBean.setSource(source);
|
||||
|
||||
BeanDefinitionBuilder entryPointBuilder = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(LoginUrlAuthenticationEntryPoint.class);
|
||||
entryPointBuilder.getRawBeanDefinition().setSource(source);
|
||||
|
@ -172,7 +165,6 @@ public class FormLoginBeanDefinitionParser {
|
|||
entryPointBuilder.addPropertyValue("portMapper", this.portMapper);
|
||||
entryPointBuilder.addPropertyValue("portResolver", this.portResolver);
|
||||
this.entryPointBean = (RootBeanDefinition) entryPointBuilder.getBeanDefinition();
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -180,24 +172,18 @@ public class FormLoginBeanDefinitionParser {
|
|||
String loginPage, String authenticationFailureUrl, String successHandlerRef, String failureHandlerRef,
|
||||
String authDetailsSourceRef, String authenticationFailureForwardUrl,
|
||||
String authenticationSuccessForwardUrl) {
|
||||
|
||||
BeanDefinitionBuilder filterBuilder = BeanDefinitionBuilder.rootBeanDefinition(this.filterClassName);
|
||||
|
||||
if (!StringUtils.hasText(loginUrl)) {
|
||||
loginUrl = this.defaultLoginProcessingUrl;
|
||||
}
|
||||
|
||||
this.loginProcessingUrl = loginUrl;
|
||||
|
||||
BeanDefinitionBuilder matcherBuilder = BeanDefinitionBuilder
|
||||
.rootBeanDefinition("org.springframework.security.web.util.matcher.AntPathRequestMatcher");
|
||||
matcherBuilder.addConstructorArgValue(loginUrl);
|
||||
if (this.loginMethod != null) {
|
||||
matcherBuilder.addConstructorArgValue("POST");
|
||||
}
|
||||
|
||||
filterBuilder.addPropertyValue("requiresAuthenticationRequestMatcher", matcherBuilder.getBeanDefinition());
|
||||
|
||||
if (StringUtils.hasText(successHandlerRef)) {
|
||||
filterBuilder.addPropertyReference("authenticationSuccessHandler", successHandlerRef);
|
||||
}
|
||||
|
@ -218,15 +204,12 @@ public class FormLoginBeanDefinitionParser {
|
|||
StringUtils.hasText(defaultTargetUrl) ? defaultTargetUrl : DEF_FORM_LOGIN_TARGET_URL);
|
||||
filterBuilder.addPropertyValue("authenticationSuccessHandler", successHandler.getBeanDefinition());
|
||||
}
|
||||
|
||||
if (StringUtils.hasText(authDetailsSourceRef)) {
|
||||
filterBuilder.addPropertyReference("authenticationDetailsSource", authDetailsSourceRef);
|
||||
}
|
||||
|
||||
if (this.sessionStrategy != null) {
|
||||
filterBuilder.addPropertyValue("sessionAuthenticationStrategy", this.sessionStrategy);
|
||||
}
|
||||
|
||||
if (StringUtils.hasText(failureHandlerRef)) {
|
||||
filterBuilder.addPropertyReference("authenticationFailureHandler", failureHandlerRef);
|
||||
}
|
||||
|
@ -252,7 +235,6 @@ public class FormLoginBeanDefinitionParser {
|
|||
failureHandler.addPropertyValue("allowSessionCreation", this.allowSessionCreation);
|
||||
filterBuilder.addPropertyValue("authenticationFailureHandler", failureHandler.getBeanDefinition());
|
||||
}
|
||||
|
||||
return (RootBeanDefinition) filterBuilder.getBeanDefinition();
|
||||
}
|
||||
|
||||
|
|
|
@ -37,7 +37,6 @@ final class GrantedAuthorityDefaultsParserUtils {
|
|||
RootBeanDefinition beanFactoryDefinition = new RootBeanDefinition(beanFactoryClass);
|
||||
String beanFactoryRef = pc.getReaderContext().generateBeanName(beanFactoryDefinition);
|
||||
pc.getRegistry().registerBeanDefinition(beanFactoryRef, beanFactoryDefinition);
|
||||
|
||||
RootBeanDefinition bean = new RootBeanDefinition();
|
||||
bean.setFactoryBeanName(beanFactoryRef);
|
||||
bean.setFactoryMethodName("getBean");
|
||||
|
|
|
@ -41,9 +41,11 @@ class HandlerMappingIntrospectorFactoryBean
|
|||
@Override
|
||||
public HandlerMappingIntrospector getObject() {
|
||||
if (!this.context.containsBean(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME)) {
|
||||
throw new NoSuchBeanDefinitionException(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME, "A Bean named "
|
||||
+ HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME + " of type " + HandlerMappingIntrospector.class.getName()
|
||||
+ " is required to use MvcRequestMatcher. Please ensure Spring Security & Spring MVC are configured in a shared ApplicationContext.");
|
||||
throw new NoSuchBeanDefinitionException(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME,
|
||||
"A Bean named " + HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME + " of type "
|
||||
+ HandlerMappingIntrospector.class.getName()
|
||||
+ " is required to use MvcRequestMatcher. Please ensure Spring Security & Spring "
|
||||
+ "MVC are configured in a shared ApplicationContext.");
|
||||
}
|
||||
return this.context.getBean(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME, HandlerMappingIntrospector.class);
|
||||
}
|
||||
|
|
|
@ -125,32 +125,22 @@ public class HeadersBeanDefinitionParser implements BeanDefinitionParser {
|
|||
|
||||
@Override
|
||||
public BeanDefinition parse(Element element, ParserContext parserContext) {
|
||||
|
||||
this.headerWriters = new ManagedList<>();
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(HeaderWriterFilter.class);
|
||||
|
||||
boolean disabled = element != null && "true".equals(resolveAttribute(parserContext, element, "disabled"));
|
||||
boolean defaultsDisabled = element != null
|
||||
&& "true".equals(resolveAttribute(parserContext, element, "defaults-disabled"));
|
||||
|
||||
boolean addIfNotPresent = element == null || !disabled && !defaultsDisabled;
|
||||
|
||||
parseCacheControlElement(addIfNotPresent, element);
|
||||
parseHstsElement(addIfNotPresent, element, parserContext);
|
||||
parseXssElement(addIfNotPresent, element, parserContext);
|
||||
parseFrameOptionsElement(addIfNotPresent, element, parserContext);
|
||||
parseContentTypeOptionsElement(addIfNotPresent, element);
|
||||
|
||||
parseHpkpElement(element == null || !disabled, element, parserContext);
|
||||
|
||||
parseContentSecurityPolicyElement(disabled, element, parserContext);
|
||||
|
||||
parseReferrerPolicyElement(element, parserContext);
|
||||
|
||||
parseFeaturePolicyElement(element, parserContext);
|
||||
|
||||
parseHeaderElements(element);
|
||||
|
||||
boolean noWriters = this.headerWriters.isEmpty();
|
||||
if (disabled && !noWriters) {
|
||||
parserContext.getReaderContext().error("Cannot specify <headers disabled=\"true\"> with child elements.",
|
||||
|
@ -159,13 +149,11 @@ public class HeadersBeanDefinitionParser implements BeanDefinitionParser {
|
|||
else if (noWriters) {
|
||||
return null;
|
||||
}
|
||||
|
||||
builder.addConstructorArgValue(this.headerWriters);
|
||||
return builder.getBeanDefinition();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Resolve the placeholder for a given attribute on a element.
|
||||
* @param pc
|
||||
* @param element
|
||||
|
@ -233,7 +221,6 @@ public class HeadersBeanDefinitionParser implements BeanDefinitionParser {
|
|||
}
|
||||
headersWriter.addPropertyValue("preload", preload);
|
||||
}
|
||||
|
||||
if (disabled) {
|
||||
return;
|
||||
}
|
||||
|
@ -253,59 +240,45 @@ public class HeadersBeanDefinitionParser implements BeanDefinitionParser {
|
|||
private void addHpkp(boolean addIfNotPresent, Element hpkpElement, ParserContext context) {
|
||||
if (hpkpElement != null) {
|
||||
boolean disabled = "true".equals(getAttribute(hpkpElement, ATT_DISABLED, "false"));
|
||||
|
||||
if (disabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
BeanDefinitionBuilder headersWriter = BeanDefinitionBuilder.genericBeanDefinition(HpkpHeaderWriter.class);
|
||||
|
||||
Element pinsElement = DomUtils.getChildElementByTagName(hpkpElement, PINS_ELEMENT);
|
||||
if (pinsElement != null) {
|
||||
List<Element> pinElements = DomUtils.getChildElements(pinsElement);
|
||||
|
||||
Map<String, String> pins = new LinkedHashMap<>();
|
||||
|
||||
for (Element pinElement : pinElements) {
|
||||
String hash = pinElement.getAttribute(ATT_ALGORITHM);
|
||||
if (!StringUtils.hasText(hash)) {
|
||||
hash = "sha256";
|
||||
}
|
||||
|
||||
Node pinValueNode = pinElement.getFirstChild();
|
||||
if (pinValueNode == null) {
|
||||
context.getReaderContext().warning("Missing value for pin entry.", hpkpElement);
|
||||
continue;
|
||||
}
|
||||
|
||||
String fingerprint = pinElement.getFirstChild().getTextContent();
|
||||
|
||||
pins.put(fingerprint, hash);
|
||||
}
|
||||
|
||||
headersWriter.addPropertyValue("pins", pins);
|
||||
}
|
||||
|
||||
String includeSubDomains = hpkpElement.getAttribute(ATT_INCLUDE_SUBDOMAINS);
|
||||
if (StringUtils.hasText(includeSubDomains)) {
|
||||
headersWriter.addPropertyValue("includeSubDomains", includeSubDomains);
|
||||
}
|
||||
|
||||
String maxAgeSeconds = hpkpElement.getAttribute(ATT_MAX_AGE_SECONDS);
|
||||
if (StringUtils.hasText(maxAgeSeconds)) {
|
||||
headersWriter.addPropertyValue("maxAgeInSeconds", maxAgeSeconds);
|
||||
}
|
||||
|
||||
String reportOnly = hpkpElement.getAttribute(ATT_REPORT_ONLY);
|
||||
if (StringUtils.hasText(reportOnly)) {
|
||||
headersWriter.addPropertyValue("reportOnly", reportOnly);
|
||||
}
|
||||
|
||||
String reportUri = hpkpElement.getAttribute(ATT_REPORT_URI);
|
||||
if (StringUtils.hasText(reportUri)) {
|
||||
headersWriter.addPropertyValue("reportUri", reportUri);
|
||||
}
|
||||
|
||||
if (addIfNotPresent) {
|
||||
this.headerWriters.add(headersWriter.getBeanDefinition());
|
||||
}
|
||||
|
@ -323,7 +296,6 @@ public class HeadersBeanDefinitionParser implements BeanDefinitionParser {
|
|||
private void addContentSecurityPolicy(Element contentSecurityPolicyElement, ParserContext context) {
|
||||
BeanDefinitionBuilder headersWriter = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(ContentSecurityPolicyHeaderWriter.class);
|
||||
|
||||
String policyDirectives = contentSecurityPolicyElement.getAttribute(ATT_POLICY_DIRECTIVES);
|
||||
if (!StringUtils.hasText(policyDirectives)) {
|
||||
context.getReaderContext().error(ATT_POLICY_DIRECTIVES + " requires a 'value' to be set.",
|
||||
|
@ -332,12 +304,10 @@ public class HeadersBeanDefinitionParser implements BeanDefinitionParser {
|
|||
else {
|
||||
headersWriter.addConstructorArgValue(policyDirectives);
|
||||
}
|
||||
|
||||
String reportOnly = contentSecurityPolicyElement.getAttribute(ATT_REPORT_ONLY);
|
||||
if (StringUtils.hasText(reportOnly)) {
|
||||
headersWriter.addPropertyValue("reportOnly", reportOnly);
|
||||
}
|
||||
|
||||
this.headerWriters.add(headersWriter.getBeanDefinition());
|
||||
}
|
||||
|
||||
|
@ -352,7 +322,6 @@ public class HeadersBeanDefinitionParser implements BeanDefinitionParser {
|
|||
private void addReferrerPolicy(Element referrerPolicyElement, ParserContext context) {
|
||||
BeanDefinitionBuilder headersWriter = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(ReferrerPolicyHeaderWriter.class);
|
||||
|
||||
String policy = referrerPolicyElement.getAttribute(ATT_POLICY);
|
||||
if (StringUtils.hasLength(policy)) {
|
||||
headersWriter.addConstructorArgValue(ReferrerPolicy.get(policy));
|
||||
|
@ -371,7 +340,6 @@ public class HeadersBeanDefinitionParser implements BeanDefinitionParser {
|
|||
private void addFeaturePolicy(Element featurePolicyElement, ParserContext context) {
|
||||
BeanDefinitionBuilder headersWriter = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(FeaturePolicyHeaderWriter.class);
|
||||
|
||||
String policyDirectives = featurePolicyElement.getAttribute(ATT_POLICY_DIRECTIVES);
|
||||
if (!StringUtils.hasText(policyDirectives)) {
|
||||
context.getReaderContext().error(ATT_POLICY_DIRECTIVES + " requires a 'value' to be set.",
|
||||
|
@ -380,7 +348,6 @@ public class HeadersBeanDefinitionParser implements BeanDefinitionParser {
|
|||
else {
|
||||
headersWriter.addConstructorArgValue(policyDirectives);
|
||||
}
|
||||
|
||||
this.headerWriters.add(headersWriter.getBeanDefinition());
|
||||
}
|
||||
|
||||
|
@ -508,7 +475,6 @@ public class HeadersBeanDefinitionParser implements BeanDefinitionParser {
|
|||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(XXssProtectionHeaderWriter.class);
|
||||
if (xssElt != null) {
|
||||
boolean disabled = "true".equals(getAttribute(xssElt, ATT_DISABLED, "false"));
|
||||
|
||||
String enabled = xssElt.getAttribute(ATT_ENABLED);
|
||||
if (StringUtils.hasText(enabled)) {
|
||||
if (disabled) {
|
||||
|
@ -516,7 +482,6 @@ public class HeadersBeanDefinitionParser implements BeanDefinitionParser {
|
|||
}
|
||||
builder.addPropertyValue("enabled", enabled);
|
||||
}
|
||||
|
||||
String block = xssElt.getAttribute(ATT_BLOCK);
|
||||
if (StringUtils.hasText(block)) {
|
||||
if (disabled) {
|
||||
|
@ -524,7 +489,6 @@ public class HeadersBeanDefinitionParser implements BeanDefinitionParser {
|
|||
}
|
||||
builder.addPropertyValue("block", block);
|
||||
}
|
||||
|
||||
if (disabled) {
|
||||
return;
|
||||
}
|
||||
|
@ -542,9 +506,7 @@ public class HeadersBeanDefinitionParser implements BeanDefinitionParser {
|
|||
if (StringUtils.hasText(value)) {
|
||||
return value;
|
||||
}
|
||||
else {
|
||||
return defaultValue;
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -71,6 +71,7 @@ import org.springframework.security.web.session.SessionManagementFilter;
|
|||
import org.springframework.security.web.session.SimpleRedirectInvalidSessionStrategy;
|
||||
import org.springframework.security.web.session.SimpleRedirectSessionInformationExpiredStrategy;
|
||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.util.xml.DomUtils;
|
||||
|
@ -113,6 +114,22 @@ class HttpConfigurationBuilder {
|
|||
|
||||
private static final String ATT_REF = "ref";
|
||||
|
||||
private static final String ATT_EXPIRY_URL = "expired-url";
|
||||
|
||||
private static final String ATT_EXPIRED_SESSION_STRATEGY_REF = "expired-session-strategy-ref";
|
||||
|
||||
private static final String ATT_SESSION_REGISTRY_ALIAS = "session-registry-alias";
|
||||
|
||||
private static final String ATT_SESSION_REGISTRY_REF = "session-registry-ref";
|
||||
|
||||
private static final String ATT_SERVLET_API_PROVISION = "servlet-api-provision";
|
||||
|
||||
private static final String DEF_SERVLET_API_PROVISION = "true";
|
||||
|
||||
private static final String ATT_JAAS_API_PROVISION = "jaas-api-provision";
|
||||
|
||||
private static final String DEF_JAAS_API_PROVISION = "false";
|
||||
|
||||
private final Element httpElt;
|
||||
|
||||
private final ParserContext pc;
|
||||
|
@ -178,25 +195,10 @@ class HttpConfigurationBuilder {
|
|||
this.portResolver = portResolver;
|
||||
this.matcherType = MatcherType.fromElement(element);
|
||||
this.interceptUrls = DomUtils.getChildElementsByTagName(element, Elements.INTERCEPT_URL);
|
||||
|
||||
for (Element urlElt : this.interceptUrls) {
|
||||
if (StringUtils.hasText(urlElt.getAttribute(HttpSecurityBeanDefinitionParser.ATT_FILTERS))) {
|
||||
pc.getReaderContext()
|
||||
.error("The use of \"filters='none'\" is no longer supported. Please define a"
|
||||
+ " separate <http> element for the pattern you want to exclude and use the attribute"
|
||||
+ " \"security='none'\".", pc.extractSource(urlElt));
|
||||
}
|
||||
}
|
||||
|
||||
validateInterceptUrls(pc);
|
||||
String createSession = element.getAttribute(ATT_CREATE_SESSION);
|
||||
|
||||
if (StringUtils.hasText(createSession)) {
|
||||
this.sessionPolicy = createPolicy(createSession);
|
||||
}
|
||||
else {
|
||||
this.sessionPolicy = SessionCreationPolicy.IF_REQUIRED;
|
||||
}
|
||||
|
||||
this.sessionPolicy = !StringUtils.hasText(createSession) ? SessionCreationPolicy.IF_REQUIRED
|
||||
: createPolicy(createSession);
|
||||
createCsrfFilter();
|
||||
createSecurityContextPersistenceFilter();
|
||||
createSessionManagementFilters();
|
||||
|
@ -210,20 +212,30 @@ class HttpConfigurationBuilder {
|
|||
createCorsFilter();
|
||||
}
|
||||
|
||||
private void validateInterceptUrls(ParserContext pc) {
|
||||
for (Element element : this.interceptUrls) {
|
||||
if (StringUtils.hasText(element.getAttribute(HttpSecurityBeanDefinitionParser.ATT_FILTERS))) {
|
||||
String message = "The use of \"filters='none'\" is no longer supported. Please define a"
|
||||
+ " separate <http> element for the pattern you want to exclude and use the attribute"
|
||||
+ " \"security='none'\".";
|
||||
pc.getReaderContext().error(message, pc.extractSource(element));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private SessionCreationPolicy createPolicy(String createSession) {
|
||||
if ("ifRequired".equals(createSession)) {
|
||||
return SessionCreationPolicy.IF_REQUIRED;
|
||||
}
|
||||
else if ("always".equals(createSession)) {
|
||||
if ("always".equals(createSession)) {
|
||||
return SessionCreationPolicy.ALWAYS;
|
||||
}
|
||||
else if ("never".equals(createSession)) {
|
||||
if ("never".equals(createSession)) {
|
||||
return SessionCreationPolicy.NEVER;
|
||||
}
|
||||
else if ("stateless".equals(createSession)) {
|
||||
if ("stateless".equals(createSession)) {
|
||||
return SessionCreationPolicy.STATELESS;
|
||||
}
|
||||
|
||||
throw new IllegalStateException(
|
||||
"Cannot convert " + createSession + " to " + SessionCreationPolicy.class.getName());
|
||||
}
|
||||
|
@ -265,13 +277,11 @@ class HttpConfigurationBuilder {
|
|||
|
||||
private void createSecurityContextPersistenceFilter() {
|
||||
BeanDefinitionBuilder scpf = BeanDefinitionBuilder.rootBeanDefinition(SecurityContextPersistenceFilter.class);
|
||||
|
||||
String repoRef = this.httpElt.getAttribute(ATT_SECURITY_CONTEXT_REPOSITORY);
|
||||
String disableUrlRewriting = this.httpElt.getAttribute(ATT_DISABLE_URL_REWRITING);
|
||||
if (!StringUtils.hasText(disableUrlRewriting)) {
|
||||
disableUrlRewriting = "true";
|
||||
}
|
||||
|
||||
if (StringUtils.hasText(repoRef)) {
|
||||
if (this.sessionPolicy == SessionCreationPolicy.ALWAYS) {
|
||||
scpf.addPropertyValue("forceEagerSessionCreation", Boolean.TRUE);
|
||||
|
@ -297,12 +307,10 @@ class HttpConfigurationBuilder {
|
|||
contextRepo.addPropertyValue("allowSessionCreation", Boolean.TRUE);
|
||||
scpf.addPropertyValue("forceEagerSessionCreation", Boolean.FALSE);
|
||||
}
|
||||
|
||||
if ("true".equals(disableUrlRewriting)) {
|
||||
contextRepo.addPropertyValue("disableUrlRewriting", Boolean.TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
BeanDefinition repoBean = contextRepo.getBeanDefinition();
|
||||
repoRef = this.pc.getReaderContext().generateBeanName(repoBean);
|
||||
this.pc.registerBeanComponent(new BeanComponentDefinition(repoBean, repoRef));
|
||||
|
@ -317,13 +325,11 @@ class HttpConfigurationBuilder {
|
|||
private void createSessionManagementFilters() {
|
||||
Element sessionMgmtElt = DomUtils.getChildElementByTagName(this.httpElt, Elements.SESSION_MANAGEMENT);
|
||||
Element sessionCtrlElt = null;
|
||||
|
||||
String sessionFixationAttribute = null;
|
||||
String invalidSessionUrl = null;
|
||||
String invalidSessionStrategyRef = null;
|
||||
String sessionAuthStratRef = null;
|
||||
String errorUrl = null;
|
||||
|
||||
boolean sessionControlEnabled = false;
|
||||
if (sessionMgmtElt != null) {
|
||||
if (this.sessionPolicy == SessionCreationPolicy.STATELESS) {
|
||||
|
@ -335,18 +341,15 @@ class HttpConfigurationBuilder {
|
|||
sessionFixationAttribute = sessionMgmtElt.getAttribute(ATT_SESSION_FIXATION_PROTECTION);
|
||||
invalidSessionUrl = sessionMgmtElt.getAttribute(ATT_INVALID_SESSION_URL);
|
||||
invalidSessionStrategyRef = sessionMgmtElt.getAttribute(ATT_INVALID_SESSION_STRATEGY_REF);
|
||||
|
||||
sessionAuthStratRef = sessionMgmtElt.getAttribute(ATT_SESSION_AUTH_STRATEGY_REF);
|
||||
errorUrl = sessionMgmtElt.getAttribute(ATT_SESSION_AUTH_ERROR_URL);
|
||||
sessionCtrlElt = DomUtils.getChildElementByTagName(sessionMgmtElt, Elements.CONCURRENT_SESSIONS);
|
||||
sessionControlEnabled = sessionCtrlElt != null;
|
||||
|
||||
if (StringUtils.hasText(invalidSessionUrl) && StringUtils.hasText(invalidSessionStrategyRef)) {
|
||||
this.pc.getReaderContext()
|
||||
.error(ATT_INVALID_SESSION_URL + " attribute cannot be used in combination with" + " the "
|
||||
+ ATT_INVALID_SESSION_STRATEGY_REF + " attribute.", sessionMgmtElt);
|
||||
}
|
||||
|
||||
if (sessionControlEnabled) {
|
||||
if (StringUtils.hasText(sessionAuthStratRef)) {
|
||||
this.pc.getReaderContext()
|
||||
|
@ -370,33 +373,25 @@ class HttpConfigurationBuilder {
|
|||
// SEC-1424: do nothing
|
||||
return;
|
||||
}
|
||||
|
||||
boolean sessionFixationProtectionRequired = !sessionFixationAttribute
|
||||
.equals(OPT_SESSION_FIXATION_NO_PROTECTION);
|
||||
|
||||
ManagedList<BeanMetadataElement> delegateSessionStrategies = new ManagedList<>();
|
||||
BeanDefinitionBuilder concurrentSessionStrategy;
|
||||
BeanDefinitionBuilder sessionFixationStrategy = null;
|
||||
BeanDefinitionBuilder registerSessionStrategy;
|
||||
|
||||
if (this.csrfAuthStrategy != null) {
|
||||
delegateSessionStrategies.add(this.csrfAuthStrategy);
|
||||
}
|
||||
|
||||
if (sessionControlEnabled) {
|
||||
assert this.sessionRegistryRef != null;
|
||||
Assert.state(this.sessionRegistryRef != null, "No sessionRegistryRef found");
|
||||
concurrentSessionStrategy = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(ConcurrentSessionControlAuthenticationStrategy.class);
|
||||
concurrentSessionStrategy.addConstructorArgValue(this.sessionRegistryRef);
|
||||
|
||||
String maxSessions = sessionCtrlElt.getAttribute("max-sessions");
|
||||
|
||||
if (StringUtils.hasText(maxSessions)) {
|
||||
concurrentSessionStrategy.addPropertyValue("maximumSessions", maxSessions);
|
||||
}
|
||||
|
||||
String exceptionIfMaximumExceeded = sessionCtrlElt.getAttribute("error-if-maximum-exceeded");
|
||||
|
||||
if (StringUtils.hasText(exceptionIfMaximumExceeded)) {
|
||||
concurrentSessionStrategy.addPropertyValue("exceptionIfMaximumExceeded", exceptionIfMaximumExceeded);
|
||||
}
|
||||
|
@ -414,23 +409,19 @@ class HttpConfigurationBuilder {
|
|||
}
|
||||
delegateSessionStrategies.add(sessionFixationStrategy.getBeanDefinition());
|
||||
}
|
||||
|
||||
if (StringUtils.hasText(sessionAuthStratRef)) {
|
||||
delegateSessionStrategies.add(new RuntimeBeanReference(sessionAuthStratRef));
|
||||
}
|
||||
|
||||
if (sessionControlEnabled) {
|
||||
registerSessionStrategy = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(RegisterSessionAuthenticationStrategy.class);
|
||||
registerSessionStrategy.addConstructorArgValue(this.sessionRegistryRef);
|
||||
delegateSessionStrategies.add(registerSessionStrategy.getBeanDefinition());
|
||||
}
|
||||
|
||||
if (delegateSessionStrategies.isEmpty()) {
|
||||
this.sfpf = null;
|
||||
return;
|
||||
}
|
||||
|
||||
BeanDefinitionBuilder sessionMgmtFilter = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(SessionManagementFilter.class);
|
||||
RootBeanDefinition failureHandler = new RootBeanDefinition(SimpleUrlAuthenticationFailureHandler.class);
|
||||
|
@ -439,15 +430,12 @@ class HttpConfigurationBuilder {
|
|||
}
|
||||
sessionMgmtFilter.addPropertyValue("authenticationFailureHandler", failureHandler);
|
||||
sessionMgmtFilter.addConstructorArgValue(this.contextRepoRef);
|
||||
|
||||
if (!StringUtils.hasText(sessionAuthStratRef) && sessionFixationStrategy != null && !useChangeSessionId) {
|
||||
|
||||
if (sessionFixationProtectionRequired) {
|
||||
sessionFixationStrategy.addPropertyValue("migrateSessionAttributes",
|
||||
sessionFixationAttribute.equals(OPT_SESSION_FIXATION_MIGRATE_SESSION));
|
||||
}
|
||||
}
|
||||
|
||||
if (!delegateSessionStrategies.isEmpty()) {
|
||||
BeanDefinitionBuilder sessionStrategy = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(CompositeSessionAuthenticationStrategy.class);
|
||||
|
@ -455,9 +443,7 @@ class HttpConfigurationBuilder {
|
|||
sessionStrategy.addConstructorArgValue(delegateSessionStrategies);
|
||||
sessionAuthStratRef = this.pc.getReaderContext().generateBeanName(strategyBean);
|
||||
this.pc.registerBeanComponent(new BeanComponentDefinition(strategyBean, sessionAuthStratRef));
|
||||
|
||||
}
|
||||
|
||||
if (StringUtils.hasText(invalidSessionUrl)) {
|
||||
BeanDefinitionBuilder invalidSessionBldr = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(SimpleRedirectInvalidSessionStrategy.class);
|
||||
|
@ -468,55 +454,39 @@ class HttpConfigurationBuilder {
|
|||
else if (StringUtils.hasText(invalidSessionStrategyRef)) {
|
||||
sessionMgmtFilter.addPropertyReference("invalidSessionStrategy", invalidSessionStrategyRef);
|
||||
}
|
||||
|
||||
sessionMgmtFilter.addConstructorArgReference(sessionAuthStratRef);
|
||||
|
||||
this.sfpf = (RootBeanDefinition) sessionMgmtFilter.getBeanDefinition();
|
||||
this.sessionStrategyRef = new RuntimeBeanReference(sessionAuthStratRef);
|
||||
}
|
||||
|
||||
private void createConcurrencyControlFilterAndSessionRegistry(Element element) {
|
||||
final String ATT_EXPIRY_URL = "expired-url";
|
||||
final String ATT_EXPIRED_SESSION_STRATEGY_REF = "expired-session-strategy-ref";
|
||||
final String ATT_SESSION_REGISTRY_ALIAS = "session-registry-alias";
|
||||
final String ATT_SESSION_REGISTRY_REF = "session-registry-ref";
|
||||
|
||||
CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(),
|
||||
this.pc.extractSource(element));
|
||||
this.pc.pushContainingComponent(compositeDef);
|
||||
|
||||
BeanDefinitionRegistry beanRegistry = this.pc.getRegistry();
|
||||
|
||||
String sessionRegistryId = element.getAttribute(ATT_SESSION_REGISTRY_REF);
|
||||
|
||||
if (!StringUtils.hasText(sessionRegistryId)) {
|
||||
// Register an internal SessionRegistryImpl if no external reference supplied.
|
||||
RootBeanDefinition sessionRegistry = new RootBeanDefinition(SessionRegistryImpl.class);
|
||||
sessionRegistryId = this.pc.getReaderContext().registerWithGeneratedName(sessionRegistry);
|
||||
this.pc.registerComponent(new BeanComponentDefinition(sessionRegistry, sessionRegistryId));
|
||||
}
|
||||
|
||||
String registryAlias = element.getAttribute(ATT_SESSION_REGISTRY_ALIAS);
|
||||
if (StringUtils.hasText(registryAlias)) {
|
||||
beanRegistry.registerAlias(sessionRegistryId, registryAlias);
|
||||
}
|
||||
|
||||
BeanDefinitionBuilder filterBuilder = BeanDefinitionBuilder.rootBeanDefinition(ConcurrentSessionFilter.class);
|
||||
filterBuilder.addConstructorArgReference(sessionRegistryId);
|
||||
|
||||
Object source = this.pc.extractSource(element);
|
||||
filterBuilder.getRawBeanDefinition().setSource(source);
|
||||
filterBuilder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
|
||||
String expiryUrl = element.getAttribute(ATT_EXPIRY_URL);
|
||||
String expiredSessionStrategyRef = element.getAttribute(ATT_EXPIRED_SESSION_STRATEGY_REF);
|
||||
|
||||
if (StringUtils.hasText(expiryUrl) && StringUtils.hasText(expiredSessionStrategyRef)) {
|
||||
this.pc.getReaderContext().error(
|
||||
"Cannot use 'expired-url' attribute and 'expired-session-strategy-ref'" + " attribute together.",
|
||||
source);
|
||||
}
|
||||
|
||||
if (StringUtils.hasText(expiryUrl)) {
|
||||
BeanDefinitionBuilder expiredSessionBldr = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(SimpleRedirectSessionInformationExpiredStrategy.class);
|
||||
|
@ -526,9 +496,7 @@ class HttpConfigurationBuilder {
|
|||
else if (StringUtils.hasText(expiredSessionStrategyRef)) {
|
||||
filterBuilder.addConstructorArgReference(expiredSessionStrategyRef);
|
||||
}
|
||||
|
||||
this.pc.popAndRegisterContainingComponent();
|
||||
|
||||
this.concurrentSessionFilter = filterBuilder.getBeanDefinition();
|
||||
this.sessionRegistryRef = new RuntimeBeanReference(sessionRegistryId);
|
||||
}
|
||||
|
@ -542,14 +510,10 @@ class HttpConfigurationBuilder {
|
|||
|
||||
// Adds the servlet-api integration filter if required
|
||||
private void createServletApiFilter(BeanReference authenticationManager) {
|
||||
final String ATT_SERVLET_API_PROVISION = "servlet-api-provision";
|
||||
final String DEF_SERVLET_API_PROVISION = "true";
|
||||
|
||||
String provideServletApi = this.httpElt.getAttribute(ATT_SERVLET_API_PROVISION);
|
||||
if (!StringUtils.hasText(provideServletApi)) {
|
||||
provideServletApi = DEF_SERVLET_API_PROVISION;
|
||||
}
|
||||
|
||||
if ("true".equals(provideServletApi)) {
|
||||
this.servApiFilter = GrantedAuthorityDefaultsParserUtils.registerWithDefaultRolePrefix(this.pc,
|
||||
SecurityContextHolderAwareRequestFilterBeanFactory.class);
|
||||
|
@ -559,14 +523,10 @@ class HttpConfigurationBuilder {
|
|||
|
||||
// Adds the jaas-api integration filter if required
|
||||
private void createJaasApiFilter() {
|
||||
final String ATT_JAAS_API_PROVISION = "jaas-api-provision";
|
||||
final String DEF_JAAS_API_PROVISION = "false";
|
||||
|
||||
String provideJaasApi = this.httpElt.getAttribute(ATT_JAAS_API_PROVISION);
|
||||
if (!StringUtils.hasText(provideJaasApi)) {
|
||||
provideJaasApi = DEF_JAAS_API_PROVISION;
|
||||
}
|
||||
|
||||
if ("true".equals(provideJaasApi)) {
|
||||
this.jaasApiFilter = new RootBeanDefinition(JaasApiIntegrationFilter.class);
|
||||
}
|
||||
|
@ -574,18 +534,13 @@ class HttpConfigurationBuilder {
|
|||
|
||||
private void createChannelProcessingFilter() {
|
||||
ManagedMap<BeanMetadataElement, BeanDefinition> channelRequestMap = parseInterceptUrlsForChannelSecurity();
|
||||
|
||||
if (channelRequestMap.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
RootBeanDefinition channelFilter = new RootBeanDefinition(ChannelProcessingFilter.class);
|
||||
BeanDefinitionBuilder metadataSourceBldr = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(DefaultFilterInvocationSecurityMetadataSource.class);
|
||||
metadataSourceBldr.addConstructorArgValue(channelRequestMap);
|
||||
// metadataSourceBldr.addPropertyValue("stripQueryStringFromUrls", matcher
|
||||
// instanceof AntUrlPathMatcher);
|
||||
|
||||
channelFilter.getPropertyValues().addPropertyValue("securityMetadataSource",
|
||||
metadataSourceBldr.getBeanDefinition());
|
||||
RootBeanDefinition channelDecisionManager = new RootBeanDefinition(ChannelDecisionManagerImpl.class);
|
||||
|
@ -593,7 +548,6 @@ class HttpConfigurationBuilder {
|
|||
RootBeanDefinition secureChannelProcessor = new RootBeanDefinition(SecureChannelProcessor.class);
|
||||
RootBeanDefinition retryWithHttp = new RootBeanDefinition(RetryWithHttpEntryPoint.class);
|
||||
RootBeanDefinition retryWithHttps = new RootBeanDefinition(RetryWithHttpsEntryPoint.class);
|
||||
|
||||
retryWithHttp.getPropertyValues().addPropertyValue("portMapper", this.portMapper);
|
||||
retryWithHttp.getPropertyValues().addPropertyValue("portResolver", this.portResolver);
|
||||
retryWithHttps.getPropertyValues().addPropertyValue("portMapper", this.portMapper);
|
||||
|
@ -604,7 +558,6 @@ class HttpConfigurationBuilder {
|
|||
channelProcessors.add(secureChannelProcessor);
|
||||
channelProcessors.add(inSecureChannelProcessor);
|
||||
channelDecisionManager.getPropertyValues().addPropertyValue("channelProcessors", channelProcessors);
|
||||
|
||||
String id = this.pc.getReaderContext().registerWithGeneratedName(channelDecisionManager);
|
||||
channelFilter.getPropertyValues().addPropertyValue("channelDecisionManager", new RuntimeBeanReference(id));
|
||||
this.cpf = channelFilter;
|
||||
|
@ -616,45 +569,35 @@ class HttpConfigurationBuilder {
|
|||
* path.
|
||||
*/
|
||||
private ManagedMap<BeanMetadataElement, BeanDefinition> parseInterceptUrlsForChannelSecurity() {
|
||||
|
||||
ManagedMap<BeanMetadataElement, BeanDefinition> channelRequestMap = new ManagedMap<>();
|
||||
|
||||
for (Element urlElt : this.interceptUrls) {
|
||||
String path = urlElt.getAttribute(HttpSecurityBeanDefinitionParser.ATT_PATH_PATTERN);
|
||||
String method = urlElt.getAttribute(HttpSecurityBeanDefinitionParser.ATT_HTTP_METHOD);
|
||||
String matcherRef = urlElt.getAttribute(HttpSecurityBeanDefinitionParser.ATT_REQUEST_MATCHER_REF);
|
||||
boolean hasMatcherRef = StringUtils.hasText(matcherRef);
|
||||
|
||||
if (!hasMatcherRef && !StringUtils.hasText(path)) {
|
||||
this.pc.getReaderContext().error("pattern attribute cannot be empty or null", urlElt);
|
||||
}
|
||||
|
||||
String requiredChannel = urlElt.getAttribute(HttpSecurityBeanDefinitionParser.ATT_REQUIRES_CHANNEL);
|
||||
|
||||
if (StringUtils.hasText(requiredChannel)) {
|
||||
BeanMetadataElement matcher = hasMatcherRef ? new RuntimeBeanReference(matcherRef)
|
||||
: this.matcherType.createMatcher(this.pc, path, method);
|
||||
|
||||
RootBeanDefinition channelAttributes = new RootBeanDefinition(ChannelAttributeFactory.class);
|
||||
channelAttributes.getConstructorArgumentValues().addGenericArgumentValue(requiredChannel);
|
||||
channelAttributes.setFactoryMethodName("createChannelAttributes");
|
||||
|
||||
channelRequestMap.put(matcher, channelAttributes);
|
||||
}
|
||||
}
|
||||
|
||||
return channelRequestMap;
|
||||
}
|
||||
|
||||
private void createRequestCacheFilter() {
|
||||
Element requestCacheElt = DomUtils.getChildElementByTagName(this.httpElt, Elements.REQUEST_CACHE);
|
||||
|
||||
if (requestCacheElt != null) {
|
||||
this.requestCache = new RuntimeBeanReference(requestCacheElt.getAttribute(ATT_REF));
|
||||
}
|
||||
else {
|
||||
BeanDefinitionBuilder requestCacheBldr;
|
||||
|
||||
if (this.sessionPolicy == SessionCreationPolicy.STATELESS) {
|
||||
requestCacheBldr = BeanDefinitionBuilder.rootBeanDefinition(NullRequestCache.class);
|
||||
}
|
||||
|
@ -671,14 +614,11 @@ class HttpConfigurationBuilder {
|
|||
requestCacheBldr.addPropertyValue("requestMatcher", requestCacheMatcherBldr.getBeanDefinition());
|
||||
}
|
||||
}
|
||||
|
||||
BeanDefinition bean = requestCacheBldr.getBeanDefinition();
|
||||
String id = this.pc.getReaderContext().generateBeanName(bean);
|
||||
this.pc.registerBeanComponent(new BeanComponentDefinition(bean, id));
|
||||
|
||||
this.requestCache = new RuntimeBeanReference(id);
|
||||
}
|
||||
|
||||
this.requestCacheAwareFilter = new RootBeanDefinition(RequestCacheAwareFilter.class);
|
||||
this.requestCacheAwareFilter.getConstructorArgumentValues().addGenericArgumentValue(this.requestCache);
|
||||
}
|
||||
|
@ -687,18 +627,14 @@ class HttpConfigurationBuilder {
|
|||
boolean useExpressions = FilterInvocationSecurityMetadataSourceParser.isUseExpressions(this.httpElt);
|
||||
RootBeanDefinition securityMds = FilterInvocationSecurityMetadataSourceParser
|
||||
.createSecurityMetadataSource(this.interceptUrls, this.addAllAuth, this.httpElt, this.pc);
|
||||
|
||||
RootBeanDefinition accessDecisionMgr;
|
||||
ManagedList<BeanDefinition> voters = new ManagedList<>(2);
|
||||
|
||||
if (useExpressions) {
|
||||
BeanDefinitionBuilder expressionVoter = BeanDefinitionBuilder.rootBeanDefinition(WebExpressionVoter.class);
|
||||
// Read the expression handler from the FISMS
|
||||
RuntimeBeanReference expressionHandler = (RuntimeBeanReference) securityMds.getConstructorArgumentValues()
|
||||
.getArgumentValue(1, RuntimeBeanReference.class).getValue();
|
||||
|
||||
expressionVoter.addPropertyValue("expressionHandler", expressionHandler);
|
||||
|
||||
voters.add(expressionVoter.getBeanDefinition());
|
||||
}
|
||||
else {
|
||||
|
@ -709,37 +645,28 @@ class HttpConfigurationBuilder {
|
|||
accessDecisionMgr = new RootBeanDefinition(AffirmativeBased.class);
|
||||
accessDecisionMgr.getConstructorArgumentValues().addGenericArgumentValue(voters);
|
||||
accessDecisionMgr.setSource(this.pc.extractSource(this.httpElt));
|
||||
|
||||
// Set up the access manager reference for http
|
||||
String accessManagerId = this.httpElt.getAttribute(ATT_ACCESS_MGR);
|
||||
|
||||
if (!StringUtils.hasText(accessManagerId)) {
|
||||
accessManagerId = this.pc.getReaderContext().generateBeanName(accessDecisionMgr);
|
||||
this.pc.registerBeanComponent(new BeanComponentDefinition(accessDecisionMgr, accessManagerId));
|
||||
}
|
||||
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(FilterSecurityInterceptor.class);
|
||||
|
||||
builder.addPropertyReference("accessDecisionManager", accessManagerId);
|
||||
builder.addPropertyValue("authenticationManager", authManager);
|
||||
|
||||
if ("false".equals(this.httpElt.getAttribute(ATT_ONCE_PER_REQUEST))) {
|
||||
builder.addPropertyValue("observeOncePerRequest", Boolean.FALSE);
|
||||
}
|
||||
|
||||
builder.addPropertyValue("securityMetadataSource", securityMds);
|
||||
BeanDefinition fsiBean = builder.getBeanDefinition();
|
||||
String fsiId = this.pc.getReaderContext().generateBeanName(fsiBean);
|
||||
this.pc.registerBeanComponent(new BeanComponentDefinition(fsiBean, fsiId));
|
||||
|
||||
// Create and register a DefaultWebInvocationPrivilegeEvaluator for use with
|
||||
// taglibs etc.
|
||||
BeanDefinition wipe = new RootBeanDefinition(DefaultWebInvocationPrivilegeEvaluator.class);
|
||||
wipe.getConstructorArgumentValues().addGenericArgumentValue(new RuntimeBeanReference(fsiId));
|
||||
|
||||
this.pc.registerBeanComponent(
|
||||
new BeanComponentDefinition(wipe, this.pc.getReaderContext().generateBeanName(wipe)));
|
||||
|
||||
this.fsi = new RuntimeBeanReference(fsiId);
|
||||
}
|
||||
|
||||
|
@ -758,12 +685,10 @@ class HttpConfigurationBuilder {
|
|||
Element elmt = DomUtils.getChildElementByTagName(this.httpElt, Elements.CSRF);
|
||||
this.csrfParser = new CsrfBeanDefinitionParser();
|
||||
this.csrfFilter = this.csrfParser.parse(elmt, this.pc);
|
||||
|
||||
if (this.csrfFilter == null) {
|
||||
this.csrfParser = null;
|
||||
return;
|
||||
}
|
||||
|
||||
this.csrfAuthStrategy = this.csrfParser.getCsrfAuthenticationStrategy();
|
||||
this.csrfLogoutHandler = this.csrfParser.getCsrfLogoutHandler();
|
||||
}
|
||||
|
@ -786,51 +711,38 @@ class HttpConfigurationBuilder {
|
|||
|
||||
List<OrderDecorator> getFilters() {
|
||||
List<OrderDecorator> filters = new ArrayList<>();
|
||||
|
||||
if (this.cpf != null) {
|
||||
filters.add(new OrderDecorator(this.cpf, SecurityFilters.CHANNEL_FILTER));
|
||||
}
|
||||
|
||||
if (this.concurrentSessionFilter != null) {
|
||||
filters.add(new OrderDecorator(this.concurrentSessionFilter, SecurityFilters.CONCURRENT_SESSION_FILTER));
|
||||
}
|
||||
|
||||
if (this.webAsyncManagerFilter != null) {
|
||||
filters.add(new OrderDecorator(this.webAsyncManagerFilter, SecurityFilters.WEB_ASYNC_MANAGER_FILTER));
|
||||
}
|
||||
|
||||
filters.add(new OrderDecorator(this.securityContextPersistenceFilter, SecurityFilters.SECURITY_CONTEXT_FILTER));
|
||||
|
||||
if (this.servApiFilter != null) {
|
||||
filters.add(new OrderDecorator(this.servApiFilter, SecurityFilters.SERVLET_API_SUPPORT_FILTER));
|
||||
}
|
||||
|
||||
if (this.jaasApiFilter != null) {
|
||||
filters.add(new OrderDecorator(this.jaasApiFilter, SecurityFilters.JAAS_API_SUPPORT_FILTER));
|
||||
}
|
||||
|
||||
if (this.sfpf != null) {
|
||||
filters.add(new OrderDecorator(this.sfpf, SecurityFilters.SESSION_MANAGEMENT_FILTER));
|
||||
}
|
||||
|
||||
filters.add(new OrderDecorator(this.fsi, SecurityFilters.FILTER_SECURITY_INTERCEPTOR));
|
||||
|
||||
if (this.sessionPolicy != SessionCreationPolicy.STATELESS) {
|
||||
filters.add(new OrderDecorator(this.requestCacheAwareFilter, SecurityFilters.REQUEST_CACHE_FILTER));
|
||||
}
|
||||
|
||||
if (this.corsFilter != null) {
|
||||
filters.add(new OrderDecorator(this.corsFilter, SecurityFilters.CORS_FILTER));
|
||||
}
|
||||
|
||||
if (this.addHeadersFilter != null) {
|
||||
filters.add(new OrderDecorator(this.addHeadersFilter, SecurityFilters.HEADERS_FILTER));
|
||||
}
|
||||
|
||||
if (this.csrfFilter != null) {
|
||||
filters.add(new OrderDecorator(this.csrfFilter, SecurityFilters.CSRF_FILTER));
|
||||
}
|
||||
|
||||
return filters;
|
||||
}
|
||||
|
||||
|
|
|
@ -36,16 +36,13 @@ public class HttpFirewallBeanDefinitionParser implements BeanDefinitionParser {
|
|||
@Override
|
||||
public BeanDefinition parse(Element element, ParserContext pc) {
|
||||
String ref = element.getAttribute("ref");
|
||||
|
||||
if (!StringUtils.hasText(ref)) {
|
||||
pc.getReaderContext().error("ref attribute is required", pc.extractSource(element));
|
||||
}
|
||||
|
||||
// Ensure the FCP is registered.
|
||||
HttpSecurityBeanDefinitionParser.registerFilterChainProxyIfNecessary(pc, pc.extractSource(element));
|
||||
BeanDefinition filterChainProxy = pc.getRegistry().getBeanDefinition(BeanIds.FILTER_CHAIN_PROXY);
|
||||
filterChainProxy.getPropertyValues().addPropertyValue("firewall", new RuntimeBeanReference(ref));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -69,11 +69,15 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
|||
private static final Log logger = LogFactory.getLog(HttpSecurityBeanDefinitionParser.class);
|
||||
|
||||
private static final String ATT_AUTHENTICATION_MANAGER_REF = "authentication-manager-ref";
|
||||
|
||||
static final String ATT_REQUEST_MATCHER_REF = "request-matcher-ref";
|
||||
|
||||
static final String ATT_PATH_PATTERN = "pattern";
|
||||
|
||||
static final String ATT_HTTP_METHOD = "method";
|
||||
|
||||
static final String ATT_FILTERS = "filters";
|
||||
|
||||
static final String OPT_FILTERS_NONE = "none";
|
||||
|
||||
static final String ATT_REQUIRES_CHANNEL = "requires-channel";
|
||||
|
@ -84,6 +88,12 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
|||
|
||||
private static final String OPT_SECURITY_NONE = "none";
|
||||
|
||||
private static final String ATT_AFTER = "after";
|
||||
|
||||
private static final String ATT_BEFORE = "before";
|
||||
|
||||
private static final String ATT_POSITION = "position";
|
||||
|
||||
public HttpSecurityBeanDefinitionParser() {
|
||||
}
|
||||
|
||||
|
@ -102,16 +112,12 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
|||
CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(),
|
||||
pc.extractSource(element));
|
||||
pc.pushContainingComponent(compositeDef);
|
||||
|
||||
registerFilterChainProxyIfNecessary(pc, pc.extractSource(element));
|
||||
|
||||
// Obtain the filter chains and add the new chain to it
|
||||
BeanDefinition listFactoryBean = pc.getRegistry().getBeanDefinition(BeanIds.FILTER_CHAINS);
|
||||
List<BeanReference> filterChains = (List<BeanReference>) listFactoryBean.getPropertyValues()
|
||||
.getPropertyValue("sourceList").getValue();
|
||||
|
||||
filterChains.add(createFilterChain(element, pc));
|
||||
|
||||
pc.popAndRegisterContainingComponent();
|
||||
return null;
|
||||
}
|
||||
|
@ -121,76 +127,62 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
|||
*/
|
||||
private BeanReference createFilterChain(Element element, ParserContext pc) {
|
||||
boolean secured = !OPT_SECURITY_NONE.equals(element.getAttribute(ATT_SECURED));
|
||||
|
||||
if (!secured) {
|
||||
if (!StringUtils.hasText(element.getAttribute(ATT_PATH_PATTERN))
|
||||
&& !StringUtils.hasText(ATT_REQUEST_MATCHER_REF)) {
|
||||
pc.getReaderContext()
|
||||
.error("The '" + ATT_SECURED + "' attribute must be used in combination with" + " the '"
|
||||
+ ATT_PATH_PATTERN + "' or '" + ATT_REQUEST_MATCHER_REF + "' attributes.",
|
||||
pc.extractSource(element));
|
||||
}
|
||||
|
||||
for (int n = 0; n < element.getChildNodes().getLength(); n++) {
|
||||
if (element.getChildNodes().item(n) instanceof Element) {
|
||||
validateSecuredFilterChainElement(element, pc);
|
||||
for (int i = 0; i < element.getChildNodes().getLength(); i++) {
|
||||
if (element.getChildNodes().item(i) instanceof Element) {
|
||||
pc.getReaderContext().error("If you are using <http> to define an unsecured pattern, "
|
||||
+ "it cannot contain child elements.", pc.extractSource(element));
|
||||
}
|
||||
}
|
||||
|
||||
return createSecurityFilterChainBean(element, pc, Collections.emptyList());
|
||||
}
|
||||
|
||||
final BeanReference portMapper = createPortMapper(element, pc);
|
||||
final BeanReference portResolver = createPortResolver(portMapper, pc);
|
||||
|
||||
BeanReference portMapper = createPortMapper(element, pc);
|
||||
BeanReference portResolver = createPortResolver(portMapper, pc);
|
||||
ManagedList<BeanReference> authenticationProviders = new ManagedList<>();
|
||||
BeanReference authenticationManager = createAuthenticationManager(element, pc, authenticationProviders);
|
||||
|
||||
boolean forceAutoConfig = isDefaultHttpConfig(element);
|
||||
HttpConfigurationBuilder httpBldr = new HttpConfigurationBuilder(element, forceAutoConfig, pc, portMapper,
|
||||
portResolver, authenticationManager);
|
||||
|
||||
AuthenticationConfigBuilder authBldr = new AuthenticationConfigBuilder(element, forceAutoConfig, pc,
|
||||
httpBldr.getSessionCreationPolicy(), httpBldr.getRequestCache(), authenticationManager,
|
||||
httpBldr.getSessionStrategy(), portMapper, portResolver, httpBldr.getCsrfLogoutHandler());
|
||||
|
||||
httpBldr.setLogoutHandlers(authBldr.getLogoutHandlers());
|
||||
httpBldr.setEntryPoint(authBldr.getEntryPointBean());
|
||||
httpBldr.setAccessDeniedHandler(authBldr.getAccessDeniedHandlerBean());
|
||||
httpBldr.setCsrfIgnoreRequestMatchers(authBldr.getCsrfIgnoreRequestMatchers());
|
||||
|
||||
authenticationProviders.addAll(authBldr.getProviders());
|
||||
|
||||
List<OrderDecorator> unorderedFilterChain = new ArrayList<>();
|
||||
|
||||
unorderedFilterChain.addAll(httpBldr.getFilters());
|
||||
unorderedFilterChain.addAll(authBldr.getFilters());
|
||||
unorderedFilterChain.addAll(buildCustomFilterList(element, pc));
|
||||
|
||||
unorderedFilterChain.sort(new OrderComparator());
|
||||
checkFilterChainOrder(unorderedFilterChain, pc, pc.extractSource(element));
|
||||
|
||||
// The list of filter beans
|
||||
List<BeanMetadataElement> filterChain = new ManagedList<>();
|
||||
|
||||
for (OrderDecorator od : unorderedFilterChain) {
|
||||
filterChain.add(od.bean);
|
||||
}
|
||||
|
||||
return createSecurityFilterChainBean(element, pc, filterChain);
|
||||
}
|
||||
|
||||
private void validateSecuredFilterChainElement(Element element, ParserContext pc) {
|
||||
if (!StringUtils.hasText(element.getAttribute(ATT_PATH_PATTERN))
|
||||
&& !StringUtils.hasText(ATT_REQUEST_MATCHER_REF)) {
|
||||
String message = "The '" + ATT_SECURED + "' attribute must be used in combination with" + " the '"
|
||||
+ ATT_PATH_PATTERN + "' or '" + ATT_REQUEST_MATCHER_REF + "' attributes.";
|
||||
pc.getReaderContext().error(message, pc.extractSource(element));
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isDefaultHttpConfig(Element httpElt) {
|
||||
return httpElt.getChildNodes().getLength() == 0 && httpElt.getAttributes().getLength() == 0;
|
||||
}
|
||||
|
||||
private BeanReference createSecurityFilterChainBean(Element element, ParserContext pc, List<?> filterChain) {
|
||||
BeanMetadataElement filterChainMatcher;
|
||||
|
||||
String requestMatcherRef = element.getAttribute(ATT_REQUEST_MATCHER_REF);
|
||||
String filterChainPattern = element.getAttribute(ATT_PATH_PATTERN);
|
||||
|
||||
if (StringUtils.hasText(requestMatcherRef)) {
|
||||
if (StringUtils.hasText(filterChainPattern)) {
|
||||
pc.getReaderContext().error(
|
||||
|
@ -206,14 +198,11 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
|||
else {
|
||||
filterChainMatcher = new RootBeanDefinition(AnyRequestMatcher.class);
|
||||
}
|
||||
|
||||
BeanDefinitionBuilder filterChainBldr = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(DefaultSecurityFilterChain.class);
|
||||
filterChainBldr.addConstructorArgValue(filterChainMatcher);
|
||||
filterChainBldr.addConstructorArgValue(filterChain);
|
||||
|
||||
BeanDefinition filterChainBean = filterChainBldr.getBeanDefinition();
|
||||
|
||||
String id = element.getAttribute("name");
|
||||
if (!StringUtils.hasText(id)) {
|
||||
id = element.getAttribute("id");
|
||||
|
@ -221,9 +210,7 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
|||
id = pc.getReaderContext().generateBeanName(filterChainBean);
|
||||
}
|
||||
}
|
||||
|
||||
pc.registerBeanComponent(new BeanComponentDefinition(filterChainBean, id));
|
||||
|
||||
return new RuntimeBeanReference(id);
|
||||
}
|
||||
|
||||
|
@ -234,7 +221,6 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
|||
.parse(DomUtils.getChildElementByTagName(elt, Elements.PORT_MAPPINGS), pc);
|
||||
String portMapperName = pc.getReaderContext().generateBeanName(portMapper);
|
||||
pc.registerBeanComponent(new BeanComponentDefinition(portMapper, portMapperName));
|
||||
|
||||
return new RuntimeBeanReference(portMapperName);
|
||||
}
|
||||
|
||||
|
@ -259,7 +245,6 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
|||
String parentMgrRef = element.getAttribute(ATT_AUTHENTICATION_MANAGER_REF);
|
||||
BeanDefinitionBuilder authManager = BeanDefinitionBuilder.rootBeanDefinition(ProviderManager.class);
|
||||
authManager.addConstructorArgValue(authenticationProviders);
|
||||
|
||||
if (StringUtils.hasText(parentMgrRef)) {
|
||||
RuntimeBeanReference parentAuthManager = new RuntimeBeanReference(parentMgrRef);
|
||||
authManager.addConstructorArgValue(parentAuthManager);
|
||||
|
@ -268,7 +253,6 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
|||
clearCredentials.getPropertyValues().addPropertyValue("targetObject", parentAuthManager);
|
||||
clearCredentials.getPropertyValues().addPropertyValue("targetMethod",
|
||||
"isEraseCredentialsAfterAuthentication");
|
||||
|
||||
authManager.addPropertyValue("eraseCredentialsAfterAuthentication", clearCredentials);
|
||||
}
|
||||
else {
|
||||
|
@ -280,11 +264,9 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
|||
clearCredentials.getPropertyValues().addPropertyValue("targetObject", new RuntimeBeanReference(amfbId));
|
||||
clearCredentials.getPropertyValues().addPropertyValue("targetMethod",
|
||||
"isEraseCredentialsAfterAuthentication");
|
||||
|
||||
authManager.addConstructorArgValue(new RuntimeBeanReference(amfbId));
|
||||
authManager.addPropertyValue("eraseCredentialsAfterAuthentication", clearCredentials);
|
||||
}
|
||||
|
||||
// gh-6009
|
||||
authManager.addPropertyValue("authenticationEventPublisher",
|
||||
new RootBeanDefinition(DefaultAuthenticationEventPublisher.class));
|
||||
|
@ -292,16 +274,13 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
|||
BeanDefinition authMgrBean = authManager.getBeanDefinition();
|
||||
String id = pc.getReaderContext().generateBeanName(authMgrBean);
|
||||
pc.registerBeanComponent(new BeanComponentDefinition(authMgrBean, id));
|
||||
|
||||
return new RuntimeBeanReference(id);
|
||||
}
|
||||
|
||||
private void checkFilterChainOrder(List<OrderDecorator> filters, ParserContext pc, Object source) {
|
||||
logger.info("Checking sorted filter chain: " + filters);
|
||||
|
||||
for (int i = 0; i < filters.size(); i++) {
|
||||
OrderDecorator filter = filters.get(i);
|
||||
|
||||
if (i > 0) {
|
||||
OrderDecorator previous = filters.get(i - 1);
|
||||
if (filter.getOrder() == previous.getOrder()) {
|
||||
|
@ -320,29 +299,19 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
|||
List<OrderDecorator> buildCustomFilterList(Element element, ParserContext pc) {
|
||||
List<Element> customFilterElts = DomUtils.getChildElementsByTagName(element, Elements.CUSTOM_FILTER);
|
||||
List<OrderDecorator> customFilters = new ArrayList<>();
|
||||
|
||||
final String ATT_AFTER = "after";
|
||||
final String ATT_BEFORE = "before";
|
||||
final String ATT_POSITION = "position";
|
||||
|
||||
for (Element elt : customFilterElts) {
|
||||
String after = elt.getAttribute(ATT_AFTER);
|
||||
String before = elt.getAttribute(ATT_BEFORE);
|
||||
String position = elt.getAttribute(ATT_POSITION);
|
||||
|
||||
String ref = elt.getAttribute(ATT_REF);
|
||||
|
||||
if (!StringUtils.hasText(ref)) {
|
||||
pc.getReaderContext().error("The '" + ATT_REF + "' attribute must be supplied", pc.extractSource(elt));
|
||||
}
|
||||
|
||||
RuntimeBeanReference bean = new RuntimeBeanReference(ref);
|
||||
|
||||
if (WebConfigUtils.countNonEmpty(new String[] { after, before, position }) != 1) {
|
||||
pc.getReaderContext().error("A single '" + ATT_AFTER + "', '" + ATT_BEFORE + "', or '" + ATT_POSITION
|
||||
+ "' attribute must be supplied", pc.extractSource(elt));
|
||||
}
|
||||
|
||||
if (StringUtils.hasText(position)) {
|
||||
customFilters.add(new OrderDecorator(bean, SecurityFilters.valueOf(position)));
|
||||
}
|
||||
|
@ -365,7 +334,6 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
return customFilters;
|
||||
}
|
||||
|
||||
|
@ -379,7 +347,6 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
|||
BeanDefinition listFactoryBean = new RootBeanDefinition(ListFactoryBean.class);
|
||||
listFactoryBean.getPropertyValues().add("sourceList", new ManagedList());
|
||||
pc.registerBeanComponent(new BeanComponentDefinition(listFactoryBean, BeanIds.FILTER_CHAINS));
|
||||
|
||||
BeanDefinitionBuilder fcpBldr = BeanDefinitionBuilder.rootBeanDefinition(FilterChainProxy.class);
|
||||
fcpBldr.getRawBeanDefinition().setSource(source);
|
||||
fcpBldr.addConstructorArgReference(BeanIds.FILTER_CHAINS);
|
||||
|
@ -387,7 +354,6 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
|||
BeanDefinition fcpBean = fcpBldr.getBeanDefinition();
|
||||
pc.registerBeanComponent(new BeanComponentDefinition(fcpBean, BeanIds.FILTER_CHAIN_PROXY));
|
||||
registry.registerAlias(BeanIds.FILTER_CHAIN_PROXY, BeanIds.SPRING_SECURITY_FILTER_CHAIN);
|
||||
|
||||
BeanDefinitionBuilder requestRejected = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(RequestRejectedHandlerPostProcessor.class);
|
||||
requestRejected.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
|
|
|
@ -44,8 +44,11 @@ class LogoutBeanDefinitionParser implements BeanDefinitionParser {
|
|||
static final String ATT_INVALIDATE_SESSION = "invalidate-session";
|
||||
|
||||
static final String ATT_LOGOUT_URL = "logout-url";
|
||||
|
||||
static final String DEF_LOGOUT_URL = "/logout";
|
||||
|
||||
static final String ATT_LOGOUT_HANDLER = "success-handler-ref";
|
||||
|
||||
static final String ATT_DELETE_COOKIES = "delete-cookies";
|
||||
|
||||
final String rememberMeServices;
|
||||
|
@ -72,9 +75,7 @@ class LogoutBeanDefinitionParser implements BeanDefinitionParser {
|
|||
String logoutSuccessUrl = null;
|
||||
String invalidateSession = null;
|
||||
String deleteCookies = null;
|
||||
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(LogoutFilter.class);
|
||||
|
||||
if (element != null) {
|
||||
Object source = pc.extractSource(element);
|
||||
builder.getRawBeanDefinition().setSource(source);
|
||||
|
@ -86,13 +87,10 @@ class LogoutBeanDefinitionParser implements BeanDefinitionParser {
|
|||
invalidateSession = element.getAttribute(ATT_INVALIDATE_SESSION);
|
||||
deleteCookies = element.getAttribute(ATT_DELETE_COOKIES);
|
||||
}
|
||||
|
||||
if (!StringUtils.hasText(logoutUrl)) {
|
||||
logoutUrl = DEF_LOGOUT_URL;
|
||||
}
|
||||
|
||||
builder.addPropertyValue("logoutRequestMatcher", getLogoutRequestMatcher(logoutUrl));
|
||||
|
||||
if (StringUtils.hasText(successHandlerRef)) {
|
||||
if (StringUtils.hasText(logoutSuccessUrl)) {
|
||||
pc.getReaderContext().error(
|
||||
|
@ -108,26 +106,20 @@ class LogoutBeanDefinitionParser implements BeanDefinitionParser {
|
|||
}
|
||||
builder.addConstructorArgValue(logoutSuccessUrl);
|
||||
}
|
||||
|
||||
BeanDefinition sclh = new RootBeanDefinition(SecurityContextLogoutHandler.class);
|
||||
sclh.getPropertyValues().addPropertyValue("invalidateHttpSession", !"false".equals(invalidateSession));
|
||||
this.logoutHandlers.add(sclh);
|
||||
|
||||
if (this.rememberMeServices != null) {
|
||||
this.logoutHandlers.add(new RuntimeBeanReference(this.rememberMeServices));
|
||||
}
|
||||
|
||||
if (StringUtils.hasText(deleteCookies)) {
|
||||
BeanDefinition cookieDeleter = new RootBeanDefinition(CookieClearingLogoutHandler.class);
|
||||
String[] names = StringUtils.tokenizeToStringArray(deleteCookies, ",");
|
||||
cookieDeleter.getConstructorArgumentValues().addGenericArgumentValue(names);
|
||||
this.logoutHandlers.add(cookieDeleter);
|
||||
}
|
||||
|
||||
this.logoutHandlers.add(new RootBeanDefinition(LogoutSuccessEventPublishingLogoutHandler.class));
|
||||
|
||||
builder.addConstructorArgValue(this.logoutHandlers);
|
||||
|
||||
return builder.getBeanDefinition();
|
||||
}
|
||||
|
||||
|
@ -138,7 +130,6 @@ class LogoutBeanDefinitionParser implements BeanDefinitionParser {
|
|||
if (this.csrfEnabled) {
|
||||
matcherBuilder.addConstructorArgValue("POST");
|
||||
}
|
||||
|
||||
return matcherBuilder.getBeanDefinition();
|
||||
}
|
||||
|
||||
|
|
|
@ -58,13 +58,10 @@ public enum MatcherType {
|
|||
if (("/**".equals(path) || "**".equals(path)) && method == null) {
|
||||
return new RootBeanDefinition(AnyRequestMatcher.class);
|
||||
}
|
||||
|
||||
BeanDefinitionBuilder matcherBldr = BeanDefinitionBuilder.rootBeanDefinition(this.type);
|
||||
|
||||
if (this == mvc) {
|
||||
matcherBldr.addConstructorArgValue(new RootBeanDefinition(HandlerMappingIntrospectorFactoryBean.class));
|
||||
}
|
||||
|
||||
matcherBldr.addConstructorArgValue(path);
|
||||
if (this == mvc) {
|
||||
matcherBldr.addPropertyValue("method", method);
|
||||
|
@ -73,11 +70,9 @@ public enum MatcherType {
|
|||
else {
|
||||
matcherBldr.addConstructorArgValue(method);
|
||||
}
|
||||
|
||||
if (this == ciRegex) {
|
||||
matcherBldr.addConstructorArgValue(true);
|
||||
}
|
||||
|
||||
return matcherBldr.getBeanDefinition();
|
||||
}
|
||||
|
||||
|
|
|
@ -66,7 +66,6 @@ final class OAuth2ClientBeanDefinitionParser implements BeanDefinitionParser {
|
|||
@Override
|
||||
public BeanDefinition parse(Element element, ParserContext parserContext) {
|
||||
Element authorizationCodeGrantElt = DomUtils.getChildElementByTagName(element, ELT_AUTHORIZATION_CODE_GRANT);
|
||||
|
||||
BeanMetadataElement clientRegistrationRepository = OAuth2ClientBeanDefinitionParserUtils
|
||||
.getClientRegistrationRepository(element);
|
||||
BeanMetadataElement authorizedClientRepository = OAuth2ClientBeanDefinitionParserUtils
|
||||
|
@ -80,7 +79,6 @@ final class OAuth2ClientBeanDefinitionParser implements BeanDefinitionParser {
|
|||
}
|
||||
BeanMetadataElement authorizationRequestRepository = getAuthorizationRequestRepository(
|
||||
authorizationCodeGrantElt);
|
||||
|
||||
BeanDefinitionBuilder authorizationRequestRedirectFilterBuilder = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(OAuth2AuthorizationRequestRedirectFilter.class);
|
||||
String authorizationRequestResolverRef = (authorizationCodeGrantElt != null)
|
||||
|
@ -94,7 +92,6 @@ final class OAuth2ClientBeanDefinitionParser implements BeanDefinitionParser {
|
|||
this.authorizationRequestRedirectFilter = authorizationRequestRedirectFilterBuilder
|
||||
.addPropertyValue("authorizationRequestRepository", authorizationRequestRepository)
|
||||
.addPropertyValue("requestCache", this.requestCache).getBeanDefinition();
|
||||
|
||||
this.authorizationCodeGrantFilter = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(OAuth2AuthorizationCodeGrantFilter.class)
|
||||
.addConstructorArgValue(clientRegistrationRepository).addConstructorArgValue(authorizedClientRepository)
|
||||
|
@ -102,7 +99,6 @@ final class OAuth2ClientBeanDefinitionParser implements BeanDefinitionParser {
|
|||
.addPropertyValue("authorizationRequestRepository", authorizationRequestRepository).getBeanDefinition();
|
||||
|
||||
BeanMetadataElement accessTokenResponseClient = getAccessTokenResponseClient(authorizationCodeGrantElt);
|
||||
|
||||
this.authorizationCodeAuthenticationProvider = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(OAuth2AuthorizationCodeAuthenticationProvider.class)
|
||||
.addConstructorArgValue(accessTokenResponseClient).getBeanDefinition();
|
||||
|
@ -111,33 +107,25 @@ final class OAuth2ClientBeanDefinitionParser implements BeanDefinitionParser {
|
|||
}
|
||||
|
||||
private BeanMetadataElement getAuthorizationRequestRepository(Element element) {
|
||||
BeanMetadataElement authorizationRequestRepository;
|
||||
String authorizationRequestRepositoryRef = (element != null)
|
||||
? element.getAttribute(ATT_AUTHORIZATION_REQUEST_REPOSITORY_REF) : null;
|
||||
if (!StringUtils.isEmpty(authorizationRequestRepositoryRef)) {
|
||||
authorizationRequestRepository = new RuntimeBeanReference(authorizationRequestRepositoryRef);
|
||||
return new RuntimeBeanReference(authorizationRequestRepositoryRef);
|
||||
}
|
||||
else {
|
||||
authorizationRequestRepository = BeanDefinitionBuilder.rootBeanDefinition(
|
||||
"org.springframework.security.oauth2.client.web.HttpSessionOAuth2AuthorizationRequestRepository")
|
||||
.getBeanDefinition();
|
||||
}
|
||||
return authorizationRequestRepository;
|
||||
return BeanDefinitionBuilder.rootBeanDefinition(
|
||||
"org.springframework.security.oauth2.client.web.HttpSessionOAuth2AuthorizationRequestRepository")
|
||||
.getBeanDefinition();
|
||||
}
|
||||
|
||||
private BeanMetadataElement getAccessTokenResponseClient(Element element) {
|
||||
BeanMetadataElement accessTokenResponseClient;
|
||||
String accessTokenResponseClientRef = (element != null)
|
||||
? element.getAttribute(ATT_ACCESS_TOKEN_RESPONSE_CLIENT_REF) : null;
|
||||
if (!StringUtils.isEmpty(accessTokenResponseClientRef)) {
|
||||
accessTokenResponseClient = new RuntimeBeanReference(accessTokenResponseClientRef);
|
||||
return new RuntimeBeanReference(accessTokenResponseClientRef);
|
||||
}
|
||||
else {
|
||||
accessTokenResponseClient = BeanDefinitionBuilder.rootBeanDefinition(
|
||||
"org.springframework.security.oauth2.client.endpoint.DefaultAuthorizationCodeTokenResponseClient")
|
||||
.getBeanDefinition();
|
||||
}
|
||||
return accessTokenResponseClient;
|
||||
return BeanDefinitionBuilder.rootBeanDefinition(
|
||||
"org.springframework.security.oauth2.client.endpoint.DefaultAuthorizationCodeTokenResponseClient")
|
||||
.getBeanDefinition();
|
||||
}
|
||||
|
||||
BeanDefinition getDefaultAuthorizedClientRepository() {
|
||||
|
|
|
@ -41,15 +41,11 @@ final class OAuth2ClientBeanDefinitionParserUtils {
|
|||
}
|
||||
|
||||
static BeanMetadataElement getClientRegistrationRepository(Element element) {
|
||||
BeanMetadataElement clientRegistrationRepository;
|
||||
String clientRegistrationRepositoryRef = element.getAttribute(ATT_CLIENT_REGISTRATION_REPOSITORY_REF);
|
||||
if (!StringUtils.isEmpty(clientRegistrationRepositoryRef)) {
|
||||
clientRegistrationRepository = new RuntimeBeanReference(clientRegistrationRepositoryRef);
|
||||
return new RuntimeBeanReference(clientRegistrationRepositoryRef);
|
||||
}
|
||||
else {
|
||||
clientRegistrationRepository = new RuntimeBeanReference(ClientRegistrationRepository.class);
|
||||
}
|
||||
return clientRegistrationRepository;
|
||||
return new RuntimeBeanReference(ClientRegistrationRepository.class);
|
||||
}
|
||||
|
||||
static BeanMetadataElement getAuthorizedClientRepository(Element element) {
|
||||
|
|
|
@ -50,11 +50,9 @@ final class OAuth2ClientWebMvcSecurityPostProcessor implements BeanDefinitionReg
|
|||
(ListableBeanFactory) this.beanFactory, ClientRegistrationRepository.class, false, false);
|
||||
String[] authorizedClientRepositoryBeanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
|
||||
(ListableBeanFactory) this.beanFactory, OAuth2AuthorizedClientRepository.class, false, false);
|
||||
|
||||
if (clientRegistrationRepositoryBeanNames.length != 1 || authorizedClientRepositoryBeanNames.length != 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (String beanName : registry.getBeanDefinitionNames()) {
|
||||
BeanDefinition beanDefinition = registry.getBeanDefinition(beanName);
|
||||
if (RequestMappingHandlerAdapter.class.getName().equals(beanDefinition.getBeanClassName())) {
|
||||
|
@ -64,10 +62,8 @@ final class OAuth2ClientWebMvcSecurityPostProcessor implements BeanDefinitionReg
|
|||
if (currentArgumentResolvers != null) {
|
||||
argumentResolvers.addAll((ManagedList<?>) currentArgumentResolvers.getValue());
|
||||
}
|
||||
|
||||
String[] authorizedClientManagerBeanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
|
||||
(ListableBeanFactory) this.beanFactory, OAuth2AuthorizedClientManager.class, false, false);
|
||||
|
||||
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(OAuth2AuthorizedClientArgumentResolver.class);
|
||||
if (authorizedClientManagerBeanNames.length == 1) {
|
||||
|
|
|
@ -144,7 +144,6 @@ final class OAuth2LoginBeanDefinitionParser implements BeanDefinitionParser {
|
|||
String oauth2LoginBeanConfigId = parserContext.getReaderContext().generateBeanName(oauth2LoginBeanConfig);
|
||||
parserContext
|
||||
.registerBeanComponent(new BeanComponentDefinition(oauth2LoginBeanConfig, oauth2LoginBeanConfigId));
|
||||
|
||||
// configure filter
|
||||
BeanMetadataElement clientRegistrationRepository = OAuth2ClientBeanDefinitionParserUtils
|
||||
.getClientRegistrationRepository(element);
|
||||
|
@ -160,17 +159,14 @@ final class OAuth2LoginBeanDefinitionParser implements BeanDefinitionParser {
|
|||
BeanMetadataElement accessTokenResponseClient = getAccessTokenResponseClient(element);
|
||||
BeanMetadataElement oauth2UserService = getOAuth2UserService(element);
|
||||
BeanMetadataElement authorizationRequestRepository = getAuthorizationRequestRepository(element);
|
||||
|
||||
BeanDefinitionBuilder oauth2LoginAuthenticationFilterBuilder = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(OAuth2LoginAuthenticationFilter.class)
|
||||
.addConstructorArgValue(clientRegistrationRepository).addConstructorArgValue(authorizedClientRepository)
|
||||
.addPropertyValue("authorizationRequestRepository", authorizationRequestRepository);
|
||||
|
||||
if (this.sessionStrategy != null) {
|
||||
oauth2LoginAuthenticationFilterBuilder.addPropertyValue("sessionAuthenticationStrategy",
|
||||
this.sessionStrategy);
|
||||
}
|
||||
|
||||
Object source = parserContext.extractSource(element);
|
||||
String loginProcessingUrl = element.getAttribute(ATT_LOGIN_PROCESSING_URL);
|
||||
if (!StringUtils.isEmpty(loginProcessingUrl)) {
|
||||
|
@ -181,25 +177,19 @@ final class OAuth2LoginBeanDefinitionParser implements BeanDefinitionParser {
|
|||
oauth2LoginAuthenticationFilterBuilder
|
||||
.addConstructorArgValue(OAuth2LoginAuthenticationFilter.DEFAULT_FILTER_PROCESSES_URI);
|
||||
}
|
||||
|
||||
BeanDefinitionBuilder oauth2LoginAuthenticationProviderBuilder = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(OAuth2LoginAuthenticationProvider.class)
|
||||
.addConstructorArgValue(accessTokenResponseClient).addConstructorArgValue(oauth2UserService);
|
||||
|
||||
String userAuthoritiesMapperRef = element.getAttribute(ATT_USER_AUTHORITIES_MAPPER_REF);
|
||||
if (!StringUtils.isEmpty(userAuthoritiesMapperRef)) {
|
||||
oauth2LoginAuthenticationProviderBuilder.addPropertyReference("authoritiesMapper",
|
||||
userAuthoritiesMapperRef);
|
||||
}
|
||||
|
||||
this.oauth2LoginAuthenticationProvider = oauth2LoginAuthenticationProviderBuilder.getBeanDefinition();
|
||||
|
||||
this.oauth2LoginOidcAuthenticationProvider = getOidcAuthProvider(element, accessTokenResponseClient,
|
||||
userAuthoritiesMapperRef);
|
||||
|
||||
BeanDefinitionBuilder oauth2AuthorizationRequestRedirectFilterBuilder = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(OAuth2AuthorizationRequestRedirectFilter.class);
|
||||
|
||||
String authorizationRequestResolverRef = element.getAttribute(ATT_AUTHORIZATION_REQUEST_RESOLVER_REF);
|
||||
if (!StringUtils.isEmpty(authorizationRequestResolverRef)) {
|
||||
oauth2AuthorizationRequestRedirectFilterBuilder.addConstructorArgReference(authorizationRequestResolverRef);
|
||||
|
@ -207,13 +197,11 @@ final class OAuth2LoginBeanDefinitionParser implements BeanDefinitionParser {
|
|||
else {
|
||||
oauth2AuthorizationRequestRedirectFilterBuilder.addConstructorArgValue(clientRegistrationRepository);
|
||||
}
|
||||
|
||||
oauth2AuthorizationRequestRedirectFilterBuilder
|
||||
.addPropertyValue("authorizationRequestRepository", authorizationRequestRepository)
|
||||
.addPropertyValue("requestCache", this.requestCache);
|
||||
this.oauth2AuthorizationRequestRedirectFilter = oauth2AuthorizationRequestRedirectFilterBuilder
|
||||
.getBeanDefinition();
|
||||
|
||||
String authenticationSuccessHandlerRef = element.getAttribute(ATT_AUTHENTICATION_SUCCESS_HANDLER_REF);
|
||||
if (!StringUtils.isEmpty(authenticationSuccessHandlerRef)) {
|
||||
oauth2LoginAuthenticationFilterBuilder.addPropertyReference("authenticationSuccessHandler",
|
||||
|
@ -226,7 +214,6 @@ final class OAuth2LoginBeanDefinitionParser implements BeanDefinitionParser {
|
|||
oauth2LoginAuthenticationFilterBuilder.addPropertyValue("authenticationSuccessHandler",
|
||||
successHandlerBuilder.getBeanDefinition());
|
||||
}
|
||||
|
||||
String loginPage = element.getAttribute(ATT_LOGIN_PAGE);
|
||||
if (!StringUtils.isEmpty(loginPage)) {
|
||||
WebConfigUtils.validateHttpRedirect(loginPage, parserContext, source);
|
||||
|
@ -244,7 +231,6 @@ final class OAuth2LoginBeanDefinitionParser implements BeanDefinitionParser {
|
|||
.getBeanDefinition();
|
||||
}
|
||||
}
|
||||
|
||||
String authenticationFailureHandlerRef = element.getAttribute(ATT_AUTHENTICATION_FAILURE_HANDLER_REF);
|
||||
if (!StringUtils.isEmpty(authenticationFailureHandlerRef)) {
|
||||
oauth2LoginAuthenticationFilterBuilder.addPropertyReference("authenticationFailureHandler",
|
||||
|
@ -259,95 +245,71 @@ final class OAuth2LoginBeanDefinitionParser implements BeanDefinitionParser {
|
|||
oauth2LoginAuthenticationFilterBuilder.addPropertyValue("authenticationFailureHandler",
|
||||
failureHandlerBuilder.getBeanDefinition());
|
||||
}
|
||||
|
||||
// prepare loginlinks
|
||||
this.oauth2LoginLinks = BeanDefinitionBuilder.rootBeanDefinition(Map.class)
|
||||
.setFactoryMethodOnBean("getLoginLinks", oauth2LoginBeanConfigId).getBeanDefinition();
|
||||
|
||||
return oauth2LoginAuthenticationFilterBuilder.getBeanDefinition();
|
||||
}
|
||||
|
||||
private BeanMetadataElement getAuthorizationRequestRepository(Element element) {
|
||||
BeanMetadataElement authorizationRequestRepository;
|
||||
String authorizationRequestRepositoryRef = element.getAttribute(ATT_AUTHORIZATION_REQUEST_REPOSITORY_REF);
|
||||
if (!StringUtils.isEmpty(authorizationRequestRepositoryRef)) {
|
||||
authorizationRequestRepository = new RuntimeBeanReference(authorizationRequestRepositoryRef);
|
||||
return new RuntimeBeanReference(authorizationRequestRepositoryRef);
|
||||
}
|
||||
else {
|
||||
authorizationRequestRepository = BeanDefinitionBuilder.rootBeanDefinition(
|
||||
"org.springframework.security.oauth2.client.web.HttpSessionOAuth2AuthorizationRequestRepository")
|
||||
.getBeanDefinition();
|
||||
}
|
||||
return authorizationRequestRepository;
|
||||
return BeanDefinitionBuilder.rootBeanDefinition(
|
||||
"org.springframework.security.oauth2.client.web.HttpSessionOAuth2AuthorizationRequestRepository")
|
||||
.getBeanDefinition();
|
||||
}
|
||||
|
||||
private BeanDefinition getOidcAuthProvider(Element element, BeanMetadataElement accessTokenResponseClient,
|
||||
String userAuthoritiesMapperRef) {
|
||||
|
||||
boolean oidcAuthenticationProviderEnabled = ClassUtils
|
||||
.isPresent("org.springframework.security.oauth2.jwt.JwtDecoder", this.getClass().getClassLoader());
|
||||
if (!oidcAuthenticationProviderEnabled) {
|
||||
return BeanDefinitionBuilder.rootBeanDefinition(OidcAuthenticationRequestChecker.class).getBeanDefinition();
|
||||
}
|
||||
|
||||
BeanMetadataElement oidcUserService = getOidcUserService(element);
|
||||
|
||||
BeanDefinitionBuilder oidcAuthProviderBuilder = BeanDefinitionBuilder.rootBeanDefinition(
|
||||
"org.springframework.security.oauth2.client.oidc.authentication.OidcAuthorizationCodeAuthenticationProvider")
|
||||
.addConstructorArgValue(accessTokenResponseClient).addConstructorArgValue(oidcUserService);
|
||||
|
||||
if (!StringUtils.isEmpty(userAuthoritiesMapperRef)) {
|
||||
oidcAuthProviderBuilder.addPropertyReference("authoritiesMapper", userAuthoritiesMapperRef);
|
||||
}
|
||||
|
||||
String jwtDecoderFactoryRef = element.getAttribute(ATT_JWT_DECODER_FACTORY_REF);
|
||||
if (!StringUtils.isEmpty(jwtDecoderFactoryRef)) {
|
||||
oidcAuthProviderBuilder.addPropertyReference("jwtDecoderFactory", jwtDecoderFactoryRef);
|
||||
}
|
||||
|
||||
return oidcAuthProviderBuilder.getBeanDefinition();
|
||||
}
|
||||
|
||||
private BeanMetadataElement getOidcUserService(Element element) {
|
||||
BeanMetadataElement oidcUserService;
|
||||
String oidcUserServiceRef = element.getAttribute(ATT_OIDC_USER_SERVICE_REF);
|
||||
if (!StringUtils.isEmpty(oidcUserServiceRef)) {
|
||||
oidcUserService = new RuntimeBeanReference(oidcUserServiceRef);
|
||||
return new RuntimeBeanReference(oidcUserServiceRef);
|
||||
}
|
||||
else {
|
||||
oidcUserService = BeanDefinitionBuilder
|
||||
.rootBeanDefinition("org.springframework.security.oauth2.client.oidc.userinfo.OidcUserService")
|
||||
.getBeanDefinition();
|
||||
}
|
||||
return oidcUserService;
|
||||
return BeanDefinitionBuilder
|
||||
.rootBeanDefinition("org.springframework.security.oauth2.client.oidc.userinfo.OidcUserService")
|
||||
.getBeanDefinition();
|
||||
}
|
||||
|
||||
private BeanMetadataElement getOAuth2UserService(Element element) {
|
||||
BeanMetadataElement oauth2UserService;
|
||||
String oauth2UserServiceRef = element.getAttribute(ATT_USER_SERVICE_REF);
|
||||
if (!StringUtils.isEmpty(oauth2UserServiceRef)) {
|
||||
oauth2UserService = new RuntimeBeanReference(oauth2UserServiceRef);
|
||||
return new RuntimeBeanReference(oauth2UserServiceRef);
|
||||
}
|
||||
else {
|
||||
oauth2UserService = BeanDefinitionBuilder
|
||||
.rootBeanDefinition("org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService")
|
||||
.getBeanDefinition();
|
||||
}
|
||||
return oauth2UserService;
|
||||
return BeanDefinitionBuilder
|
||||
.rootBeanDefinition("org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService")
|
||||
.getBeanDefinition();
|
||||
}
|
||||
|
||||
private BeanMetadataElement getAccessTokenResponseClient(Element element) {
|
||||
BeanMetadataElement accessTokenResponseClient;
|
||||
String accessTokenResponseClientRef = element.getAttribute(ATT_ACCESS_TOKEN_RESPONSE_CLIENT_REF);
|
||||
if (!StringUtils.isEmpty(accessTokenResponseClientRef)) {
|
||||
accessTokenResponseClient = new RuntimeBeanReference(accessTokenResponseClientRef);
|
||||
return new RuntimeBeanReference(accessTokenResponseClientRef);
|
||||
}
|
||||
else {
|
||||
accessTokenResponseClient = BeanDefinitionBuilder.rootBeanDefinition(
|
||||
"org.springframework.security.oauth2.client.endpoint.DefaultAuthorizationCodeTokenResponseClient")
|
||||
.getBeanDefinition();
|
||||
}
|
||||
return accessTokenResponseClient;
|
||||
return BeanDefinitionBuilder.rootBeanDefinition(
|
||||
"org.springframework.security.oauth2.client.endpoint.DefaultAuthorizationCodeTokenResponseClient")
|
||||
.getBeanDefinition();
|
||||
}
|
||||
|
||||
BeanDefinition getDefaultAuthorizedClientRepository() {
|
||||
|
@ -386,10 +348,8 @@ final class OAuth2LoginBeanDefinitionParser implements BeanDefinitionParser {
|
|||
RequestMatcher defaultEntryPointMatcher = this.getAuthenticationEntryPointMatcher();
|
||||
RequestMatcher defaultLoginPageMatcher = new AndRequestMatcher(
|
||||
new OrRequestMatcher(loginPageMatcher, faviconMatcher), defaultEntryPointMatcher);
|
||||
|
||||
RequestMatcher notXRequestedWith = new NegatedRequestMatcher(
|
||||
new RequestHeaderRequestMatcher("X-Requested-With", "XMLHttpRequest"));
|
||||
|
||||
Element clientRegElt = clientRegList.get(0);
|
||||
entryPoints = new LinkedHashMap<>();
|
||||
entryPoints.put(
|
||||
|
@ -417,22 +377,19 @@ final class OAuth2LoginBeanDefinitionParser implements BeanDefinitionParser {
|
|||
@Override
|
||||
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
|
||||
OAuth2LoginAuthenticationToken authorizationCodeAuthentication = (OAuth2LoginAuthenticationToken) authentication;
|
||||
|
||||
// Section 3.1.2.1 Authentication Request -
|
||||
// https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest
|
||||
// scope
|
||||
// REQUIRED. OpenID Connect requests MUST contain the "openid" scope value.
|
||||
if (authorizationCodeAuthentication.getAuthorizationExchange().getAuthorizationRequest().getScopes()
|
||||
if (!authorizationCodeAuthentication.getAuthorizationExchange().getAuthorizationRequest().getScopes()
|
||||
.contains(OidcScopes.OPENID)) {
|
||||
|
||||
OAuth2Error oauth2Error = new OAuth2Error("oidc_provider_not_configured",
|
||||
"An OpenID Connect Authentication Provider has not been configured. "
|
||||
+ "Check to ensure you include the dependency 'spring-security-oauth2-jose'.",
|
||||
null);
|
||||
throw new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString());
|
||||
return null;
|
||||
}
|
||||
|
||||
return null;
|
||||
// Section 3.1.2.1 Authentication Request -
|
||||
// https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest scope
|
||||
// REQUIRED. OpenID Connect requests MUST contain the "openid" scope
|
||||
// value.
|
||||
OAuth2Error oauth2Error = new OAuth2Error("oidc_provider_not_configured",
|
||||
"An OpenID Connect Authentication Provider has not been configured. "
|
||||
+ "Check to ensure you include the dependency 'spring-security-oauth2-jose'.",
|
||||
null);
|
||||
throw new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -466,13 +423,11 @@ final class OAuth2LoginBeanDefinitionParser implements BeanDefinitionParser {
|
|||
if (clientRegistrations == null) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
String authorizationRequestBaseUri = DEFAULT_AUTHORIZATION_REQUEST_BASE_URI;
|
||||
Map<String, String> loginUrlToClientName = new HashMap<>();
|
||||
clientRegistrations.forEach((registration) -> loginUrlToClientName.put(
|
||||
authorizationRequestBaseUri + "/" + registration.getRegistrationId(),
|
||||
registration.getClientName()));
|
||||
|
||||
return loginUrlToClientName;
|
||||
}
|
||||
|
||||
|
|
|
@ -62,10 +62,13 @@ import org.springframework.util.xml.DomUtils;
|
|||
final class OAuth2ResourceServerBeanDefinitionParser implements BeanDefinitionParser {
|
||||
|
||||
static final String AUTHENTICATION_MANAGER_RESOLVER_REF = "authentication-manager-resolver-ref";
|
||||
|
||||
static final String BEARER_TOKEN_RESOLVER_REF = "bearer-token-resolver-ref";
|
||||
|
||||
static final String ENTRY_POINT_REF = "entry-point-ref";
|
||||
|
||||
static final String BEARER_TOKEN_RESOLVER = "bearerTokenResolver";
|
||||
|
||||
static final String AUTHENTICATION_ENTRY_POINT = "authenticationEntryPoint";
|
||||
|
||||
private final BeanReference authenticationManager;
|
||||
|
@ -105,34 +108,27 @@ final class OAuth2ResourceServerBeanDefinitionParser implements BeanDefinitionPa
|
|||
public BeanDefinition parse(Element oauth2ResourceServer, ParserContext pc) {
|
||||
Element jwt = DomUtils.getChildElementByTagName(oauth2ResourceServer, Elements.JWT);
|
||||
Element opaqueToken = DomUtils.getChildElementByTagName(oauth2ResourceServer, Elements.OPAQUE_TOKEN);
|
||||
|
||||
validateConfiguration(oauth2ResourceServer, jwt, opaqueToken, pc);
|
||||
|
||||
if (jwt != null) {
|
||||
BeanDefinition jwtAuthenticationProvider = new JwtBeanDefinitionParser().parse(jwt, pc);
|
||||
this.authenticationProviders.add(new RuntimeBeanReference(
|
||||
pc.getReaderContext().registerWithGeneratedName(jwtAuthenticationProvider)));
|
||||
}
|
||||
|
||||
if (opaqueToken != null) {
|
||||
BeanDefinition opaqueTokenAuthenticationProvider = new OpaqueTokenBeanDefinitionParser().parse(opaqueToken,
|
||||
pc);
|
||||
this.authenticationProviders.add(new RuntimeBeanReference(
|
||||
pc.getReaderContext().registerWithGeneratedName(opaqueTokenAuthenticationProvider)));
|
||||
}
|
||||
|
||||
BeanMetadataElement bearerTokenResolver = getBearerTokenResolver(oauth2ResourceServer);
|
||||
BeanDefinitionBuilder requestMatcherBuilder = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(BearerTokenRequestMatcher.class);
|
||||
requestMatcherBuilder.addConstructorArgValue(bearerTokenResolver);
|
||||
BeanDefinition requestMatcher = requestMatcherBuilder.getBeanDefinition();
|
||||
|
||||
BeanMetadataElement authenticationEntryPoint = getEntryPoint(oauth2ResourceServer);
|
||||
|
||||
this.entryPoints.put(requestMatcher, authenticationEntryPoint);
|
||||
this.deniedHandlers.put(requestMatcher, this.accessDeniedHandler);
|
||||
this.ignoreCsrfRequestMatchers.add(requestMatcher);
|
||||
|
||||
BeanDefinitionBuilder filterBuilder = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(BearerTokenAuthenticationFilter.class);
|
||||
BeanMetadataElement authenticationManagerResolver = getAuthenticationManagerResolver(oauth2ResourceServer);
|
||||
|
@ -145,22 +141,19 @@ final class OAuth2ResourceServerBeanDefinitionParser implements BeanDefinitionPa
|
|||
void validateConfiguration(Element oauth2ResourceServer, Element jwt, Element opaqueToken, ParserContext pc) {
|
||||
if (!oauth2ResourceServer.hasAttribute(AUTHENTICATION_MANAGER_RESOLVER_REF)) {
|
||||
if (jwt == null && opaqueToken == null) {
|
||||
pc.getReaderContext()
|
||||
.error("Didn't find authentication-manager-resolver-ref, <jwt>, or <opaque-token>. "
|
||||
+ "Please select one.", oauth2ResourceServer);
|
||||
pc.getReaderContext().error("Didn't find authentication-manager-resolver-ref, "
|
||||
+ "<jwt>, or <opaque-token>. " + "Please select one.", oauth2ResourceServer);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (jwt != null) {
|
||||
pc.getReaderContext().error(
|
||||
"Found <jwt> as well as authentication-manager-resolver-ref. " + "Please select just one.",
|
||||
"Found <jwt> as well as authentication-manager-resolver-ref. Please select just one.",
|
||||
oauth2ResourceServer);
|
||||
}
|
||||
|
||||
if (opaqueToken != null) {
|
||||
pc.getReaderContext().error(
|
||||
"Found <opaque-token> as well as authentication-manager-resolver-ref. " + "Please select just one.",
|
||||
"Found <opaque-token> as well as authentication-manager-resolver-ref. Please select just one.",
|
||||
oauth2ResourceServer);
|
||||
}
|
||||
}
|
||||
|
@ -181,9 +174,7 @@ final class OAuth2ResourceServerBeanDefinitionParser implements BeanDefinitionPa
|
|||
if (StringUtils.isEmpty(bearerTokenResolverRef)) {
|
||||
return new RootBeanDefinition(DefaultBearerTokenResolver.class);
|
||||
}
|
||||
else {
|
||||
return new RuntimeBeanReference(bearerTokenResolverRef);
|
||||
}
|
||||
return new RuntimeBeanReference(bearerTokenResolverRef);
|
||||
}
|
||||
|
||||
BeanMetadataElement getEntryPoint(Element element) {
|
||||
|
@ -191,34 +182,35 @@ final class OAuth2ResourceServerBeanDefinitionParser implements BeanDefinitionPa
|
|||
if (StringUtils.isEmpty(entryPointRef)) {
|
||||
return this.authenticationEntryPoint;
|
||||
}
|
||||
else {
|
||||
return new RuntimeBeanReference(entryPointRef);
|
||||
}
|
||||
return new RuntimeBeanReference(entryPointRef);
|
||||
}
|
||||
|
||||
static final class JwtBeanDefinitionParser implements BeanDefinitionParser {
|
||||
|
||||
static final String DECODER_REF = "decoder-ref";
|
||||
|
||||
static final String JWK_SET_URI = "jwk-set-uri";
|
||||
|
||||
static final String JWT_AUTHENTICATION_CONVERTER_REF = "jwt-authentication-converter-ref";
|
||||
|
||||
static final String JWT_AUTHENTICATION_CONVERTER = "jwtAuthenticationConverter";
|
||||
|
||||
JwtBeanDefinitionParser() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public BeanDefinition parse(Element element, ParserContext pc) {
|
||||
validateConfiguration(element, pc);
|
||||
|
||||
BeanDefinitionBuilder jwtProviderBuilder = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(JwtAuthenticationProvider.class);
|
||||
jwtProviderBuilder.addConstructorArgValue(getDecoder(element));
|
||||
jwtProviderBuilder.addPropertyValue(JWT_AUTHENTICATION_CONVERTER, getJwtAuthenticationConverter(element));
|
||||
|
||||
return jwtProviderBuilder.getBeanDefinition();
|
||||
}
|
||||
|
||||
void validateConfiguration(Element element, ParserContext pc) {
|
||||
boolean usesDecoder = element.hasAttribute(DECODER_REF);
|
||||
boolean usesJwkSetUri = element.hasAttribute(JWK_SET_URI);
|
||||
|
||||
if (usesDecoder == usesJwkSetUri) {
|
||||
pc.getReaderContext().error("Please specify either decoder-ref or jwk-set-uri.", element);
|
||||
}
|
||||
|
@ -229,7 +221,6 @@ final class OAuth2ResourceServerBeanDefinitionParser implements BeanDefinitionPa
|
|||
if (!StringUtils.isEmpty(decoderRef)) {
|
||||
return new RuntimeBeanReference(decoderRef);
|
||||
}
|
||||
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(NimbusJwtDecoderJwkSetUriFactoryBean.class);
|
||||
builder.addConstructorArgValue(element.getAttribute(JWK_SET_URI));
|
||||
|
@ -238,14 +229,8 @@ final class OAuth2ResourceServerBeanDefinitionParser implements BeanDefinitionPa
|
|||
|
||||
Object getJwtAuthenticationConverter(Element element) {
|
||||
String jwtDecoderRef = element.getAttribute(JWT_AUTHENTICATION_CONVERTER_REF);
|
||||
if (!StringUtils.isEmpty(jwtDecoderRef)) {
|
||||
return new RuntimeBeanReference(jwtDecoderRef);
|
||||
}
|
||||
|
||||
return new JwtAuthenticationConverter();
|
||||
}
|
||||
|
||||
JwtBeanDefinitionParser() {
|
||||
return (!StringUtils.isEmpty(jwtDecoderRef)) ? new RuntimeBeanReference(jwtDecoderRef)
|
||||
: new JwtAuthenticationConverter();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -253,19 +238,23 @@ final class OAuth2ResourceServerBeanDefinitionParser implements BeanDefinitionPa
|
|||
static final class OpaqueTokenBeanDefinitionParser implements BeanDefinitionParser {
|
||||
|
||||
static final String INTROSPECTOR_REF = "introspector-ref";
|
||||
|
||||
static final String INTROSPECTION_URI = "introspection-uri";
|
||||
|
||||
static final String CLIENT_ID = "client-id";
|
||||
|
||||
static final String CLIENT_SECRET = "client-secret";
|
||||
|
||||
OpaqueTokenBeanDefinitionParser() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public BeanDefinition parse(Element element, ParserContext pc) {
|
||||
validateConfiguration(element, pc);
|
||||
|
||||
BeanMetadataElement introspector = getIntrospector(element);
|
||||
BeanDefinitionBuilder opaqueTokenProviderBuilder = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(OpaqueTokenAuthenticationProvider.class);
|
||||
opaqueTokenProviderBuilder.addConstructorArgValue(introspector);
|
||||
|
||||
return opaqueTokenProviderBuilder.getBeanDefinition();
|
||||
}
|
||||
|
||||
|
@ -273,13 +262,11 @@ final class OAuth2ResourceServerBeanDefinitionParser implements BeanDefinitionPa
|
|||
boolean usesIntrospector = element.hasAttribute(INTROSPECTOR_REF);
|
||||
boolean usesEndpoint = element.hasAttribute(INTROSPECTION_URI) || element.hasAttribute(CLIENT_ID)
|
||||
|| element.hasAttribute(CLIENT_SECRET);
|
||||
|
||||
if (usesIntrospector == usesEndpoint) {
|
||||
pc.getReaderContext().error("Please specify either introspector-ref or all of "
|
||||
+ "introspection-uri, client-id, and client-secret.", element);
|
||||
return;
|
||||
}
|
||||
|
||||
if (usesEndpoint) {
|
||||
if (!(element.hasAttribute(INTROSPECTION_URI) && element.hasAttribute(CLIENT_ID)
|
||||
&& element.hasAttribute(CLIENT_SECRET))) {
|
||||
|
@ -294,23 +281,17 @@ final class OAuth2ResourceServerBeanDefinitionParser implements BeanDefinitionPa
|
|||
if (!StringUtils.isEmpty(introspectorRef)) {
|
||||
return new RuntimeBeanReference(introspectorRef);
|
||||
}
|
||||
|
||||
String introspectionUri = element.getAttribute(INTROSPECTION_URI);
|
||||
String clientId = element.getAttribute(CLIENT_ID);
|
||||
String clientSecret = element.getAttribute(CLIENT_SECRET);
|
||||
|
||||
BeanDefinitionBuilder introspectorBuilder = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(NimbusOpaqueTokenIntrospector.class);
|
||||
introspectorBuilder.addConstructorArgValue(introspectionUri);
|
||||
introspectorBuilder.addConstructorArgValue(clientId);
|
||||
introspectorBuilder.addConstructorArgValue(clientSecret);
|
||||
|
||||
return introspectorBuilder.getBeanDefinition();
|
||||
}
|
||||
|
||||
OpaqueTokenBeanDefinitionParser() {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static final class StaticAuthenticationManagerResolver
|
||||
|
|
|
@ -48,33 +48,25 @@ class PortMappingsBeanDefinitionParser implements BeanDefinitionParser {
|
|||
public BeanDefinition parse(Element element, ParserContext parserContext) {
|
||||
RootBeanDefinition portMapper = new RootBeanDefinition(PortMapperImpl.class);
|
||||
portMapper.setSource(parserContext.extractSource(element));
|
||||
|
||||
if (element != null) {
|
||||
List<Element> mappingElts = DomUtils.getChildElementsByTagName(element, Elements.PORT_MAPPING);
|
||||
if (mappingElts.isEmpty()) {
|
||||
parserContext.getReaderContext().error("No port-mapping child elements specified", element);
|
||||
}
|
||||
|
||||
Map mappings = new ManagedMap();
|
||||
|
||||
for (Element elt : mappingElts) {
|
||||
String httpPort = elt.getAttribute(ATT_HTTP_PORT);
|
||||
String httpsPort = elt.getAttribute(ATT_HTTPS_PORT);
|
||||
|
||||
if (!StringUtils.hasText(httpPort)) {
|
||||
parserContext.getReaderContext().error("No http port supplied in port mapping", elt);
|
||||
}
|
||||
|
||||
if (!StringUtils.hasText(httpsPort)) {
|
||||
parserContext.getReaderContext().error("No https port supplied in port mapping", elt);
|
||||
}
|
||||
|
||||
mappings.put(httpPort, httpsPort);
|
||||
}
|
||||
|
||||
portMapper.getPropertyValues().addPropertyValue("portMappings", mappings);
|
||||
}
|
||||
|
||||
return portMapper;
|
||||
}
|
||||
|
||||
|
|
|
@ -45,14 +45,23 @@ import org.springframework.util.StringUtils;
|
|||
class RememberMeBeanDefinitionParser implements BeanDefinitionParser {
|
||||
|
||||
static final String ATT_DATA_SOURCE = "data-source-ref";
|
||||
|
||||
static final String ATT_SERVICES_REF = "services-ref";
|
||||
|
||||
static final String ATT_SERVICES_ALIAS = "services-alias";
|
||||
|
||||
static final String ATT_TOKEN_REPOSITORY = "token-repository-ref";
|
||||
|
||||
static final String ATT_USER_SERVICE_REF = "user-service-ref";
|
||||
|
||||
static final String ATT_SUCCESS_HANDLER_REF = "authentication-success-handler-ref";
|
||||
|
||||
static final String ATT_TOKEN_VALIDITY = "token-validity-seconds";
|
||||
|
||||
static final String ATT_SECURE_COOKIE = "use-secure-cookie";
|
||||
|
||||
static final String ATT_FORM_REMEMBERME_PARAMETER = "remember-me-parameter";
|
||||
|
||||
static final String ATT_REMEMBERME_COOKIE = "remember-me-cookie";
|
||||
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
@ -73,7 +82,6 @@ class RememberMeBeanDefinitionParser implements BeanDefinitionParser {
|
|||
CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(),
|
||||
pc.extractSource(element));
|
||||
pc.pushContainingComponent(compositeDef);
|
||||
|
||||
String tokenRepository = element.getAttribute(ATT_TOKEN_REPOSITORY);
|
||||
String dataSource = element.getAttribute(ATT_DATA_SOURCE);
|
||||
String userServiceRef = element.getAttribute(ATT_USER_SERVICE_REF);
|
||||
|
@ -84,9 +92,7 @@ class RememberMeBeanDefinitionParser implements BeanDefinitionParser {
|
|||
String remembermeParameter = element.getAttribute(ATT_FORM_REMEMBERME_PARAMETER);
|
||||
String remembermeCookie = element.getAttribute(ATT_REMEMBERME_COOKIE);
|
||||
Object source = pc.extractSource(element);
|
||||
|
||||
RootBeanDefinition services = null;
|
||||
|
||||
boolean dataSourceSet = StringUtils.hasText(dataSource);
|
||||
boolean tokenRepoSet = StringUtils.hasText(tokenRepository);
|
||||
boolean servicesRefSet = StringUtils.hasText(rememberMeServicesRef);
|
||||
|
@ -95,7 +101,6 @@ class RememberMeBeanDefinitionParser implements BeanDefinitionParser {
|
|||
boolean tokenValiditySet = StringUtils.hasText(tokenValiditySeconds);
|
||||
boolean remembermeParameterSet = StringUtils.hasText(remembermeParameter);
|
||||
boolean remembermeCookieSet = StringUtils.hasText(remembermeCookie);
|
||||
|
||||
if (servicesRefSet && (dataSourceSet || tokenRepoSet || userServiceSet || tokenValiditySet || useSecureCookieSet
|
||||
|| remembermeParameterSet || remembermeCookieSet)) {
|
||||
pc.getReaderContext()
|
||||
|
@ -104,18 +109,14 @@ class RememberMeBeanDefinitionParser implements BeanDefinitionParser {
|
|||
+ ATT_SECURE_COOKIE + ", " + ATT_FORM_REMEMBERME_PARAMETER + " or " + ATT_REMEMBERME_COOKIE,
|
||||
source);
|
||||
}
|
||||
|
||||
if (dataSourceSet && tokenRepoSet) {
|
||||
pc.getReaderContext().error("Specify " + ATT_TOKEN_REPOSITORY + " or " + ATT_DATA_SOURCE + " but not both",
|
||||
source);
|
||||
}
|
||||
|
||||
boolean isPersistent = dataSourceSet | tokenRepoSet;
|
||||
|
||||
if (isPersistent) {
|
||||
Object tokenRepo;
|
||||
services = new RootBeanDefinition(PersistentTokenBasedRememberMeServices.class);
|
||||
|
||||
if (tokenRepoSet) {
|
||||
tokenRepo = new RuntimeBeanReference(tokenRepository);
|
||||
}
|
||||
|
@ -129,24 +130,19 @@ class RememberMeBeanDefinitionParser implements BeanDefinitionParser {
|
|||
else if (!servicesRefSet) {
|
||||
services = new RootBeanDefinition(TokenBasedRememberMeServices.class);
|
||||
}
|
||||
|
||||
String servicesName;
|
||||
|
||||
if (services != null) {
|
||||
RootBeanDefinition uds = new RootBeanDefinition();
|
||||
uds.setFactoryBeanName(BeanIds.USER_DETAILS_SERVICE_FACTORY);
|
||||
uds.setFactoryMethodName("cachingUserDetailsService");
|
||||
uds.getConstructorArgumentValues().addGenericArgumentValue(userServiceRef);
|
||||
|
||||
services.getConstructorArgumentValues().addGenericArgumentValue(this.key);
|
||||
services.getConstructorArgumentValues().addGenericArgumentValue(uds);
|
||||
// tokenRepo is already added if it is a
|
||||
// PersistentTokenBasedRememberMeServices
|
||||
|
||||
if (useSecureCookieSet) {
|
||||
services.getPropertyValues().addPropertyValue("useSecureCookie", Boolean.valueOf(useSecureCookie));
|
||||
}
|
||||
|
||||
if (tokenValiditySet) {
|
||||
boolean isTokenValidityNegative = tokenValiditySeconds.startsWith("-");
|
||||
if (isTokenValidityNegative && isPersistent) {
|
||||
|
@ -155,15 +151,12 @@ class RememberMeBeanDefinitionParser implements BeanDefinitionParser {
|
|||
}
|
||||
services.getPropertyValues().addPropertyValue("tokenValiditySeconds", tokenValiditySeconds);
|
||||
}
|
||||
|
||||
if (remembermeParameterSet) {
|
||||
services.getPropertyValues().addPropertyValue("parameter", remembermeParameter);
|
||||
}
|
||||
|
||||
if (remembermeCookieSet) {
|
||||
services.getPropertyValues().addPropertyValue("cookieName", remembermeCookie);
|
||||
}
|
||||
|
||||
services.setSource(source);
|
||||
servicesName = pc.getReaderContext().generateBeanName(services);
|
||||
pc.registerBeanComponent(new BeanComponentDefinition(services, servicesName));
|
||||
|
@ -171,25 +164,18 @@ class RememberMeBeanDefinitionParser implements BeanDefinitionParser {
|
|||
else {
|
||||
servicesName = rememberMeServicesRef;
|
||||
}
|
||||
|
||||
if (StringUtils.hasText(element.getAttribute(ATT_SERVICES_ALIAS))) {
|
||||
pc.getRegistry().registerAlias(servicesName, element.getAttribute(ATT_SERVICES_ALIAS));
|
||||
}
|
||||
|
||||
this.rememberMeServicesId = servicesName;
|
||||
|
||||
BeanDefinitionBuilder filter = BeanDefinitionBuilder.rootBeanDefinition(RememberMeAuthenticationFilter.class);
|
||||
filter.getRawBeanDefinition().setSource(source);
|
||||
|
||||
if (StringUtils.hasText(successHandlerRef)) {
|
||||
filter.addPropertyReference("authenticationSuccessHandler", successHandlerRef);
|
||||
}
|
||||
|
||||
filter.addConstructorArgValue(this.authenticationManager);
|
||||
filter.addConstructorArgReference(servicesName);
|
||||
|
||||
pc.popAndRegisterContainingComponent();
|
||||
|
||||
return filter.getBeanDefinition();
|
||||
}
|
||||
|
||||
|
|
|
@ -28,15 +28,22 @@ import org.springframework.security.core.context.SecurityContext;
|
|||
*/
|
||||
public enum SessionCreationPolicy {
|
||||
|
||||
/** Always create an {@link HttpSession} */
|
||||
/**
|
||||
* Always create an {@link HttpSession}
|
||||
*/
|
||||
ALWAYS,
|
||||
|
||||
/**
|
||||
* Spring Security will never create an {@link HttpSession}, but will use the
|
||||
* {@link HttpSession} if it already exists
|
||||
*/
|
||||
NEVER,
|
||||
/** Spring Security will only create an {@link HttpSession} if required */
|
||||
|
||||
/**
|
||||
* Spring Security will only create an {@link HttpSession} if required
|
||||
*/
|
||||
IF_REQUIRED,
|
||||
|
||||
/**
|
||||
* Spring Security will never create an {@link HttpSession} and it will never use it
|
||||
* to obtain the {@link SecurityContext}
|
||||
|
|
|
@ -46,7 +46,6 @@ public class UserDetailsServiceFactoryBean implements ApplicationContextAware {
|
|||
if (!StringUtils.hasText(id)) {
|
||||
return getUserDetailsService();
|
||||
}
|
||||
|
||||
return (UserDetailsService) this.beanFactory.getBean(id);
|
||||
}
|
||||
|
||||
|
@ -56,21 +55,17 @@ public class UserDetailsServiceFactoryBean implements ApplicationContextAware {
|
|||
}
|
||||
// Overwrite with the caching version if available
|
||||
String cachingId = id + AbstractUserDetailsServiceBeanDefinitionParser.CACHING_SUFFIX;
|
||||
|
||||
if (this.beanFactory.containsBeanDefinition(cachingId)) {
|
||||
return (UserDetailsService) this.beanFactory.getBean(cachingId);
|
||||
}
|
||||
|
||||
return (UserDetailsService) this.beanFactory.getBean(id);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
AuthenticationUserDetailsService authenticationUserDetailsService(String name) {
|
||||
UserDetailsService uds;
|
||||
|
||||
if (!StringUtils.hasText(name)) {
|
||||
Map<String, ?> beans = getBeansOfType(AuthenticationUserDetailsService.class);
|
||||
|
||||
if (!beans.isEmpty()) {
|
||||
if (beans.size() > 1) {
|
||||
throw new ApplicationContextException("More than one AuthenticationUserDetailsService registered."
|
||||
|
@ -78,18 +73,15 @@ public class UserDetailsServiceFactoryBean implements ApplicationContextAware {
|
|||
}
|
||||
return (AuthenticationUserDetailsService) beans.values().toArray()[0];
|
||||
}
|
||||
|
||||
uds = getUserDetailsService();
|
||||
}
|
||||
else {
|
||||
Object bean = this.beanFactory.getBean(name);
|
||||
|
||||
if (bean instanceof AuthenticationUserDetailsService) {
|
||||
return (AuthenticationUserDetailsService) bean;
|
||||
}
|
||||
else if (bean instanceof UserDetailsService) {
|
||||
uds = cachingUserDetailsService(name);
|
||||
|
||||
if (uds == null) {
|
||||
uds = (UserDetailsService) bean;
|
||||
}
|
||||
|
@ -99,7 +91,6 @@ public class UserDetailsServiceFactoryBean implements ApplicationContextAware {
|
|||
"Bean '" + name + "' must be a UserDetailsService or an" + " AuthenticationUserDetailsService");
|
||||
}
|
||||
}
|
||||
|
||||
return new UserDetailsByNameServiceWrapper(uds);
|
||||
}
|
||||
|
||||
|
@ -110,20 +101,16 @@ public class UserDetailsServiceFactoryBean implements ApplicationContextAware {
|
|||
*/
|
||||
private UserDetailsService getUserDetailsService() {
|
||||
Map<String, ?> beans = getBeansOfType(CachingUserDetailsService.class);
|
||||
|
||||
if (beans.size() == 0) {
|
||||
beans = getBeansOfType(UserDetailsService.class);
|
||||
}
|
||||
|
||||
if (beans.size() == 0) {
|
||||
throw new ApplicationContextException("No UserDetailsService registered.");
|
||||
|
||||
}
|
||||
else if (beans.size() > 1) {
|
||||
if (beans.size() > 1) {
|
||||
throw new ApplicationContextException("More than one UserDetailsService registered. Please "
|
||||
+ "use a specific Id reference in <remember-me/> <openid-login/> or <x509 /> elements.");
|
||||
}
|
||||
|
||||
return (UserDetailsService) beans.values().toArray()[0];
|
||||
}
|
||||
|
||||
|
@ -134,7 +121,6 @@ public class UserDetailsServiceFactoryBean implements ApplicationContextAware {
|
|||
|
||||
private Map<String, ?> getBeansOfType(Class<?> type) {
|
||||
Map<String, ?> beans = this.beanFactory.getBeansOfType(type);
|
||||
|
||||
// Check ancestor bean factories if they exist and the current one has none of the
|
||||
// required type
|
||||
BeanFactory parent = this.beanFactory.getParentBeanFactory();
|
||||
|
@ -149,7 +135,6 @@ public class UserDetailsServiceFactoryBean implements ApplicationContextAware {
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return beans;
|
||||
}
|
||||
|
||||
|
|
|
@ -50,37 +50,34 @@ public class ContextSourceSettingPostProcessor implements BeanFactoryPostProcess
|
|||
|
||||
@Override
|
||||
public void postProcessBeanFactory(ConfigurableListableBeanFactory bf) throws BeansException {
|
||||
Class<?> contextSourceClass;
|
||||
|
||||
try {
|
||||
contextSourceClass = ClassUtils.forName(REQUIRED_CONTEXT_SOURCE_CLASS_NAME,
|
||||
ClassUtils.getDefaultClassLoader());
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
throw new ApplicationContextException("Couldn't locate: " + REQUIRED_CONTEXT_SOURCE_CLASS_NAME + ". "
|
||||
+ " If you are using LDAP with Spring Security, please ensure that you include the spring-ldap "
|
||||
+ "jar file in your application", ex);
|
||||
}
|
||||
|
||||
Class<?> contextSourceClass = getContextSourceClass();
|
||||
String[] sources = bf.getBeanNamesForType(contextSourceClass, false, false);
|
||||
|
||||
if (sources.length == 0) {
|
||||
throw new ApplicationContextException("No BaseLdapPathContextSource instances found. Have you "
|
||||
+ "added an <" + Elements.LDAP_SERVER + " /> element to your application context? If you have "
|
||||
+ "declared an explicit bean, do not use lazy-init");
|
||||
}
|
||||
|
||||
if (!bf.containsBean(BeanIds.CONTEXT_SOURCE) && this.defaultNameRequired) {
|
||||
if (sources.length > 1) {
|
||||
throw new ApplicationContextException("More than one BaseLdapPathContextSource instance found. "
|
||||
+ "Please specify a specific server id using the 'server-ref' attribute when configuring your <"
|
||||
+ Elements.LDAP_PROVIDER + "> " + "or <" + Elements.LDAP_USER_SERVICE + ">.");
|
||||
}
|
||||
|
||||
bf.registerAlias(sources[0], BeanIds.CONTEXT_SOURCE);
|
||||
}
|
||||
}
|
||||
|
||||
private Class<?> getContextSourceClass() throws LinkageError {
|
||||
try {
|
||||
return ClassUtils.forName(REQUIRED_CONTEXT_SOURCE_CLASS_NAME, ClassUtils.getDefaultClassLoader());
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
throw new ApplicationContextException("Couldn't locate: " + REQUIRED_CONTEXT_SOURCE_CLASS_NAME + ". "
|
||||
+ " If you are using LDAP with Spring Security, please ensure that you include the spring-ldap "
|
||||
+ "jar file in your application", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void setDefaultNameRequired(boolean defaultNameRequired) {
|
||||
this.defaultNameRequired = defaultNameRequired;
|
||||
}
|
||||
|
|
|
@ -49,19 +49,18 @@ public class LdapProviderBeanDefinitionParser implements BeanDefinitionParser {
|
|||
private static final String DEF_USER_SEARCH_FILTER = "uid={0}";
|
||||
|
||||
static final String PROVIDER_CLASS = "org.springframework.security.ldap.authentication.LdapAuthenticationProvider";
|
||||
|
||||
static final String BIND_AUTH_CLASS = "org.springframework.security.ldap.authentication.BindAuthenticator";
|
||||
|
||||
static final String PASSWD_AUTH_CLASS = "org.springframework.security.ldap.authentication.PasswordComparisonAuthenticator";
|
||||
|
||||
@Override
|
||||
public BeanDefinition parse(Element elt, ParserContext parserContext) {
|
||||
RuntimeBeanReference contextSource = LdapUserServiceBeanDefinitionParser.parseServerReference(elt,
|
||||
parserContext);
|
||||
|
||||
BeanDefinition searchBean = LdapUserServiceBeanDefinitionParser.parseSearchBean(elt, parserContext);
|
||||
String userDnPattern = elt.getAttribute(ATT_USER_DN_PATTERN);
|
||||
|
||||
String[] userDnPatternArray = new String[0];
|
||||
|
||||
if (StringUtils.hasText(userDnPattern)) {
|
||||
userDnPatternArray = new String[] { userDnPattern };
|
||||
// TODO: Validate the pattern and make sure it is a valid DN.
|
||||
|
@ -77,22 +76,17 @@ public class LdapProviderBeanDefinitionParser implements BeanDefinitionParser {
|
|||
searchBeanBuilder.addConstructorArgValue(contextSource);
|
||||
searchBean = searchBeanBuilder.getBeanDefinition();
|
||||
}
|
||||
|
||||
BeanDefinitionBuilder authenticatorBuilder = BeanDefinitionBuilder.rootBeanDefinition(BIND_AUTH_CLASS);
|
||||
Element passwordCompareElt = DomUtils.getChildElementByTagName(elt, Elements.LDAP_PASSWORD_COMPARE);
|
||||
|
||||
if (passwordCompareElt != null) {
|
||||
authenticatorBuilder = BeanDefinitionBuilder.rootBeanDefinition(PASSWD_AUTH_CLASS);
|
||||
|
||||
String passwordAttribute = passwordCompareElt.getAttribute(ATT_USER_PASSWORD);
|
||||
if (StringUtils.hasText(passwordAttribute)) {
|
||||
authenticatorBuilder.addPropertyValue("passwordAttributeName", passwordAttribute);
|
||||
}
|
||||
|
||||
Element passwordEncoderElement = DomUtils.getChildElementByTagName(passwordCompareElt,
|
||||
Elements.PASSWORD_ENCODER);
|
||||
String hash = passwordCompareElt.getAttribute(ATT_HASH);
|
||||
|
||||
if (passwordEncoderElement != null) {
|
||||
if (StringUtils.hasText(hash)) {
|
||||
parserContext.getReaderContext().warning(
|
||||
|
@ -107,21 +101,17 @@ public class LdapProviderBeanDefinitionParser implements BeanDefinitionParser {
|
|||
PasswordEncoderParser.createPasswordEncoderBeanDefinition(hash, false));
|
||||
}
|
||||
}
|
||||
|
||||
authenticatorBuilder.addConstructorArgValue(contextSource);
|
||||
authenticatorBuilder.addPropertyValue("userDnPatterns", userDnPatternArray);
|
||||
|
||||
if (searchBean != null) {
|
||||
authenticatorBuilder.addPropertyValue("userSearch", searchBean);
|
||||
}
|
||||
|
||||
BeanDefinitionBuilder ldapProvider = BeanDefinitionBuilder.rootBeanDefinition(PROVIDER_CLASS);
|
||||
ldapProvider.addConstructorArgValue(authenticatorBuilder.getBeanDefinition());
|
||||
ldapProvider.addConstructorArgValue(
|
||||
LdapUserServiceBeanDefinitionParser.parseAuthoritiesPopulator(elt, parserContext));
|
||||
ldapProvider.addPropertyValue("userDetailsContextMapper",
|
||||
LdapUserServiceBeanDefinitionParser.parseUserDetailsClassOrUserMapperRef(elt, parserContext));
|
||||
|
||||
return ldapProvider.getBeanDefinition();
|
||||
}
|
||||
|
||||
|
|
|
@ -89,9 +89,7 @@ public class LdapServerBeanDefinitionParser implements BeanDefinitionParser {
|
|||
@Override
|
||||
public BeanDefinition parse(Element elt, ParserContext parserContext) {
|
||||
String url = elt.getAttribute(ATT_URL);
|
||||
|
||||
RootBeanDefinition contextSource;
|
||||
|
||||
if (!StringUtils.hasText(url)) {
|
||||
contextSource = createEmbeddedServer(elt, parserContext);
|
||||
}
|
||||
|
@ -100,28 +98,20 @@ public class LdapServerBeanDefinitionParser implements BeanDefinitionParser {
|
|||
contextSource.setBeanClassName(CONTEXT_SOURCE_CLASS);
|
||||
contextSource.getConstructorArgumentValues().addIndexedArgumentValue(0, url);
|
||||
}
|
||||
|
||||
contextSource.setSource(parserContext.extractSource(elt));
|
||||
|
||||
String managerDn = elt.getAttribute(ATT_PRINCIPAL);
|
||||
String managerPassword = elt.getAttribute(ATT_PASSWORD);
|
||||
|
||||
if (StringUtils.hasText(managerDn)) {
|
||||
if (!StringUtils.hasText(managerPassword)) {
|
||||
parserContext.getReaderContext()
|
||||
.error("You must specify the " + ATT_PASSWORD + " if you supply a " + managerDn, elt);
|
||||
}
|
||||
|
||||
contextSource.getPropertyValues().addPropertyValue("userDn", managerDn);
|
||||
contextSource.getPropertyValues().addPropertyValue("password", managerPassword);
|
||||
}
|
||||
|
||||
String id = elt.getAttribute(AbstractBeanDefinitionParser.ID_ATTRIBUTE);
|
||||
|
||||
String contextSourceId = StringUtils.hasText(id) ? id : BeanIds.CONTEXT_SOURCE;
|
||||
|
||||
parserContext.getRegistry().registerBeanDefinition(contextSourceId, contextSource);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -136,52 +126,40 @@ public class LdapServerBeanDefinitionParser implements BeanDefinitionParser {
|
|||
*/
|
||||
private RootBeanDefinition createEmbeddedServer(Element element, ParserContext parserContext) {
|
||||
Object source = parserContext.extractSource(element);
|
||||
|
||||
String suffix = element.getAttribute(ATT_ROOT_SUFFIX);
|
||||
|
||||
if (!StringUtils.hasText(suffix)) {
|
||||
suffix = OPT_DEFAULT_ROOT_SUFFIX;
|
||||
}
|
||||
|
||||
BeanDefinitionBuilder contextSource = BeanDefinitionBuilder.rootBeanDefinition(CONTEXT_SOURCE_CLASS);
|
||||
contextSource.addConstructorArgValue(suffix);
|
||||
contextSource.addPropertyValue("userDn", "uid=admin,ou=system");
|
||||
contextSource.addPropertyValue("password", "secret");
|
||||
|
||||
BeanDefinition embeddedLdapServerConfigBean = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(EmbeddedLdapServerConfigBean.class).getBeanDefinition();
|
||||
String embeddedLdapServerConfigBeanName = parserContext.getReaderContext()
|
||||
.generateBeanName(embeddedLdapServerConfigBean);
|
||||
|
||||
parserContext.registerBeanComponent(
|
||||
new BeanComponentDefinition(embeddedLdapServerConfigBean, embeddedLdapServerConfigBeanName));
|
||||
|
||||
contextSource.setFactoryMethodOnBean("createEmbeddedContextSource", embeddedLdapServerConfigBeanName);
|
||||
|
||||
String mode = element.getAttribute("mode");
|
||||
RootBeanDefinition ldapContainer = getRootBeanDefinition(mode);
|
||||
ldapContainer.setSource(source);
|
||||
ldapContainer.getConstructorArgumentValues().addGenericArgumentValue(suffix);
|
||||
|
||||
String ldifs = element.getAttribute(ATT_LDIF_FILE);
|
||||
if (!StringUtils.hasText(ldifs)) {
|
||||
ldifs = OPT_DEFAULT_LDIF_FILE;
|
||||
}
|
||||
|
||||
ldapContainer.getConstructorArgumentValues().addGenericArgumentValue(ldifs);
|
||||
ldapContainer.getPropertyValues().addPropertyValue("port", getPort(element));
|
||||
|
||||
if (parserContext.getRegistry().containsBeanDefinition(BeanIds.EMBEDDED_APACHE_DS)
|
||||
|| parserContext.getRegistry().containsBeanDefinition(BeanIds.EMBEDDED_UNBOUNDID)) {
|
||||
parserContext.getReaderContext().error("Only one embedded server bean is allowed per application context",
|
||||
element);
|
||||
}
|
||||
|
||||
String beanId = resolveBeanId(mode);
|
||||
if (beanId != null) {
|
||||
parserContext.getRegistry().registerBeanDefinition(beanId, ldapContainer);
|
||||
}
|
||||
|
||||
return (RootBeanDefinition) contextSource.getBeanDefinition();
|
||||
}
|
||||
|
||||
|
@ -189,7 +167,7 @@ public class LdapServerBeanDefinitionParser implements BeanDefinitionParser {
|
|||
if (isApacheDsEnabled(mode)) {
|
||||
return new RootBeanDefinition(APACHEDS_CONTAINER_CLASSNAME, null, null);
|
||||
}
|
||||
else if (isUnboundidEnabled(mode)) {
|
||||
if (isUnboundidEnabled(mode)) {
|
||||
return new RootBeanDefinition(UNBOUNDID_CONTAINER_CLASSNAME, null, null);
|
||||
}
|
||||
throw new IllegalStateException("Embedded LDAP server is not provided");
|
||||
|
@ -199,7 +177,7 @@ public class LdapServerBeanDefinitionParser implements BeanDefinitionParser {
|
|||
if (isApacheDsEnabled(mode)) {
|
||||
return BeanIds.EMBEDDED_APACHE_DS;
|
||||
}
|
||||
else if (isUnboundidEnabled(mode)) {
|
||||
if (isUnboundidEnabled(mode)) {
|
||||
return BeanIds.EMBEDDED_UNBOUNDID;
|
||||
}
|
||||
return null;
|
||||
|
@ -238,22 +216,21 @@ public class LdapServerBeanDefinitionParser implements BeanDefinitionParser {
|
|||
|
||||
@SuppressWarnings("unused")
|
||||
private DefaultSpringSecurityContextSource createEmbeddedContextSource(String suffix) {
|
||||
int port;
|
||||
int port = getPort();
|
||||
String providerUrl = "ldap://127.0.0.1:" + port + "/" + suffix;
|
||||
return new DefaultSpringSecurityContextSource(providerUrl);
|
||||
}
|
||||
|
||||
private int getPort() {
|
||||
if (ClassUtils.isPresent(APACHEDS_CLASSNAME, getClass().getClassLoader())) {
|
||||
ApacheDSContainer apacheDSContainer = this.applicationContext.getBean(ApacheDSContainer.class);
|
||||
port = apacheDSContainer.getLocalPort();
|
||||
return apacheDSContainer.getLocalPort();
|
||||
}
|
||||
else if (ClassUtils.isPresent(UNBOUNID_CLASSNAME, getClass().getClassLoader())) {
|
||||
if (ClassUtils.isPresent(UNBOUNID_CLASSNAME, getClass().getClassLoader())) {
|
||||
UnboundIdContainer unboundIdContainer = this.applicationContext.getBean(UnboundIdContainer.class);
|
||||
port = unboundIdContainer.getPort();
|
||||
return unboundIdContainer.getPort();
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException("Embedded LDAP server is not provided");
|
||||
}
|
||||
|
||||
String providerUrl = "ldap://127.0.0.1:" + port + "/" + suffix;
|
||||
|
||||
return new DefaultSpringSecurityContextSource(providerUrl);
|
||||
throw new IllegalStateException("Embedded LDAP server is not provided");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -54,9 +54,13 @@ public class LdapUserServiceBeanDefinitionParser extends AbstractUserDetailsServ
|
|||
public static final String DEF_GROUP_SEARCH_BASE = "";
|
||||
|
||||
static final String ATT_ROLE_PREFIX = "role-prefix";
|
||||
|
||||
static final String ATT_USER_CLASS = "user-details-class";
|
||||
|
||||
static final String ATT_USER_CONTEXT_MAPPER_REF = "user-context-mapper-ref";
|
||||
|
||||
static final String OPT_PERSON = "person";
|
||||
|
||||
static final String OPT_INETORGPERSON = "inetOrgPerson";
|
||||
|
||||
public static final String LDAP_SEARCH_CLASS = "org.springframework.security.ldap.search.FilterBasedLdapUserSearch";
|
||||
|
@ -76,11 +80,9 @@ public class LdapUserServiceBeanDefinitionParser extends AbstractUserDetailsServ
|
|||
|
||||
@Override
|
||||
protected void doParse(Element elt, ParserContext parserContext, BeanDefinitionBuilder builder) {
|
||||
|
||||
if (!StringUtils.hasText(elt.getAttribute(ATT_USER_SEARCH_FILTER))) {
|
||||
parserContext.getReaderContext().error("User search filter must be supplied", elt);
|
||||
}
|
||||
|
||||
builder.addConstructorArgValue(parseSearchBean(elt, parserContext));
|
||||
builder.getRawBeanDefinition().setSource(parserContext.extractSource(elt));
|
||||
builder.addConstructorArgValue(parseAuthoritiesPopulator(elt, parserContext));
|
||||
|
@ -91,7 +93,6 @@ public class LdapUserServiceBeanDefinitionParser extends AbstractUserDetailsServ
|
|||
String userSearchFilter = elt.getAttribute(ATT_USER_SEARCH_FILTER);
|
||||
String userSearchBase = elt.getAttribute(ATT_USER_SEARCH_BASE);
|
||||
Object source = parserContext.extractSource(elt);
|
||||
|
||||
if (StringUtils.hasText(userSearchBase)) {
|
||||
if (!StringUtils.hasText(userSearchFilter)) {
|
||||
parserContext.getReaderContext()
|
||||
|
@ -101,33 +102,27 @@ public class LdapUserServiceBeanDefinitionParser extends AbstractUserDetailsServ
|
|||
else {
|
||||
userSearchBase = DEF_USER_SEARCH_BASE;
|
||||
}
|
||||
|
||||
if (!StringUtils.hasText(userSearchFilter)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
BeanDefinitionBuilder searchBuilder = BeanDefinitionBuilder.rootBeanDefinition(LDAP_SEARCH_CLASS);
|
||||
searchBuilder.getRawBeanDefinition().setSource(source);
|
||||
searchBuilder.addConstructorArgValue(userSearchBase);
|
||||
searchBuilder.addConstructorArgValue(userSearchFilter);
|
||||
searchBuilder.addConstructorArgValue(parseServerReference(elt, parserContext));
|
||||
|
||||
return (RootBeanDefinition) searchBuilder.getBeanDefinition();
|
||||
}
|
||||
|
||||
static RuntimeBeanReference parseServerReference(Element elt, ParserContext parserContext) {
|
||||
String server = elt.getAttribute(ATT_SERVER);
|
||||
boolean requiresDefaultName = false;
|
||||
|
||||
if (!StringUtils.hasText(server)) {
|
||||
server = BeanIds.CONTEXT_SOURCE;
|
||||
requiresDefaultName = true;
|
||||
}
|
||||
|
||||
RuntimeBeanReference contextSource = new RuntimeBeanReference(server);
|
||||
contextSource.setSource(parserContext.extractSource(elt));
|
||||
registerPostProcessorIfNecessary(parserContext.getRegistry(), requiresDefaultName);
|
||||
|
||||
return contextSource;
|
||||
}
|
||||
|
||||
|
@ -139,7 +134,6 @@ public class LdapUserServiceBeanDefinitionParser extends AbstractUserDetailsServ
|
|||
}
|
||||
return;
|
||||
}
|
||||
|
||||
BeanDefinitionBuilder bdb = BeanDefinitionBuilder.rootBeanDefinition(ContextSourceSettingPostProcessor.class);
|
||||
bdb.addPropertyValue("defaultNameRequired", defaultNameRequired);
|
||||
registry.registerBeanDefinition(BeanIds.CONTEXT_SOURCE_SETTING_POST_PROCESSOR, bdb.getBeanDefinition());
|
||||
|
@ -148,65 +142,54 @@ public class LdapUserServiceBeanDefinitionParser extends AbstractUserDetailsServ
|
|||
static BeanMetadataElement parseUserDetailsClassOrUserMapperRef(Element elt, ParserContext parserContext) {
|
||||
String userDetailsClass = elt.getAttribute(ATT_USER_CLASS);
|
||||
String userMapperRef = elt.getAttribute(ATT_USER_CONTEXT_MAPPER_REF);
|
||||
|
||||
if (StringUtils.hasText(userDetailsClass) && StringUtils.hasText(userMapperRef)) {
|
||||
parserContext.getReaderContext().error("Attributes " + ATT_USER_CLASS + " and "
|
||||
+ ATT_USER_CONTEXT_MAPPER_REF + " cannot be used together.", parserContext.extractSource(elt));
|
||||
}
|
||||
|
||||
if (StringUtils.hasText(userMapperRef)) {
|
||||
return new RuntimeBeanReference(userMapperRef);
|
||||
}
|
||||
|
||||
RootBeanDefinition mapper;
|
||||
|
||||
if (OPT_PERSON.equals(userDetailsClass)) {
|
||||
mapper = new RootBeanDefinition(PERSON_MAPPER_CLASS, null, null);
|
||||
}
|
||||
else if (OPT_INETORGPERSON.equals(userDetailsClass)) {
|
||||
mapper = new RootBeanDefinition(INET_ORG_PERSON_MAPPER_CLASS, null, null);
|
||||
}
|
||||
else {
|
||||
mapper = new RootBeanDefinition(LDAP_USER_MAPPER_CLASS, null, null);
|
||||
}
|
||||
|
||||
RootBeanDefinition mapper = getMapper(userDetailsClass);
|
||||
mapper.setSource(parserContext.extractSource(elt));
|
||||
|
||||
return mapper;
|
||||
}
|
||||
|
||||
private static RootBeanDefinition getMapper(String userDetailsClass) {
|
||||
if (OPT_PERSON.equals(userDetailsClass)) {
|
||||
return new RootBeanDefinition(PERSON_MAPPER_CLASS, null, null);
|
||||
}
|
||||
if (OPT_INETORGPERSON.equals(userDetailsClass)) {
|
||||
return new RootBeanDefinition(INET_ORG_PERSON_MAPPER_CLASS, null, null);
|
||||
}
|
||||
return new RootBeanDefinition(LDAP_USER_MAPPER_CLASS, null, null);
|
||||
}
|
||||
|
||||
static RootBeanDefinition parseAuthoritiesPopulator(Element elt, ParserContext parserContext) {
|
||||
String groupSearchFilter = elt.getAttribute(ATT_GROUP_SEARCH_FILTER);
|
||||
String groupSearchBase = elt.getAttribute(ATT_GROUP_SEARCH_BASE);
|
||||
String groupRoleAttribute = elt.getAttribute(ATT_GROUP_ROLE_ATTRIBUTE);
|
||||
String rolePrefix = elt.getAttribute(ATT_ROLE_PREFIX);
|
||||
|
||||
if (!StringUtils.hasText(groupSearchFilter)) {
|
||||
groupSearchFilter = DEF_GROUP_SEARCH_FILTER;
|
||||
}
|
||||
|
||||
if (!StringUtils.hasText(groupSearchBase)) {
|
||||
groupSearchBase = DEF_GROUP_SEARCH_BASE;
|
||||
}
|
||||
|
||||
BeanDefinitionBuilder populator = BeanDefinitionBuilder.rootBeanDefinition(LDAP_AUTHORITIES_POPULATOR_CLASS);
|
||||
populator.getRawBeanDefinition().setSource(parserContext.extractSource(elt));
|
||||
populator.addConstructorArgValue(parseServerReference(elt, parserContext));
|
||||
populator.addConstructorArgValue(groupSearchBase);
|
||||
populator.addPropertyValue("groupSearchFilter", groupSearchFilter);
|
||||
populator.addPropertyValue("searchSubtree", Boolean.TRUE);
|
||||
|
||||
if (StringUtils.hasText(rolePrefix)) {
|
||||
if ("none".equals(rolePrefix)) {
|
||||
rolePrefix = "";
|
||||
}
|
||||
populator.addPropertyValue("rolePrefix", rolePrefix);
|
||||
}
|
||||
|
||||
if (StringUtils.hasLength(groupRoleAttribute)) {
|
||||
populator.addPropertyValue("groupRoleAttribute", groupRoleAttribute);
|
||||
}
|
||||
|
||||
return (RootBeanDefinition) populator.getBeanDefinition();
|
||||
}
|
||||
|
||||
|
|
|
@ -48,6 +48,7 @@ import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
|||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.core.log.LogMessage;
|
||||
import org.springframework.security.access.ConfigAttribute;
|
||||
import org.springframework.security.access.SecurityConfig;
|
||||
import org.springframework.security.access.annotation.Jsr250MethodSecurityMetadataSource;
|
||||
|
@ -122,36 +123,28 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP
|
|||
CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(),
|
||||
pc.extractSource(element));
|
||||
pc.pushContainingComponent(compositeDef);
|
||||
|
||||
Object source = pc.extractSource(element);
|
||||
// The list of method metadata delegates
|
||||
ManagedList<BeanMetadataElement> delegates = new ManagedList<>();
|
||||
|
||||
boolean jsr250Enabled = "enabled".equals(element.getAttribute(ATT_USE_JSR250));
|
||||
boolean useSecured = "enabled".equals(element.getAttribute(ATT_USE_SECURED));
|
||||
boolean prePostAnnotationsEnabled = "enabled".equals(element.getAttribute(ATT_USE_PREPOST));
|
||||
boolean useAspectJ = "aspectj".equals(element.getAttribute(ATT_MODE));
|
||||
|
||||
BeanDefinition preInvocationVoter = null;
|
||||
ManagedList<BeanMetadataElement> afterInvocationProviders = new ManagedList<>();
|
||||
|
||||
// Check for an external SecurityMetadataSource, which takes priority over other
|
||||
// sources
|
||||
String metaDataSourceId = element.getAttribute(ATT_META_DATA_SOURCE_REF);
|
||||
|
||||
if (StringUtils.hasText(metaDataSourceId)) {
|
||||
delegates.add(new RuntimeBeanReference(metaDataSourceId));
|
||||
}
|
||||
|
||||
if (prePostAnnotationsEnabled) {
|
||||
Element prePostElt = DomUtils.getChildElementByTagName(element, Elements.INVOCATION_HANDLING);
|
||||
Element expressionHandlerElt = DomUtils.getChildElementByTagName(element, Elements.EXPRESSION_HANDLER);
|
||||
|
||||
if (prePostElt != null && expressionHandlerElt != null) {
|
||||
pc.getReaderContext().error(Elements.INVOCATION_HANDLING + " and " + Elements.EXPRESSION_HANDLER
|
||||
+ " cannot be used together ", source);
|
||||
}
|
||||
|
||||
BeanDefinitionBuilder preInvocationVoterBldr = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(PreInvocationAuthorizationAdviceVoter.class);
|
||||
// After-invocation provider to handle post-invocation filtering and
|
||||
|
@ -161,7 +154,6 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP
|
|||
// The metadata source for the security interceptor
|
||||
BeanDefinitionBuilder mds = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(PrePostAnnotationSecurityMetadataSource.class);
|
||||
|
||||
if (prePostElt != null) {
|
||||
// Customized override of expression handling system
|
||||
String attributeFactoryRef = DomUtils
|
||||
|
@ -171,7 +163,6 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP
|
|||
.getAttribute("ref");
|
||||
String postAdviceRef = DomUtils.getChildElementByTagName(prePostElt, Elements.POST_INVOCATION_ADVICE)
|
||||
.getAttribute("ref");
|
||||
|
||||
mds.addConstructorArgReference(attributeFactoryRef);
|
||||
preInvocationVoterBldr.addConstructorArgReference(preAdviceRef);
|
||||
afterInvocationBldr.addConstructorArgReference(postAdviceRef);
|
||||
|
@ -180,80 +171,65 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP
|
|||
// The default expression-based system
|
||||
String expressionHandlerRef = (expressionHandlerElt != null) ? expressionHandlerElt.getAttribute("ref")
|
||||
: null;
|
||||
|
||||
if (StringUtils.hasText(expressionHandlerRef)) {
|
||||
this.logger.info(
|
||||
"Using bean '" + expressionHandlerRef + "' as method ExpressionHandler implementation");
|
||||
this.logger.info(LogMessage.format("Using bean '%s' as method ExpressionHandler implementation",
|
||||
expressionHandlerRef));
|
||||
RootBeanDefinition lazyInitPP = new RootBeanDefinition(
|
||||
LazyInitBeanDefinitionRegistryPostProcessor.class);
|
||||
lazyInitPP.getConstructorArgumentValues().addGenericArgumentValue(expressionHandlerRef);
|
||||
pc.getReaderContext().registerWithGeneratedName(lazyInitPP);
|
||||
|
||||
BeanDefinitionBuilder lazyMethodSecurityExpressionHandlerBldr = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(LazyInitTargetSource.class);
|
||||
lazyMethodSecurityExpressionHandlerBldr.addPropertyValue("targetBeanName", expressionHandlerRef);
|
||||
|
||||
BeanDefinitionBuilder expressionHandlerProxyBldr = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(ProxyFactoryBean.class);
|
||||
expressionHandlerProxyBldr.addPropertyValue("targetSource",
|
||||
lazyMethodSecurityExpressionHandlerBldr.getBeanDefinition());
|
||||
expressionHandlerProxyBldr.addPropertyValue("proxyInterfaces",
|
||||
MethodSecurityExpressionHandler.class);
|
||||
|
||||
expressionHandlerRef = pc.getReaderContext()
|
||||
.generateBeanName(expressionHandlerProxyBldr.getBeanDefinition());
|
||||
|
||||
pc.registerBeanComponent(new BeanComponentDefinition(expressionHandlerProxyBldr.getBeanDefinition(),
|
||||
expressionHandlerRef));
|
||||
}
|
||||
else {
|
||||
RootBeanDefinition expressionHandler = registerWithDefaultRolePrefix(pc,
|
||||
DefaultMethodSecurityExpressionHandlerBeanFactory.class);
|
||||
|
||||
expressionHandlerRef = pc.getReaderContext().generateBeanName(expressionHandler);
|
||||
pc.registerBeanComponent(new BeanComponentDefinition(expressionHandler, expressionHandlerRef));
|
||||
this.logger.info(
|
||||
"Expressions were enabled for method security but no SecurityExpressionHandler was configured. "
|
||||
+ "All hasPermission() expressions will evaluate to false.");
|
||||
this.logger.info("Expressions were enabled for method security but no SecurityExpressionHandler "
|
||||
+ "was configured. All hasPermission() expressions will evaluate to false.");
|
||||
}
|
||||
|
||||
BeanDefinitionBuilder expressionPreAdviceBldr = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(ExpressionBasedPreInvocationAdvice.class);
|
||||
expressionPreAdviceBldr.addPropertyReference("expressionHandler", expressionHandlerRef);
|
||||
preInvocationVoterBldr.addConstructorArgValue(expressionPreAdviceBldr.getBeanDefinition());
|
||||
|
||||
BeanDefinitionBuilder expressionPostAdviceBldr = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(ExpressionBasedPostInvocationAdvice.class);
|
||||
expressionPostAdviceBldr.addConstructorArgReference(expressionHandlerRef);
|
||||
afterInvocationBldr.addConstructorArgValue(expressionPostAdviceBldr.getBeanDefinition());
|
||||
|
||||
BeanDefinitionBuilder annotationInvocationFactory = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(ExpressionBasedAnnotationAttributeFactory.class);
|
||||
annotationInvocationFactory.addConstructorArgReference(expressionHandlerRef);
|
||||
mds.addConstructorArgValue(annotationInvocationFactory.getBeanDefinition());
|
||||
}
|
||||
|
||||
preInvocationVoter = preInvocationVoterBldr.getBeanDefinition();
|
||||
afterInvocationProviders.add(afterInvocationBldr.getBeanDefinition());
|
||||
delegates.add(mds.getBeanDefinition());
|
||||
}
|
||||
|
||||
if (useSecured) {
|
||||
delegates.add(BeanDefinitionBuilder.rootBeanDefinition(SecuredAnnotationSecurityMetadataSource.class)
|
||||
.getBeanDefinition());
|
||||
}
|
||||
|
||||
if (jsr250Enabled) {
|
||||
RootBeanDefinition jsrMetadataSource = registerWithDefaultRolePrefix(pc,
|
||||
Jsr250MethodSecurityMetadataSourceBeanFactory.class);
|
||||
delegates.add(jsrMetadataSource);
|
||||
}
|
||||
|
||||
// Now create a Map<String, ConfigAttribute> for each <protect-pointcut>
|
||||
// sub-element
|
||||
Map<String, List<ConfigAttribute>> pointcutMap = parseProtectPointcuts(pc,
|
||||
DomUtils.getChildElementsByTagName(element, Elements.PROTECT_POINTCUT));
|
||||
|
||||
if (pointcutMap.size() > 0) {
|
||||
if (useAspectJ) {
|
||||
pc.getReaderContext().error("You can't use AspectJ mode with protect-pointcut definitions", source);
|
||||
|
@ -262,34 +238,25 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP
|
|||
BeanDefinition mapBasedMetadataSource = new RootBeanDefinition(MapBasedMethodSecurityMetadataSource.class);
|
||||
BeanReference ref = new RuntimeBeanReference(
|
||||
pc.getReaderContext().generateBeanName(mapBasedMetadataSource));
|
||||
|
||||
delegates.add(ref);
|
||||
pc.registerBeanComponent(new BeanComponentDefinition(mapBasedMetadataSource, ref.getBeanName()));
|
||||
registerProtectPointcutPostProcessor(pc, pointcutMap, ref, source);
|
||||
}
|
||||
|
||||
BeanReference metadataSource = registerDelegatingMethodSecurityMetadataSource(pc, delegates, source);
|
||||
|
||||
// Check for additional after-invocation-providers..
|
||||
List<Element> afterInvocationElts = DomUtils.getChildElementsByTagName(element,
|
||||
Elements.AFTER_INVOCATION_PROVIDER);
|
||||
|
||||
for (Element elt : afterInvocationElts) {
|
||||
afterInvocationProviders.add(new RuntimeBeanReference(elt.getAttribute(ATT_REF)));
|
||||
}
|
||||
|
||||
String accessManagerId = element.getAttribute(ATT_ACCESS_MGR);
|
||||
|
||||
if (!StringUtils.hasText(accessManagerId)) {
|
||||
accessManagerId = registerAccessManager(pc, jsr250Enabled, preInvocationVoter);
|
||||
}
|
||||
|
||||
String authMgrRef = element.getAttribute(ATT_AUTHENTICATION_MANAGER_REF);
|
||||
|
||||
String runAsManagerId = element.getAttribute(ATT_RUN_AS_MGR);
|
||||
BeanReference interceptor = registerMethodSecurityInterceptor(pc, authMgrRef, accessManagerId, runAsManagerId,
|
||||
metadataSource, afterInvocationProviders, source, useAspectJ);
|
||||
|
||||
if (useAspectJ) {
|
||||
BeanDefinitionBuilder aspect = BeanDefinitionBuilder.rootBeanDefinition(
|
||||
"org.springframework.security.access.intercept.aspectj.aspect.AnnotationSecurityAspect");
|
||||
|
@ -303,9 +270,7 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP
|
|||
registerAdvisor(pc, interceptor, metadataSource, source, element.getAttribute(ATT_ADVICE_ORDER));
|
||||
AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(pc, element);
|
||||
}
|
||||
|
||||
pc.popAndRegisterContainingComponent();
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -316,26 +281,20 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP
|
|||
*/
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
private String registerAccessManager(ParserContext pc, boolean jsr250Enabled, BeanDefinition expressionVoter) {
|
||||
|
||||
BeanDefinitionBuilder accessMgrBuilder = BeanDefinitionBuilder.rootBeanDefinition(AffirmativeBased.class);
|
||||
ManagedList voters = new ManagedList(4);
|
||||
|
||||
if (expressionVoter != null) {
|
||||
voters.add(expressionVoter);
|
||||
}
|
||||
voters.add(new RootBeanDefinition(RoleVoter.class));
|
||||
voters.add(new RootBeanDefinition(AuthenticatedVoter.class));
|
||||
|
||||
if (jsr250Enabled) {
|
||||
voters.add(new RootBeanDefinition(Jsr250Voter.class));
|
||||
}
|
||||
|
||||
accessMgrBuilder.addConstructorArgValue(voters);
|
||||
|
||||
BeanDefinition accessManager = accessMgrBuilder.getBeanDefinition();
|
||||
String id = pc.getReaderContext().generateBeanName(accessManager);
|
||||
pc.registerBeanComponent(new BeanComponentDefinition(accessManager, id));
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
|
@ -346,7 +305,6 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP
|
|||
DelegatingMethodSecurityMetadataSource.class);
|
||||
delegatingMethodSecurityMetadataSource.setSource(source);
|
||||
delegatingMethodSecurityMetadataSource.getConstructorArgumentValues().addGenericArgumentValue(delegates);
|
||||
|
||||
String id = pc.getReaderContext().generateBeanName(delegatingMethodSecurityMetadataSource);
|
||||
pc.registerBeanComponent(new BeanComponentDefinition(delegatingMethodSecurityMetadataSource, id));
|
||||
|
||||
|
@ -367,31 +325,24 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP
|
|||
private Map<String, List<ConfigAttribute>> parseProtectPointcuts(ParserContext parserContext,
|
||||
List<Element> protectPointcutElts) {
|
||||
Map<String, List<ConfigAttribute>> pointcutMap = new LinkedHashMap<>();
|
||||
|
||||
for (Element childElt : protectPointcutElts) {
|
||||
String accessConfig = childElt.getAttribute(ATT_ACCESS);
|
||||
String expression = childElt.getAttribute(ATT_EXPRESSION);
|
||||
|
||||
if (!StringUtils.hasText(accessConfig)) {
|
||||
parserContext.getReaderContext().error("Access configuration required",
|
||||
parserContext.extractSource(childElt));
|
||||
}
|
||||
|
||||
if (!StringUtils.hasText(expression)) {
|
||||
parserContext.getReaderContext().error("Pointcut expression required",
|
||||
parserContext.extractSource(childElt));
|
||||
}
|
||||
|
||||
String[] attributeTokens = StringUtils.commaDelimitedListToStringArray(accessConfig);
|
||||
List<ConfigAttribute> attributes = new ArrayList<>(attributeTokens.length);
|
||||
|
||||
for (String token : attributeTokens) {
|
||||
attributes.add(new SecurityConfig(token));
|
||||
}
|
||||
|
||||
pointcutMap.put(expression, attributes);
|
||||
}
|
||||
|
||||
return pointcutMap;
|
||||
}
|
||||
|
||||
|
@ -406,22 +357,18 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP
|
|||
authMgr.getConstructorArgumentValues().addGenericArgumentValue(authMgrRef);
|
||||
bldr.addPropertyValue("authenticationManager", authMgr);
|
||||
bldr.addPropertyValue("securityMetadataSource", metadataSource);
|
||||
|
||||
if (StringUtils.hasText(runAsManagerId)) {
|
||||
bldr.addPropertyReference("runAsManager", runAsManagerId);
|
||||
}
|
||||
|
||||
if (!afterInvocationProviders.isEmpty()) {
|
||||
BeanDefinition afterInvocationManager;
|
||||
afterInvocationManager = new RootBeanDefinition(AfterInvocationProviderManager.class);
|
||||
afterInvocationManager.getPropertyValues().addPropertyValue("providers", afterInvocationProviders);
|
||||
bldr.addPropertyValue("afterInvocationManager", afterInvocationManager);
|
||||
}
|
||||
|
||||
BeanDefinition bean = bldr.getBeanDefinition();
|
||||
String id = pc.getReaderContext().generateBeanName(bean);
|
||||
pc.registerBeanComponent(new BeanComponentDefinition(bean, id));
|
||||
|
||||
return new RuntimeBeanReference(id);
|
||||
}
|
||||
|
||||
|
@ -431,11 +378,9 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP
|
|||
parserContext.getReaderContext().error("Duplicate <global-method-security> detected.", source);
|
||||
}
|
||||
RootBeanDefinition advisor = new RootBeanDefinition(MethodSecurityMetadataSourceAdvisor.class);
|
||||
|
||||
if (StringUtils.hasText(adviceOrder)) {
|
||||
advisor.getPropertyValues().addPropertyValue("order", adviceOrder);
|
||||
}
|
||||
|
||||
// advisor must be an infrastructure bean as Spring's
|
||||
// InfrastructureAdvisorAutoProxyCreator will ignore it
|
||||
// otherwise
|
||||
|
@ -444,7 +389,6 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP
|
|||
advisor.getConstructorArgumentValues().addGenericArgumentValue(interceptor.getBeanName());
|
||||
advisor.getConstructorArgumentValues().addGenericArgumentValue(metadataSource);
|
||||
advisor.getConstructorArgumentValues().addGenericArgumentValue(metadataSource.getBeanName());
|
||||
|
||||
parserContext.getRegistry().registerBeanDefinition(BeanIds.METHOD_SECURITY_METADATA_SOURCE_ADVISOR, advisor);
|
||||
}
|
||||
|
||||
|
@ -453,7 +397,6 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP
|
|||
RootBeanDefinition beanFactoryDefinition = new RootBeanDefinition(beanFactoryClass);
|
||||
String beanFactoryRef = pc.getReaderContext().generateBeanName(beanFactoryDefinition);
|
||||
pc.getRegistry().registerBeanDefinition(beanFactoryRef, beanFactoryDefinition);
|
||||
|
||||
RootBeanDefinition bean = new RootBeanDefinition();
|
||||
bean.setFactoryBeanName(beanFactoryRef);
|
||||
bean.setFactoryMethodName("getBean");
|
||||
|
@ -499,7 +442,6 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
return this.delegate.authenticate(authentication);
|
||||
}
|
||||
|
||||
|
|
|
@ -52,7 +52,6 @@ public class InterceptMethodsBeanDefinitionDecorator implements BeanDefinitionDe
|
|||
@Override
|
||||
public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder definition, ParserContext parserContext) {
|
||||
MethodConfigUtils.registerDefaultMethodAccessManagerIfNecessary(parserContext);
|
||||
|
||||
return this.delegate.decorate(node, definition, parserContext);
|
||||
}
|
||||
|
||||
|
@ -64,6 +63,7 @@ public class InterceptMethodsBeanDefinitionDecorator implements BeanDefinitionDe
|
|||
extends AbstractInterceptorDrivenBeanDefinitionDecorator {
|
||||
|
||||
static final String ATT_METHOD = "method";
|
||||
|
||||
static final String ATT_ACCESS = "access";
|
||||
|
||||
private static final String ATT_ACCESS_MGR = "access-decision-manager-ref";
|
||||
|
@ -73,49 +73,36 @@ public class InterceptMethodsBeanDefinitionDecorator implements BeanDefinitionDe
|
|||
Element interceptMethodsElt = (Element) node;
|
||||
BeanDefinitionBuilder interceptor = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(MethodSecurityInterceptor.class);
|
||||
|
||||
// Default to autowiring to pick up after invocation mgr
|
||||
interceptor.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
|
||||
|
||||
String accessManagerId = interceptMethodsElt.getAttribute(ATT_ACCESS_MGR);
|
||||
|
||||
if (!StringUtils.hasText(accessManagerId)) {
|
||||
accessManagerId = BeanIds.METHOD_ACCESS_MANAGER;
|
||||
}
|
||||
|
||||
interceptor.addPropertyValue("accessDecisionManager", new RuntimeBeanReference(accessManagerId));
|
||||
interceptor.addPropertyValue("authenticationManager",
|
||||
new RuntimeBeanReference(BeanIds.AUTHENTICATION_MANAGER));
|
||||
|
||||
// Lookup parent bean information
|
||||
|
||||
String parentBeanClass = ((Element) node.getParentNode()).getAttribute("class");
|
||||
|
||||
// Parse the included methods
|
||||
List<Element> methods = DomUtils.getChildElementsByTagName(interceptMethodsElt, Elements.PROTECT);
|
||||
Map<String, BeanDefinition> mappings = new ManagedMap<>();
|
||||
|
||||
for (Element protectmethodElt : methods) {
|
||||
BeanDefinitionBuilder attributeBuilder = BeanDefinitionBuilder.rootBeanDefinition(SecurityConfig.class);
|
||||
attributeBuilder.setFactoryMethod("createListFromCommaDelimitedString");
|
||||
attributeBuilder.addConstructorArgValue(protectmethodElt.getAttribute(ATT_ACCESS));
|
||||
|
||||
// Support inference of class names
|
||||
String methodName = protectmethodElt.getAttribute(ATT_METHOD);
|
||||
|
||||
if (methodName.lastIndexOf(".") == -1) {
|
||||
if (parentBeanClass != null && !"".equals(parentBeanClass)) {
|
||||
methodName = parentBeanClass + "." + methodName;
|
||||
}
|
||||
}
|
||||
|
||||
mappings.put(methodName, attributeBuilder.getBeanDefinition());
|
||||
}
|
||||
|
||||
BeanDefinition metadataSource = new RootBeanDefinition(MapBasedMethodSecurityMetadataSource.class);
|
||||
metadataSource.getConstructorArgumentValues().addGenericArgumentValue(mappings);
|
||||
interceptor.addPropertyValue("securityMetadataSource", metadataSource);
|
||||
|
||||
return interceptor.getBeanDefinition();
|
||||
}
|
||||
|
||||
|
|
|
@ -46,11 +46,9 @@ abstract class MethodConfigUtils {
|
|||
@SuppressWarnings("unchecked")
|
||||
private static RootBeanDefinition createAccessManagerBean(Class<? extends AccessDecisionVoter>... voters) {
|
||||
ManagedList defaultVoters = new ManagedList(voters.length);
|
||||
|
||||
for (Class<? extends AccessDecisionVoter> voter : voters) {
|
||||
defaultVoters.add(new RootBeanDefinition(voter));
|
||||
}
|
||||
|
||||
BeanDefinitionBuilder accessMgrBuilder = BeanDefinitionBuilder.rootBeanDefinition(AffirmativeBased.class);
|
||||
accessMgrBuilder.addConstructorArgValue(defaultVoters);
|
||||
return (RootBeanDefinition) accessMgrBuilder.getBeanDefinition();
|
||||
|
|
|
@ -40,6 +40,7 @@ import org.springframework.util.xml.DomUtils;
|
|||
public class MethodSecurityMetadataSourceBeanDefinitionParser extends AbstractBeanDefinitionParser {
|
||||
|
||||
static final String ATT_METHOD = "method";
|
||||
|
||||
static final String ATT_ACCESS = "access";
|
||||
|
||||
@Override
|
||||
|
@ -47,17 +48,13 @@ public class MethodSecurityMetadataSourceBeanDefinitionParser extends AbstractBe
|
|||
// Parse the included methods
|
||||
List<Element> methods = DomUtils.getChildElementsByTagName(elt, Elements.PROTECT);
|
||||
Map<String, List<ConfigAttribute>> mappings = new LinkedHashMap<>();
|
||||
|
||||
for (Element protectmethodElt : methods) {
|
||||
String[] tokens = StringUtils.commaDelimitedListToStringArray(protectmethodElt.getAttribute(ATT_ACCESS));
|
||||
String methodName = protectmethodElt.getAttribute(ATT_METHOD);
|
||||
|
||||
mappings.put(methodName, SecurityConfig.createList(tokens));
|
||||
}
|
||||
|
||||
RootBeanDefinition metadataSource = new RootBeanDefinition(MapBasedMethodSecurityMetadataSource.class);
|
||||
metadataSource.getConstructorArgumentValues().addGenericArgumentValue(mappings);
|
||||
|
||||
return metadataSource;
|
||||
}
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue