16 changed files with 2 additions and 670 deletions
@ -1,74 +0,0 @@
@@ -1,74 +0,0 @@
|
||||
/* |
||||
* Copyright 2002-2016 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package org.springframework.security.config.authentication; |
||||
|
||||
import org.springframework.beans.BeanMetadataElement; |
||||
import org.springframework.beans.factory.config.BeanDefinition; |
||||
import org.springframework.beans.factory.config.RuntimeBeanReference; |
||||
import org.springframework.beans.factory.support.RootBeanDefinition; |
||||
import org.springframework.beans.factory.xml.ParserContext; |
||||
import org.springframework.security.authentication.dao.ReflectionSaltSource; |
||||
import org.springframework.security.authentication.dao.SystemWideSaltSource; |
||||
import org.springframework.security.config.Elements; |
||||
import org.springframework.util.StringUtils; |
||||
import org.w3c.dom.Element; |
||||
|
||||
/** |
||||
* @author Luke Taylor |
||||
* @since 2.0 |
||||
*/ |
||||
class SaltSourceBeanDefinitionParser { |
||||
private static final String ATT_USER_PROPERTY = "user-property"; |
||||
private static final String ATT_REF = "ref"; |
||||
private static final String ATT_SYSTEM_WIDE = "system-wide"; |
||||
|
||||
public BeanMetadataElement parse(Element element, ParserContext parserContext) { |
||||
String ref = element.getAttribute(ATT_REF); |
||||
|
||||
if (StringUtils.hasText(ref)) { |
||||
return new RuntimeBeanReference(ref); |
||||
} |
||||
|
||||
String userProperty = element.getAttribute(ATT_USER_PROPERTY); |
||||
RootBeanDefinition saltSource; |
||||
|
||||
if (StringUtils.hasText(userProperty)) { |
||||
saltSource = new RootBeanDefinition(ReflectionSaltSource.class); |
||||
saltSource.getPropertyValues().addPropertyValue("userPropertyToUse", |
||||
userProperty); |
||||
saltSource.setSource(parserContext.extractSource(element)); |
||||
saltSource.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); |
||||
|
||||
return saltSource; |
||||
} |
||||
|
||||
String systemWideSalt = element.getAttribute(ATT_SYSTEM_WIDE); |
||||
|
||||
if (StringUtils.hasText(systemWideSalt)) { |
||||
saltSource = new RootBeanDefinition(SystemWideSaltSource.class); |
||||
saltSource.getPropertyValues().addPropertyValue("systemWideSalt", |
||||
systemWideSalt); |
||||
saltSource.setSource(parserContext.extractSource(element)); |
||||
saltSource.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); |
||||
|
||||
return saltSource; |
||||
} |
||||
|
||||
parserContext.getReaderContext().error( |
||||
Elements.SALT_SOURCE + " requires an attribute", element); |
||||
return null; |
||||
} |
||||
} |
||||
@ -1,122 +0,0 @@
@@ -1,122 +0,0 @@
|
||||
/* |
||||
* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.security.authentication.dao; |
||||
|
||||
import org.springframework.security.authentication.AuthenticationServiceException; |
||||
import org.springframework.security.core.userdetails.UserDetails; |
||||
|
||||
import org.springframework.beans.factory.InitializingBean; |
||||
import org.springframework.beans.BeanUtils; |
||||
import org.springframework.util.ReflectionUtils; |
||||
import org.springframework.util.Assert; |
||||
|
||||
import java.lang.reflect.Method; |
||||
import java.beans.PropertyDescriptor; |
||||
|
||||
/** |
||||
* Obtains a salt from a specified property of the |
||||
* {@link org.springframework.security.core.userdetails.User} object. |
||||
* <p> |
||||
* This allows you to subclass <code>User</code> and provide an additional bean getter for |
||||
* a salt. You should use a synthetic value that does not change, such as a database |
||||
* primary key. Do not use <code>username</code> if it is likely to change. |
||||
* |
||||
* @author Ben Alex |
||||
*/ |
||||
public class ReflectionSaltSource implements SaltSource, InitializingBean { |
||||
// ~ Instance fields
|
||||
// ================================================================================================
|
||||
|
||||
private String userPropertyToUse; |
||||
|
||||
// ~ Methods
|
||||
// ========================================================================================================
|
||||
|
||||
public void afterPropertiesSet() throws Exception { |
||||
Assert.hasText(userPropertyToUse, "A userPropertyToUse must be set"); |
||||
} |
||||
|
||||
/** |
||||
* Performs reflection on the passed <code>User</code> to obtain the salt. |
||||
* <p> |
||||
* The property identified by <code>userPropertyToUse</code> must be available from |
||||
* the passed <code>User</code> object. If it is not available, an |
||||
* {@link AuthenticationServiceException} will be thrown. |
||||
* |
||||
* @param user which contains the method identified by <code>userPropertyToUse</code> |
||||
* |
||||
* @return the result of invoking <tt>user.userPropertyToUse()</tt>, or if the method |
||||
* doesn't exist, <tt>user.getUserPropertyToUse()</tt>. |
||||
* |
||||
* @throws AuthenticationServiceException if reflection fails |
||||
*/ |
||||
public Object getSalt(UserDetails user) { |
||||
Method saltMethod = findSaltMethod(user); |
||||
|
||||
try { |
||||
return saltMethod.invoke(user); |
||||
} |
||||
catch (Exception exception) { |
||||
throw new AuthenticationServiceException(exception.getMessage(), exception); |
||||
} |
||||
} |
||||
|
||||
private Method findSaltMethod(UserDetails user) { |
||||
Method saltMethod = ReflectionUtils.findMethod(user.getClass(), |
||||
userPropertyToUse, new Class[0]); |
||||
|
||||
if (saltMethod == null) { |
||||
PropertyDescriptor pd = BeanUtils.getPropertyDescriptor(user.getClass(), |
||||
userPropertyToUse); |
||||
|
||||
if (pd != null) { |
||||
saltMethod = pd.getReadMethod(); |
||||
} |
||||
|
||||
if (saltMethod == null) { |
||||
throw new AuthenticationServiceException( |
||||
"Unable to find salt method on user Object. Does the class '" |
||||
+ user.getClass().getName() |
||||
+ "' have a method or getter named '" + userPropertyToUse |
||||
+ "' ?"); |
||||
} |
||||
} |
||||
|
||||
return saltMethod; |
||||
} |
||||
|
||||
protected String getUserPropertyToUse() { |
||||
return userPropertyToUse; |
||||
} |
||||
|
||||
/** |
||||
* The method name to call to obtain the salt. Can be either a method name or a bean |
||||
* property name. If your <code>UserDetails</code> contains a |
||||
* <code>UserDetails.getSalt()</code> method, you should set this property to |
||||
* "getSalt" or "salt". |
||||
* |
||||
* @param userPropertyToUse the name of the <b>getter</b> to call to obtain the salt |
||||
* from the <code>UserDetails</code> |
||||
*/ |
||||
public void setUserPropertyToUse(String userPropertyToUse) { |
||||
this.userPropertyToUse = userPropertyToUse; |
||||
} |
||||
|
||||
public String toString() { |
||||
return "ReflectionSaltSource[ userPropertyToUse='" + userPropertyToUse + "'; ]"; |
||||
} |
||||
} |
||||
@ -1,38 +0,0 @@
@@ -1,38 +0,0 @@
|
||||
/* |
||||
* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.security.authentication.dao; |
||||
|
||||
import org.springframework.security.core.userdetails.UserDetails; |
||||
|
||||
/** |
||||
* Provides alternative sources of the salt to use for encoding passwords. |
||||
* |
||||
* @author Ben Alex |
||||
*/ |
||||
public interface SaltSource { |
||||
// ~ Methods
|
||||
// ========================================================================================================
|
||||
|
||||
/** |
||||
* Returns the salt to use for the indicated user. |
||||
* |
||||
* @param user from the <code>AuthenticationDao</code> |
||||
* |
||||
* @return the salt to use for this <code>UserDetails</code> |
||||
*/ |
||||
Object getSalt(UserDetails user); |
||||
} |
||||
@ -1,70 +0,0 @@
@@ -1,70 +0,0 @@
|
||||
/* |
||||
* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.security.authentication.dao; |
||||
|
||||
import org.springframework.security.core.userdetails.UserDetails; |
||||
|
||||
import org.springframework.beans.factory.InitializingBean; |
||||
|
||||
/** |
||||
* Uses a static system-wide <code>String</code> as the salt. |
||||
* <P> |
||||
* Does not supply a different salt for each |
||||
* {@link org.springframework.security.core.userdetails.User}. This means users sharing |
||||
* the same password will still have the same digested password. Of benefit is the |
||||
* digested passwords will at least be more protected than if stored without any salt. |
||||
* </p> |
||||
* |
||||
* @author Ben Alex |
||||
*/ |
||||
public class SystemWideSaltSource implements SaltSource, InitializingBean { |
||||
// ~ Instance fields
|
||||
// ================================================================================================
|
||||
|
||||
private String systemWideSalt; |
||||
|
||||
// ~ Methods
|
||||
// ========================================================================================================
|
||||
|
||||
public void afterPropertiesSet() throws Exception { |
||||
if ((this.systemWideSalt == null) || "".equals(this.systemWideSalt)) { |
||||
throw new IllegalArgumentException("A systemWideSalt must be set"); |
||||
} |
||||
} |
||||
|
||||
public Object getSalt(UserDetails user) { |
||||
return this.systemWideSalt; |
||||
} |
||||
|
||||
public String getSystemWideSalt() { |
||||
return this.systemWideSalt; |
||||
} |
||||
|
||||
public void setSystemWideSalt(String systemWideSalt) { |
||||
this.systemWideSalt = systemWideSalt; |
||||
} |
||||
|
||||
/** |
||||
* Displays the system wide salt |
||||
* @since 4.0 |
||||
* @return |
||||
*/ |
||||
@Override |
||||
public String toString() { |
||||
return systemWideSalt; |
||||
} |
||||
} |
||||
@ -1,68 +0,0 @@
@@ -1,68 +0,0 @@
|
||||
/* |
||||
* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.security.authentication.dao.salt; |
||||
|
||||
import static org.assertj.core.api.Assertions.*; |
||||
|
||||
import org.junit.Test; |
||||
import org.springframework.security.authentication.AuthenticationServiceException; |
||||
import org.springframework.security.authentication.dao.ReflectionSaltSource; |
||||
import org.springframework.security.core.authority.AuthorityUtils; |
||||
import org.springframework.security.core.userdetails.User; |
||||
import org.springframework.security.core.userdetails.UserDetails; |
||||
|
||||
/** |
||||
* Tests {@link ReflectionSaltSource}. |
||||
* |
||||
* @author Ben Alex |
||||
*/ |
||||
public class ReflectionSaltSourceTests { |
||||
private UserDetails user = new User("scott", "wombat", true, true, true, true, |
||||
AuthorityUtils.createAuthorityList("HOLDER")); |
||||
|
||||
// ~ Methods
|
||||
// ========================================================================================================
|
||||
|
||||
@Test(expected = IllegalArgumentException.class) |
||||
public void detectsMissingUserPropertyToUse() throws Exception { |
||||
ReflectionSaltSource saltSource = new ReflectionSaltSource(); |
||||
saltSource.afterPropertiesSet(); |
||||
} |
||||
|
||||
@Test(expected = AuthenticationServiceException.class) |
||||
public void exceptionIsThrownWhenInvalidPropertyRequested() throws Exception { |
||||
ReflectionSaltSource saltSource = new ReflectionSaltSource(); |
||||
saltSource.setUserPropertyToUse("getDoesNotExist"); |
||||
saltSource.afterPropertiesSet(); |
||||
saltSource.getSalt(user); |
||||
} |
||||
|
||||
@Test |
||||
public void methodNameAsPropertyToUseReturnsCorrectSaltValue() { |
||||
ReflectionSaltSource saltSource = new ReflectionSaltSource(); |
||||
saltSource.setUserPropertyToUse("getUsername"); |
||||
|
||||
assertThat(saltSource.getSalt(user)).isEqualTo("scott"); |
||||
} |
||||
|
||||
@Test |
||||
public void propertyNameAsPropertyToUseReturnsCorrectSaltValue() { |
||||
ReflectionSaltSource saltSource = new ReflectionSaltSource(); |
||||
saltSource.setUserPropertyToUse("password"); |
||||
assertThat(saltSource.getSalt(user)).isEqualTo("wombat"); |
||||
} |
||||
} |
||||
@ -1,76 +0,0 @@
@@ -1,76 +0,0 @@
|
||||
/* |
||||
* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.security.authentication.dao.salt; |
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat; |
||||
import static org.assertj.core.api.Assertions.fail; |
||||
|
||||
import org.junit.Test; |
||||
import org.springframework.security.authentication.dao.SystemWideSaltSource; |
||||
|
||||
/** |
||||
* Tests {@link SystemWideSaltSource}. |
||||
* |
||||
* @author Ben Alex |
||||
*/ |
||||
public class SystemWideSaltSourceTests { |
||||
// ~ Constructors
|
||||
// ===================================================================================================
|
||||
|
||||
public SystemWideSaltSourceTests() { |
||||
super(); |
||||
} |
||||
|
||||
// ~ Methods
|
||||
// ========================================================================================================
|
||||
@Test |
||||
public void testDetectsMissingSystemWideSalt() throws Exception { |
||||
SystemWideSaltSource saltSource = new SystemWideSaltSource(); |
||||
|
||||
try { |
||||
saltSource.afterPropertiesSet(); |
||||
fail("Should have thrown IllegalArgumentException"); |
||||
} |
||||
catch (IllegalArgumentException expected) { |
||||
assertThat(expected.getMessage()).isEqualTo("A systemWideSalt must be set"); |
||||
} |
||||
} |
||||
|
||||
@Test |
||||
public void testGettersSetters() { |
||||
SystemWideSaltSource saltSource = new SystemWideSaltSource(); |
||||
saltSource.setSystemWideSalt("helloWorld"); |
||||
assertThat(saltSource.getSystemWideSalt()).isEqualTo("helloWorld"); |
||||
} |
||||
|
||||
@Test |
||||
public void testNormalOperation() throws Exception { |
||||
SystemWideSaltSource saltSource = new SystemWideSaltSource(); |
||||
saltSource.setSystemWideSalt("helloWorld"); |
||||
saltSource.afterPropertiesSet(); |
||||
assertThat(saltSource.getSalt(null)).isEqualTo("helloWorld"); |
||||
} |
||||
|
||||
// SEC-2173
|
||||
@Test |
||||
public void testToString() { |
||||
String systemWideSalt = "helloWorld"; |
||||
SystemWideSaltSource saltSource = new SystemWideSaltSource(); |
||||
saltSource.setSystemWideSalt(systemWideSalt); |
||||
assertThat(saltSource.toString()).isEqualTo(systemWideSalt); |
||||
} |
||||
} |
||||
Loading…
Reference in new issue