From f2ccc53549c8b5235ceb105166e8f4b714212f3c Mon Sep 17 00:00:00 2001 From: Rob Winch Date: Thu, 9 Nov 2017 14:01:43 -0600 Subject: [PATCH] Add UserDetailsMapFactoryBean Fixes gh-4804 --- .../UserDetailsMapFactoryBean.java | 86 +++++++++++++++++++ .../UserDetailsResourceFactoryBean.java | 28 +----- 2 files changed, 88 insertions(+), 26 deletions(-) create mode 100644 config/src/main/java/org/springframework/security/config/core/userdetails/UserDetailsMapFactoryBean.java diff --git a/config/src/main/java/org/springframework/security/config/core/userdetails/UserDetailsMapFactoryBean.java b/config/src/main/java/org/springframework/security/config/core/userdetails/UserDetailsMapFactoryBean.java new file mode 100644 index 0000000000..b53f82a5a1 --- /dev/null +++ b/config/src/main/java/org/springframework/security/config/core/userdetails/UserDetailsMapFactoryBean.java @@ -0,0 +1,86 @@ +/* + * Copyright 2002-2017 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.security.config.core.userdetails; + +import org.springframework.beans.factory.FactoryBean; +import org.springframework.lang.Nullable; +import org.springframework.security.core.userdetails.User; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.memory.UserAttribute; +import org.springframework.security.core.userdetails.memory.UserAttributeEditor; +import org.springframework.util.Assert; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Map; + +/** + * Creates a {@code Collection} from a @{code Map} in the format of + *

+ * + * username=password[,enabled|disabled],roles... + * + *

+ * The enabled and disabled properties are optional with enabled being the default. For example: + *

+ * + * user=password,ROLE_USER + * admin=secret,ROLE_USER,ROLE_ADMIN + * disabled_user=does_not_matter,disabled,ROLE_USER + * + * + * @author Rob Winch + * @since 5.0 + */ +public class UserDetailsMapFactoryBean implements FactoryBean> { + private final Map userProperties; + + public UserDetailsMapFactoryBean(Map userProperties) { + Assert.notNull(userProperties, "userProperties cannot be null"); + this.userProperties = userProperties; + } + + @Nullable + @Override + public Collection getObject() throws Exception { + Collection users = new ArrayList<>(this.userProperties.size()); + + UserAttributeEditor editor = new UserAttributeEditor(); + for (Map.Entry entry : this.userProperties.entrySet()) { + String name = entry.getKey(); + String property = entry.getValue(); + 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."); + } + UserDetails user = User.withUsername(name) + .password(attr.getPassword()) + .disabled(!attr.isEnabled()) + .authorities(attr.getAuthorities()) + .build(); + users.add(user); + } return users; + } + + @Nullable + @Override + public Class getObjectType() { + return Collection.class; + } +} diff --git a/config/src/main/java/org/springframework/security/config/core/userdetails/UserDetailsResourceFactoryBean.java b/config/src/main/java/org/springframework/security/config/core/userdetails/UserDetailsResourceFactoryBean.java index f53a57b25a..d51d924397 100644 --- a/config/src/main/java/org/springframework/security/config/core/userdetails/UserDetailsResourceFactoryBean.java +++ b/config/src/main/java/org/springframework/security/config/core/userdetails/UserDetailsResourceFactoryBean.java @@ -21,17 +21,13 @@ import org.springframework.context.ResourceLoaderAware; import org.springframework.core.io.DefaultResourceLoader; import org.springframework.core.io.Resource; import org.springframework.core.io.ResourceLoader; -import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.security.core.userdetails.memory.UserAttribute; -import org.springframework.security.core.userdetails.memory.UserAttributeEditor; import org.springframework.security.util.InMemoryResource; import org.springframework.util.Assert; import java.io.InputStream; -import java.util.ArrayList; import java.util.Collection; -import java.util.Enumeration; +import java.util.Map; import java.util.Properties; /** @@ -72,27 +68,7 @@ public class UserDetailsResourceFactoryBean implements ResourceLoaderAware, Fact try(InputStream in = resource.getInputStream()){ userProperties.load(in); } - - Collection users = new ArrayList<>(userProperties.size()); - Enumeration names = userProperties.propertyNames(); - UserAttributeEditor editor = new UserAttributeEditor(); - - while (names.hasMoreElements()) { - String name = (String) names.nextElement(); - String property = userProperties.getProperty(name); - 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."); - } - UserDetails user = User.withUsername(name) - .password(attr.getPassword()) - .disabled(!attr.isEnabled()) - .authorities(attr.getAuthorities()) - .build(); - users.add(user); - } - return users; + return new UserDetailsMapFactoryBean((Map) userProperties).getObject(); } @Override