SEC-2915: Updated Java Code Formatting

This commit is contained in:
Rob Winch
2015-03-23 11:21:19 -05:00
parent 0a2e496a84
commit ae6af5d73c
1420 changed files with 92995 additions and 85097 deletions

View File

@@ -9,20 +9,22 @@ import java.util.*;
* @author Luke Taylor
*/
public class BeanNameCollectingPostProcessor implements BeanPostProcessor {
Set<String> beforeInitPostProcessedBeans = new HashSet<String>();
Set<String> afterInitPostProcessedBeans = new HashSet<String>();
Set<String> beforeInitPostProcessedBeans = new HashSet<String>();
Set<String> afterInitPostProcessedBeans = new HashSet<String>();
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (beanName != null) {
beforeInitPostProcessedBeans.add(beanName);
}
return bean;
}
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
if (beanName != null) {
beforeInitPostProcessedBeans.add(beanName);
}
return bean;
}
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (beanName != null) {
afterInitPostProcessedBeans.add(beanName);
}
return bean;
}
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
if (beanName != null) {
afterInitPostProcessedBeans.add(beanName);
}
return bean;
}
}

View File

@@ -15,39 +15,39 @@ import org.springframework.security.authentication.event.AbstractAuthenticationF
* @since 3.1
*/
public class CollectingAppListener implements ApplicationListener {
Set<ApplicationEvent> events = new HashSet<ApplicationEvent>();
Set<AbstractAuthenticationEvent> authenticationEvents = new HashSet<AbstractAuthenticationEvent>();
Set<AbstractAuthenticationFailureEvent> authenticationFailureEvents = new HashSet<AbstractAuthenticationFailureEvent>();
Set<AbstractAuthorizationEvent> authorizationEvents = new HashSet<AbstractAuthorizationEvent>();
Set<ApplicationEvent> events = new HashSet<ApplicationEvent>();
Set<AbstractAuthenticationEvent> authenticationEvents = new HashSet<AbstractAuthenticationEvent>();
Set<AbstractAuthenticationFailureEvent> authenticationFailureEvents = new HashSet<AbstractAuthenticationFailureEvent>();
Set<AbstractAuthorizationEvent> authorizationEvents = new HashSet<AbstractAuthorizationEvent>();
public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof AbstractAuthenticationEvent) {
events.add(event);
authenticationEvents.add((AbstractAuthenticationEvent) event);
}
if (event instanceof AbstractAuthenticationFailureEvent) {
events.add(event);
authenticationFailureEvents.add((AbstractAuthenticationFailureEvent) event);
}
if (event instanceof AbstractAuthorizationEvent) {
events.add(event);
authorizationEvents.add((AbstractAuthorizationEvent) event);
}
}
public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof AbstractAuthenticationEvent) {
events.add(event);
authenticationEvents.add((AbstractAuthenticationEvent) event);
}
if (event instanceof AbstractAuthenticationFailureEvent) {
events.add(event);
authenticationFailureEvents.add((AbstractAuthenticationFailureEvent) event);
}
if (event instanceof AbstractAuthorizationEvent) {
events.add(event);
authorizationEvents.add((AbstractAuthorizationEvent) event);
}
}
public Set<ApplicationEvent> getEvents() {
return events;
}
public Set<ApplicationEvent> getEvents() {
return events;
}
public Set<AbstractAuthenticationEvent> getAuthenticationEvents() {
return authenticationEvents;
}
public Set<AbstractAuthenticationEvent> getAuthenticationEvents() {
return authenticationEvents;
}
public Set<AbstractAuthenticationFailureEvent> getAuthenticationFailureEvents() {
return authenticationFailureEvents;
}
public Set<AbstractAuthenticationFailureEvent> getAuthenticationFailureEvents() {
return authenticationFailureEvents;
}
public Set<AbstractAuthorizationEvent> getAuthorizationEvents() {
return authorizationEvents;
}
public Set<AbstractAuthorizationEvent> getAuthorizationEvents() {
return authorizationEvents;
}
}

View File

@@ -1,15 +1,14 @@
package org.springframework.security.config;
public abstract class ConfigTestUtils {
public static final String AUTH_PROVIDER_XML =
"<authentication-manager alias='authManager'>" +
" <authentication-provider>" +
" <user-service id='us'>" +
" <user name='bob' password='bobspassword' authorities='ROLE_A,ROLE_B' />" +
" <user name='bill' password='billspassword' authorities='ROLE_A,ROLE_B,AUTH_OTHER' />" +
" <user name='admin' password='password' authorities='ROLE_ADMIN,ROLE_USER' />" +
" <user name='user' password='password' authorities='ROLE_USER' />" +
" </user-service>" +
" </authentication-provider>" +
"</authentication-manager>";
public static final String AUTH_PROVIDER_XML = "<authentication-manager alias='authManager'>"
+ " <authentication-provider>"
+ " <user-service id='us'>"
+ " <user name='bob' password='bobspassword' authorities='ROLE_A,ROLE_B' />"
+ " <user name='bill' password='billspassword' authorities='ROLE_A,ROLE_B,AUTH_OTHER' />"
+ " <user name='admin' password='password' authorities='ROLE_ADMIN,ROLE_USER' />"
+ " <user name='user' password='password' authorities='ROLE_USER' />"
+ " </user-service>"
+ " </authentication-provider>"
+ "</authentication-manager>";
}

View File

@@ -20,53 +20,49 @@ import org.springframework.beans.factory.InitializingBean;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.util.Assert;
/**
* Populates a database with test data for JDBC testing.
*
* @author Ben Alex
*/
public class DataSourcePopulator implements InitializingBean {
//~ Instance fields ================================================================================================
// ~ Instance fields
// ================================================================================================
JdbcTemplate template;
JdbcTemplate template;
public void afterPropertiesSet() throws Exception {
Assert.notNull(template, "dataSource required");
public void afterPropertiesSet() throws Exception {
Assert.notNull(template, "dataSource required");
template.execute("CREATE TABLE USERS(USERNAME VARCHAR_IGNORECASE(50) NOT NULL PRIMARY KEY,PASSWORD VARCHAR_IGNORECASE(500) NOT NULL,ENABLED BOOLEAN NOT NULL);");
template.execute("CREATE TABLE AUTHORITIES(USERNAME VARCHAR_IGNORECASE(50) NOT NULL,AUTHORITY VARCHAR_IGNORECASE(50) NOT NULL,CONSTRAINT FK_AUTHORITIES_USERS FOREIGN KEY(USERNAME) REFERENCES USERS(USERNAME));");
template.execute("CREATE UNIQUE INDEX IX_AUTH_USERNAME ON AUTHORITIES(USERNAME,AUTHORITY);");
template.execute("CREATE TABLE USERS(USERNAME VARCHAR_IGNORECASE(50) NOT NULL PRIMARY KEY,PASSWORD VARCHAR_IGNORECASE(500) NOT NULL,ENABLED BOOLEAN NOT NULL);");
template.execute("CREATE TABLE AUTHORITIES(USERNAME VARCHAR_IGNORECASE(50) NOT NULL,AUTHORITY VARCHAR_IGNORECASE(50) NOT NULL,CONSTRAINT FK_AUTHORITIES_USERS FOREIGN KEY(USERNAME) REFERENCES USERS(USERNAME));");
template.execute("CREATE UNIQUE INDEX IX_AUTH_USERNAME ON AUTHORITIES(USERNAME,AUTHORITY);");
/*
Passwords encoded using MD5, NOT in Base64 format, with null as salt
Encoded password for rod is "koala"
Encoded password for dianne is "emu"
Encoded password for scott is "wombat"
Encoded password for peter is "opal" (but user is disabled)
Encoded password for bill is "wombat"
Encoded password for bob is "wombat"
Encoded password for jane is "wombat"
/*
* Passwords encoded using MD5, NOT in Base64 format, with null as salt Encoded
* password for rod is "koala" Encoded password for dianne is "emu" Encoded
* password for scott is "wombat" Encoded password for peter is "opal" (but user
* is disabled) Encoded password for bill is "wombat" Encoded password for bob is
* "wombat" Encoded password for jane is "wombat"
*/
template.execute("INSERT INTO USERS VALUES('rod','koala',TRUE);");
template.execute("INSERT INTO USERS VALUES('dianne','65d15fe9156f9c4bbffd98085992a44e',TRUE);");
template.execute("INSERT INTO USERS VALUES('scott','2b58af6dddbd072ed27ffc86725d7d3a',TRUE);");
template.execute("INSERT INTO USERS VALUES('peter','22b5c9accc6e1ba628cedc63a72d57f8',FALSE);");
template.execute("INSERT INTO USERS VALUES('bill','2b58af6dddbd072ed27ffc86725d7d3a',TRUE);");
template.execute("INSERT INTO USERS VALUES('bob','2b58af6dddbd072ed27ffc86725d7d3a',TRUE);");
template.execute("INSERT INTO USERS VALUES('jane','2b58af6dddbd072ed27ffc86725d7d3a',TRUE);");
template.execute("INSERT INTO AUTHORITIES VALUES('rod','ROLE_USER');");
template.execute("INSERT INTO AUTHORITIES VALUES('rod','ROLE_SUPERVISOR');");
template.execute("INSERT INTO AUTHORITIES VALUES('dianne','ROLE_USER');");
template.execute("INSERT INTO AUTHORITIES VALUES('scott','ROLE_USER');");
template.execute("INSERT INTO AUTHORITIES VALUES('peter','ROLE_USER');");
template.execute("INSERT INTO AUTHORITIES VALUES('bill','ROLE_USER');");
template.execute("INSERT INTO AUTHORITIES VALUES('bob','ROLE_USER');");
template.execute("INSERT INTO AUTHORITIES VALUES('jane','ROLE_USER');");
}
*/
template.execute("INSERT INTO USERS VALUES('rod','koala',TRUE);");
template.execute("INSERT INTO USERS VALUES('dianne','65d15fe9156f9c4bbffd98085992a44e',TRUE);");
template.execute("INSERT INTO USERS VALUES('scott','2b58af6dddbd072ed27ffc86725d7d3a',TRUE);");
template.execute("INSERT INTO USERS VALUES('peter','22b5c9accc6e1ba628cedc63a72d57f8',FALSE);");
template.execute("INSERT INTO USERS VALUES('bill','2b58af6dddbd072ed27ffc86725d7d3a',TRUE);");
template.execute("INSERT INTO USERS VALUES('bob','2b58af6dddbd072ed27ffc86725d7d3a',TRUE);");
template.execute("INSERT INTO USERS VALUES('jane','2b58af6dddbd072ed27ffc86725d7d3a',TRUE);");
template.execute("INSERT INTO AUTHORITIES VALUES('rod','ROLE_USER');");
template.execute("INSERT INTO AUTHORITIES VALUES('rod','ROLE_SUPERVISOR');");
template.execute("INSERT INTO AUTHORITIES VALUES('dianne','ROLE_USER');");
template.execute("INSERT INTO AUTHORITIES VALUES('scott','ROLE_USER');");
template.execute("INSERT INTO AUTHORITIES VALUES('peter','ROLE_USER');");
template.execute("INSERT INTO AUTHORITIES VALUES('bill','ROLE_USER');");
template.execute("INSERT INTO AUTHORITIES VALUES('bob','ROLE_USER');");
template.execute("INSERT INTO AUTHORITIES VALUES('jane','ROLE_USER');");
}
public void setDataSource(DataSource dataSource) {
this.template = new JdbcTemplate(dataSource);
}
public void setDataSource(DataSource dataSource) {
this.template = new JdbcTemplate(dataSource);
}
}

View File

@@ -50,107 +50,119 @@ import org.springframework.security.web.util.matcher.RequestMatcher;
* @author Ben Alex
*/
public class FilterChainProxyConfigTests {
private ClassPathXmlApplicationContext appCtx;
private ClassPathXmlApplicationContext appCtx;
//~ Methods ========================================================================================================
// ~ Methods
// ========================================================================================================
@Before
public void loadContext() {
System.setProperty("sec1235.pattern1", "/login");
System.setProperty("sec1235.pattern2", "/logout");
appCtx = new ClassPathXmlApplicationContext("org/springframework/security/util/filtertest-valid.xml");
}
@Before
public void loadContext() {
System.setProperty("sec1235.pattern1", "/login");
System.setProperty("sec1235.pattern2", "/logout");
appCtx = new ClassPathXmlApplicationContext(
"org/springframework/security/util/filtertest-valid.xml");
}
@After
public void closeContext() {
if (appCtx != null) {
appCtx.close();
}
}
@After
public void closeContext() {
if (appCtx != null) {
appCtx.close();
}
}
@Test
public void normalOperation() throws Exception {
FilterChainProxy filterChainProxy = appCtx.getBean("filterChain", FilterChainProxy.class);
doNormalOperation(filterChainProxy);
}
@Test
public void normalOperation() throws Exception {
FilterChainProxy filterChainProxy = appCtx.getBean("filterChain",
FilterChainProxy.class);
doNormalOperation(filterChainProxy);
}
@Test
public void normalOperationWithNewConfig() throws Exception {
FilterChainProxy filterChainProxy = appCtx.getBean("newFilterChainProxy", FilterChainProxy.class);
checkPathAndFilterOrder(filterChainProxy);
doNormalOperation(filterChainProxy);
}
@Test
public void normalOperationWithNewConfig() throws Exception {
FilterChainProxy filterChainProxy = appCtx.getBean("newFilterChainProxy",
FilterChainProxy.class);
checkPathAndFilterOrder(filterChainProxy);
doNormalOperation(filterChainProxy);
}
@Test
public void normalOperationWithNewConfigRegex() throws Exception {
FilterChainProxy filterChainProxy = appCtx.getBean("newFilterChainProxyRegex", FilterChainProxy.class);
checkPathAndFilterOrder(filterChainProxy);
doNormalOperation(filterChainProxy);
}
@Test
public void normalOperationWithNewConfigRegex() throws Exception {
FilterChainProxy filterChainProxy = appCtx.getBean("newFilterChainProxyRegex",
FilterChainProxy.class);
checkPathAndFilterOrder(filterChainProxy);
doNormalOperation(filterChainProxy);
}
@Test
public void normalOperationWithNewConfigNonNamespace() throws Exception {
FilterChainProxy filterChainProxy = appCtx.getBean("newFilterChainProxyNonNamespace", FilterChainProxy.class);
checkPathAndFilterOrder(filterChainProxy);
doNormalOperation(filterChainProxy);
}
@Test
public void normalOperationWithNewConfigNonNamespace() throws Exception {
FilterChainProxy filterChainProxy = appCtx.getBean(
"newFilterChainProxyNonNamespace", FilterChainProxy.class);
checkPathAndFilterOrder(filterChainProxy);
doNormalOperation(filterChainProxy);
}
@Test
public void pathWithNoMatchHasNoFilters() throws Exception {
FilterChainProxy filterChainProxy = appCtx.getBean("newFilterChainProxyNoDefaultPath", FilterChainProxy.class);
assertEquals(null, filterChainProxy.getFilters("/nomatch"));
}
@Test
public void pathWithNoMatchHasNoFilters() throws Exception {
FilterChainProxy filterChainProxy = appCtx.getBean(
"newFilterChainProxyNoDefaultPath", FilterChainProxy.class);
assertEquals(null, filterChainProxy.getFilters("/nomatch"));
}
// SEC-1235
@Test
public void mixingPatternsAndPlaceholdersDoesntCauseOrderingIssues() throws Exception {
FilterChainProxy fcp = appCtx.getBean("sec1235FilterChainProxy", FilterChainProxy.class);
// SEC-1235
@Test
public void mixingPatternsAndPlaceholdersDoesntCauseOrderingIssues() throws Exception {
FilterChainProxy fcp = appCtx.getBean("sec1235FilterChainProxy",
FilterChainProxy.class);
List<SecurityFilterChain> chains = fcp.getFilterChains();
assertEquals("/login*", getPattern(chains.get(0)));
assertEquals("/logout", getPattern(chains.get(1)));
assertTrue(((DefaultSecurityFilterChain)chains.get(2)).getRequestMatcher() instanceof AnyRequestMatcher);
}
List<SecurityFilterChain> chains = fcp.getFilterChains();
assertEquals("/login*", getPattern(chains.get(0)));
assertEquals("/logout", getPattern(chains.get(1)));
assertTrue(((DefaultSecurityFilterChain) chains.get(2)).getRequestMatcher() instanceof AnyRequestMatcher);
}
private String getPattern(SecurityFilterChain chain) {
return ((AntPathRequestMatcher)((DefaultSecurityFilterChain)chain).getRequestMatcher()).getPattern();
}
private String getPattern(SecurityFilterChain chain) {
return ((AntPathRequestMatcher) ((DefaultSecurityFilterChain) chain)
.getRequestMatcher()).getPattern();
}
private void checkPathAndFilterOrder(FilterChainProxy filterChainProxy) throws Exception {
List<Filter> filters = filterChainProxy.getFilters("/foo/blah;x=1");
assertEquals(1, filters.size());
assertTrue(filters.get(0) instanceof SecurityContextHolderAwareRequestFilter);
private void checkPathAndFilterOrder(FilterChainProxy filterChainProxy)
throws Exception {
List<Filter> filters = filterChainProxy.getFilters("/foo/blah;x=1");
assertEquals(1, filters.size());
assertTrue(filters.get(0) instanceof SecurityContextHolderAwareRequestFilter);
filters = filterChainProxy.getFilters("/some;x=2,y=3/other/path;z=4/blah");
assertNotNull(filters);
assertEquals(3, filters.size());
assertTrue(filters.get(0) instanceof SecurityContextPersistenceFilter);
assertTrue(filters.get(1) instanceof SecurityContextHolderAwareRequestFilter);
assertTrue(filters.get(2) instanceof SecurityContextHolderAwareRequestFilter);
filters = filterChainProxy.getFilters("/some;x=2,y=3/other/path;z=4/blah");
assertNotNull(filters);
assertEquals(3, filters.size());
assertTrue(filters.get(0) instanceof SecurityContextPersistenceFilter);
assertTrue(filters.get(1) instanceof SecurityContextHolderAwareRequestFilter);
assertTrue(filters.get(2) instanceof SecurityContextHolderAwareRequestFilter);
filters = filterChainProxy.getFilters("/do/not/filter;x=7");
assertEquals(0, filters.size());
filters = filterChainProxy.getFilters("/do/not/filter;x=7");
assertEquals(0, filters.size());
filters = filterChainProxy.getFilters("/another/nonspecificmatch");
assertEquals(3, filters.size());
assertTrue(filters.get(0) instanceof SecurityContextPersistenceFilter);
assertTrue(filters.get(1) instanceof UsernamePasswordAuthenticationFilter);
assertTrue(filters.get(2) instanceof SecurityContextHolderAwareRequestFilter);
}
filters = filterChainProxy.getFilters("/another/nonspecificmatch");
assertEquals(3, filters.size());
assertTrue(filters.get(0) instanceof SecurityContextPersistenceFilter);
assertTrue(filters.get(1) instanceof UsernamePasswordAuthenticationFilter);
assertTrue(filters.get(2) instanceof SecurityContextHolderAwareRequestFilter);
}
private void doNormalOperation(FilterChainProxy filterChainProxy) throws Exception {
MockHttpServletRequest request = new MockHttpServletRequest();
request.setServletPath("/foo/secure/super/somefile.html");
private void doNormalOperation(FilterChainProxy filterChainProxy) throws Exception {
MockHttpServletRequest request = new MockHttpServletRequest();
request.setServletPath("/foo/secure/super/somefile.html");
MockHttpServletResponse response = new MockHttpServletResponse();
FilterChain chain = mock(FilterChain.class);
MockHttpServletResponse response = new MockHttpServletResponse();
FilterChain chain = mock(FilterChain.class);
filterChainProxy.doFilter(request, response, chain);
verify(chain).doFilter(any(HttpServletRequest.class), any(HttpServletResponse.class));
filterChainProxy.doFilter(request, response, chain);
verify(chain).doFilter(any(HttpServletRequest.class),
any(HttpServletResponse.class));
request.setServletPath("/a/path/which/doesnt/match/any/filter.html");
chain = mock(FilterChain.class);
filterChainProxy.doFilter(request, response, chain);
verify(chain).doFilter(any(HttpServletRequest.class), any(HttpServletResponse.class));
}
request.setServletPath("/a/path/which/doesnt/match/any/filter.html");
chain = mock(FilterChain.class);
filterChainProxy.doFilter(request, response, chain);
verify(chain).doFilter(any(HttpServletRequest.class),
any(HttpServletResponse.class));
}
}

View File

@@ -11,54 +11,56 @@ import org.springframework.security.config.authentication.AuthenticationManagerF
import org.springframework.security.config.util.InMemoryXmlApplicationContext;
/**
* Tests which make sure invalid configurations are rejected by the namespace. In particular invalid top-level
* elements. These are likely to fail after the namespace has been updated using trang, but the spring-security.xsl
* transform has not been applied.
* Tests which make sure invalid configurations are rejected by the namespace. In
* particular invalid top-level elements. These are likely to fail after the namespace has
* been updated using trang, but the spring-security.xsl transform has not been applied.
*
* @author Luke Taylor
*/
public class InvalidConfigurationTests {
private InMemoryXmlApplicationContext appContext;
private InMemoryXmlApplicationContext appContext;
@After
public void closeAppContext() {
if (appContext != null) {
appContext.close();
}
}
@After
public void closeAppContext() {
if (appContext != null) {
appContext.close();
}
}
// Parser should throw a SAXParseException
@Test(expected=XmlBeanDefinitionStoreException.class)
public void passwordEncoderCannotAppearAtTopLevel() {
setContext("<password-encoder hash='md5'/>");
}
// Parser should throw a SAXParseException
@Test(expected = XmlBeanDefinitionStoreException.class)
public void passwordEncoderCannotAppearAtTopLevel() {
setContext("<password-encoder hash='md5'/>");
}
@Test(expected=XmlBeanDefinitionStoreException.class)
public void authenticationProviderCannotAppearAtTopLevel() {
setContext("<authentication-provider ref='blah'/>");
}
@Test(expected = XmlBeanDefinitionStoreException.class)
public void authenticationProviderCannotAppearAtTopLevel() {
setContext("<authentication-provider ref='blah'/>");
}
@Test
public void missingAuthenticationManagerGivesSensibleErrorMessage() {
try {
setContext("<http auto-config='true' />");
} catch (BeanCreationException e) {
Throwable cause = ultimateCause(e);
assertTrue(cause instanceof NoSuchBeanDefinitionException);
NoSuchBeanDefinitionException nsbe = (NoSuchBeanDefinitionException) cause;
assertEquals(BeanIds.AUTHENTICATION_MANAGER, nsbe.getBeanName());
assertTrue(nsbe.getMessage().endsWith(AuthenticationManagerFactoryBean.MISSING_BEAN_ERROR_MESSAGE));
}
}
@Test
public void missingAuthenticationManagerGivesSensibleErrorMessage() {
try {
setContext("<http auto-config='true' />");
}
catch (BeanCreationException e) {
Throwable cause = ultimateCause(e);
assertTrue(cause instanceof NoSuchBeanDefinitionException);
NoSuchBeanDefinitionException nsbe = (NoSuchBeanDefinitionException) cause;
assertEquals(BeanIds.AUTHENTICATION_MANAGER, nsbe.getBeanName());
assertTrue(nsbe.getMessage().endsWith(
AuthenticationManagerFactoryBean.MISSING_BEAN_ERROR_MESSAGE));
}
}
private Throwable ultimateCause(Throwable e) {
if (e.getCause() == null) {
return e;
}
return ultimateCause(e.getCause());
}
private Throwable ultimateCause(Throwable e) {
if (e.getCause() == null) {
return e;
}
return ultimateCause(e.getCause());
}
private void setContext(String context) {
appContext = new InMemoryXmlApplicationContext(context);
}
private void setContext(String context) {
appContext = new InMemoryXmlApplicationContext(context);
}
}

View File

@@ -9,17 +9,18 @@ import org.springframework.security.core.Authentication;
public class MockAfterInvocationProvider implements AfterInvocationProvider {
public Object decide(Authentication authentication, Object object, Collection<ConfigAttribute> config, Object returnedObject)
throws AccessDeniedException {
return returnedObject;
}
public Object decide(Authentication authentication, Object object,
Collection<ConfigAttribute> config, Object returnedObject)
throws AccessDeniedException {
return returnedObject;
}
public boolean supports(ConfigAttribute attribute) {
return true;
}
public boolean supports(ConfigAttribute attribute) {
return true;
}
public boolean supports(Class<?> clazz) {
return true;
}
public boolean supports(Class<?> clazz) {
return true;
}
}

View File

@@ -11,13 +11,14 @@ import org.springframework.transaction.TransactionStatus;
* @author Luke Taylor
*/
public class MockTransactionManager implements PlatformTransactionManager {
public TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {
return mock(TransactionStatus.class);
}
public TransactionStatus getTransaction(TransactionDefinition definition)
throws TransactionException {
return mock(TransactionStatus.class);
}
public void commit(TransactionStatus status) throws TransactionException {
}
public void commit(TransactionStatus status) throws TransactionException {
}
public void rollback(TransactionStatus status) throws TransactionException {
}
public void rollback(TransactionStatus status) throws TransactionException {
}
}

View File

@@ -4,21 +4,25 @@ import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
/**
* Test bean post processor which injects a message into a PostProcessedMockUserDetailsService.
* Test bean post processor which injects a message into a
* PostProcessedMockUserDetailsService.
*
* @author Luke Taylor
*/
public class MockUserServiceBeanPostProcessor implements BeanPostProcessor {
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
return bean;
}
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof PostProcessedMockUserDetailsService) {
((PostProcessedMockUserDetailsService)bean).setPostProcessorWasHere("Hello from the post processor!");
}
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
if (bean instanceof PostProcessedMockUserDetailsService) {
((PostProcessedMockUserDetailsService) bean)
.setPostProcessorWasHere("Hello from the post processor!");
}
return bean;
}
return bean;
}
}

View File

@@ -4,21 +4,21 @@ import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
public class PostProcessedMockUserDetailsService implements UserDetailsService {
private String postProcessorWasHere;
private String postProcessorWasHere;
public PostProcessedMockUserDetailsService() {
this.postProcessorWasHere = "Post processor hasn't been yet";
}
public PostProcessedMockUserDetailsService() {
this.postProcessorWasHere = "Post processor hasn't been yet";
}
public String getPostProcessorWasHere() {
return postProcessorWasHere;
}
public String getPostProcessorWasHere() {
return postProcessorWasHere;
}
public void setPostProcessorWasHere(String postProcessorWasHere) {
this.postProcessorWasHere = postProcessorWasHere;
}
public void setPostProcessorWasHere(String postProcessorWasHere) {
this.postProcessorWasHere = postProcessorWasHere;
}
public UserDetails loadUserByUsername(String username) {
throw new UnsupportedOperationException("Not for actual use");
}
public UserDetails loadUserByUsername(String username) {
throw new UnsupportedOperationException("Not for actual use");
}
}

View File

@@ -24,115 +24,112 @@ import org.springframework.util.ClassUtils;
* @since 3.0
*/
@RunWith(PowerMockRunner.class)
@PrepareForTest({ClassUtils.class})
@PrepareForTest({ ClassUtils.class })
public class SecurityNamespaceHandlerTests {
@Rule
public ExpectedException thrown = ExpectedException.none();
@Rule
public ExpectedException thrown = ExpectedException.none();
private static final String XML_AUTHENTICATION_MANAGER =
"<authentication-manager>"+
" <authentication-provider>"+
" <user-service id='us'>"+
" <user name='bob' password='bobspassword' authorities='ROLE_A' />" +
" </user-service>"+
" </authentication-provider>"+
"</authentication-manager>";
private static final String XML_HTTP_BLOCK = "<http auto-config='true'/>";
private static final String FILTER_CHAIN_PROXY_CLASSNAME = "org.springframework.security.web.FilterChainProxy";
private static final String XML_AUTHENTICATION_MANAGER = "<authentication-manager>"
+ " <authentication-provider>" + " <user-service id='us'>"
+ " <user name='bob' password='bobspassword' authorities='ROLE_A' />"
+ " </user-service>" + " </authentication-provider>"
+ "</authentication-manager>";
private static final String XML_HTTP_BLOCK = "<http auto-config='true'/>";
private static final String FILTER_CHAIN_PROXY_CLASSNAME = "org.springframework.security.web.FilterChainProxy";
@Test
public void constructionSucceeds() {
new SecurityNamespaceHandler();
// Shameless class coverage stats boosting
new BeanIds() {};
new Elements() {};
}
@Test
public void constructionSucceeds() {
new SecurityNamespaceHandler();
// Shameless class coverage stats boosting
new BeanIds() {
};
new Elements() {
};
}
@Test
public void pre32SchemaAreNotSupported() throws Exception {
try {
new InMemoryXmlApplicationContext(
"<user-service id='us'>" +
" <user name='bob' password='bobspassword' authorities='ROLE_A' />" +
"</user-service>", "3.0.3", null
);
fail("Expected BeanDefinitionParsingException");
} catch (BeanDefinitionParsingException expected) {
assertTrue(expected.getMessage().contains("You cannot use a spring-security-2.0.xsd"));
}
}
@Test
public void pre32SchemaAreNotSupported() throws Exception {
try {
new InMemoryXmlApplicationContext(
"<user-service id='us'>"
+ " <user name='bob' password='bobspassword' authorities='ROLE_A' />"
+ "</user-service>", "3.0.3", null);
fail("Expected BeanDefinitionParsingException");
}
catch (BeanDefinitionParsingException expected) {
assertTrue(expected.getMessage().contains(
"You cannot use a spring-security-2.0.xsd"));
}
}
// SEC-1868
@Test
public void initDoesNotLogErrorWhenFilterChainProxyFailsToLoad() throws Exception {
String className = "javax.servlet.Filter";
spy(ClassUtils.class);
doThrow(new NoClassDefFoundError(className)).when(ClassUtils.class,"forName",eq(FILTER_CHAIN_PROXY_CLASSNAME),any(ClassLoader.class));
// SEC-1868
@Test
public void initDoesNotLogErrorWhenFilterChainProxyFailsToLoad() throws Exception {
String className = "javax.servlet.Filter";
spy(ClassUtils.class);
doThrow(new NoClassDefFoundError(className)).when(ClassUtils.class, "forName",
eq(FILTER_CHAIN_PROXY_CLASSNAME), any(ClassLoader.class));
Log logger = mock(Log.class);
SecurityNamespaceHandler handler = new SecurityNamespaceHandler();
WhiteboxImpl.setInternalState(handler, Log.class, logger);
Log logger = mock(Log.class);
SecurityNamespaceHandler handler = new SecurityNamespaceHandler();
WhiteboxImpl.setInternalState(handler, Log.class, logger);
handler.init();
handler.init();
verifyStatic();
ClassUtils.forName(eq(FILTER_CHAIN_PROXY_CLASSNAME),any(ClassLoader.class));
verifyZeroInteractions(logger);
}
verifyStatic();
ClassUtils.forName(eq(FILTER_CHAIN_PROXY_CLASSNAME), any(ClassLoader.class));
verifyZeroInteractions(logger);
}
@Test
public void filterNoClassDefFoundError() throws Exception {
String className = "javax.servlet.Filter";
thrown.expect(BeanDefinitionParsingException.class);
thrown.expectMessage("NoClassDefFoundError: "+className);
spy(ClassUtils.class);
doThrow(new NoClassDefFoundError(className)).when(ClassUtils.class,"forName",eq(FILTER_CHAIN_PROXY_CLASSNAME),any(ClassLoader.class));
new InMemoryXmlApplicationContext(
XML_AUTHENTICATION_MANAGER +
XML_HTTP_BLOCK);
}
@Test
public void filterNoClassDefFoundError() throws Exception {
String className = "javax.servlet.Filter";
thrown.expect(BeanDefinitionParsingException.class);
thrown.expectMessage("NoClassDefFoundError: " + className);
spy(ClassUtils.class);
doThrow(new NoClassDefFoundError(className)).when(ClassUtils.class, "forName",
eq(FILTER_CHAIN_PROXY_CLASSNAME), any(ClassLoader.class));
new InMemoryXmlApplicationContext(XML_AUTHENTICATION_MANAGER + XML_HTTP_BLOCK);
}
@Test
public void filterNoClassDefFoundErrorNoHttpBlock() throws Exception {
String className = "javax.servlet.Filter";
spy(ClassUtils.class);
doThrow(new NoClassDefFoundError(className)).when(ClassUtils.class,"forName",eq(FILTER_CHAIN_PROXY_CLASSNAME),any(ClassLoader.class));
new InMemoryXmlApplicationContext(
XML_AUTHENTICATION_MANAGER);
// should load just fine since no http block
}
@Test
public void filterNoClassDefFoundErrorNoHttpBlock() throws Exception {
String className = "javax.servlet.Filter";
spy(ClassUtils.class);
doThrow(new NoClassDefFoundError(className)).when(ClassUtils.class, "forName",
eq(FILTER_CHAIN_PROXY_CLASSNAME), any(ClassLoader.class));
new InMemoryXmlApplicationContext(XML_AUTHENTICATION_MANAGER);
// should load just fine since no http block
}
@Test
public void filterChainProxyClassNotFoundException() throws Exception {
String className = FILTER_CHAIN_PROXY_CLASSNAME;
thrown.expect(BeanDefinitionParsingException.class);
thrown.expectMessage("ClassNotFoundException: "+className);
spy(ClassUtils.class);
doThrow(new ClassNotFoundException(className)).when(ClassUtils.class,"forName",eq(FILTER_CHAIN_PROXY_CLASSNAME),any(ClassLoader.class));
new InMemoryXmlApplicationContext(
XML_AUTHENTICATION_MANAGER +
XML_HTTP_BLOCK);
}
@Test
public void filterChainProxyClassNotFoundException() throws Exception {
String className = FILTER_CHAIN_PROXY_CLASSNAME;
thrown.expect(BeanDefinitionParsingException.class);
thrown.expectMessage("ClassNotFoundException: " + className);
spy(ClassUtils.class);
doThrow(new ClassNotFoundException(className)).when(ClassUtils.class, "forName",
eq(FILTER_CHAIN_PROXY_CLASSNAME), any(ClassLoader.class));
new InMemoryXmlApplicationContext(XML_AUTHENTICATION_MANAGER + XML_HTTP_BLOCK);
}
@Test
public void filterChainProxyClassNotFoundExceptionNoHttpBlock() throws Exception {
String className = FILTER_CHAIN_PROXY_CLASSNAME;
spy(ClassUtils.class);
doThrow(new ClassNotFoundException(className)).when(ClassUtils.class,"forName",eq(FILTER_CHAIN_PROXY_CLASSNAME),any(ClassLoader.class));
new InMemoryXmlApplicationContext(
XML_AUTHENTICATION_MANAGER);
// should load just fine since no http block
}
@Test
public void filterChainProxyClassNotFoundExceptionNoHttpBlock() throws Exception {
String className = FILTER_CHAIN_PROXY_CLASSNAME;
spy(ClassUtils.class);
doThrow(new ClassNotFoundException(className)).when(ClassUtils.class, "forName",
eq(FILTER_CHAIN_PROXY_CLASSNAME), any(ClassLoader.class));
new InMemoryXmlApplicationContext(XML_AUTHENTICATION_MANAGER);
// should load just fine since no http block
}
@Test
public void websocketNotFoundExceptionNoMessageBlock() throws Exception {
String className = FILTER_CHAIN_PROXY_CLASSNAME;
spy(ClassUtils.class);
doThrow(new ClassNotFoundException(className)).when(ClassUtils.class,"forName",eq(Message.class.getName()),any(ClassLoader.class));
new InMemoryXmlApplicationContext(
XML_AUTHENTICATION_MANAGER);
// should load just fine since no websocket block
}
@Test
public void websocketNotFoundExceptionNoMessageBlock() throws Exception {
String className = FILTER_CHAIN_PROXY_CLASSNAME;
spy(ClassUtils.class);
doThrow(new ClassNotFoundException(className)).when(ClassUtils.class, "forName",
eq(Message.class.getName()), any(ClassLoader.class));
new InMemoryXmlApplicationContext(XML_AUTHENTICATION_MANAGER);
// should load just fine since no websocket block
}
}

View File

@@ -5,13 +5,13 @@ package org.springframework.security.config;
*/
public interface TestBusinessBean {
void setInteger(int i);
void setInteger(int i);
int getInteger();
int getInteger();
void setString(String s);
void setString(String s);
void doSomething();
void doSomething();
void unprotected();
void unprotected();
}

View File

@@ -7,28 +7,29 @@ import org.springframework.transaction.annotation.Transactional;
/**
* @author Luke Taylor
*/
public class TestBusinessBeanImpl implements TestBusinessBean, ApplicationListener<SessionCreationEvent> {
public void setInteger(int i) {
}
public class TestBusinessBeanImpl implements TestBusinessBean,
ApplicationListener<SessionCreationEvent> {
public void setInteger(int i) {
}
public int getInteger() {
return 1314;
}
public int getInteger() {
return 1314;
}
public void setString(String s) {
}
public void setString(String s) {
}
public String getString() {
return "A string.";
}
public String getString() {
return "A string.";
}
public void doSomething() {
}
public void doSomething() {
}
public void unprotected() {
}
public void unprotected() {
}
public void onApplicationEvent(SessionCreationEvent event) {
System.out.println(event);
}
public void onApplicationEvent(SessionCreationEvent event) {
System.out.println(event);
}
}

View File

@@ -6,20 +6,20 @@ import org.springframework.transaction.annotation.Transactional;
* @author Luke Taylor
*/
public class TransactionalTestBusinessBean implements TestBusinessBean {
public void setInteger(int i) {
}
public void setInteger(int i) {
}
public int getInteger() {
return 0;
}
public int getInteger() {
return 0;
}
public void setString(String s) {
}
public void setString(String s) {
}
@Transactional
public void doSomething() {
}
@Transactional
public void doSomething() {
}
public void unprotected() {
}
public void unprotected() {
}
}

View File

@@ -55,84 +55,83 @@ import org.springframework.web.servlet.config.annotation.EnableWebMvc;
@WebAppConfiguration
public class WebMvcSecurityConfigurationTests {
@Autowired
WebApplicationContext context;
@Autowired
WebApplicationContext context;
MockMvc mockMvc;
MockMvc mockMvc;
Authentication authentication;
Authentication authentication;
@Before
public void setup() {
mockMvc = MockMvcBuilders.webAppContextSetup(context).build();
authentication = new TestingAuthenticationToken("user","password", AuthorityUtils.createAuthorityList("ROLE_USER"));
SecurityContextHolder.getContext().setAuthentication(authentication);
}
@Before
public void setup() {
mockMvc = MockMvcBuilders.webAppContextSetup(context).build();
authentication = new TestingAuthenticationToken("user", "password",
AuthorityUtils.createAuthorityList("ROLE_USER"));
SecurityContextHolder.getContext().setAuthentication(authentication);
}
@After
public void cleanup() {
SecurityContextHolder.clearContext();
}
@After
public void cleanup() {
SecurityContextHolder.clearContext();
}
@Test
public void authenticationPrincipalResolved() throws Exception {
mockMvc
.perform(get("/authentication-principal"))
.andExpect(assertResult(authentication.getPrincipal()))
.andExpect(view().name("authentication-principal-view"));
}
@Test
public void authenticationPrincipalResolved() throws Exception {
mockMvc.perform(get("/authentication-principal"))
.andExpect(assertResult(authentication.getPrincipal()))
.andExpect(view().name("authentication-principal-view"));
}
@Test
public void deprecatedAuthenticationPrincipalResolved() throws Exception {
mockMvc
.perform(get("/deprecated-authentication-principal"))
.andExpect(assertResult(authentication.getPrincipal()))
.andExpect(view().name("deprecated-authentication-principal-view"));
}
@Test
public void deprecatedAuthenticationPrincipalResolved() throws Exception {
mockMvc.perform(get("/deprecated-authentication-principal"))
.andExpect(assertResult(authentication.getPrincipal()))
.andExpect(view().name("deprecated-authentication-principal-view"));
}
@Test
public void csrfToken() throws Exception {
CsrfToken csrfToken = new DefaultCsrfToken("headerName", "paramName", "token");
MockHttpServletRequestBuilder request =
get("/csrf")
.requestAttr(CsrfToken.class.getName(), csrfToken);
@Test
public void csrfToken() throws Exception {
CsrfToken csrfToken = new DefaultCsrfToken("headerName", "paramName", "token");
MockHttpServletRequestBuilder request = get("/csrf").requestAttr(
CsrfToken.class.getName(), csrfToken);
mockMvc
.perform(request)
.andExpect(assertResult(csrfToken));
}
mockMvc.perform(request).andExpect(assertResult(csrfToken));
}
private ResultMatcher assertResult(Object expected) {
return model().attribute("result", expected);
}
private ResultMatcher assertResult(Object expected) {
return model().attribute("result", expected);
}
@Controller
static class TestController {
@Controller
static class TestController {
@RequestMapping("/authentication-principal")
public ModelAndView authenticationPrincipal(@AuthenticationPrincipal String principal) {
return new ModelAndView("authentication-principal-view", "result", principal);
}
@RequestMapping("/authentication-principal")
public ModelAndView authenticationPrincipal(
@AuthenticationPrincipal String principal) {
return new ModelAndView("authentication-principal-view", "result", principal);
}
@RequestMapping("/deprecated-authentication-principal")
public ModelAndView deprecatedAuthenticationPrincipal(@org.springframework.security.web.bind.annotation.AuthenticationPrincipal String principal) {
return new ModelAndView("deprecated-authentication-principal-view", "result", principal);
}
@RequestMapping("/deprecated-authentication-principal")
public ModelAndView deprecatedAuthenticationPrincipal(
@org.springframework.security.web.bind.annotation.AuthenticationPrincipal String principal) {
return new ModelAndView("deprecated-authentication-principal-view", "result",
principal);
}
@RequestMapping("/csrf")
public ModelAndView csrf(CsrfToken token) {
return new ModelAndView("view", "result", token);
}
}
@RequestMapping("/csrf")
public ModelAndView csrf(CsrfToken token) {
return new ModelAndView("view", "result", token);
}
}
@Configuration
@EnableWebMvc
@EnableWebSecurity
static class Config {
@Bean
public TestController testController() {
return new TestController();
}
}
@Configuration
@EnableWebMvc
@EnableWebSecurity
static class Config {
@Bean
public TestController testController() {
return new TestController();
}
}
}

View File

@@ -36,64 +36,65 @@ import org.springframework.web.servlet.support.RequestDataValueProcessor;
*
*/
public class CsrfConfigurerNoWebMvcTests {
ConfigurableApplicationContext context;
ConfigurableApplicationContext context;
@After
public void teardown() {
if(context != null) {
context.close();
}
}
@After
public void teardown() {
if (context != null) {
context.close();
}
}
@Test
public void missingDispatcherServletPreventsCsrfRequestDataValueProcessor() {
loadContext(EnableWebConfig.class);
@Test
public void missingDispatcherServletPreventsCsrfRequestDataValueProcessor() {
loadContext(EnableWebConfig.class);
assertThat(context.containsBeanDefinition("requestDataValueProcessor")).isTrue();
}
assertThat(context.containsBeanDefinition("requestDataValueProcessor")).isTrue();
}
@Test
public void findDispatcherServletPreventsCsrfRequestDataValueProcessor() {
loadContext(EnableWebMvcConfig.class);
@Test
public void findDispatcherServletPreventsCsrfRequestDataValueProcessor() {
loadContext(EnableWebMvcConfig.class);
assertThat(context.containsBeanDefinition("requestDataValueProcessor")).isTrue();
}
assertThat(context.containsBeanDefinition("requestDataValueProcessor")).isTrue();
}
@Test
public void overrideCsrfRequestDataValueProcessor() {
loadContext(EnableWebOverrideRequestDataConfig.class);
@Test
public void overrideCsrfRequestDataValueProcessor() {
loadContext(EnableWebOverrideRequestDataConfig.class);
assertThat(context.getBean(RequestDataValueProcessor.class).getClass()).isNotEqualTo(CsrfRequestDataValueProcessor.class);
}
assertThat(context.getBean(RequestDataValueProcessor.class).getClass())
.isNotEqualTo(CsrfRequestDataValueProcessor.class);
}
@EnableWebSecurity
static class EnableWebConfig extends WebSecurityConfigurerAdapter {
@EnableWebSecurity
static class EnableWebConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
}
}
@Override
protected void configure(HttpSecurity http) throws Exception {
}
}
@EnableWebSecurity
static class EnableWebOverrideRequestDataConfig {
@Bean
public RequestDataValueProcessor requestDataValueProcessor() {
return mock(RequestDataValueProcessor.class);
}
}
@EnableWebSecurity
static class EnableWebOverrideRequestDataConfig {
@Bean
public RequestDataValueProcessor requestDataValueProcessor() {
return mock(RequestDataValueProcessor.class);
}
}
@EnableWebSecurity
static class EnableWebMvcConfig extends WebSecurityConfigurerAdapter {
@EnableWebSecurity
static class EnableWebMvcConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
}
}
@Override
protected void configure(HttpSecurity http) throws Exception {
}
}
private void loadContext(Class<?> configs) {
AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext();
annotationConfigApplicationContext.register(configs);
annotationConfigApplicationContext.refresh();
this.context = annotationConfigApplicationContext;
}
private void loadContext(Class<?> configs) {
AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext();
annotationConfigApplicationContext.register(configs);
annotationConfigApplicationContext.refresh();
this.context = annotationConfigApplicationContext;
}
}

View File

@@ -52,96 +52,104 @@ import org.springframework.security.web.csrf.CsrfToken;
import org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository;
import org.springframework.util.ReflectionUtils;
/**
*
* @author Rob Winch
*/
@RunWith(PowerMockRunner.class)
@PrepareForTest({ReflectionUtils.class, Method.class})
@PrepareForTest({ ReflectionUtils.class, Method.class })
public class SessionManagementConfigurerServlet31Tests {
@Mock
Method method;
@Mock
Method method;
MockHttpServletRequest request;
MockHttpServletResponse response;
MockFilterChain chain;
MockHttpServletRequest request;
MockHttpServletResponse response;
MockFilterChain chain;
ConfigurableApplicationContext context;
ConfigurableApplicationContext context;
Filter springSecurityFilterChain;
Filter springSecurityFilterChain;
@Before
public void setup() {
request = new MockHttpServletRequest();
response = new MockHttpServletResponse();
chain = new MockFilterChain();
}
@Before
public void setup() {
request = new MockHttpServletRequest();
response = new MockHttpServletResponse();
chain = new MockFilterChain();
}
@After
public void teardown() {
if(context != null) {
context.close();
}
}
@After
public void teardown() {
if (context != null) {
context.close();
}
}
@Test
public void changeSessionIdDefaultsInServlet31Plus() throws Exception {
spy(ReflectionUtils.class);
Method method = mock(Method.class);
MockHttpServletRequest request = new MockHttpServletRequest();
request.getSession();
request.setServletPath("/login");
request.setMethod("POST");
request.setParameter("username", "user");
request.setParameter("password", "password");
HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
CsrfToken token = repository.generateToken(request);
repository.saveToken(token, request, response);
request.setParameter(token.getParameterName(),token.getToken());
when(ReflectionUtils.findMethod(HttpServletRequest.class, "changeSessionId")).thenReturn(method);
@Test
public void changeSessionIdDefaultsInServlet31Plus() throws Exception {
spy(ReflectionUtils.class);
Method method = mock(Method.class);
MockHttpServletRequest request = new MockHttpServletRequest();
request.getSession();
request.setServletPath("/login");
request.setMethod("POST");
request.setParameter("username", "user");
request.setParameter("password", "password");
HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
CsrfToken token = repository.generateToken(request);
repository.saveToken(token, request, response);
request.setParameter(token.getParameterName(), token.getToken());
when(ReflectionUtils.findMethod(HttpServletRequest.class, "changeSessionId"))
.thenReturn(method);
loadConfig(SessionManagementDefaultSessionFixationServlet31Config.class);
loadConfig(SessionManagementDefaultSessionFixationServlet31Config.class);
springSecurityFilterChain.doFilter(request,response,chain);
springSecurityFilterChain.doFilter(request, response, chain);
verifyStatic();
ReflectionUtils.invokeMethod(same(method), any(HttpServletRequest.class));
}
verifyStatic();
ReflectionUtils.invokeMethod(same(method), any(HttpServletRequest.class));
}
@EnableWebSecurity
static class SessionManagementDefaultSessionFixationServlet31Config extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.formLogin()
.and()
.sessionManagement();
}
@EnableWebSecurity
static class SessionManagementDefaultSessionFixationServlet31Config extends
WebSecurityConfigurerAdapter {
// @formatter:off
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.formLogin()
.and()
.sessionManagement();
}
// @formatter:on
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER");
}
}
// @formatter:off
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER");
}
// @formatter:on
}
private void loadConfig(Class<?>...classes) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(classes);
context.refresh();
this.context = context;
this.springSecurityFilterChain = this.context.getBean("springSecurityFilterChain",Filter.class);
}
private void loadConfig(Class<?>... classes) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(classes);
context.refresh();
this.context = context;
this.springSecurityFilterChain = this.context.getBean(
"springSecurityFilterChain", Filter.class);
}
private void login(Authentication auth) {
HttpSessionSecurityContextRepository repo = new HttpSessionSecurityContextRepository();
HttpRequestResponseHolder requestResponseHolder = new HttpRequestResponseHolder(request, response);
repo.loadContext(requestResponseHolder);
private void login(Authentication auth) {
HttpSessionSecurityContextRepository repo = new HttpSessionSecurityContextRepository();
HttpRequestResponseHolder requestResponseHolder = new HttpRequestResponseHolder(
request, response);
repo.loadContext(requestResponseHolder);
SecurityContextImpl securityContextImpl = new SecurityContextImpl();
securityContextImpl.setAuthentication(auth);
repo.saveContext(securityContextImpl, requestResponseHolder.getRequest(), requestResponseHolder.getResponse());
}
SecurityContextImpl securityContextImpl = new SecurityContextImpl();
securityContextImpl.setAuthentication(auth);
repo.saveContext(securityContextImpl, requestResponseHolder.getRequest(),
requestResponseHolder.getResponse());
}
}

View File

@@ -36,298 +36,270 @@ import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
public class MessageSecurityMetadataSourceRegistryTests {
@Mock
private MessageMatcher<Object> matcher;
@Mock
private MessageMatcher<Object> matcher;
private MessageSecurityMetadataSourceRegistry messages;
private MessageSecurityMetadataSourceRegistry messages;
private Message<String> message;
private Message<String> message;
@Before
public void setup() {
messages = new MessageSecurityMetadataSourceRegistry();
message = MessageBuilder
.withPayload("Hi")
.setHeader(SimpMessageHeaderAccessor.DESTINATION_HEADER, "location")
.setHeader(SimpMessageHeaderAccessor.MESSAGE_TYPE_HEADER, SimpMessageType.MESSAGE)
.build();
}
@Before
public void setup() {
messages = new MessageSecurityMetadataSourceRegistry();
message = MessageBuilder
.withPayload("Hi")
.setHeader(SimpMessageHeaderAccessor.DESTINATION_HEADER, "location")
.setHeader(SimpMessageHeaderAccessor.MESSAGE_TYPE_HEADER,
SimpMessageType.MESSAGE).build();
}
// See https://github.com/spring-projects/spring-security/commit/3f30529039c76facf335d6ca69d18d8ae287f3f9#commitcomment-7412712
// https://jira.spring.io/browse/SPR-11660
@Test
public void simpDestMatchersCustom() {
message = MessageBuilder
.withPayload("Hi")
.setHeader(SimpMessageHeaderAccessor.DESTINATION_HEADER, "price.stock.1.2")
.build();
messages
.simpDestPathMatcher(new AntPathMatcher("."))
.simpDestMatchers("price.stock.*").permitAll();
// See
// https://github.com/spring-projects/spring-security/commit/3f30529039c76facf335d6ca69d18d8ae287f3f9#commitcomment-7412712
// https://jira.spring.io/browse/SPR-11660
@Test
public void simpDestMatchersCustom() {
message = MessageBuilder
.withPayload("Hi")
.setHeader(SimpMessageHeaderAccessor.DESTINATION_HEADER,
"price.stock.1.2").build();
messages.simpDestPathMatcher(new AntPathMatcher("."))
.simpDestMatchers("price.stock.*").permitAll();
assertThat(getAttribute()).isNull();
assertThat(getAttribute()).isNull();
message = MessageBuilder
.withPayload("Hi")
.setHeader(SimpMessageHeaderAccessor.DESTINATION_HEADER, "price.stock.1.2")
.build();
messages
.simpDestPathMatcher(new AntPathMatcher("."))
.simpDestMatchers("price.stock.**").permitAll();
message = MessageBuilder
.withPayload("Hi")
.setHeader(SimpMessageHeaderAccessor.DESTINATION_HEADER,
"price.stock.1.2").build();
messages.simpDestPathMatcher(new AntPathMatcher("."))
.simpDestMatchers("price.stock.**").permitAll();
assertThat(getAttribute()).isEqualTo("permitAll");
}
assertThat(getAttribute()).isEqualTo("permitAll");
}
@Test
public void simpDestMatchersCustomSetAfterMatchersDoesNotMatter() {
message = MessageBuilder
.withPayload("Hi")
.setHeader(SimpMessageHeaderAccessor.DESTINATION_HEADER, "price.stock.1.2")
.build();
messages
.simpDestMatchers("price.stock.*").permitAll()
.simpDestPathMatcher(new AntPathMatcher("."));
@Test
public void simpDestMatchersCustomSetAfterMatchersDoesNotMatter() {
message = MessageBuilder
.withPayload("Hi")
.setHeader(SimpMessageHeaderAccessor.DESTINATION_HEADER,
"price.stock.1.2").build();
messages.simpDestMatchers("price.stock.*").permitAll()
.simpDestPathMatcher(new AntPathMatcher("."));
assertThat(getAttribute()).isNull();
assertThat(getAttribute()).isNull();
message = MessageBuilder
.withPayload("Hi")
.setHeader(SimpMessageHeaderAccessor.DESTINATION_HEADER, "price.stock.1.2")
.build();
messages
.simpDestMatchers("price.stock.**").permitAll()
.simpDestPathMatcher(new AntPathMatcher("."));
message = MessageBuilder
.withPayload("Hi")
.setHeader(SimpMessageHeaderAccessor.DESTINATION_HEADER,
"price.stock.1.2").build();
messages.simpDestMatchers("price.stock.**").permitAll()
.simpDestPathMatcher(new AntPathMatcher("."));
assertThat(getAttribute()).isEqualTo("permitAll");
}
assertThat(getAttribute()).isEqualTo("permitAll");
}
@Test(expected = IllegalArgumentException.class)
public void pathMatcherNull() {
messages.simpDestPathMatcher(null);
}
@Test(expected = IllegalArgumentException.class)
public void pathMatcherNull() {
messages.simpDestPathMatcher(null);
}
@Test
public void matchersFalse() {
messages
.matchers(matcher).permitAll();
@Test
public void matchersFalse() {
messages.matchers(matcher).permitAll();
assertThat(getAttribute()).isNull();
}
assertThat(getAttribute()).isNull();
}
@Test
public void matchersTrue() {
when(matcher.matches(message)).thenReturn(true);
messages
.matchers(matcher).permitAll();
@Test
public void matchersTrue() {
when(matcher.matches(message)).thenReturn(true);
messages.matchers(matcher).permitAll();
assertThat(getAttribute()).isEqualTo("permitAll");
}
assertThat(getAttribute()).isEqualTo("permitAll");
}
@Test
public void simpDestMatchersExact() {
messages
.simpDestMatchers("location").permitAll();
@Test
public void simpDestMatchersExact() {
messages.simpDestMatchers("location").permitAll();
assertThat(getAttribute()).isEqualTo("permitAll");
}
assertThat(getAttribute()).isEqualTo("permitAll");
}
@Test
public void simpDestMatchersMulti() {
messages
.simpDestMatchers("admin/**","api/**").hasRole("ADMIN")
.simpDestMatchers("location").permitAll();
@Test
public void simpDestMatchersMulti() {
messages.simpDestMatchers("admin/**", "api/**").hasRole("ADMIN")
.simpDestMatchers("location").permitAll();
assertThat(getAttribute()).isEqualTo("permitAll");
}
assertThat(getAttribute()).isEqualTo("permitAll");
}
@Test
public void simpDestMatchersRole() {
messages
.simpDestMatchers("admin/**","location/**").hasRole("ADMIN")
.anyMessage().denyAll();
@Test
public void simpDestMatchersRole() {
messages.simpDestMatchers("admin/**", "location/**").hasRole("ADMIN")
.anyMessage().denyAll();
assertThat(getAttribute()).isEqualTo("hasRole('ROLE_ADMIN')");
}
assertThat(getAttribute()).isEqualTo("hasRole('ROLE_ADMIN')");
}
@Test
public void simpDestMatchersAnyRole() {
messages
.simpDestMatchers("admin/**","location/**").hasAnyRole("ADMIN", "ROOT")
.anyMessage().denyAll();
@Test
public void simpDestMatchersAnyRole() {
messages.simpDestMatchers("admin/**", "location/**").hasAnyRole("ADMIN", "ROOT")
.anyMessage().denyAll();
assertThat(getAttribute()).isEqualTo("hasAnyRole('ROLE_ADMIN','ROLE_ROOT')");
}
assertThat(getAttribute()).isEqualTo("hasAnyRole('ROLE_ADMIN','ROLE_ROOT')");
}
@Test
public void simpDestMatchersAuthority() {
messages
.simpDestMatchers("admin/**","location/**").hasAuthority("ROLE_ADMIN")
.anyMessage().fullyAuthenticated();
@Test
public void simpDestMatchersAuthority() {
messages.simpDestMatchers("admin/**", "location/**").hasAuthority("ROLE_ADMIN")
.anyMessage().fullyAuthenticated();
assertThat(getAttribute()).isEqualTo("hasAuthority('ROLE_ADMIN')");
}
assertThat(getAttribute()).isEqualTo("hasAuthority('ROLE_ADMIN')");
}
@Test
public void simpDestMatchersAccess() {
String expected = "hasRole('ROLE_ADMIN') and fullyAuthenticated";
messages
.simpDestMatchers("admin/**","location/**").access(expected)
.anyMessage().denyAll();
@Test
public void simpDestMatchersAccess() {
String expected = "hasRole('ROLE_ADMIN') and fullyAuthenticated";
messages.simpDestMatchers("admin/**", "location/**").access(expected)
.anyMessage().denyAll();
assertThat(getAttribute()).isEqualTo(expected);
}
assertThat(getAttribute()).isEqualTo(expected);
}
@Test
public void simpDestMatchersAnyAuthority() {
messages
.simpDestMatchers("admin/**","location/**").hasAnyAuthority("ROLE_ADMIN", "ROLE_ROOT")
.anyMessage().denyAll();
@Test
public void simpDestMatchersAnyAuthority() {
messages.simpDestMatchers("admin/**", "location/**")
.hasAnyAuthority("ROLE_ADMIN", "ROLE_ROOT").anyMessage().denyAll();
assertThat(getAttribute()).isEqualTo("hasAnyAuthority('ROLE_ADMIN','ROLE_ROOT')");
}
assertThat(getAttribute()).isEqualTo("hasAnyAuthority('ROLE_ADMIN','ROLE_ROOT')");
}
@Test
public void simpDestMatchersRememberMe() {
messages
.simpDestMatchers("admin/**","location/**").rememberMe()
.anyMessage().denyAll();
@Test
public void simpDestMatchersRememberMe() {
messages.simpDestMatchers("admin/**", "location/**").rememberMe().anyMessage()
.denyAll();
assertThat(getAttribute()).isEqualTo("rememberMe");
}
assertThat(getAttribute()).isEqualTo("rememberMe");
}
@Test
public void simpDestMatchersAnonymous() {
messages
.simpDestMatchers("admin/**","location/**").anonymous()
.anyMessage().denyAll();
@Test
public void simpDestMatchersAnonymous() {
messages.simpDestMatchers("admin/**", "location/**").anonymous().anyMessage()
.denyAll();
assertThat(getAttribute()).isEqualTo("anonymous");
}
assertThat(getAttribute()).isEqualTo("anonymous");
}
@Test
public void simpDestMatchersFullyAuthenticated() {
messages
.simpDestMatchers("admin/**","location/**").fullyAuthenticated()
.anyMessage().denyAll();
@Test
public void simpDestMatchersFullyAuthenticated() {
messages.simpDestMatchers("admin/**", "location/**").fullyAuthenticated()
.anyMessage().denyAll();
assertThat(getAttribute()).isEqualTo("fullyAuthenticated");
}
assertThat(getAttribute()).isEqualTo("fullyAuthenticated");
}
@Test
public void simpDestMatchersDenyAll() {
messages
.simpDestMatchers("admin/**","location/**").denyAll()
.anyMessage().permitAll();
@Test
public void simpDestMatchersDenyAll() {
messages.simpDestMatchers("admin/**", "location/**").denyAll().anyMessage()
.permitAll();
assertThat(getAttribute()).isEqualTo("denyAll");
}
assertThat(getAttribute()).isEqualTo("denyAll");
}
@Test
public void simpDestMessageMatchersNotMatch() {
messages
.simpMessageDestMatchers("admin/**").denyAll()
.anyMessage().permitAll();
@Test
public void simpDestMessageMatchersNotMatch() {
messages.simpMessageDestMatchers("admin/**").denyAll().anyMessage().permitAll();
assertThat(getAttribute()).isEqualTo("permitAll");
}
assertThat(getAttribute()).isEqualTo("permitAll");
}
@Test
public void simpDestMessageMatchersMatch() {
messages
.simpMessageDestMatchers("location/**").denyAll()
.anyMessage().permitAll();
@Test
public void simpDestMessageMatchersMatch() {
messages.simpMessageDestMatchers("location/**").denyAll().anyMessage()
.permitAll();
assertThat(getAttribute()).isEqualTo("denyAll");
}
assertThat(getAttribute()).isEqualTo("denyAll");
}
@Test
public void simpDestSubscribeMatchersNotMatch() {
messages
.simpSubscribeDestMatchers("location/**").denyAll()
.anyMessage().permitAll();
@Test
public void simpDestSubscribeMatchersNotMatch() {
messages.simpSubscribeDestMatchers("location/**").denyAll().anyMessage()
.permitAll();
assertThat(getAttribute()).isEqualTo("permitAll");
}
assertThat(getAttribute()).isEqualTo("permitAll");
}
@Test
public void simpDestSubscribeMatchersMatch() {
message = MessageBuilder.fromMessage(message)
.setHeader(SimpMessageHeaderAccessor.MESSAGE_TYPE_HEADER, SimpMessageType.SUBSCRIBE)
.build();
@Test
public void simpDestSubscribeMatchersMatch() {
message = MessageBuilder
.fromMessage(message)
.setHeader(SimpMessageHeaderAccessor.MESSAGE_TYPE_HEADER,
SimpMessageType.SUBSCRIBE).build();
messages
.simpSubscribeDestMatchers("location/**").denyAll()
.anyMessage().permitAll();
messages.simpSubscribeDestMatchers("location/**").denyAll().anyMessage()
.permitAll();
assertThat(getAttribute()).isEqualTo("denyAll");
}
assertThat(getAttribute()).isEqualTo("denyAll");
}
@Test
public void nullDestMatcherNotMatches() {
messages
.nullDestMatcher().denyAll()
.anyMessage().permitAll();
@Test
public void nullDestMatcherNotMatches() {
messages.nullDestMatcher().denyAll().anyMessage().permitAll();
assertThat(getAttribute()).isEqualTo("permitAll");
}
assertThat(getAttribute()).isEqualTo("permitAll");
}
@Test
public void nullDestMatcherMatch() {
message = MessageBuilder
.withPayload("Hi")
.setHeader(SimpMessageHeaderAccessor.MESSAGE_TYPE_HEADER, SimpMessageType.CONNECT)
.build();
@Test
public void nullDestMatcherMatch() {
message = MessageBuilder
.withPayload("Hi")
.setHeader(SimpMessageHeaderAccessor.MESSAGE_TYPE_HEADER,
SimpMessageType.CONNECT).build();
messages
.nullDestMatcher().denyAll()
.anyMessage().permitAll();
messages.nullDestMatcher().denyAll().anyMessage().permitAll();
assertThat(getAttribute()).isEqualTo("denyAll");
}
assertThat(getAttribute()).isEqualTo("denyAll");
}
@Test
public void simpTypeMatchersMatch() {
messages
.simpTypeMatchers(SimpMessageType.MESSAGE).denyAll()
.anyMessage().permitAll();
@Test
public void simpTypeMatchersMatch() {
messages.simpTypeMatchers(SimpMessageType.MESSAGE).denyAll().anyMessage()
.permitAll();
assertThat(getAttribute()).isEqualTo("denyAll");
}
assertThat(getAttribute()).isEqualTo("denyAll");
}
@Test
public void simpTypeMatchersMatchMulti() {
messages
.simpTypeMatchers(SimpMessageType.CONNECT, SimpMessageType.MESSAGE).denyAll()
.anyMessage().permitAll();
@Test
public void simpTypeMatchersMatchMulti() {
messages.simpTypeMatchers(SimpMessageType.CONNECT, SimpMessageType.MESSAGE)
.denyAll().anyMessage().permitAll();
assertThat(getAttribute()).isEqualTo("denyAll");
}
assertThat(getAttribute()).isEqualTo("denyAll");
}
@Test
public void simpTypeMatchersNotMatch() {
messages
.simpTypeMatchers(SimpMessageType.CONNECT).denyAll()
.anyMessage().permitAll();
@Test
public void simpTypeMatchersNotMatch() {
messages.simpTypeMatchers(SimpMessageType.CONNECT).denyAll().anyMessage()
.permitAll();
assertThat(getAttribute()).isEqualTo("permitAll");
}
assertThat(getAttribute()).isEqualTo("permitAll");
}
@Test
public void simpTypeMatchersNotMatchMulti() {
messages
.simpTypeMatchers(SimpMessageType.CONNECT, SimpMessageType.DISCONNECT).denyAll()
.anyMessage().permitAll();
@Test
public void simpTypeMatchersNotMatchMulti() {
messages.simpTypeMatchers(SimpMessageType.CONNECT, SimpMessageType.DISCONNECT)
.denyAll().anyMessage().permitAll();
assertThat(getAttribute()).isEqualTo("permitAll");
}
assertThat(getAttribute()).isEqualTo("permitAll");
}
private String getAttribute() {
MessageSecurityMetadataSource source = messages.createMetadataSource();
Collection<ConfigAttribute> attrs = source.getAttributes(message);
if(attrs == null) {
return null;
}
assertThat(attrs.size()).isEqualTo(1);
return attrs.iterator().next().toString();
}
private String getAttribute() {
MessageSecurityMetadataSource source = messages.createMetadataSource();
Collection<ConfigAttribute> attrs = source.getAttributes(message);
if (attrs == null) {
return null;
}
assertThat(attrs.size()).isEqualTo(1);
return attrs.iterator().next().toString();
}
}

View File

@@ -68,124 +68,127 @@ import static org.fest.assertions.Assertions.assertThat;
import static org.junit.Assert.fail;
public class AbstractSecurityWebSocketMessageBrokerConfigurerDocTests {
AnnotationConfigWebApplicationContext context;
AnnotationConfigWebApplicationContext context;
TestingAuthenticationToken messageUser;
TestingAuthenticationToken messageUser;
CsrfToken token;
CsrfToken token;
String sessionAttr;
String sessionAttr;
@Before
public void setup() {
token = new DefaultCsrfToken("header", "param", "token");
sessionAttr = "sessionAttr";
messageUser = new TestingAuthenticationToken("user","pass","ROLE_USER");
}
@Before
public void setup() {
token = new DefaultCsrfToken("header", "param", "token");
sessionAttr = "sessionAttr";
messageUser = new TestingAuthenticationToken("user", "pass", "ROLE_USER");
}
@After
public void cleanup() {
if(context != null) {
context.close();
}
}
@After
public void cleanup() {
if (context != null) {
context.close();
}
}
@Test
public void securityMappings() {
loadConfig(WebSocketSecurityConfig.class);
@Test
public void securityMappings() {
loadConfig(WebSocketSecurityConfig.class);
clientInboundChannel().send(message("/user/queue/errors",SimpMessageType.SUBSCRIBE));
clientInboundChannel().send(
message("/user/queue/errors", SimpMessageType.SUBSCRIBE));
try {
clientInboundChannel().send(message("/denyAll", SimpMessageType.MESSAGE));
fail("Expected Exception");
} catch(MessageDeliveryException expected) {
assertThat(expected.getCause()).isInstanceOf(AccessDeniedException.class);
}
}
try {
clientInboundChannel().send(message("/denyAll", SimpMessageType.MESSAGE));
fail("Expected Exception");
}
catch (MessageDeliveryException expected) {
assertThat(expected.getCause()).isInstanceOf(AccessDeniedException.class);
}
}
private void loadConfig(Class<?>... configs) {
context = new AnnotationConfigWebApplicationContext();
context.register(configs);
context.register(WebSocketConfig.class, SyncExecutorConfig.class);
context.setServletConfig(new MockServletConfig());
context.refresh();
}
private void loadConfig(Class<?>... configs) {
context = new AnnotationConfigWebApplicationContext();
context.register(configs);
context.register(WebSocketConfig.class,SyncExecutorConfig.class);
context.setServletConfig(new MockServletConfig());
context.refresh();
}
private MessageChannel clientInboundChannel() {
return context.getBean("clientInboundChannel", MessageChannel.class);
}
private MessageChannel clientInboundChannel() {
return context.getBean("clientInboundChannel", MessageChannel.class);
}
private Message<String> message(String destination, SimpMessageType type) {
SimpMessageHeaderAccessor headers = SimpMessageHeaderAccessor.create(type);
return message(headers, destination);
}
private Message<String> message(String destination, SimpMessageType type) {
SimpMessageHeaderAccessor headers = SimpMessageHeaderAccessor.create(type);
return message(headers, destination);
}
private Message<String> message(SimpMessageHeaderAccessor headers, String destination) {
headers.setSessionId("123");
headers.setSessionAttributes(new HashMap<String, Object>());
if (destination != null) {
headers.setDestination(destination);
}
if (messageUser != null) {
headers.setUser(messageUser);
}
return new GenericMessage<String>("hi", headers.getMessageHeaders());
}
private Message<String> message(SimpMessageHeaderAccessor headers, String destination) {
headers.setSessionId("123");
headers.setSessionAttributes(new HashMap<String, Object>());
if(destination != null) {
headers.setDestination(destination);
}
if(messageUser != null) {
headers.setUser(messageUser);
}
return new GenericMessage<String>("hi",headers.getMessageHeaders());
}
@Controller
static class MyController {
@Controller
static class MyController {
@MessageMapping("/authentication")
public void authentication(@AuthenticationPrincipal String un) {
// ... do something ...
}
}
@MessageMapping("/authentication")
public void authentication(@AuthenticationPrincipal String un) {
// ... do something ...
}
}
@Configuration
static class WebSocketSecurityConfig extends
AbstractSecurityWebSocketMessageBrokerConfigurer {
@Configuration
static class WebSocketSecurityConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer {
@Override
protected void configureInbound(MessageSecurityMetadataSourceRegistry messages) {
messages.nullDestMatcher().authenticated()
// <1>
.simpSubscribeDestMatchers("/user/queue/errors").permitAll()
// <2>
.simpDestMatchers("/app/**").hasRole("USER")
// <3>
.simpSubscribeDestMatchers("/user/**", "/topic/friends/*")
.hasRole("USER") // <4>
.simpTypeMatchers(MESSAGE, SUBSCRIBE).denyAll() // <5>
.anyMessage().denyAll(); // <6>
@Override
protected void configureInbound(MessageSecurityMetadataSourceRegistry messages) {
messages
.nullDestMatcher().authenticated() // <1>
.simpSubscribeDestMatchers("/user/queue/errors").permitAll() // <2>
.simpDestMatchers("/app/**").hasRole("USER") // <3>
.simpSubscribeDestMatchers("/user/**", "/topic/friends/*").hasRole("USER") // <4>
.simpTypeMatchers(MESSAGE, SUBSCRIBE).denyAll() // <5>
.anyMessage().denyAll(); // <6>
}
}
}
}
@Configuration
@EnableWebSocketMessageBroker
static class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
@Configuration
@EnableWebSocketMessageBroker
static class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/chat").withSockJS();
}
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry
.addEndpoint("/chat")
.withSockJS();
}
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.enableSimpleBroker("/queue/", "/topic/");
registry.setApplicationDestinationPrefixes("/permitAll", "/denyAll");
}
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.enableSimpleBroker("/queue/", "/topic/");
registry.setApplicationDestinationPrefixes("/permitAll", "/denyAll");
}
@Bean
public MyController myController() {
return new MyController();
}
}
@Bean
public MyController myController() {
return new MyController();
}
}
@Configuration
static class SyncExecutorConfig {
@Bean
public static SyncExecutorSubscribableChannelPostProcessor postProcessor() {
return new SyncExecutorSubscribableChannelPostProcessor();
}
}
@Configuration
static class SyncExecutorConfig {
@Bean
public static SyncExecutorSubscribableChannelPostProcessor postProcessor() {
return new SyncExecutorSubscribableChannelPostProcessor();
}
}
}

View File

@@ -15,7 +15,6 @@
*/
package org.springframework.security.config.annotation.web.socket;
import org.junit.After;
import org.junit.Before;
@@ -67,380 +66,387 @@ import static org.fest.assertions.Assertions.assertThat;
import static org.junit.Assert.fail;
public class AbstractSecurityWebSocketMessageBrokerConfigurerTests {
AnnotationConfigWebApplicationContext context;
TestingAuthenticationToken messageUser;
CsrfToken token;
String sessionAttr;
@Before
public void setup() {
token = new DefaultCsrfToken("header", "param", "token");
sessionAttr = "sessionAttr";
messageUser = new TestingAuthenticationToken("user","pass","ROLE_USER");
}
@After
public void cleanup() {
if(context != null) {
context.close();
}
}
@Test
public void simpleRegistryMappings() {
loadConfig(SockJsSecurityConfig.class);
clientInboundChannel().send(message("/permitAll"));
try {
clientInboundChannel().send(message("/denyAll"));
fail("Expected Exception");
} catch(MessageDeliveryException expected) {
assertThat(expected.getCause()).isInstanceOf(AccessDeniedException.class);
}
}
@Test
public void annonymousSupported() {
loadConfig(SockJsSecurityConfig.class);
messageUser = null;
clientInboundChannel().send(message("/permitAll"));
}
@Test
public void addsAuthenticationPrincipalResolver() throws InterruptedException {
loadConfig(SockJsSecurityConfig.class);
MessageChannel messageChannel = clientInboundChannel();
Message<String> message = message("/permitAll/authentication");
messageChannel.send(message);
assertThat(context.getBean(MyController.class).authenticationPrincipal).isEqualTo((String) messageUser.getPrincipal());
}
@Test
public void addsAuthenticationPrincipalResolverWhenNoAuthorization() throws InterruptedException {
loadConfig(NoInboundSecurityConfig.class);
MessageChannel messageChannel = clientInboundChannel();
Message<String> message = message("/permitAll/authentication");
messageChannel.send(message);
assertThat(context.getBean(MyController.class).authenticationPrincipal).isEqualTo((String) messageUser.getPrincipal());
}
@Test
public void addsCsrfProtectionWhenNoAuthorization() throws InterruptedException {
loadConfig(NoInboundSecurityConfig.class);
SimpMessageHeaderAccessor headers = SimpMessageHeaderAccessor.create(SimpMessageType.CONNECT);
Message<?> message = message(headers, "/authentication");
MessageChannel messageChannel = clientInboundChannel();
try {
messageChannel.send(message);
fail("Expected Exception");
} catch(MessageDeliveryException success) {
assertThat(success.getCause()).isInstanceOf(MissingCsrfTokenException.class);
}
}
@Test
public void csrfProtectionForConnect() throws InterruptedException {
loadConfig(SockJsSecurityConfig.class);
SimpMessageHeaderAccessor headers = SimpMessageHeaderAccessor.create(SimpMessageType.CONNECT);
Message<?> message = message(headers, "/authentication");
MessageChannel messageChannel = clientInboundChannel();
try {
messageChannel.send(message);
fail("Expected Exception");
} catch(MessageDeliveryException success) {
assertThat(success.getCause()).isInstanceOf(MissingCsrfTokenException.class);
}
}
@Test
public void csrfProtectionDisabledForConnect() throws InterruptedException {
loadConfig(CsrfDisabledSockJsSecurityConfig.class);
SimpMessageHeaderAccessor headers = SimpMessageHeaderAccessor.create(SimpMessageType.CONNECT);
Message<?> message = message(headers, "/permitAll/connect");
MessageChannel messageChannel = clientInboundChannel();
messageChannel.send(message);
}
@Test
public void messagesConnectUseCsrfTokenHandshakeInterceptor() throws Exception {
loadConfig(SockJsSecurityConfig.class);
SimpMessageHeaderAccessor headers = SimpMessageHeaderAccessor.create(SimpMessageType.CONNECT);
Message<?> message = message(headers, "/authentication");
MockHttpServletRequest request = sockjsHttpRequest("/chat");
HttpRequestHandler handler = handler(request);
handler.handleRequest(request, new MockHttpServletResponse());
assertHandshake(request);
}
@Test
public void messagesConnectUseCsrfTokenHandshakeInterceptorMultipleMappings() throws Exception {
loadConfig(SockJsSecurityConfig.class);
SimpMessageHeaderAccessor headers = SimpMessageHeaderAccessor.create(SimpMessageType.CONNECT);
Message<?> message = message(headers, "/authentication");
MockHttpServletRequest request = sockjsHttpRequest("/other");
HttpRequestHandler handler = handler(request);
handler.handleRequest(request, new MockHttpServletResponse());
assertHandshake(request);
}
@Test
public void messagesConnectWebSocketUseCsrfTokenHandshakeInterceptor() throws Exception {
loadConfig(WebSocketSecurityConfig.class);
SimpMessageHeaderAccessor headers = SimpMessageHeaderAccessor.create(SimpMessageType.CONNECT);
Message<?> message = message(headers, "/authentication");
MockHttpServletRequest request = websocketHttpRequest("/websocket");
HttpRequestHandler handler = handler(request);
handler.handleRequest(request, new MockHttpServletResponse());
assertHandshake(request);
}
private void assertHandshake(HttpServletRequest request) {
TestHandshakeHandler handshakeHandler = context.getBean(TestHandshakeHandler.class);
assertThat(handshakeHandler.attributes.get(CsrfToken.class.getName())).isSameAs(token);
assertThat(handshakeHandler.attributes.get(sessionAttr)).isEqualTo(request.getSession().getAttribute(sessionAttr));
}
private HttpRequestHandler handler(HttpServletRequest request) throws Exception {
HandlerMapping handlerMapping = context.getBean(HandlerMapping.class);
return (HttpRequestHandler) handlerMapping.getHandler(request).getHandler();
}
private MockHttpServletRequest websocketHttpRequest(String mapping) {
MockHttpServletRequest request = sockjsHttpRequest(mapping);
request.setRequestURI(mapping);
return request;
}
private MockHttpServletRequest sockjsHttpRequest(String mapping) {
MockHttpServletRequest request = new MockHttpServletRequest();
request.setMethod("GET");
request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "/289/tpyx6mde/websocket");
request.setRequestURI(mapping + "/289/tpyx6mde/websocket");
request.getSession().setAttribute(sessionAttr,"sessionValue");
request.setAttribute(CsrfToken.class.getName(), token);
return request;
}
private Message<String> message(String destination) {
SimpMessageHeaderAccessor headers = SimpMessageHeaderAccessor.create();
return message(headers, destination);
}
private Message<String> message(SimpMessageHeaderAccessor headers, String destination) {
headers.setSessionId("123");
headers.setSessionAttributes(new HashMap<String, Object>());
if(destination != null) {
headers.setDestination(destination);
}
if(messageUser != null) {
headers.setUser(messageUser);
}
return new GenericMessage<String>("hi",headers.getMessageHeaders());
}
private MessageChannel clientInboundChannel() {
return context.getBean("clientInboundChannel", MessageChannel.class);
}
private void loadConfig(Class<?>... configs) {
context = new AnnotationConfigWebApplicationContext();
context.register(configs);
context.setServletConfig(new MockServletConfig());
context.refresh();
}
@Controller
static class MyController {
String authenticationPrincipal;
MyCustomArgument myCustomArgument;
@MessageMapping("/authentication")
public void authentication(@AuthenticationPrincipal String un) {
this.authenticationPrincipal = un;
}
@MessageMapping("/myCustom")
public void myCustom(MyCustomArgument myCustomArgument) {
this.myCustomArgument = myCustomArgument;
}
}
static class MyCustomArgument {
MyCustomArgument(String notDefaultConstr) {}
}
static class MyCustomArgumentResolver implements HandlerMethodArgumentResolver {
public boolean supportsParameter(MethodParameter parameter) {
return parameter.getParameterType().isAssignableFrom(MyCustomArgument.class);
}
public Object resolveArgument(MethodParameter parameter, Message<?> message) throws Exception {
return new MyCustomArgument("");
}
}
static class TestHandshakeHandler implements HandshakeHandler {
Map<String, Object> attributes;
public boolean doHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws HandshakeFailureException {
this.attributes = attributes;
if(wsHandler instanceof SockJsWebSocketHandler) {
// work around SPR-12716
SockJsWebSocketHandler sockJs = (SockJsWebSocketHandler) wsHandler;
WebSocketServerSockJsSession session = (WebSocketServerSockJsSession) ReflectionTestUtils.getField(sockJs, "sockJsSession");
this.attributes = session.getAttributes();
}
return true;
}
}
@Configuration
@EnableWebSocketMessageBroker
@Import(SyncExecutorConfig.class)
static class SockJsSecurityConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer {
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry
.addEndpoint("/other")
.setHandshakeHandler(testHandshakeHandler())
.withSockJS()
.setInterceptors(new HttpSessionHandshakeInterceptor());
registry
.addEndpoint("/chat")
.setHandshakeHandler(testHandshakeHandler())
.withSockJS()
.setInterceptors(new HttpSessionHandshakeInterceptor());
}
@Override
protected void configureInbound(MessageSecurityMetadataSourceRegistry messages) {
messages
.simpDestMatchers("/permitAll/**").permitAll()
.anyMessage().denyAll();
}
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.enableSimpleBroker("/queue/", "/topic/");
registry.setApplicationDestinationPrefixes("/permitAll", "/denyAll");
}
@Bean
public MyController myController() {
return new MyController();
}
@Bean
public TestHandshakeHandler testHandshakeHandler() {
return new TestHandshakeHandler();
}
}
@Configuration
@EnableWebSocketMessageBroker
@Import(SyncExecutorConfig.class)
static class NoInboundSecurityConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer {
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry
.addEndpoint("/other")
.withSockJS()
.setInterceptors(new HttpSessionHandshakeInterceptor());
registry
.addEndpoint("/chat")
.withSockJS()
.setInterceptors(new HttpSessionHandshakeInterceptor());
}
@Override
protected void configureInbound(MessageSecurityMetadataSourceRegistry messages) {
}
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.enableSimpleBroker("/queue/", "/topic/");
registry.setApplicationDestinationPrefixes("/permitAll", "/denyAll");
}
@Bean
public MyController myController() {
return new MyController();
}
}
@Configuration
static class CsrfDisabledSockJsSecurityConfig extends SockJsSecurityConfig {
@Override
protected boolean sameOriginDisabled() {
return true;
}
}
@Configuration
@EnableWebSocketMessageBroker
@Import(SyncExecutorConfig.class)
static class WebSocketSecurityConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer {
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry
.addEndpoint("/websocket")
.setHandshakeHandler(testHandshakeHandler())
.addInterceptors(new HttpSessionHandshakeInterceptor());
}
@Override
protected void configureInbound(MessageSecurityMetadataSourceRegistry messages) {
messages
.simpDestMatchers("/permitAll/**").permitAll()
.anyMessage().denyAll();
}
@Bean
public TestHandshakeHandler testHandshakeHandler() {
return new TestHandshakeHandler();
}
}
@Configuration
static class SyncExecutorConfig {
@Bean
public static SyncExecutorSubscribableChannelPostProcessor postProcessor() {
return new SyncExecutorSubscribableChannelPostProcessor();
}
}
AnnotationConfigWebApplicationContext context;
TestingAuthenticationToken messageUser;
CsrfToken token;
String sessionAttr;
@Before
public void setup() {
token = new DefaultCsrfToken("header", "param", "token");
sessionAttr = "sessionAttr";
messageUser = new TestingAuthenticationToken("user", "pass", "ROLE_USER");
}
@After
public void cleanup() {
if (context != null) {
context.close();
}
}
@Test
public void simpleRegistryMappings() {
loadConfig(SockJsSecurityConfig.class);
clientInboundChannel().send(message("/permitAll"));
try {
clientInboundChannel().send(message("/denyAll"));
fail("Expected Exception");
}
catch (MessageDeliveryException expected) {
assertThat(expected.getCause()).isInstanceOf(AccessDeniedException.class);
}
}
@Test
public void annonymousSupported() {
loadConfig(SockJsSecurityConfig.class);
messageUser = null;
clientInboundChannel().send(message("/permitAll"));
}
@Test
public void addsAuthenticationPrincipalResolver() throws InterruptedException {
loadConfig(SockJsSecurityConfig.class);
MessageChannel messageChannel = clientInboundChannel();
Message<String> message = message("/permitAll/authentication");
messageChannel.send(message);
assertThat(context.getBean(MyController.class).authenticationPrincipal)
.isEqualTo((String) messageUser.getPrincipal());
}
@Test
public void addsAuthenticationPrincipalResolverWhenNoAuthorization()
throws InterruptedException {
loadConfig(NoInboundSecurityConfig.class);
MessageChannel messageChannel = clientInboundChannel();
Message<String> message = message("/permitAll/authentication");
messageChannel.send(message);
assertThat(context.getBean(MyController.class).authenticationPrincipal)
.isEqualTo((String) messageUser.getPrincipal());
}
@Test
public void addsCsrfProtectionWhenNoAuthorization() throws InterruptedException {
loadConfig(NoInboundSecurityConfig.class);
SimpMessageHeaderAccessor headers = SimpMessageHeaderAccessor
.create(SimpMessageType.CONNECT);
Message<?> message = message(headers, "/authentication");
MessageChannel messageChannel = clientInboundChannel();
try {
messageChannel.send(message);
fail("Expected Exception");
}
catch (MessageDeliveryException success) {
assertThat(success.getCause()).isInstanceOf(MissingCsrfTokenException.class);
}
}
@Test
public void csrfProtectionForConnect() throws InterruptedException {
loadConfig(SockJsSecurityConfig.class);
SimpMessageHeaderAccessor headers = SimpMessageHeaderAccessor
.create(SimpMessageType.CONNECT);
Message<?> message = message(headers, "/authentication");
MessageChannel messageChannel = clientInboundChannel();
try {
messageChannel.send(message);
fail("Expected Exception");
}
catch (MessageDeliveryException success) {
assertThat(success.getCause()).isInstanceOf(MissingCsrfTokenException.class);
}
}
@Test
public void csrfProtectionDisabledForConnect() throws InterruptedException {
loadConfig(CsrfDisabledSockJsSecurityConfig.class);
SimpMessageHeaderAccessor headers = SimpMessageHeaderAccessor
.create(SimpMessageType.CONNECT);
Message<?> message = message(headers, "/permitAll/connect");
MessageChannel messageChannel = clientInboundChannel();
messageChannel.send(message);
}
@Test
public void messagesConnectUseCsrfTokenHandshakeInterceptor() throws Exception {
loadConfig(SockJsSecurityConfig.class);
SimpMessageHeaderAccessor headers = SimpMessageHeaderAccessor
.create(SimpMessageType.CONNECT);
Message<?> message = message(headers, "/authentication");
MockHttpServletRequest request = sockjsHttpRequest("/chat");
HttpRequestHandler handler = handler(request);
handler.handleRequest(request, new MockHttpServletResponse());
assertHandshake(request);
}
@Test
public void messagesConnectUseCsrfTokenHandshakeInterceptorMultipleMappings()
throws Exception {
loadConfig(SockJsSecurityConfig.class);
SimpMessageHeaderAccessor headers = SimpMessageHeaderAccessor
.create(SimpMessageType.CONNECT);
Message<?> message = message(headers, "/authentication");
MockHttpServletRequest request = sockjsHttpRequest("/other");
HttpRequestHandler handler = handler(request);
handler.handleRequest(request, new MockHttpServletResponse());
assertHandshake(request);
}
@Test
public void messagesConnectWebSocketUseCsrfTokenHandshakeInterceptor()
throws Exception {
loadConfig(WebSocketSecurityConfig.class);
SimpMessageHeaderAccessor headers = SimpMessageHeaderAccessor
.create(SimpMessageType.CONNECT);
Message<?> message = message(headers, "/authentication");
MockHttpServletRequest request = websocketHttpRequest("/websocket");
HttpRequestHandler handler = handler(request);
handler.handleRequest(request, new MockHttpServletResponse());
assertHandshake(request);
}
private void assertHandshake(HttpServletRequest request) {
TestHandshakeHandler handshakeHandler = context
.getBean(TestHandshakeHandler.class);
assertThat(handshakeHandler.attributes.get(CsrfToken.class.getName())).isSameAs(
token);
assertThat(handshakeHandler.attributes.get(sessionAttr)).isEqualTo(
request.getSession().getAttribute(sessionAttr));
}
private HttpRequestHandler handler(HttpServletRequest request) throws Exception {
HandlerMapping handlerMapping = context.getBean(HandlerMapping.class);
return (HttpRequestHandler) handlerMapping.getHandler(request).getHandler();
}
private MockHttpServletRequest websocketHttpRequest(String mapping) {
MockHttpServletRequest request = sockjsHttpRequest(mapping);
request.setRequestURI(mapping);
return request;
}
private MockHttpServletRequest sockjsHttpRequest(String mapping) {
MockHttpServletRequest request = new MockHttpServletRequest();
request.setMethod("GET");
request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE,
"/289/tpyx6mde/websocket");
request.setRequestURI(mapping + "/289/tpyx6mde/websocket");
request.getSession().setAttribute(sessionAttr, "sessionValue");
request.setAttribute(CsrfToken.class.getName(), token);
return request;
}
private Message<String> message(String destination) {
SimpMessageHeaderAccessor headers = SimpMessageHeaderAccessor.create();
return message(headers, destination);
}
private Message<String> message(SimpMessageHeaderAccessor headers, String destination) {
headers.setSessionId("123");
headers.setSessionAttributes(new HashMap<String, Object>());
if (destination != null) {
headers.setDestination(destination);
}
if (messageUser != null) {
headers.setUser(messageUser);
}
return new GenericMessage<String>("hi", headers.getMessageHeaders());
}
private MessageChannel clientInboundChannel() {
return context.getBean("clientInboundChannel", MessageChannel.class);
}
private void loadConfig(Class<?>... configs) {
context = new AnnotationConfigWebApplicationContext();
context.register(configs);
context.setServletConfig(new MockServletConfig());
context.refresh();
}
@Controller
static class MyController {
String authenticationPrincipal;
MyCustomArgument myCustomArgument;
@MessageMapping("/authentication")
public void authentication(@AuthenticationPrincipal String un) {
this.authenticationPrincipal = un;
}
@MessageMapping("/myCustom")
public void myCustom(MyCustomArgument myCustomArgument) {
this.myCustomArgument = myCustomArgument;
}
}
static class MyCustomArgument {
MyCustomArgument(String notDefaultConstr) {
}
}
static class MyCustomArgumentResolver implements HandlerMethodArgumentResolver {
public boolean supportsParameter(MethodParameter parameter) {
return parameter.getParameterType().isAssignableFrom(MyCustomArgument.class);
}
public Object resolveArgument(MethodParameter parameter, Message<?> message)
throws Exception {
return new MyCustomArgument("");
}
}
static class TestHandshakeHandler implements HandshakeHandler {
Map<String, Object> attributes;
public boolean doHandshake(ServerHttpRequest request,
ServerHttpResponse response, WebSocketHandler wsHandler,
Map<String, Object> attributes) throws HandshakeFailureException {
this.attributes = attributes;
if (wsHandler instanceof SockJsWebSocketHandler) {
// work around SPR-12716
SockJsWebSocketHandler sockJs = (SockJsWebSocketHandler) wsHandler;
WebSocketServerSockJsSession session = (WebSocketServerSockJsSession) ReflectionTestUtils
.getField(sockJs, "sockJsSession");
this.attributes = session.getAttributes();
}
return true;
}
}
@Configuration
@EnableWebSocketMessageBroker
@Import(SyncExecutorConfig.class)
static class SockJsSecurityConfig extends
AbstractSecurityWebSocketMessageBrokerConfigurer {
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/other").setHandshakeHandler(testHandshakeHandler())
.withSockJS().setInterceptors(new HttpSessionHandshakeInterceptor());
registry.addEndpoint("/chat").setHandshakeHandler(testHandshakeHandler())
.withSockJS().setInterceptors(new HttpSessionHandshakeInterceptor());
}
@Override
protected void configureInbound(MessageSecurityMetadataSourceRegistry messages) {
messages.simpDestMatchers("/permitAll/**").permitAll().anyMessage().denyAll();
}
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.enableSimpleBroker("/queue/", "/topic/");
registry.setApplicationDestinationPrefixes("/permitAll", "/denyAll");
}
@Bean
public MyController myController() {
return new MyController();
}
@Bean
public TestHandshakeHandler testHandshakeHandler() {
return new TestHandshakeHandler();
}
}
@Configuration
@EnableWebSocketMessageBroker
@Import(SyncExecutorConfig.class)
static class NoInboundSecurityConfig extends
AbstractSecurityWebSocketMessageBrokerConfigurer {
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/other").withSockJS()
.setInterceptors(new HttpSessionHandshakeInterceptor());
registry.addEndpoint("/chat").withSockJS()
.setInterceptors(new HttpSessionHandshakeInterceptor());
}
@Override
protected void configureInbound(MessageSecurityMetadataSourceRegistry messages) {
}
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.enableSimpleBroker("/queue/", "/topic/");
registry.setApplicationDestinationPrefixes("/permitAll", "/denyAll");
}
@Bean
public MyController myController() {
return new MyController();
}
}
@Configuration
static class CsrfDisabledSockJsSecurityConfig extends SockJsSecurityConfig {
@Override
protected boolean sameOriginDisabled() {
return true;
}
}
@Configuration
@EnableWebSocketMessageBroker
@Import(SyncExecutorConfig.class)
static class WebSocketSecurityConfig extends
AbstractSecurityWebSocketMessageBrokerConfigurer {
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/websocket")
.setHandshakeHandler(testHandshakeHandler())
.addInterceptors(new HttpSessionHandshakeInterceptor());
}
@Override
protected void configureInbound(MessageSecurityMetadataSourceRegistry messages) {
messages.simpDestMatchers("/permitAll/**").permitAll().anyMessage().denyAll();
}
@Bean
public TestHandshakeHandler testHandshakeHandler() {
return new TestHandshakeHandler();
}
}
@Configuration
static class SyncExecutorConfig {
@Bean
public static SyncExecutorSubscribableChannelPostProcessor postProcessor() {
return new SyncExecutorSubscribableChannelPostProcessor();
}
}
}

View File

@@ -24,17 +24,19 @@ import org.springframework.messaging.support.ExecutorSubscribableChannel;
*/
public class SyncExecutorSubscribableChannelPostProcessor implements BeanPostProcessor {
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if(bean instanceof ExecutorSubscribableChannel) {
ExecutorSubscribableChannel original = (ExecutorSubscribableChannel) bean;
ExecutorSubscribableChannel channel = new ExecutorSubscribableChannel();
channel.setInterceptors(original.getInterceptors());
return channel;
}
return bean;
}
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
if (bean instanceof ExecutorSubscribableChannel) {
ExecutorSubscribableChannel original = (ExecutorSubscribableChannel) bean;
ExecutorSubscribableChannel channel = new ExecutorSubscribableChannel();
channel.setInterceptors(original.getInterceptors());
return channel;
}
return bean;
}
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
return bean;
}
}

View File

@@ -21,61 +21,63 @@ import org.springframework.security.util.FieldUtils;
* @author Luke Taylor
*/
public class AuthenticationManagerBeanDefinitionParserTests {
private static final String CONTEXT =
"<authentication-manager id='am'>" +
" <authentication-provider>" +
" <user-service>" +
" <user name='bob' password='bobspassword' authorities='ROLE_A,ROLE_B' />" +
" </user-service>" +
" </authentication-provider>" +
"</authentication-manager>";
private AbstractXmlApplicationContext appContext;
private static final String CONTEXT = "<authentication-manager id='am'>"
+ " <authentication-provider>"
+ " <user-service>"
+ " <user name='bob' password='bobspassword' authorities='ROLE_A,ROLE_B' />"
+ " </user-service>" + " </authentication-provider>"
+ "</authentication-manager>";
private AbstractXmlApplicationContext appContext;
@Test
// SEC-1225
public void providersAreRegisteredAsTopLevelBeans() throws Exception {
setContext(CONTEXT);
assertEquals(1, appContext.getBeansOfType(AuthenticationProvider.class).size());
}
@Test
// SEC-1225
public void providersAreRegisteredAsTopLevelBeans() throws Exception {
setContext(CONTEXT);
assertEquals(1, appContext.getBeansOfType(AuthenticationProvider.class).size());
}
@Test
public void eventsArePublishedByDefault() throws Exception {
setContext(CONTEXT);
AuthListener listener = new AuthListener();
appContext.addApplicationListener(listener);
@Test
public void eventsArePublishedByDefault() throws Exception {
setContext(CONTEXT);
AuthListener listener = new AuthListener();
appContext.addApplicationListener(listener);
ProviderManager pm = (ProviderManager) appContext.getBeansOfType(ProviderManager.class).values().toArray()[0];
Object eventPublisher = FieldUtils.getFieldValue(pm, "eventPublisher");
assertNotNull(eventPublisher);
assertTrue(eventPublisher instanceof DefaultAuthenticationEventPublisher);
ProviderManager pm = (ProviderManager) appContext
.getBeansOfType(ProviderManager.class).values().toArray()[0];
Object eventPublisher = FieldUtils.getFieldValue(pm, "eventPublisher");
assertNotNull(eventPublisher);
assertTrue(eventPublisher instanceof DefaultAuthenticationEventPublisher);
pm.authenticate(new UsernamePasswordAuthenticationToken("bob", "bobspassword"));
assertEquals(1, listener.events.size());
}
pm.authenticate(new UsernamePasswordAuthenticationToken("bob", "bobspassword"));
assertEquals(1, listener.events.size());
}
@Test
public void credentialsAreClearedByDefault() throws Exception {
setContext(CONTEXT);
ProviderManager pm = (ProviderManager) appContext.getBeansOfType(ProviderManager.class).values().toArray()[0];
assertTrue(pm.isEraseCredentialsAfterAuthentication());
}
@Test
public void credentialsAreClearedByDefault() throws Exception {
setContext(CONTEXT);
ProviderManager pm = (ProviderManager) appContext
.getBeansOfType(ProviderManager.class).values().toArray()[0];
assertTrue(pm.isEraseCredentialsAfterAuthentication());
}
@Test
public void clearCredentialsPropertyIsRespected() throws Exception {
setContext("<authentication-manager erase-credentials='false'/>");
ProviderManager pm = (ProviderManager) appContext.getBeansOfType(ProviderManager.class).values().toArray()[0];
assertFalse(pm.isEraseCredentialsAfterAuthentication());
}
@Test
public void clearCredentialsPropertyIsRespected() throws Exception {
setContext("<authentication-manager erase-credentials='false'/>");
ProviderManager pm = (ProviderManager) appContext
.getBeansOfType(ProviderManager.class).values().toArray()[0];
assertFalse(pm.isEraseCredentialsAfterAuthentication());
}
private void setContext(String context) {
appContext = new InMemoryXmlApplicationContext(context);
}
private void setContext(String context) {
appContext = new InMemoryXmlApplicationContext(context);
}
private static class AuthListener implements ApplicationListener<AbstractAuthenticationEvent> {
List<AbstractAuthenticationEvent> events = new ArrayList<AbstractAuthenticationEvent>();
private static class AuthListener implements
ApplicationListener<AbstractAuthenticationEvent> {
List<AbstractAuthenticationEvent> events = new ArrayList<AbstractAuthenticationEvent>();
public void onApplicationEvent(AbstractAuthenticationEvent event) {
events.add(event);
}
}
public void onApplicationEvent(AbstractAuthenticationEvent event) {
events.add(event);
}
}
}

View File

@@ -24,166 +24,167 @@ import java.util.List;
* @author Luke Taylor
*/
public class AuthenticationProviderBeanDefinitionParserTests {
private AbstractXmlApplicationContext appContext;
private UsernamePasswordAuthenticationToken bob = new UsernamePasswordAuthenticationToken("bob", "bobspassword");
private AbstractXmlApplicationContext appContext;
private UsernamePasswordAuthenticationToken bob = new UsernamePasswordAuthenticationToken(
"bob", "bobspassword");
@After
public void closeAppContext() {
if (appContext != null) {
appContext.close();
}
}
@After
public void closeAppContext() {
if (appContext != null) {
appContext.close();
}
}
@Test
public void worksWithEmbeddedUserService() {
setContext(" <authentication-provider>" +
" <user-service>" +
" <user name='bob' password='bobspassword' authorities='ROLE_A' />" +
" </user-service>" +
" </authentication-provider>");
getProvider().authenticate(bob);
}
@Test
public void worksWithEmbeddedUserService() {
setContext(" <authentication-provider>"
+ " <user-service>"
+ " <user name='bob' password='bobspassword' authorities='ROLE_A' />"
+ " </user-service>" + " </authentication-provider>");
getProvider().authenticate(bob);
}
@Test
public void externalUserServiceRefWorks() throws Exception {
appContext = new InMemoryXmlApplicationContext(
" <authentication-manager>" +
" <authentication-provider user-service-ref='myUserService' />" +
" </authentication-manager>" +
" <user-service id='myUserService'>" +
" <user name='bob' password='bobspassword' authorities='ROLE_A' />" +
" </user-service>");
getProvider().authenticate(bob);
}
@Test
public void externalUserServiceRefWorks() throws Exception {
appContext = new InMemoryXmlApplicationContext(
" <authentication-manager>"
+ " <authentication-provider user-service-ref='myUserService' />"
+ " </authentication-manager>"
+ " <user-service id='myUserService'>"
+ " <user name='bob' password='bobspassword' authorities='ROLE_A' />"
+ " </user-service>");
getProvider().authenticate(bob);
}
@Test
public void providerWithBCryptPasswordEncoderWorks() throws Exception {
setContext(" <authentication-provider>" +
" <password-encoder hash='bcrypt'/>" +
" <user-service>" +
" <user name='bob' password='$2a$05$dRmjl1T05J7rvCPD2NgsHesCEJHww3pdmesUhjM3PD4m/gaEYyx/G' authorities='ROLE_A' />" +
" </user-service>" +
" </authentication-provider>");
@Test
public void providerWithBCryptPasswordEncoderWorks() throws Exception {
setContext(" <authentication-provider>"
+ " <password-encoder hash='bcrypt'/>"
+ " <user-service>"
+ " <user name='bob' password='$2a$05$dRmjl1T05J7rvCPD2NgsHesCEJHww3pdmesUhjM3PD4m/gaEYyx/G' authorities='ROLE_A' />"
+ " </user-service>" + " </authentication-provider>");
getProvider().authenticate(bob);
}
getProvider().authenticate(bob);
}
@Test(expected=BeanDefinitionParsingException.class)
public void bCryptAndSaltSourceRaisesException() throws Exception {
appContext = new InMemoryXmlApplicationContext("" +
" <authentication-manager>" +
" <authentication-provider>" +
" <password-encoder hash='bcrypt'>" +
" <salt-source ref='saltSource'/>" +
" </password-encoder>" +
" <user-service>" +
" <user name='bob' password='$2a$05$dRmjl1T05J7rvCPD2NgsHesCEJHww3pdmesUhjM3PD4m/gaEYyx/G' authorities='ROLE_A' />" +
" </user-service>" +
" </authentication-provider>" +
" </authentication-manager>" +
" <b:bean id='saltSource' class='" + ReflectionSaltSource.class.getName() +"'>" +
" <b:property name='userPropertyToUse' value='username'/>" +
" </b:bean>");
}
@Test
public void providerWithMd5PasswordEncoderWorks() throws Exception {
setContext(" <authentication-provider>" +
" <password-encoder hash='md5'/>" +
" <user-service>" +
" <user name='bob' password='12b141f35d58b8b3a46eea65e6ac179e' authorities='ROLE_A' />" +
" </user-service>" +
" </authentication-provider>");
@Test(expected = BeanDefinitionParsingException.class)
public void bCryptAndSaltSourceRaisesException() throws Exception {
appContext = new InMemoryXmlApplicationContext(
""
+ " <authentication-manager>"
+ " <authentication-provider>"
+ " <password-encoder hash='bcrypt'>"
+ " <salt-source ref='saltSource'/>"
+ " </password-encoder>"
+ " <user-service>"
+ " <user name='bob' password='$2a$05$dRmjl1T05J7rvCPD2NgsHesCEJHww3pdmesUhjM3PD4m/gaEYyx/G' authorities='ROLE_A' />"
+ " </user-service>" + " </authentication-provider>"
+ " </authentication-manager>"
+ " <b:bean id='saltSource' class='"
+ ReflectionSaltSource.class.getName() + "'>"
+ " <b:property name='userPropertyToUse' value='username'/>"
+ " </b:bean>");
}
getProvider().authenticate(bob);
}
@Test
public void providerWithMd5PasswordEncoderWorks() throws Exception {
setContext(" <authentication-provider>"
+ " <password-encoder hash='md5'/>"
+ " <user-service>"
+ " <user name='bob' password='12b141f35d58b8b3a46eea65e6ac179e' authorities='ROLE_A' />"
+ " </user-service>" + " </authentication-provider>");
@Test
public void providerWithShaPasswordEncoderWorks() throws Exception {
setContext(" <authentication-provider>" +
" <password-encoder hash='{sha}'/>" +
" <user-service>" +
" <user name='bob' password='{SSHA}PpuEwfdj7M1rs0C2W4ssSM2XEN/Y6S5U' authorities='ROLE_A' />" +
" </user-service>" +
" </authentication-provider>");
getProvider().authenticate(bob);
}
getProvider().authenticate(bob);
}
@Test
public void providerWithShaPasswordEncoderWorks() throws Exception {
setContext(" <authentication-provider>"
+ " <password-encoder hash='{sha}'/>"
+ " <user-service>"
+ " <user name='bob' password='{SSHA}PpuEwfdj7M1rs0C2W4ssSM2XEN/Y6S5U' authorities='ROLE_A' />"
+ " </user-service>" + " </authentication-provider>");
@Test
public void providerWithSha256PasswordEncoderIsSupported() throws Exception {
setContext(" <authentication-provider>" +
" <password-encoder hash='sha-256'/>" +
" <user-service>" +
" <user name='bob' password='notused' authorities='ROLE_A' />" +
" </user-service>" +
" </authentication-provider>");
getProvider().authenticate(bob);
}
ShaPasswordEncoder encoder = (ShaPasswordEncoder) FieldUtils.getFieldValue(getProvider(), "passwordEncoder");
assertEquals("SHA-256", encoder.getAlgorithm());
}
@Test
public void providerWithSha256PasswordEncoderIsSupported() throws Exception {
setContext(" <authentication-provider>"
+ " <password-encoder hash='sha-256'/>"
+ " <user-service>"
+ " <user name='bob' password='notused' authorities='ROLE_A' />"
+ " </user-service>" + " </authentication-provider>");
@Test
public void passwordIsBase64EncodedWhenBase64IsEnabled() throws Exception {
setContext(" <authentication-provider>" +
" <password-encoder hash='md5' base64='true'/>" +
" <user-service>" +
" <user name='bob' password='ErFB811YuLOkbupl5qwXng==' authorities='ROLE_A' />" +
" </user-service>" +
" </authentication-provider>");
ShaPasswordEncoder encoder = (ShaPasswordEncoder) FieldUtils.getFieldValue(
getProvider(), "passwordEncoder");
assertEquals("SHA-256", encoder.getAlgorithm());
}
getProvider().authenticate(bob);
}
@Test
public void passwordIsBase64EncodedWhenBase64IsEnabled() throws Exception {
setContext(" <authentication-provider>"
+ " <password-encoder hash='md5' base64='true'/>"
+ " <user-service>"
+ " <user name='bob' password='ErFB811YuLOkbupl5qwXng==' authorities='ROLE_A' />"
+ " </user-service>" + " </authentication-provider>");
@Test
public void externalUserServicePasswordEncoderAndSaltSourceWork() throws Exception {
appContext = new InMemoryXmlApplicationContext(
" <authentication-manager>" +
" <authentication-provider user-service-ref='customUserService'>" +
" <password-encoder ref='customPasswordEncoder'>" +
" <salt-source ref='saltSource'/>" +
" </password-encoder>" +
" </authentication-provider>" +
" </authentication-manager>" +
getProvider().authenticate(bob);
}
" <b:bean id='customPasswordEncoder' " +
"class='org.springframework.security.authentication.encoding.Md5PasswordEncoder'/>" +
" <b:bean id='saltSource' " +
" class='" + ReflectionSaltSource.class.getName() +"'>" +
" <b:property name='userPropertyToUse' value='username'/>" +
" </b:bean>" +
" <b:bean id='customUserService' " +
" class='org.springframework.security.provisioning.InMemoryUserDetailsManager'>" +
" <b:constructor-arg>" +
" <b:props>" +
" <b:prop key='bob'>f117f0862384e9497ff4f470e3522606,ROLE_A</b:prop>" +
" </b:props>" +
" </b:constructor-arg>" +
" </b:bean>");
getProvider().authenticate(bob);
}
@Test
public void externalUserServicePasswordEncoderAndSaltSourceWork() throws Exception {
appContext = new InMemoryXmlApplicationContext(
" <authentication-manager>"
+ " <authentication-provider user-service-ref='customUserService'>"
+ " <password-encoder ref='customPasswordEncoder'>"
+ " <salt-source ref='saltSource'/>"
+ " </password-encoder>"
+ " </authentication-provider>"
+ " </authentication-manager>"
+
// SEC-1466
@Test(expected=BeanDefinitionParsingException.class)
public void exernalProviderDoesNotSupportChildElements() throws Exception {
appContext = new InMemoryXmlApplicationContext(
" <authentication-manager>" +
" <authentication-provider ref='aProvider'> " +
" <password-encoder ref='customPasswordEncoder'/>" +
" </authentication-provider>" +
" </authentication-manager>" +
" <b:bean id='aProvider' class='org.springframework.security.authentication.TestingAuthenticationProvider'/>" +
" <b:bean id='customPasswordEncoder' " +
" class='org.springframework.security.authentication.encoding.Md5PasswordEncoder'/>");
}
" <b:bean id='customPasswordEncoder' "
+ "class='org.springframework.security.authentication.encoding.Md5PasswordEncoder'/>"
+ " <b:bean id='saltSource' "
+ " class='"
+ ReflectionSaltSource.class.getName()
+ "'>"
+ " <b:property name='userPropertyToUse' value='username'/>"
+ " </b:bean>"
+ " <b:bean id='customUserService' "
+ " class='org.springframework.security.provisioning.InMemoryUserDetailsManager'>"
+ " <b:constructor-arg>"
+ " <b:props>"
+ " <b:prop key='bob'>f117f0862384e9497ff4f470e3522606,ROLE_A</b:prop>"
+ " </b:props>" + " </b:constructor-arg>"
+ " </b:bean>");
getProvider().authenticate(bob);
}
private AuthenticationProvider getProvider() {
List<AuthenticationProvider> providers =
((ProviderManager)appContext.getBean(BeanIds.AUTHENTICATION_MANAGER)).getProviders();
// SEC-1466
@Test(expected = BeanDefinitionParsingException.class)
public void exernalProviderDoesNotSupportChildElements() throws Exception {
appContext = new InMemoryXmlApplicationContext(
" <authentication-manager>"
+ " <authentication-provider ref='aProvider'> "
+ " <password-encoder ref='customPasswordEncoder'/>"
+ " </authentication-provider>"
+ " </authentication-manager>"
+ " <b:bean id='aProvider' class='org.springframework.security.authentication.TestingAuthenticationProvider'/>"
+ " <b:bean id='customPasswordEncoder' "
+ " class='org.springframework.security.authentication.encoding.Md5PasswordEncoder'/>");
}
return providers.get(0);
}
private AuthenticationProvider getProvider() {
List<AuthenticationProvider> providers = ((ProviderManager) appContext
.getBean(BeanIds.AUTHENTICATION_MANAGER)).getProviders();
private void setContext(String context) {
appContext = new InMemoryXmlApplicationContext("<authentication-manager>" + context + "</authentication-manager>");
}
return providers.get(0);
}
private void setContext(String context) {
appContext = new InMemoryXmlApplicationContext("<authentication-manager>"
+ context + "</authentication-manager>");
}
}

View File

@@ -25,116 +25,127 @@ import org.w3c.dom.Element;
* @author Luke Taylor
*/
public class JdbcUserServiceBeanDefinitionParserTests {
private static String USER_CACHE_XML = "<b:bean id='userCache' class='org.springframework.security.authentication.dao.MockUserCache'/>";
private static String USER_CACHE_XML = "<b:bean id='userCache' class='org.springframework.security.authentication.dao.MockUserCache'/>";
private static String DATA_SOURCE =
" <b:bean id='populator' class='org.springframework.security.config.DataSourcePopulator'>" +
" <b:property name='dataSource' ref='dataSource'/>" +
" </b:bean>" +
private static String DATA_SOURCE = " <b:bean id='populator' class='org.springframework.security.config.DataSourcePopulator'>"
+ " <b:property name='dataSource' ref='dataSource'/>"
+ " </b:bean>"
+
" <b:bean id='dataSource' class='org.springframework.security.TestDataSource'>" +
" <b:constructor-arg value='jdbcnamespaces'/>" +
" </b:bean>";
" <b:bean id='dataSource' class='org.springframework.security.TestDataSource'>"
+ " <b:constructor-arg value='jdbcnamespaces'/>" + " </b:bean>";
private InMemoryXmlApplicationContext appContext;
private InMemoryXmlApplicationContext appContext;
@After
public void closeAppContext() {
if (appContext != null) {
appContext.close();
}
}
@After
public void closeAppContext() {
if (appContext != null) {
appContext.close();
}
}
@Test
public void beanNameIsCorrect() throws Exception {
assertEquals(JdbcUserDetailsManager.class.getName(), new JdbcUserServiceBeanDefinitionParser().getBeanClassName(mock(Element.class)));
}
@Test
public void beanNameIsCorrect() throws Exception {
assertEquals(JdbcUserDetailsManager.class.getName(),
new JdbcUserServiceBeanDefinitionParser()
.getBeanClassName(mock(Element.class)));
}
@Test
public void validUsernameIsFound() {
setContext("<jdbc-user-service data-source-ref='dataSource'/>" + DATA_SOURCE);
JdbcUserDetailsManager mgr = (JdbcUserDetailsManager) appContext.getBean(BeanIds.USER_DETAILS_SERVICE);
assertNotNull(mgr.loadUserByUsername("rod"));
}
@Test
public void validUsernameIsFound() {
setContext("<jdbc-user-service data-source-ref='dataSource'/>" + DATA_SOURCE);
JdbcUserDetailsManager mgr = (JdbcUserDetailsManager) appContext
.getBean(BeanIds.USER_DETAILS_SERVICE);
assertNotNull(mgr.loadUserByUsername("rod"));
}
@Test
public void beanIdIsParsedCorrectly() {
setContext("<jdbc-user-service id='myUserService' data-source-ref='dataSource'/>" + DATA_SOURCE);
assertTrue(appContext.getBean("myUserService") instanceof JdbcUserDetailsManager);
}
@Test
public void beanIdIsParsedCorrectly() {
setContext("<jdbc-user-service id='myUserService' data-source-ref='dataSource'/>"
+ DATA_SOURCE);
assertTrue(appContext.getBean("myUserService") instanceof JdbcUserDetailsManager);
}
@Test
public void usernameAndAuthorityQueriesAreParsedCorrectly() throws Exception {
String userQuery = "select username, password, true from users where username = ?";
String authoritiesQuery = "select username, authority from authorities where username = ? and 1 = 1";
setContext("<jdbc-user-service id='myUserService' " +
"data-source-ref='dataSource' " +
"users-by-username-query='"+ userQuery +"' " +
"authorities-by-username-query='" + authoritiesQuery + "'/>" + DATA_SOURCE);
JdbcUserDetailsManager mgr = (JdbcUserDetailsManager) appContext.getBean("myUserService");
assertEquals(userQuery, FieldUtils.getFieldValue(mgr, "usersByUsernameQuery"));
assertEquals(authoritiesQuery, FieldUtils.getFieldValue(mgr, "authoritiesByUsernameQuery"));
assertTrue(mgr.loadUserByUsername("rod") != null);
}
@Test
public void usernameAndAuthorityQueriesAreParsedCorrectly() throws Exception {
String userQuery = "select username, password, true from users where username = ?";
String authoritiesQuery = "select username, authority from authorities where username = ? and 1 = 1";
setContext("<jdbc-user-service id='myUserService' "
+ "data-source-ref='dataSource' " + "users-by-username-query='"
+ userQuery + "' " + "authorities-by-username-query='" + authoritiesQuery
+ "'/>" + DATA_SOURCE);
JdbcUserDetailsManager mgr = (JdbcUserDetailsManager) appContext
.getBean("myUserService");
assertEquals(userQuery, FieldUtils.getFieldValue(mgr, "usersByUsernameQuery"));
assertEquals(authoritiesQuery,
FieldUtils.getFieldValue(mgr, "authoritiesByUsernameQuery"));
assertTrue(mgr.loadUserByUsername("rod") != null);
}
@Test
public void groupQueryIsParsedCorrectly() throws Exception {
setContext("<jdbc-user-service id='myUserService' " +
"data-source-ref='dataSource' " +
"group-authorities-by-username-query='blah blah'/>" + DATA_SOURCE);
JdbcUserDetailsManager mgr = (JdbcUserDetailsManager) appContext.getBean("myUserService");
assertEquals("blah blah", FieldUtils.getFieldValue(mgr, "groupAuthoritiesByUsernameQuery"));
assertTrue((Boolean)FieldUtils.getFieldValue(mgr, "enableGroups"));
}
@Test
public void groupQueryIsParsedCorrectly() throws Exception {
setContext("<jdbc-user-service id='myUserService' "
+ "data-source-ref='dataSource' "
+ "group-authorities-by-username-query='blah blah'/>" + DATA_SOURCE);
JdbcUserDetailsManager mgr = (JdbcUserDetailsManager) appContext
.getBean("myUserService");
assertEquals("blah blah",
FieldUtils.getFieldValue(mgr, "groupAuthoritiesByUsernameQuery"));
assertTrue((Boolean) FieldUtils.getFieldValue(mgr, "enableGroups"));
}
@Test
public void cacheRefIsparsedCorrectly() {
setContext("<jdbc-user-service id='myUserService' cache-ref='userCache' data-source-ref='dataSource'/>"
+ DATA_SOURCE +USER_CACHE_XML);
CachingUserDetailsService cachingUserService =
(CachingUserDetailsService) appContext.getBean("myUserService" + AbstractUserDetailsServiceBeanDefinitionParser.CACHING_SUFFIX);
assertSame(cachingUserService.getUserCache(), appContext.getBean("userCache"));
assertNotNull(cachingUserService.loadUserByUsername("rod"));
assertNotNull(cachingUserService.loadUserByUsername("rod"));
}
@Test
public void cacheRefIsparsedCorrectly() {
setContext("<jdbc-user-service id='myUserService' cache-ref='userCache' data-source-ref='dataSource'/>"
+ DATA_SOURCE + USER_CACHE_XML);
CachingUserDetailsService cachingUserService = (CachingUserDetailsService) appContext
.getBean("myUserService"
+ AbstractUserDetailsServiceBeanDefinitionParser.CACHING_SUFFIX);
assertSame(cachingUserService.getUserCache(), appContext.getBean("userCache"));
assertNotNull(cachingUserService.loadUserByUsername("rod"));
assertNotNull(cachingUserService.loadUserByUsername("rod"));
}
@Test
public void isSupportedByAuthenticationProviderElement() {
setContext(
"<authentication-manager>" +
" <authentication-provider>" +
" <jdbc-user-service data-source-ref='dataSource'/>" +
" </authentication-provider>" +
"</authentication-manager>" + DATA_SOURCE);
AuthenticationManager mgr = (AuthenticationManager) appContext.getBean(BeanIds.AUTHENTICATION_MANAGER);
mgr.authenticate(new UsernamePasswordAuthenticationToken("rod", "koala"));
}
@Test
public void isSupportedByAuthenticationProviderElement() {
setContext("<authentication-manager>" + " <authentication-provider>"
+ " <jdbc-user-service data-source-ref='dataSource'/>"
+ " </authentication-provider>" + "</authentication-manager>"
+ DATA_SOURCE);
AuthenticationManager mgr = (AuthenticationManager) appContext
.getBean(BeanIds.AUTHENTICATION_MANAGER);
mgr.authenticate(new UsernamePasswordAuthenticationToken("rod", "koala"));
}
@Test
public void cacheIsInjectedIntoAuthenticationProvider() {
setContext(
"<authentication-manager>" +
" <authentication-provider>" +
" <jdbc-user-service cache-ref='userCache' data-source-ref='dataSource'/>" +
" </authentication-provider>" +
"</authentication-manager>" + DATA_SOURCE + USER_CACHE_XML);
ProviderManager mgr = (ProviderManager) appContext.getBean(BeanIds.AUTHENTICATION_MANAGER);
DaoAuthenticationProvider provider = (DaoAuthenticationProvider) mgr.getProviders().get(0);
assertSame(provider.getUserCache(), appContext.getBean("userCache"));
provider.authenticate(new UsernamePasswordAuthenticationToken("rod","koala"));
assertNotNull("Cache should contain user after authentication", provider.getUserCache().getUserFromCache("rod"));
}
@Test
public void cacheIsInjectedIntoAuthenticationProvider() {
setContext("<authentication-manager>"
+ " <authentication-provider>"
+ " <jdbc-user-service cache-ref='userCache' data-source-ref='dataSource'/>"
+ " </authentication-provider>" + "</authentication-manager>"
+ DATA_SOURCE + USER_CACHE_XML);
ProviderManager mgr = (ProviderManager) appContext
.getBean(BeanIds.AUTHENTICATION_MANAGER);
DaoAuthenticationProvider provider = (DaoAuthenticationProvider) mgr
.getProviders().get(0);
assertSame(provider.getUserCache(), appContext.getBean("userCache"));
provider.authenticate(new UsernamePasswordAuthenticationToken("rod", "koala"));
assertNotNull("Cache should contain user after authentication", provider
.getUserCache().getUserFromCache("rod"));
}
@Test
public void rolePrefixIsUsedWhenSet() {
setContext("<jdbc-user-service id='myUserService' role-prefix='PREFIX_' data-source-ref='dataSource'/>" + DATA_SOURCE);
JdbcUserDetailsManager mgr = (JdbcUserDetailsManager) appContext.getBean("myUserService");
UserDetails rod = mgr.loadUserByUsername("rod");
assertTrue(AuthorityUtils.authorityListToSet(rod.getAuthorities()).contains("PREFIX_ROLE_SUPERVISOR"));
}
@Test
public void rolePrefixIsUsedWhenSet() {
setContext("<jdbc-user-service id='myUserService' role-prefix='PREFIX_' data-source-ref='dataSource'/>"
+ DATA_SOURCE);
JdbcUserDetailsManager mgr = (JdbcUserDetailsManager) appContext
.getBean("myUserService");
UserDetails rod = mgr.loadUserByUsername("rod");
assertTrue(AuthorityUtils.authorityListToSet(rod.getAuthorities()).contains(
"PREFIX_ROLE_SUPERVISOR"));
}
private void setContext(String context) {
appContext = new InMemoryXmlApplicationContext(context);
}
private void setContext(String context) {
appContext = new InMemoryXmlApplicationContext(context);
}
}

View File

@@ -15,115 +15,117 @@ import org.junit.After;
* @author Luke Taylor
*/
public class UserServiceBeanDefinitionParserTests {
private AbstractXmlApplicationContext appContext;
private AbstractXmlApplicationContext appContext;
@After
public void closeAppContext() {
if (appContext != null) {
appContext.close();
}
}
@After
public void closeAppContext() {
if (appContext != null) {
appContext.close();
}
}
@Test
public void userServiceWithValidPropertiesFileWorksSuccessfully() {
setContext(
"<user-service id='service' " +
"properties='classpath:org/springframework/security/config/users.properties'/>");
UserDetailsService userService = (UserDetailsService) appContext.getBean("service");
userService.loadUserByUsername("bob");
userService.loadUserByUsername("joe");
}
@Test
public void userServiceWithValidPropertiesFileWorksSuccessfully() {
setContext("<user-service id='service' "
+ "properties='classpath:org/springframework/security/config/users.properties'/>");
UserDetailsService userService = (UserDetailsService) appContext
.getBean("service");
userService.loadUserByUsername("bob");
userService.loadUserByUsername("joe");
}
@Test
public void userServiceWithEmbeddedUsersWorksSuccessfully() {
setContext(
"<user-service id='service'>" +
" <user name='joe' password='joespassword' authorities='ROLE_A'/>" +
"</user-service>");
UserDetailsService userService = (UserDetailsService) appContext.getBean("service");
userService.loadUserByUsername("joe");
}
@Test
public void userServiceWithEmbeddedUsersWorksSuccessfully() {
setContext("<user-service id='service'>"
+ " <user name='joe' password='joespassword' authorities='ROLE_A'/>"
+ "</user-service>");
UserDetailsService userService = (UserDetailsService) appContext
.getBean("service");
userService.loadUserByUsername("joe");
}
@Test
public void namePasswordAndAuthoritiesSupportPlaceholders() {
System.setProperty("principal.name", "joe");
System.setProperty("principal.pass", "joespassword");
System.setProperty("principal.authorities", "ROLE_A,ROLE_B");
setContext(
"<b:bean class='org.springframework.beans.factory.config.PropertyPlaceholderConfigurer'/>" +
"<user-service id='service'>" +
" <user name='${principal.name}' password='${principal.pass}' authorities='${principal.authorities}'/>" +
"</user-service>");
UserDetailsService userService = (UserDetailsService) appContext.getBean("service");
UserDetails joe = userService.loadUserByUsername("joe");
assertEquals("joespassword", joe.getPassword());
assertEquals(2, joe.getAuthorities().size());
}
@Test
public void namePasswordAndAuthoritiesSupportPlaceholders() {
System.setProperty("principal.name", "joe");
System.setProperty("principal.pass", "joespassword");
System.setProperty("principal.authorities", "ROLE_A,ROLE_B");
setContext("<b:bean class='org.springframework.beans.factory.config.PropertyPlaceholderConfigurer'/>"
+ "<user-service id='service'>"
+ " <user name='${principal.name}' password='${principal.pass}' authorities='${principal.authorities}'/>"
+ "</user-service>");
UserDetailsService userService = (UserDetailsService) appContext
.getBean("service");
UserDetails joe = userService.loadUserByUsername("joe");
assertEquals("joespassword", joe.getPassword());
assertEquals(2, joe.getAuthorities().size());
}
@Test
public void embeddedUsersWithNoPasswordIsGivenGeneratedValue() {
setContext(
"<user-service id='service'>" +
" <user name='joe' authorities='ROLE_A'/>" +
"</user-service>");
UserDetailsService userService = (UserDetailsService) appContext.getBean("service");
UserDetails joe = userService.loadUserByUsername("joe");
assertTrue(joe.getPassword().length() > 0);
Long.parseLong(joe.getPassword());
}
@Test
public void embeddedUsersWithNoPasswordIsGivenGeneratedValue() {
setContext("<user-service id='service'>"
+ " <user name='joe' authorities='ROLE_A'/>" + "</user-service>");
UserDetailsService userService = (UserDetailsService) appContext
.getBean("service");
UserDetails joe = userService.loadUserByUsername("joe");
assertTrue(joe.getPassword().length() > 0);
Long.parseLong(joe.getPassword());
}
@Test
public void worksWithOpenIDUrlsAsNames() {
setContext(
"<user-service id='service'>" +
" <user name='http://joe.myopenid.com/' authorities='ROLE_A'/>" +
" <user name='https://www.google.com/accounts/o8/id?id=MPtOaenBIk5yzW9n7n9' authorities='ROLE_A'/>" +
"</user-service>");
UserDetailsService userService = (UserDetailsService) appContext.getBean("service");
assertEquals("http://joe.myopenid.com/", userService.loadUserByUsername("http://joe.myopenid.com/").getUsername());
assertEquals("https://www.google.com/accounts/o8/id?id=MPtOaenBIk5yzW9n7n9",
userService.loadUserByUsername("https://www.google.com/accounts/o8/id?id=MPtOaenBIk5yzW9n7n9").getUsername());
}
@Test
public void worksWithOpenIDUrlsAsNames() {
setContext("<user-service id='service'>"
+ " <user name='http://joe.myopenid.com/' authorities='ROLE_A'/>"
+ " <user name='https://www.google.com/accounts/o8/id?id=MPtOaenBIk5yzW9n7n9' authorities='ROLE_A'/>"
+ "</user-service>");
UserDetailsService userService = (UserDetailsService) appContext
.getBean("service");
assertEquals("http://joe.myopenid.com/",
userService.loadUserByUsername("http://joe.myopenid.com/").getUsername());
assertEquals(
"https://www.google.com/accounts/o8/id?id=MPtOaenBIk5yzW9n7n9",
userService.loadUserByUsername(
"https://www.google.com/accounts/o8/id?id=MPtOaenBIk5yzW9n7n9")
.getUsername());
}
@Test
public void disabledAndEmbeddedFlagsAreSupported() {
setContext(
"<user-service id='service'>" +
" <user name='joe' password='joespassword' authorities='ROLE_A' locked='true'/>" +
" <user name='Bob' password='bobspassword' authorities='ROLE_A' disabled='true'/>" +
"</user-service>");
UserDetailsService userService = (UserDetailsService) appContext.getBean("service");
UserDetails joe = userService.loadUserByUsername("joe");
assertFalse(joe.isAccountNonLocked());
// Check case-sensitive lookup SEC-1432
UserDetails bob = userService.loadUserByUsername("Bob");
assertFalse(bob.isEnabled());
}
@Test
public void disabledAndEmbeddedFlagsAreSupported() {
setContext("<user-service id='service'>"
+ " <user name='joe' password='joespassword' authorities='ROLE_A' locked='true'/>"
+ " <user name='Bob' password='bobspassword' authorities='ROLE_A' disabled='true'/>"
+ "</user-service>");
UserDetailsService userService = (UserDetailsService) appContext
.getBean("service");
UserDetails joe = userService.loadUserByUsername("joe");
assertFalse(joe.isAccountNonLocked());
// Check case-sensitive lookup SEC-1432
UserDetails bob = userService.loadUserByUsername("Bob");
assertFalse(bob.isEnabled());
}
@Test(expected=FatalBeanException.class)
public void userWithBothPropertiesAndEmbeddedUsersThrowsException() {
setContext(
"<user-service id='service' properties='doesntmatter.props'>" +
" <user name='joe' password='joespassword' authorities='ROLE_A'/>" +
"</user-service>");
UserDetailsService userService = (UserDetailsService) appContext.getBean("service");
userService.loadUserByUsername("Joe");
}
@Test(expected = FatalBeanException.class)
public void userWithBothPropertiesAndEmbeddedUsersThrowsException() {
setContext("<user-service id='service' properties='doesntmatter.props'>"
+ " <user name='joe' password='joespassword' authorities='ROLE_A'/>"
+ "</user-service>");
UserDetailsService userService = (UserDetailsService) appContext
.getBean("service");
userService.loadUserByUsername("Joe");
}
@Test(expected= FatalBeanException.class)
public void multipleTopLevelUseWithoutIdThrowsException() {
setContext(
"<user-service properties='classpath:org/springframework/security/config/users.properties'/>" +
"<user-service properties='classpath:org/springframework/security/config/users.properties'/>");
@Test(expected = FatalBeanException.class)
public void multipleTopLevelUseWithoutIdThrowsException() {
setContext("<user-service properties='classpath:org/springframework/security/config/users.properties'/>"
+ "<user-service properties='classpath:org/springframework/security/config/users.properties'/>");
}
}
@Test(expected= FatalBeanException.class)
public void userServiceWithMissingPropertiesFileThrowsException() {
setContext("<user-service id='service' properties='classpath:doesntexist.properties'/>");
}
@Test(expected = FatalBeanException.class)
public void userServiceWithMissingPropertiesFileThrowsException() {
setContext("<user-service id='service' properties='classpath:doesntexist.properties'/>");
}
private void setContext(String context) {
appContext = new InMemoryXmlApplicationContext(context);
}
private void setContext(String context) {
appContext = new InMemoryXmlApplicationContext(context);
}
}

View File

@@ -46,49 +46,56 @@ import org.springframework.security.web.util.matcher.AnyRequestMatcher;
*/
@RunWith(MockitoJUnitRunner.class)
public class DefaultFilterChainValidatorTests {
private DefaultFilterChainValidator validator;
private FilterChainProxy fcp;
@Mock
private Log logger;
@Mock
private DefaultFilterInvocationSecurityMetadataSource metadataSource;
@Mock
private AccessDecisionManager accessDecisionManager;
private DefaultFilterChainValidator validator;
private FilterChainProxy fcp;
@Mock
private Log logger;
@Mock
private DefaultFilterInvocationSecurityMetadataSource metadataSource;
@Mock
private AccessDecisionManager accessDecisionManager;
private FilterSecurityInterceptor fsi;
private FilterSecurityInterceptor fsi;
@Before
public void setUp() throws Exception {
AnonymousAuthenticationFilter aaf = new AnonymousAuthenticationFilter("anonymous");
fsi = new FilterSecurityInterceptor();
fsi.setAccessDecisionManager(accessDecisionManager);
fsi.setSecurityMetadataSource(metadataSource);
AuthenticationEntryPoint authenticationEntryPoint = new LoginUrlAuthenticationEntryPoint("/login");
ExceptionTranslationFilter etf = new ExceptionTranslationFilter(authenticationEntryPoint);
DefaultSecurityFilterChain securityChain = new DefaultSecurityFilterChain(AnyRequestMatcher.INSTANCE, aaf, etf, fsi);
fcp = new FilterChainProxy(securityChain);
validator = new DefaultFilterChainValidator();
Whitebox.setInternalState(validator, "logger", logger);
}
@Before
public void setUp() throws Exception {
AnonymousAuthenticationFilter aaf = new AnonymousAuthenticationFilter("anonymous");
fsi = new FilterSecurityInterceptor();
fsi.setAccessDecisionManager(accessDecisionManager);
fsi.setSecurityMetadataSource(metadataSource);
AuthenticationEntryPoint authenticationEntryPoint = new LoginUrlAuthenticationEntryPoint(
"/login");
ExceptionTranslationFilter etf = new ExceptionTranslationFilter(
authenticationEntryPoint);
DefaultSecurityFilterChain securityChain = new DefaultSecurityFilterChain(
AnyRequestMatcher.INSTANCE, aaf, etf, fsi);
fcp = new FilterChainProxy(securityChain);
validator = new DefaultFilterChainValidator();
Whitebox.setInternalState(validator, "logger", logger);
}
// SEC-1878
@SuppressWarnings("unchecked")
@Test
public void validateCheckLoginPageIsntProtectedThrowsIllegalArgumentException() {
IllegalArgumentException toBeThrown = new IllegalArgumentException("failed to eval expression");
doThrow(toBeThrown).when(accessDecisionManager).decide(any(Authentication.class), anyObject(), any(Collection.class));
validator.validate(fcp);
verify(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.", toBeThrown);
}
// SEC-1878
@SuppressWarnings("unchecked")
@Test
public void validateCheckLoginPageIsntProtectedThrowsIllegalArgumentException() {
IllegalArgumentException toBeThrown = new IllegalArgumentException(
"failed to eval expression");
doThrow(toBeThrown).when(accessDecisionManager).decide(any(Authentication.class),
anyObject(), any(Collection.class));
validator.validate(fcp);
verify(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.",
toBeThrown);
}
// SEC-1957
@Test
public void validateCustomMetadataSource() {
FilterInvocationSecurityMetadataSource customMetaDataSource = mock(FilterInvocationSecurityMetadataSource.class);
fsi.setSecurityMetadataSource(customMetaDataSource);
// SEC-1957
@Test
public void validateCustomMetadataSource() {
FilterInvocationSecurityMetadataSource customMetaDataSource = mock(FilterInvocationSecurityMetadataSource.class);
fsi.setSecurityMetadataSource(customMetaDataSource);
validator.validate(fcp);
validator.validate(fcp);
verify(customMetaDataSource).getAttributes(any());
}
verify(customMetaDataSource).getAttributes(any());
}
}

View File

@@ -26,87 +26,89 @@ import org.springframework.security.web.access.intercept.DefaultFilterInvocation
* @author Luke Taylor
*/
public class FilterSecurityMetadataSourceBeanDefinitionParserTests {
private AbstractXmlApplicationContext appContext;
private AbstractXmlApplicationContext appContext;
@After
public void closeAppContext() {
if (appContext != null) {
appContext.close();
appContext = null;
}
}
@After
public void closeAppContext() {
if (appContext != null) {
appContext.close();
appContext = null;
}
}
private void setContext(String context) {
appContext = new InMemoryXmlApplicationContext(context);
}
private void setContext(String context) {
appContext = new InMemoryXmlApplicationContext(context);
}
@Test
public void parsingMinimalConfigurationIsSuccessful() {
setContext("<filter-security-metadata-source id='fids' use-expressions='false'>"
+ " <intercept-url pattern='/**' access='ROLE_A'/>"
+ "</filter-security-metadata-source>");
DefaultFilterInvocationSecurityMetadataSource fids = (DefaultFilterInvocationSecurityMetadataSource) appContext
.getBean("fids");
Collection<ConfigAttribute> cad = fids.getAttributes(createFilterInvocation(
"/anything", "GET"));
assertNotNull(cad);
assertTrue(cad.contains(new SecurityConfig("ROLE_A")));
}
@Test
public void parsingMinimalConfigurationIsSuccessful() {
setContext(
"<filter-security-metadata-source id='fids' use-expressions='false'>" +
" <intercept-url pattern='/**' access='ROLE_A'/>" +
"</filter-security-metadata-source>");
DefaultFilterInvocationSecurityMetadataSource fids = (DefaultFilterInvocationSecurityMetadataSource) appContext.getBean("fids");
Collection<ConfigAttribute> cad = fids.getAttributes(createFilterInvocation("/anything", "GET"));
assertNotNull(cad);
assertTrue(cad.contains(new SecurityConfig("ROLE_A")));
}
@Test
public void expressionsAreSupported() {
setContext("<filter-security-metadata-source id='fids'>"
+ " <intercept-url pattern='/**' access=\"hasRole('ROLE_A')\" />"
+ "</filter-security-metadata-source>");
@Test
public void expressionsAreSupported() {
setContext(
"<filter-security-metadata-source id='fids'>" +
" <intercept-url pattern='/**' access=\"hasRole('ROLE_A')\" />" +
"</filter-security-metadata-source>");
ExpressionBasedFilterInvocationSecurityMetadataSource fids = (ExpressionBasedFilterInvocationSecurityMetadataSource) appContext
.getBean("fids");
ConfigAttribute[] cad = fids.getAttributes(
createFilterInvocation("/anything", "GET")).toArray(
new ConfigAttribute[0]);
assertEquals(1, cad.length);
assertEquals("hasRole('ROLE_A')", cad[0].toString());
}
ExpressionBasedFilterInvocationSecurityMetadataSource fids =
(ExpressionBasedFilterInvocationSecurityMetadataSource) appContext.getBean("fids");
ConfigAttribute[] cad = fids.getAttributes(createFilterInvocation("/anything", "GET")).toArray(new ConfigAttribute[0]);
assertEquals(1, cad.length);
assertEquals("hasRole('ROLE_A')", cad[0].toString());
}
// SEC-1201
@Test
public void interceptUrlsSupportPropertyPlaceholders() {
System.setProperty("secure.url", "/secure");
System.setProperty("secure.role", "ROLE_A");
setContext("<b:bean class='org.springframework.beans.factory.config.PropertyPlaceholderConfigurer'/>"
+ "<filter-security-metadata-source id='fids' use-expressions='false'>"
+ " <intercept-url pattern='${secure.url}' access='${secure.role}'/>"
+ "</filter-security-metadata-source>");
DefaultFilterInvocationSecurityMetadataSource fids = (DefaultFilterInvocationSecurityMetadataSource) appContext
.getBean("fids");
Collection<ConfigAttribute> cad = fids.getAttributes(createFilterInvocation(
"/secure", "GET"));
assertNotNull(cad);
assertEquals(1, cad.size());
assertTrue(cad.contains(new SecurityConfig("ROLE_A")));
}
// SEC-1201
@Test
public void interceptUrlsSupportPropertyPlaceholders() {
System.setProperty("secure.url", "/secure");
System.setProperty("secure.role", "ROLE_A");
setContext(
"<b:bean class='org.springframework.beans.factory.config.PropertyPlaceholderConfigurer'/>" +
"<filter-security-metadata-source id='fids' use-expressions='false'>" +
" <intercept-url pattern='${secure.url}' access='${secure.role}'/>" +
"</filter-security-metadata-source>");
DefaultFilterInvocationSecurityMetadataSource fids = (DefaultFilterInvocationSecurityMetadataSource) appContext.getBean("fids");
Collection<ConfigAttribute> cad = fids.getAttributes(createFilterInvocation("/secure", "GET"));
assertNotNull(cad);
assertEquals(1, cad.size());
assertTrue(cad.contains(new SecurityConfig("ROLE_A")));
}
@Test
public void parsingWithinFilterSecurityInterceptorIsSuccessful() {
setContext("<http auto-config='true' use-expressions='false'/>"
+ "<b:bean id='fsi' class='org.springframework.security.web.access.intercept.FilterSecurityInterceptor' autowire='byType'>"
+ " <b:property name='securityMetadataSource'>"
+ " <filter-security-metadata-source use-expressions='false'>"
+ " <intercept-url pattern='/secure/extreme/**' access='ROLE_SUPERVISOR'/>"
+ " <intercept-url pattern='/secure/**' access='ROLE_USER'/>"
+ " <intercept-url pattern='/**' access='ROLE_USER'/>"
+ " </filter-security-metadata-source>" + " </b:property>"
+ " <b:property name='authenticationManager' ref='"
+ BeanIds.AUTHENTICATION_MANAGER + "'/>" + "</b:bean>"
+ ConfigTestUtils.AUTH_PROVIDER_XML);
}
@Test
public void parsingWithinFilterSecurityInterceptorIsSuccessful() {
setContext(
"<http auto-config='true' use-expressions='false'/>" +
"<b:bean id='fsi' class='org.springframework.security.web.access.intercept.FilterSecurityInterceptor' autowire='byType'>" +
" <b:property name='securityMetadataSource'>" +
" <filter-security-metadata-source use-expressions='false'>" +
" <intercept-url pattern='/secure/extreme/**' access='ROLE_SUPERVISOR'/>" +
" <intercept-url pattern='/secure/**' access='ROLE_USER'/>" +
" <intercept-url pattern='/**' access='ROLE_USER'/>" +
" </filter-security-metadata-source>" +
" </b:property>" +
" <b:property name='authenticationManager' ref='" + BeanIds.AUTHENTICATION_MANAGER +"'/>"+
"</b:bean>" + ConfigTestUtils.AUTH_PROVIDER_XML);
}
private FilterInvocation createFilterInvocation(String path, String method) {
MockHttpServletRequest request = new MockHttpServletRequest();
request.setRequestURI(null);
request.setMethod(method);
private FilterInvocation createFilterInvocation(String path, String method) {
MockHttpServletRequest request = new MockHttpServletRequest();
request.setRequestURI(null);
request.setMethod(method);
request.setServletPath(path);
request.setServletPath(path);
return new FilterInvocation(request, new MockHttpServletResponse(), new MockFilterChain());
}
return new FilterInvocation(request, new MockHttpServletResponse(),
new MockFilterChain());
}
}

View File

@@ -56,105 +56,102 @@ import org.springframework.util.ReflectionUtils;
*
*/
@RunWith(PowerMockRunner.class)
@PrepareForTest({ReflectionUtils.class, Method.class})
@PrepareForTest({ ReflectionUtils.class, Method.class })
public class SessionManagementConfigServlet31Tests {
private static final String XML_AUTHENTICATION_MANAGER =
"<authentication-manager>"+
" <authentication-provider>"+
" <user-service>"+
" <user name='user' password='password' authorities='ROLE_USER' />" +
" </user-service>"+
" </authentication-provider>"+
"</authentication-manager>";
private static final String XML_AUTHENTICATION_MANAGER = "<authentication-manager>"
+ " <authentication-provider>" + " <user-service>"
+ " <user name='user' password='password' authorities='ROLE_USER' />"
+ " </user-service>" + " </authentication-provider>"
+ "</authentication-manager>";
@Mock
Method method;
@Mock
Method method;
MockHttpServletRequest request;
MockHttpServletResponse response;
MockFilterChain chain;
MockHttpServletRequest request;
MockHttpServletResponse response;
MockFilterChain chain;
ConfigurableApplicationContext context;
ConfigurableApplicationContext context;
Filter springSecurityFilterChain;
Filter springSecurityFilterChain;
@Before
public void setup() {
request = new MockHttpServletRequest();
response = new MockHttpServletResponse();
chain = new MockFilterChain();
}
@Before
public void setup() {
request = new MockHttpServletRequest();
response = new MockHttpServletResponse();
chain = new MockFilterChain();
}
@After
public void teardown() {
if(context != null) {
context.close();
}
}
@After
public void teardown() {
if (context != null) {
context.close();
}
}
@Test
public void changeSessionIdDefaultsInServlet31Plus() throws Exception {
spy(ReflectionUtils.class);
Method method = mock(Method.class);
MockHttpServletRequest request = new MockHttpServletRequest();
request.getSession();
request.setServletPath("/login");
request.setMethod("POST");
request.setParameter("username", "user");
request.setParameter("password", "password");
when(ReflectionUtils.findMethod(HttpServletRequest.class, "changeSessionId")).thenReturn(method);
@Test
public void changeSessionIdDefaultsInServlet31Plus() throws Exception {
spy(ReflectionUtils.class);
Method method = mock(Method.class);
MockHttpServletRequest request = new MockHttpServletRequest();
request.getSession();
request.setServletPath("/login");
request.setMethod("POST");
request.setParameter("username", "user");
request.setParameter("password", "password");
when(ReflectionUtils.findMethod(HttpServletRequest.class, "changeSessionId"))
.thenReturn(method);
loadContext("<http>\n" +
" <form-login/>\n" +
" <session-management/>\n" +
" <csrf disabled='true'/>\n" +
" </http>" +
XML_AUTHENTICATION_MANAGER);
loadContext("<http>\n" + " <form-login/>\n"
+ " <session-management/>\n" + " <csrf disabled='true'/>\n"
+ " </http>" + XML_AUTHENTICATION_MANAGER);
springSecurityFilterChain.doFilter(request,response,chain);
springSecurityFilterChain.doFilter(request, response, chain);
verifyStatic();
ReflectionUtils.invokeMethod(same(method), any(HttpServletRequest.class));
}
verifyStatic();
ReflectionUtils.invokeMethod(same(method), any(HttpServletRequest.class));
}
@Test
public void changeSessionId() throws Exception {
spy(ReflectionUtils.class);
Method method = mock(Method.class);
MockHttpServletRequest request = new MockHttpServletRequest();
request.getSession();
request.setServletPath("/login");
request.setMethod("POST");
request.setParameter("username", "user");
request.setParameter("password", "password");
when(ReflectionUtils.findMethod(HttpServletRequest.class, "changeSessionId"))
.thenReturn(method);
@Test
public void changeSessionId() throws Exception {
spy(ReflectionUtils.class);
Method method = mock(Method.class);
MockHttpServletRequest request = new MockHttpServletRequest();
request.getSession();
request.setServletPath("/login");
request.setMethod("POST");
request.setParameter("username", "user");
request.setParameter("password", "password");
when(ReflectionUtils.findMethod(HttpServletRequest.class, "changeSessionId")).thenReturn(method);
loadContext("<http>\n"
+ " <form-login/>\n"
+ " <session-management session-fixation-protection='changeSessionId'/>\n"
+ " <csrf disabled='true'/>\n" + " </http>"
+ XML_AUTHENTICATION_MANAGER);
loadContext("<http>\n" +
" <form-login/>\n" +
" <session-management session-fixation-protection='changeSessionId'/>\n" +
" <csrf disabled='true'/>\n" +
" </http>" +
XML_AUTHENTICATION_MANAGER);
springSecurityFilterChain.doFilter(request, response, chain);
springSecurityFilterChain.doFilter(request,response,chain);
verifyStatic();
ReflectionUtils.invokeMethod(same(method), any(HttpServletRequest.class));
}
verifyStatic();
ReflectionUtils.invokeMethod(same(method), any(HttpServletRequest.class));
}
private void loadContext(String context) {
this.context = new InMemoryXmlApplicationContext(context);
this.springSecurityFilterChain = this.context.getBean(
"springSecurityFilterChain", Filter.class);
}
private void loadContext(String context) {
this.context = new InMemoryXmlApplicationContext(context);
this.springSecurityFilterChain = this.context.getBean("springSecurityFilterChain",Filter.class);
}
private void login(Authentication auth) {
HttpSessionSecurityContextRepository repo = new HttpSessionSecurityContextRepository();
HttpRequestResponseHolder requestResponseHolder = new HttpRequestResponseHolder(
request, response);
repo.loadContext(requestResponseHolder);
private void login(Authentication auth) {
HttpSessionSecurityContextRepository repo = new HttpSessionSecurityContextRepository();
HttpRequestResponseHolder requestResponseHolder = new HttpRequestResponseHolder(request, response);
repo.loadContext(requestResponseHolder);
SecurityContextImpl securityContextImpl = new SecurityContextImpl();
securityContextImpl.setAuthentication(auth);
repo.saveContext(securityContextImpl, requestResponseHolder.getRequest(), requestResponseHolder.getResponse());
}
SecurityContextImpl securityContextImpl = new SecurityContextImpl();
securityContextImpl.setAuthentication(auth);
repo.saveContext(securityContextImpl, requestResponseHolder.getRequest(),
requestResponseHolder.getResponse());
}
}

View File

@@ -24,19 +24,20 @@ import org.powermock.core.classloader.annotations.PrepareOnlyThisForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.springframework.beans.factory.xml.ParserContext;
@RunWith(PowerMockRunner.class)
@PrepareOnlyThisForTest(ParserContext.class)
public class WebConfigUtilsTest {
public final static String URL = "/url";
public final static String URL = "/url";
@Mock
private ParserContext parserContext;
@Mock
private ParserContext parserContext;
// SEC-1980
@Test
public void validateHttpRedirectSpELNoParserWarning() {
WebConfigUtils.validateHttpRedirect("#{T(org.springframework.security.config.http.WebConfigUtilsTest).URL}", parserContext, "fakeSource");
verifyZeroInteractions(parserContext);
}
// SEC-1980
@Test
public void validateHttpRedirectSpELNoParserWarning() {
WebConfigUtils.validateHttpRedirect(
"#{T(org.springframework.security.config.http.WebConfigUtilsTest).URL}",
parserContext, "fakeSource");
verifyZeroInteractions(parserContext);
}
}

View File

@@ -49,391 +49,406 @@ import org.springframework.security.util.FieldUtils;
* @author Luke Taylor
*/
public class GlobalMethodSecurityBeanDefinitionParserTests {
private final UsernamePasswordAuthenticationToken bob = new UsernamePasswordAuthenticationToken("bob","bobspassword");
private final UsernamePasswordAuthenticationToken bob = new UsernamePasswordAuthenticationToken(
"bob", "bobspassword");
private AbstractXmlApplicationContext appContext;
private AbstractXmlApplicationContext appContext;
private BusinessService target;
private BusinessService target;
public void loadContext() {
setContext(
"<b:bean id='target' class='org.springframework.security.access.annotation.BusinessServiceImpl'/>" +
"<global-method-security order='1001' proxy-target-class='false' >" +
" <protect-pointcut expression='execution(* *.someUser*(..))' access='ROLE_USER'/>" +
" <protect-pointcut expression='execution(* *.someAdmin*(..))' access='ROLE_ADMIN'/>" +
"</global-method-security>" + ConfigTestUtils.AUTH_PROVIDER_XML
);
target = (BusinessService) appContext.getBean("target");
}
public void loadContext() {
setContext("<b:bean id='target' class='org.springframework.security.access.annotation.BusinessServiceImpl'/>"
+ "<global-method-security order='1001' proxy-target-class='false' >"
+ " <protect-pointcut expression='execution(* *.someUser*(..))' access='ROLE_USER'/>"
+ " <protect-pointcut expression='execution(* *.someAdmin*(..))' access='ROLE_ADMIN'/>"
+ "</global-method-security>" + ConfigTestUtils.AUTH_PROVIDER_XML);
target = (BusinessService) appContext.getBean("target");
}
@After
public void closeAppContext() {
if (appContext != null) {
appContext.close();
appContext = null;
}
SecurityContextHolder.clearContext();
target = null;
}
@After
public void closeAppContext() {
if (appContext != null) {
appContext.close();
appContext = null;
}
SecurityContextHolder.clearContext();
target = null;
}
@Test(expected=AuthenticationCredentialsNotFoundException.class)
public void targetShouldPreventProtectedMethodInvocationWithNoContext() {
loadContext();
@Test(expected = AuthenticationCredentialsNotFoundException.class)
public void targetShouldPreventProtectedMethodInvocationWithNoContext() {
loadContext();
target.someUserMethod1();
}
target.someUserMethod1();
}
@Test
public void targetShouldAllowProtectedMethodInvocationWithCorrectRole() {
loadContext();
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("user", "password");
SecurityContextHolder.getContext().setAuthentication(token);
@Test
public void targetShouldAllowProtectedMethodInvocationWithCorrectRole() {
loadContext();
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(
"user", "password");
SecurityContextHolder.getContext().setAuthentication(token);
target.someUserMethod1();
target.someUserMethod1();
// SEC-1213. Check the order
Advisor[] advisors = ((Advised)target).getAdvisors();
assertEquals(1, advisors.length);
assertEquals(1001, ((MethodSecurityMetadataSourceAdvisor)advisors[0]).getOrder());
}
// SEC-1213. Check the order
Advisor[] advisors = ((Advised) target).getAdvisors();
assertEquals(1, advisors.length);
assertEquals(1001, ((MethodSecurityMetadataSourceAdvisor) advisors[0]).getOrder());
}
@Test(expected=AccessDeniedException.class)
public void targetShouldPreventProtectedMethodInvocationWithIncorrectRole() {
loadContext();
TestingAuthenticationToken token = new TestingAuthenticationToken("Test", "Password", "ROLE_SOMEOTHERROLE");
token.setAuthenticated(true);
@Test(expected = AccessDeniedException.class)
public void targetShouldPreventProtectedMethodInvocationWithIncorrectRole() {
loadContext();
TestingAuthenticationToken token = new TestingAuthenticationToken("Test",
"Password", "ROLE_SOMEOTHERROLE");
token.setAuthenticated(true);
SecurityContextHolder.getContext().setAuthentication(token);
SecurityContextHolder.getContext().setAuthentication(token);
target.someAdminMethod();
}
target.someAdminMethod();
}
@Test
public void doesntInterfereWithBeanPostProcessing() {
setContext(
"<b:bean id='myUserService' class='org.springframework.security.config.PostProcessedMockUserDetailsService'/>" +
"<global-method-security />" +
"<authentication-manager>" +
" <authentication-provider user-service-ref='myUserService'/>" +
"</authentication-manager>" +
"<b:bean id='beanPostProcessor' class='org.springframework.security.config.MockUserServiceBeanPostProcessor'/>"
);
@Test
public void doesntInterfereWithBeanPostProcessing() {
setContext("<b:bean id='myUserService' class='org.springframework.security.config.PostProcessedMockUserDetailsService'/>"
+ "<global-method-security />"
+ "<authentication-manager>"
+ " <authentication-provider user-service-ref='myUserService'/>"
+ "</authentication-manager>"
+ "<b:bean id='beanPostProcessor' class='org.springframework.security.config.MockUserServiceBeanPostProcessor'/>");
PostProcessedMockUserDetailsService service = (PostProcessedMockUserDetailsService)appContext.getBean("myUserService");
PostProcessedMockUserDetailsService service = (PostProcessedMockUserDetailsService) appContext
.getBean("myUserService");
assertEquals("Hello from the post processor!", service.getPostProcessorWasHere());
}
assertEquals("Hello from the post processor!", service.getPostProcessorWasHere());
}
@Test(expected=AccessDeniedException.class)
public void worksWithAspectJAutoproxy() {
setContext(
"<global-method-security>" +
" <protect-pointcut expression='execution(* org.springframework.security.config.*Service.*(..))'" +
" access='ROLE_SOMETHING' />" +
"</global-method-security>" +
"<b:bean id='myUserService' class='org.springframework.security.config.PostProcessedMockUserDetailsService'/>" +
"<aop:aspectj-autoproxy />" +
"<authentication-manager>" +
" <authentication-provider user-service-ref='myUserService'/>" +
"</authentication-manager>"
);
@Test(expected = AccessDeniedException.class)
public void worksWithAspectJAutoproxy() {
setContext("<global-method-security>"
+ " <protect-pointcut expression='execution(* org.springframework.security.config.*Service.*(..))'"
+ " access='ROLE_SOMETHING' />"
+ "</global-method-security>"
+ "<b:bean id='myUserService' class='org.springframework.security.config.PostProcessedMockUserDetailsService'/>"
+ "<aop:aspectj-autoproxy />" + "<authentication-manager>"
+ " <authentication-provider user-service-ref='myUserService'/>"
+ "</authentication-manager>");
UserDetailsService service = (UserDetailsService) appContext.getBean("myUserService");
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password",
AuthorityUtils.createAuthorityList("ROLE_SOMEOTHERROLE"));
SecurityContextHolder.getContext().setAuthentication(token);
UserDetailsService service = (UserDetailsService) appContext
.getBean("myUserService");
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(
"Test", "Password",
AuthorityUtils.createAuthorityList("ROLE_SOMEOTHERROLE"));
SecurityContextHolder.getContext().setAuthentication(token);
service.loadUserByUsername("notused");
}
service.loadUserByUsername("notused");
}
@Test
public void supportsMethodArgumentsInPointcut() {
setContext(
"<b:bean id='target' class='org.springframework.security.access.annotation.BusinessServiceImpl'/>" +
"<global-method-security>" +
" <protect-pointcut expression='execution(* org.springframework.security.access.annotation.BusinessService.someOther(String))' access='ROLE_ADMIN'/>" +
" <protect-pointcut expression='execution(* org.springframework.security.access.annotation.BusinessService.*(..))' access='ROLE_USER'/>" +
"</global-method-security>" + ConfigTestUtils.AUTH_PROVIDER_XML
);
SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken("user", "password"));
target = (BusinessService) appContext.getBean("target");
// someOther(int) should not be matched by someOther(String), but should require ROLE_USER
target.someOther(0);
@Test
public void supportsMethodArgumentsInPointcut() {
setContext("<b:bean id='target' class='org.springframework.security.access.annotation.BusinessServiceImpl'/>"
+ "<global-method-security>"
+ " <protect-pointcut expression='execution(* org.springframework.security.access.annotation.BusinessService.someOther(String))' access='ROLE_ADMIN'/>"
+ " <protect-pointcut expression='execution(* org.springframework.security.access.annotation.BusinessService.*(..))' access='ROLE_USER'/>"
+ "</global-method-security>" + ConfigTestUtils.AUTH_PROVIDER_XML);
SecurityContextHolder.getContext().setAuthentication(
new UsernamePasswordAuthenticationToken("user", "password"));
target = (BusinessService) appContext.getBean("target");
// someOther(int) should not be matched by someOther(String), but should require
// ROLE_USER
target.someOther(0);
try {
// String version should required admin role
target.someOther("somestring");
fail("Expected AccessDeniedException");
} catch (AccessDeniedException expected) {
}
}
try {
// String version should required admin role
target.someOther("somestring");
fail("Expected AccessDeniedException");
}
catch (AccessDeniedException expected) {
}
}
@Test
public void supportsBooleanPointcutExpressions() {
setContext(
"<b:bean id='target' class='org.springframework.security.access.annotation.BusinessServiceImpl'/>" +
"<global-method-security>" +
" <protect-pointcut expression=" +
" 'execution(* org.springframework.security.access.annotation.BusinessService.*(..)) " +
" and not execution(* org.springframework.security.access.annotation.BusinessService.someOther(String)))' " +
" access='ROLE_USER'/>" +
"</global-method-security>" + AUTH_PROVIDER_XML
);
target = (BusinessService) appContext.getBean("target");
// String method should not be protected
target.someOther("somestring");
@Test
public void supportsBooleanPointcutExpressions() {
setContext("<b:bean id='target' class='org.springframework.security.access.annotation.BusinessServiceImpl'/>"
+ "<global-method-security>"
+ " <protect-pointcut expression="
+ " 'execution(* org.springframework.security.access.annotation.BusinessService.*(..)) "
+ " and not execution(* org.springframework.security.access.annotation.BusinessService.someOther(String)))' "
+ " access='ROLE_USER'/>"
+ "</global-method-security>"
+ AUTH_PROVIDER_XML);
target = (BusinessService) appContext.getBean("target");
// String method should not be protected
target.someOther("somestring");
// All others should require ROLE_USER
try {
target.someOther(0);
fail("Expected AuthenticationCredentialsNotFoundException");
} catch (AuthenticationCredentialsNotFoundException expected) {
}
// All others should require ROLE_USER
try {
target.someOther(0);
fail("Expected AuthenticationCredentialsNotFoundException");
}
catch (AuthenticationCredentialsNotFoundException expected) {
}
SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken("user", "password"));
target.someOther(0);
}
SecurityContextHolder.getContext().setAuthentication(
new UsernamePasswordAuthenticationToken("user", "password"));
target.someOther(0);
}
@Test(expected=BeanDefinitionParsingException.class)
public void duplicateElementCausesError() {
setContext(
"<global-method-security />" +
"<global-method-security />"
);
}
@Test(expected = BeanDefinitionParsingException.class)
public void duplicateElementCausesError() {
setContext("<global-method-security />" + "<global-method-security />");
}
// SEC-936
@Test(expected=AccessDeniedException.class)
public void worksWithoutTargetOrClass() {
setContext(
"<global-method-security secured-annotations='enabled'/>" +
"<b:bean id='businessService' class='org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean'>" +
" <b:property name='serviceUrl' value='http://localhost:8080/SomeService'/>" +
" <b:property name='serviceInterface' value='org.springframework.security.access.annotation.BusinessService'/>" +
"</b:bean>" + AUTH_PROVIDER_XML
);
// SEC-936
@Test(expected = AccessDeniedException.class)
public void worksWithoutTargetOrClass() {
setContext("<global-method-security secured-annotations='enabled'/>"
+ "<b:bean id='businessService' class='org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean'>"
+ " <b:property name='serviceUrl' value='http://localhost:8080/SomeService'/>"
+ " <b:property name='serviceInterface' value='org.springframework.security.access.annotation.BusinessService'/>"
+ "</b:bean>" + AUTH_PROVIDER_XML);
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password",
AuthorityUtils.createAuthorityList("ROLE_SOMEOTHERROLE"));
SecurityContextHolder.getContext().setAuthentication(token);
target = (BusinessService) appContext.getBean("businessService");
target.someUserMethod1();
}
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(
"Test", "Password",
AuthorityUtils.createAuthorityList("ROLE_SOMEOTHERROLE"));
SecurityContextHolder.getContext().setAuthentication(token);
target = (BusinessService) appContext.getBean("businessService");
target.someUserMethod1();
}
// Expression configuration tests
// Expression configuration tests
@SuppressWarnings("unchecked")
@Test
public void expressionVoterAndAfterInvocationProviderUseSameExpressionHandlerInstance() throws Exception {
setContext("<global-method-security pre-post-annotations='enabled'/>" + AUTH_PROVIDER_XML);
AffirmativeBased adm = (AffirmativeBased) appContext.getBeansOfType(AffirmativeBased.class).values().toArray()[0];
List voters = (List) FieldUtils.getFieldValue(adm, "decisionVoters");
PreInvocationAuthorizationAdviceVoter mev = (PreInvocationAuthorizationAdviceVoter) voters.get(0);
MethodSecurityMetadataSourceAdvisor msi = (MethodSecurityMetadataSourceAdvisor)
appContext.getBeansOfType(MethodSecurityMetadataSourceAdvisor.class).values().toArray()[0];
AfterInvocationProviderManager pm = (AfterInvocationProviderManager) ((MethodSecurityInterceptor)msi.getAdvice()).getAfterInvocationManager();
PostInvocationAdviceProvider aip = (PostInvocationAdviceProvider) pm.getProviders().get(0);
assertTrue(FieldUtils.getFieldValue(mev, "preAdvice.expressionHandler") == FieldUtils.getFieldValue(aip, "postAdvice.expressionHandler"));
}
@SuppressWarnings("unchecked")
@Test
public void expressionVoterAndAfterInvocationProviderUseSameExpressionHandlerInstance()
throws Exception {
setContext("<global-method-security pre-post-annotations='enabled'/>"
+ AUTH_PROVIDER_XML);
AffirmativeBased adm = (AffirmativeBased) appContext
.getBeansOfType(AffirmativeBased.class).values().toArray()[0];
List voters = (List) FieldUtils.getFieldValue(adm, "decisionVoters");
PreInvocationAuthorizationAdviceVoter mev = (PreInvocationAuthorizationAdviceVoter) voters
.get(0);
MethodSecurityMetadataSourceAdvisor msi = (MethodSecurityMetadataSourceAdvisor) appContext
.getBeansOfType(MethodSecurityMetadataSourceAdvisor.class).values()
.toArray()[0];
AfterInvocationProviderManager pm = (AfterInvocationProviderManager) ((MethodSecurityInterceptor) msi
.getAdvice()).getAfterInvocationManager();
PostInvocationAdviceProvider aip = (PostInvocationAdviceProvider) pm
.getProviders().get(0);
assertTrue(FieldUtils.getFieldValue(mev, "preAdvice.expressionHandler") == FieldUtils
.getFieldValue(aip, "postAdvice.expressionHandler"));
}
@Test(expected=AccessDeniedException.class)
public void accessIsDeniedForHasRoleExpression() {
setContext(
"<global-method-security pre-post-annotations='enabled'/>" +
"<b:bean id='target' class='org.springframework.security.access.annotation.ExpressionProtectedBusinessServiceImpl'/>" +
AUTH_PROVIDER_XML);
SecurityContextHolder.getContext().setAuthentication(bob);
target = (BusinessService) appContext.getBean("target");
target.someAdminMethod();
}
@Test(expected = AccessDeniedException.class)
public void accessIsDeniedForHasRoleExpression() {
setContext("<global-method-security pre-post-annotations='enabled'/>"
+ "<b:bean id='target' class='org.springframework.security.access.annotation.ExpressionProtectedBusinessServiceImpl'/>"
+ AUTH_PROVIDER_XML);
SecurityContextHolder.getContext().setAuthentication(bob);
target = (BusinessService) appContext.getBean("target");
target.someAdminMethod();
}
@Test
public void beanNameExpressionPropertyIsSupported() {
setContext(
"<global-method-security pre-post-annotations='enabled' proxy-target-class='true'/>" +
"<b:bean id='number' class='java.lang.Integer'>" +
" <b:constructor-arg value='1294'/>" +
"</b:bean>" +
"<b:bean id='target' class='org.springframework.security.access.annotation.ExpressionProtectedBusinessServiceImpl'/>" +
AUTH_PROVIDER_XML);
SecurityContextHolder.getContext().setAuthentication(bob);
ExpressionProtectedBusinessServiceImpl target = (ExpressionProtectedBusinessServiceImpl) appContext.getBean("target");
target.methodWithBeanNamePropertyAccessExpression("x");
}
@Test
public void beanNameExpressionPropertyIsSupported() {
setContext("<global-method-security pre-post-annotations='enabled' proxy-target-class='true'/>"
+ "<b:bean id='number' class='java.lang.Integer'>"
+ " <b:constructor-arg value='1294'/>"
+ "</b:bean>"
+ "<b:bean id='target' class='org.springframework.security.access.annotation.ExpressionProtectedBusinessServiceImpl'/>"
+ AUTH_PROVIDER_XML);
SecurityContextHolder.getContext().setAuthentication(bob);
ExpressionProtectedBusinessServiceImpl target = (ExpressionProtectedBusinessServiceImpl) appContext
.getBean("target");
target.methodWithBeanNamePropertyAccessExpression("x");
}
@Test
public void preAndPostFilterAnnotationsWorkWithLists() {
setContext(
"<global-method-security pre-post-annotations='enabled'/>" +
"<b:bean id='target' class='org.springframework.security.access.annotation.ExpressionProtectedBusinessServiceImpl'/>" +
AUTH_PROVIDER_XML);
SecurityContextHolder.getContext().setAuthentication(bob);
target = (BusinessService) appContext.getBean("target");
List<String> arg = new ArrayList<String>();
arg.add("joe");
arg.add("bob");
arg.add("sam");
List<?> result = target.methodReturningAList(arg);
// Expression is (filterObject == name or filterObject == 'sam'), so "joe" should be gone after pre-filter
// PostFilter should remove sam from the return object
assertEquals(1, result.size());
assertEquals("bob", result.get(0));
}
@Test
public void preAndPostFilterAnnotationsWorkWithLists() {
setContext("<global-method-security pre-post-annotations='enabled'/>"
+ "<b:bean id='target' class='org.springframework.security.access.annotation.ExpressionProtectedBusinessServiceImpl'/>"
+ AUTH_PROVIDER_XML);
SecurityContextHolder.getContext().setAuthentication(bob);
target = (BusinessService) appContext.getBean("target");
List<String> arg = new ArrayList<String>();
arg.add("joe");
arg.add("bob");
arg.add("sam");
List<?> result = target.methodReturningAList(arg);
// Expression is (filterObject == name or filterObject == 'sam'), so "joe" should
// be gone after pre-filter
// PostFilter should remove sam from the return object
assertEquals(1, result.size());
assertEquals("bob", result.get(0));
}
@Test
public void prePostFilterAnnotationWorksWithArrays() {
setContext(
"<global-method-security pre-post-annotations='enabled'/>" +
"<b:bean id='target' class='org.springframework.security.access.annotation.ExpressionProtectedBusinessServiceImpl'/>" +
AUTH_PROVIDER_XML);
SecurityContextHolder.getContext().setAuthentication(bob);
target = (BusinessService) appContext.getBean("target");
Object[] arg = new String[] {"joe", "bob", "sam"};
Object[] result = target.methodReturningAnArray(arg);
assertEquals(1, result.length);
assertEquals("bob", result[0]);
}
@Test
public void prePostFilterAnnotationWorksWithArrays() {
setContext("<global-method-security pre-post-annotations='enabled'/>"
+ "<b:bean id='target' class='org.springframework.security.access.annotation.ExpressionProtectedBusinessServiceImpl'/>"
+ AUTH_PROVIDER_XML);
SecurityContextHolder.getContext().setAuthentication(bob);
target = (BusinessService) appContext.getBean("target");
Object[] arg = new String[] { "joe", "bob", "sam" };
Object[] result = target.methodReturningAnArray(arg);
assertEquals(1, result.length);
assertEquals("bob", result[0]);
}
// SEC-1392
@Test
public void customPermissionEvaluatorIsSupported() throws Exception {
setContext(
"<global-method-security pre-post-annotations='enabled'>" +
" <expression-handler ref='expressionHandler'/>" +
"</global-method-security>" +
"<b:bean id='expressionHandler' class='org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler'>" +
" <b:property name='permissionEvaluator' ref='myPermissionEvaluator'/>" +
"</b:bean>" +
"<b:bean id='myPermissionEvaluator' class='org.springframework.security.config.method.TestPermissionEvaluator'/>" +
AUTH_PROVIDER_XML);
}
// SEC-1392
@Test
public void customPermissionEvaluatorIsSupported() throws Exception {
setContext("<global-method-security pre-post-annotations='enabled'>"
+ " <expression-handler ref='expressionHandler'/>"
+ "</global-method-security>"
+ "<b:bean id='expressionHandler' class='org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler'>"
+ " <b:property name='permissionEvaluator' ref='myPermissionEvaluator'/>"
+ "</b:bean>"
+ "<b:bean id='myPermissionEvaluator' class='org.springframework.security.config.method.TestPermissionEvaluator'/>"
+ AUTH_PROVIDER_XML);
}
// SEC-1450
@Test(expected=AuthenticationException.class)
@SuppressWarnings("unchecked")
public void genericsAreMatchedByProtectPointcut() throws Exception {
setContext(
"<b:bean id='target' class='org.springframework.security.config.method.GlobalMethodSecurityBeanDefinitionParserTests$ConcreteFoo'/>" +
"<global-method-security>" +
" <protect-pointcut expression='execution(* org..*Foo.foo(..))' access='ROLE_USER'/>" +
"</global-method-security>" + AUTH_PROVIDER_XML
);
Foo foo = (Foo) appContext.getBean("target");
foo.foo(new SecurityConfig("A"));
}
// SEC-1450
@Test(expected = AuthenticationException.class)
@SuppressWarnings("unchecked")
public void genericsAreMatchedByProtectPointcut() throws Exception {
setContext("<b:bean id='target' class='org.springframework.security.config.method.GlobalMethodSecurityBeanDefinitionParserTests$ConcreteFoo'/>"
+ "<global-method-security>"
+ " <protect-pointcut expression='execution(* org..*Foo.foo(..))' access='ROLE_USER'/>"
+ "</global-method-security>" + AUTH_PROVIDER_XML);
Foo foo = (Foo) appContext.getBean("target");
foo.foo(new SecurityConfig("A"));
}
// SEC-1448
@Test
@SuppressWarnings("unchecked")
public void genericsMethodArgumentNamesAreResolved() throws Exception {
setContext(
"<b:bean id='target' class='" + ConcreteFoo.class.getName() + "'/>" +
"<global-method-security pre-post-annotations='enabled'/>" + AUTH_PROVIDER_XML
);
SecurityContextHolder.getContext().setAuthentication(bob);
Foo foo = (Foo) appContext.getBean("target");
foo.foo(new SecurityConfig("A"));
}
// SEC-1448
@Test
@SuppressWarnings("unchecked")
public void genericsMethodArgumentNamesAreResolved() throws Exception {
setContext("<b:bean id='target' class='" + ConcreteFoo.class.getName() + "'/>"
+ "<global-method-security pre-post-annotations='enabled'/>"
+ AUTH_PROVIDER_XML);
SecurityContextHolder.getContext().setAuthentication(bob);
Foo foo = (Foo) appContext.getBean("target");
foo.foo(new SecurityConfig("A"));
}
@Test
public void runAsManagerIsSetCorrectly() throws Exception {
StaticApplicationContext parent = new StaticApplicationContext();
MutablePropertyValues props = new MutablePropertyValues();
props.addPropertyValue("key", "blah");
parent.registerSingleton("runAsMgr", RunAsManagerImpl.class, props);
parent.refresh();
@Test
public void runAsManagerIsSetCorrectly() throws Exception {
StaticApplicationContext parent = new StaticApplicationContext();
MutablePropertyValues props = new MutablePropertyValues();
props.addPropertyValue("key", "blah");
parent.registerSingleton("runAsMgr", RunAsManagerImpl.class, props);
parent.refresh();
setContext("<global-method-security run-as-manager-ref='runAsMgr'/>" + AUTH_PROVIDER_XML, parent);
RunAsManagerImpl ram = (RunAsManagerImpl) appContext.getBean("runAsMgr");
MethodSecurityMetadataSourceAdvisor msi = (MethodSecurityMetadataSourceAdvisor)
appContext.getBeansOfType(MethodSecurityMetadataSourceAdvisor.class).values().toArray()[0];
assertSame(ram, FieldUtils.getFieldValue(msi.getAdvice(), "runAsManager"));
}
setContext("<global-method-security run-as-manager-ref='runAsMgr'/>"
+ AUTH_PROVIDER_XML, parent);
RunAsManagerImpl ram = (RunAsManagerImpl) appContext.getBean("runAsMgr");
MethodSecurityMetadataSourceAdvisor msi = (MethodSecurityMetadataSourceAdvisor) appContext
.getBeansOfType(MethodSecurityMetadataSourceAdvisor.class).values()
.toArray()[0];
assertSame(ram, FieldUtils.getFieldValue(msi.getAdvice(), "runAsManager"));
}
@Test
@SuppressWarnings("unchecked")
public void supportsExternalMetadataSource() throws Exception {
setContext(
"<b:bean id='target' class='" + ConcreteFoo.class.getName() + "'/>" +
"<method-security-metadata-source id='mds'>" +
" <protect method='"+ Foo.class.getName() + ".foo' access='ROLE_ADMIN'/>" +
"</method-security-metadata-source>" +
"<global-method-security pre-post-annotations='enabled' metadata-source-ref='mds'/>" + AUTH_PROVIDER_XML
);
// External MDS should take precedence over PreAuthorize
SecurityContextHolder.getContext().setAuthentication(bob);
Foo foo = (Foo) appContext.getBean("target");
try {
foo.foo(new SecurityConfig("A"));
fail("Bob can't invoke admin methods");
} catch (AccessDeniedException expected) {
}
SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken("admin", "password"));
foo.foo(new SecurityConfig("A"));
}
@Test
@SuppressWarnings("unchecked")
public void supportsExternalMetadataSource() throws Exception {
setContext("<b:bean id='target' class='"
+ ConcreteFoo.class.getName()
+ "'/>"
+ "<method-security-metadata-source id='mds'>"
+ " <protect method='"
+ Foo.class.getName()
+ ".foo' access='ROLE_ADMIN'/>"
+ "</method-security-metadata-source>"
+ "<global-method-security pre-post-annotations='enabled' metadata-source-ref='mds'/>"
+ AUTH_PROVIDER_XML);
// External MDS should take precedence over PreAuthorize
SecurityContextHolder.getContext().setAuthentication(bob);
Foo foo = (Foo) appContext.getBean("target");
try {
foo.foo(new SecurityConfig("A"));
fail("Bob can't invoke admin methods");
}
catch (AccessDeniedException expected) {
}
SecurityContextHolder.getContext().setAuthentication(
new UsernamePasswordAuthenticationToken("admin", "password"));
foo.foo(new SecurityConfig("A"));
}
@Test
public void supportsCustomAuthenticationManager() throws Exception {
setContext(
"<b:bean id='target' class='" + ConcreteFoo.class.getName() + "'/>" +
"<method-security-metadata-source id='mds'>" +
" <protect method='"+ Foo.class.getName() + ".foo' access='ROLE_ADMIN'/>" +
"</method-security-metadata-source>" +
"<global-method-security pre-post-annotations='enabled' metadata-source-ref='mds' authentication-manager-ref='customAuthMgr'/>" +
"<b:bean id='customAuthMgr' class='org.springframework.security.config.method.GlobalMethodSecurityBeanDefinitionParserTests$CustomAuthManager'>" +
" <b:constructor-arg value='authManager'/>" +
"</b:bean>" +
AUTH_PROVIDER_XML
);
SecurityContextHolder.getContext().setAuthentication(bob);
Foo foo = (Foo) appContext.getBean("target");
try {
foo.foo(new SecurityConfig("A"));
fail("Bob can't invoke admin methods");
} catch (AccessDeniedException expected) {
}
SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken("admin", "password"));
foo.foo(new SecurityConfig("A"));
}
@Test
public void supportsCustomAuthenticationManager() throws Exception {
setContext("<b:bean id='target' class='"
+ ConcreteFoo.class.getName()
+ "'/>"
+ "<method-security-metadata-source id='mds'>"
+ " <protect method='"
+ Foo.class.getName()
+ ".foo' access='ROLE_ADMIN'/>"
+ "</method-security-metadata-source>"
+ "<global-method-security pre-post-annotations='enabled' metadata-source-ref='mds' authentication-manager-ref='customAuthMgr'/>"
+ "<b:bean id='customAuthMgr' class='org.springframework.security.config.method.GlobalMethodSecurityBeanDefinitionParserTests$CustomAuthManager'>"
+ " <b:constructor-arg value='authManager'/>" + "</b:bean>"
+ AUTH_PROVIDER_XML);
SecurityContextHolder.getContext().setAuthentication(bob);
Foo foo = (Foo) appContext.getBean("target");
try {
foo.foo(new SecurityConfig("A"));
fail("Bob can't invoke admin methods");
}
catch (AccessDeniedException expected) {
}
SecurityContextHolder.getContext().setAuthentication(
new UsernamePasswordAuthenticationToken("admin", "password"));
foo.foo(new SecurityConfig("A"));
}
static class CustomAuthManager implements AuthenticationManager, ApplicationContextAware {
private String beanName;
private AuthenticationManager authenticationManager;
static class CustomAuthManager implements AuthenticationManager,
ApplicationContextAware {
private String beanName;
private AuthenticationManager authenticationManager;
CustomAuthManager(String beanName) {
this.beanName = beanName;
}
CustomAuthManager(String beanName) {
this.beanName = beanName;
}
public Authentication authenticate(Authentication authentication)
throws AuthenticationException {
return authenticationManager.authenticate(authentication);
}
public Authentication authenticate(Authentication authentication)
throws AuthenticationException {
return authenticationManager.authenticate(authentication);
}
/* (non-Javadoc)
* @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
*/
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
this.authenticationManager = applicationContext.getBean(beanName,AuthenticationManager.class);
}
}
/*
* (non-Javadoc)
*
* @see
* org.springframework.context.ApplicationContextAware#setApplicationContext(org
* .springframework.context.ApplicationContext)
*/
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
this.authenticationManager = applicationContext.getBean(beanName,
AuthenticationManager.class);
}
}
private void setContext(String context) {
appContext = new InMemoryXmlApplicationContext(context);
}
private void setContext(String context) {
appContext = new InMemoryXmlApplicationContext(context);
}
private void setContext(String context, ApplicationContext parent) {
appContext = new InMemoryXmlApplicationContext(context, parent);
}
private void setContext(String context, ApplicationContext parent) {
appContext = new InMemoryXmlApplicationContext(context, parent);
}
interface Foo<T extends ConfigAttribute> {
void foo(T action);
}
interface Foo<T extends ConfigAttribute> {
void foo(T action);
}
public static class ConcreteFoo implements Foo<SecurityConfig> {
@PreAuthorize("#action.attribute == 'A'")
public void foo(SecurityConfig action) {
}
}
public static class ConcreteFoo implements Foo<SecurityConfig> {
@PreAuthorize("#action.attribute == 'A'")
public void foo(SecurityConfig action) {
}
}
}

View File

@@ -27,69 +27,73 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:org/springframework/security/config/method-security.xml")
public class InterceptMethodsBeanDefinitionDecoratorTests implements ApplicationContextAware {
@Autowired
@Qualifier("target")
private TestBusinessBean target;
@Autowired
@Qualifier("transactionalTarget")
private TestBusinessBean transactionalTarget;
private ApplicationContext appContext;
public class InterceptMethodsBeanDefinitionDecoratorTests implements
ApplicationContextAware {
@Autowired
@Qualifier("target")
private TestBusinessBean target;
@Autowired
@Qualifier("transactionalTarget")
private TestBusinessBean transactionalTarget;
private ApplicationContext appContext;
@BeforeClass
public static void loadContext() {
// Set value for placeholder
System.setProperty("admin.role", "ROLE_ADMIN");
}
@BeforeClass
public static void loadContext() {
// Set value for placeholder
System.setProperty("admin.role", "ROLE_ADMIN");
}
@After
public void clearContext() {
SecurityContextHolder.clearContext();
}
@After
public void clearContext() {
SecurityContextHolder.clearContext();
}
@Test
public void targetDoesntLoseApplicationListenerInterface() {
assertEquals(1, appContext.getBeansOfType(ApplicationListener.class).size());
assertEquals(1, appContext.getBeanNamesForType(ApplicationListener.class).length);
appContext.publishEvent(new AuthenticationSuccessEvent(new TestingAuthenticationToken("user", "")));
@Test
public void targetDoesntLoseApplicationListenerInterface() {
assertEquals(1, appContext.getBeansOfType(ApplicationListener.class).size());
assertEquals(1, appContext.getBeanNamesForType(ApplicationListener.class).length);
appContext.publishEvent(new AuthenticationSuccessEvent(
new TestingAuthenticationToken("user", "")));
assertTrue(target instanceof ApplicationListener<?>);
}
assertTrue(target instanceof ApplicationListener<?>);
}
@Test
public void targetShouldAllowUnprotectedMethodInvocationWithNoContext() {
target.unprotected();
}
@Test
public void targetShouldAllowUnprotectedMethodInvocationWithNoContext() {
target.unprotected();
}
@Test(expected=AuthenticationCredentialsNotFoundException.class)
public void targetShouldPreventProtectedMethodInvocationWithNoContext() {
target.doSomething();
}
@Test(expected = AuthenticationCredentialsNotFoundException.class)
public void targetShouldPreventProtectedMethodInvocationWithNoContext() {
target.doSomething();
}
@Test
public void targetShouldAllowProtectedMethodInvocationWithCorrectRole() {
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password",
AuthorityUtils.createAuthorityList("ROLE_USER"));
SecurityContextHolder.getContext().setAuthentication(token);
@Test
public void targetShouldAllowProtectedMethodInvocationWithCorrectRole() {
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(
"Test", "Password", AuthorityUtils.createAuthorityList("ROLE_USER"));
SecurityContextHolder.getContext().setAuthentication(token);
target.doSomething();
}
target.doSomething();
}
@Test(expected=AccessDeniedException.class)
public void targetShouldPreventProtectedMethodInvocationWithIncorrectRole() {
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password",
AuthorityUtils.createAuthorityList("ROLE_SOMEOTHERROLE"));
SecurityContextHolder.getContext().setAuthentication(token);
@Test(expected = AccessDeniedException.class)
public void targetShouldPreventProtectedMethodInvocationWithIncorrectRole() {
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(
"Test", "Password",
AuthorityUtils.createAuthorityList("ROLE_SOMEOTHERROLE"));
SecurityContextHolder.getContext().setAuthentication(token);
target.doSomething();
}
target.doSomething();
}
@Test(expected = AuthenticationException.class)
public void transactionalMethodsShouldBeSecured() throws Exception {
transactionalTarget.doSomething();
}
@Test(expected = AuthenticationException.class)
public void transactionalMethodsShouldBeSecured() throws Exception {
transactionalTarget.doSomething();
}
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.appContext = applicationContext;
}
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
this.appContext = applicationContext;
}
}

View File

@@ -16,66 +16,66 @@ import org.springframework.security.core.context.SecurityContextHolder;
* @author Luke Taylor
*/
public class Jsr250AnnotationDrivenBeanDefinitionParserTests {
private InMemoryXmlApplicationContext appContext;
private InMemoryXmlApplicationContext appContext;
private BusinessService target;
private BusinessService target;
@Before
public void loadContext() {
appContext = new InMemoryXmlApplicationContext(
"<b:bean id='target' class='org.springframework.security.access.annotation.Jsr250BusinessServiceImpl'/>" +
"<global-method-security jsr250-annotations='enabled'/>" + ConfigTestUtils.AUTH_PROVIDER_XML
);
target = (BusinessService) appContext.getBean("target");
}
@Before
public void loadContext() {
appContext = new InMemoryXmlApplicationContext(
"<b:bean id='target' class='org.springframework.security.access.annotation.Jsr250BusinessServiceImpl'/>"
+ "<global-method-security jsr250-annotations='enabled'/>"
+ ConfigTestUtils.AUTH_PROVIDER_XML);
target = (BusinessService) appContext.getBean("target");
}
@After
public void closeAppContext() {
if (appContext != null) {
appContext.close();
}
SecurityContextHolder.clearContext();
}
@After
public void closeAppContext() {
if (appContext != null) {
appContext.close();
}
SecurityContextHolder.clearContext();
}
@Test(expected=AuthenticationCredentialsNotFoundException.class)
public void targetShouldPreventProtectedMethodInvocationWithNoContext() {
target.someUserMethod1();
}
@Test(expected = AuthenticationCredentialsNotFoundException.class)
public void targetShouldPreventProtectedMethodInvocationWithNoContext() {
target.someUserMethod1();
}
@Test
public void permitAllShouldBeDefaultAttribute() {
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password",
AuthorityUtils.createAuthorityList("ROLE_USER"));
SecurityContextHolder.getContext().setAuthentication(token);
@Test
public void permitAllShouldBeDefaultAttribute() {
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(
"Test", "Password", AuthorityUtils.createAuthorityList("ROLE_USER"));
SecurityContextHolder.getContext().setAuthentication(token);
target.someOther(0);
}
target.someOther(0);
}
@Test
public void targetShouldAllowProtectedMethodInvocationWithCorrectRole() {
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password",
AuthorityUtils.createAuthorityList("ROLE_USER"));
SecurityContextHolder.getContext().setAuthentication(token);
@Test
public void targetShouldAllowProtectedMethodInvocationWithCorrectRole() {
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(
"Test", "Password", AuthorityUtils.createAuthorityList("ROLE_USER"));
SecurityContextHolder.getContext().setAuthentication(token);
target.someUserMethod1();
}
target.someUserMethod1();
}
@Test(expected=AccessDeniedException.class)
public void targetShouldPreventProtectedMethodInvocationWithIncorrectRole() {
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password",
AuthorityUtils.createAuthorityList("ROLE_SOMEOTHERROLE"));
SecurityContextHolder.getContext().setAuthentication(token);
@Test(expected = AccessDeniedException.class)
public void targetShouldPreventProtectedMethodInvocationWithIncorrectRole() {
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(
"Test", "Password",
AuthorityUtils.createAuthorityList("ROLE_SOMEOTHERROLE"));
SecurityContextHolder.getContext().setAuthentication(token);
target.someAdminMethod();
}
target.someAdminMethod();
}
@Test
public void hasAnyRoleAddsDefaultPrefix() {
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(
"Test", "Password", AuthorityUtils.createAuthorityList("ROLE_USER"));
SecurityContextHolder.getContext().setAuthentication(token);
@Test
public void hasAnyRoleAddsDefaultPrefix() {
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password",
AuthorityUtils.createAuthorityList("ROLE_USER"));
SecurityContextHolder.getContext().setAuthentication(token);
target.rolesAllowedUser();
}
target.rolesAllowedUser();
}
}

View File

@@ -30,50 +30,50 @@ import org.springframework.security.core.context.SecurityContextHolder;
*/
public class Sec2196Tests {
private ConfigurableApplicationContext context;
private ConfigurableApplicationContext context;
@Test(expected = AccessDeniedException.class)
public void genericMethodsProtected() {
loadContext("<global-method-security secured-annotations=\"enabled\" pre-post-annotations=\"enabled\"/>"
+ "<b:bean class='" + Service.class.getName() + "'/>");
@Test(expected = AccessDeniedException.class)
public void genericMethodsProtected() {
loadContext("<global-method-security secured-annotations=\"enabled\" pre-post-annotations=\"enabled\"/>"
+ "<b:bean class='" + Service.class.getName() + "'/>");
SecurityContextHolder.getContext().setAuthentication(
new TestingAuthenticationToken("test", "pass", "ROLE_USER"));
Service service = context.getBean(Service.class);
service.save(new User());
}
SecurityContextHolder.getContext().setAuthentication(
new TestingAuthenticationToken("test", "pass", "ROLE_USER"));
Service service = context.getBean(Service.class);
service.save(new User());
}
@Test
public void genericMethodsAllowed() {
loadContext("<global-method-security secured-annotations=\"enabled\" pre-post-annotations=\"enabled\"/>"
+ "<b:bean class='" + Service.class.getName() + "'/>");
@Test
public void genericMethodsAllowed() {
loadContext("<global-method-security secured-annotations=\"enabled\" pre-post-annotations=\"enabled\"/>"
+ "<b:bean class='" + Service.class.getName() + "'/>");
SecurityContextHolder.getContext().setAuthentication(
new TestingAuthenticationToken("test", "pass", "saveUsers"));
Service service = context.getBean(Service.class);
service.save(new User());
}
SecurityContextHolder.getContext().setAuthentication(
new TestingAuthenticationToken("test", "pass", "saveUsers"));
Service service = context.getBean(Service.class);
service.save(new User());
}
private void loadContext(String context) {
this.context = new InMemoryXmlApplicationContext(context);
}
private void loadContext(String context) {
this.context = new InMemoryXmlApplicationContext(context);
}
@After
public void closeAppContext() {
if (context != null) {
context.close();
context = null;
}
SecurityContextHolder.clearContext();
}
@After
public void closeAppContext() {
if (context != null) {
context.close();
context = null;
}
SecurityContextHolder.clearContext();
}
public static class Service {
@PreAuthorize("hasAuthority('saveUsers')")
public <T extends User> T save(T dto) {
return dto;
}
}
public static class Service {
@PreAuthorize("hasAuthority('saveUsers')")
public <T extends User> T save(T dto) {
return dto;
}
}
static class User {
}
static class User {
}
}

View File

@@ -23,83 +23,86 @@ import org.springframework.security.core.context.SecurityContextHolder;
* @author Ben Alex
*/
public class SecuredAnnotationDrivenBeanDefinitionParserTests {
private InMemoryXmlApplicationContext appContext;
private InMemoryXmlApplicationContext appContext;
private BusinessService target;
private BusinessService target;
@Before
public void loadContext() {
SecurityContextHolder.clearContext();
appContext = new InMemoryXmlApplicationContext(
"<b:bean id='target' class='org.springframework.security.access.annotation.BusinessServiceImpl'/>" +
"<global-method-security secured-annotations='enabled'/>" + ConfigTestUtils.AUTH_PROVIDER_XML
);
target = (BusinessService) appContext.getBean("target");
}
@Before
public void loadContext() {
SecurityContextHolder.clearContext();
appContext = new InMemoryXmlApplicationContext(
"<b:bean id='target' class='org.springframework.security.access.annotation.BusinessServiceImpl'/>"
+ "<global-method-security secured-annotations='enabled'/>"
+ ConfigTestUtils.AUTH_PROVIDER_XML);
target = (BusinessService) appContext.getBean("target");
}
@After
public void closeAppContext() {
if (appContext != null) {
appContext.close();
}
SecurityContextHolder.clearContext();
}
@After
public void closeAppContext() {
if (appContext != null) {
appContext.close();
}
SecurityContextHolder.clearContext();
}
@Test(expected=AuthenticationCredentialsNotFoundException.class)
public void targetShouldPreventProtectedMethodInvocationWithNoContext() {
target.someUserMethod1();
}
@Test(expected = AuthenticationCredentialsNotFoundException.class)
public void targetShouldPreventProtectedMethodInvocationWithNoContext() {
target.someUserMethod1();
}
@Test
public void targetShouldAllowProtectedMethodInvocationWithCorrectRole() {
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password",
AuthorityUtils.createAuthorityList("ROLE_USER"));
SecurityContextHolder.getContext().setAuthentication(token);
@Test
public void targetShouldAllowProtectedMethodInvocationWithCorrectRole() {
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(
"Test", "Password", AuthorityUtils.createAuthorityList("ROLE_USER"));
SecurityContextHolder.getContext().setAuthentication(token);
target.someUserMethod1();
}
target.someUserMethod1();
}
@Test(expected=AccessDeniedException.class)
public void targetShouldPreventProtectedMethodInvocationWithIncorrectRole() {
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password",
AuthorityUtils.createAuthorityList("ROLE_SOMEOTHER"));
SecurityContextHolder.getContext().setAuthentication(token);
@Test(expected = AccessDeniedException.class)
public void targetShouldPreventProtectedMethodInvocationWithIncorrectRole() {
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(
"Test", "Password", AuthorityUtils.createAuthorityList("ROLE_SOMEOTHER"));
SecurityContextHolder.getContext().setAuthentication(token);
target.someAdminMethod();
}
target.someAdminMethod();
}
// SEC-1387
@Test(expected=AuthenticationCredentialsNotFoundException.class)
public void targetIsSerializableBeforeUse() throws Exception {
BusinessService chompedTarget = (BusinessService) serializeAndDeserialize(target);
chompedTarget.someAdminMethod();
}
// SEC-1387
@Test(expected = AuthenticationCredentialsNotFoundException.class)
public void targetIsSerializableBeforeUse() throws Exception {
BusinessService chompedTarget = (BusinessService) serializeAndDeserialize(target);
chompedTarget.someAdminMethod();
}
@Test(expected=AccessDeniedException.class)
public void targetIsSerializableAfterUse() throws Exception {
try {
target.someAdminMethod();
} catch (AuthenticationCredentialsNotFoundException expected) {
}
SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken("u","p","ROLE_A"));
@Test(expected = AccessDeniedException.class)
public void targetIsSerializableAfterUse() throws Exception {
try {
target.someAdminMethod();
}
catch (AuthenticationCredentialsNotFoundException expected) {
}
SecurityContextHolder.getContext().setAuthentication(
new TestingAuthenticationToken("u", "p", "ROLE_A"));
BusinessService chompedTarget = (BusinessService) serializeAndDeserialize(target);
chompedTarget.someAdminMethod();
}
BusinessService chompedTarget = (BusinessService) serializeAndDeserialize(target);
chompedTarget.someAdminMethod();
}
private Object serializeAndDeserialize(Object o) throws IOException, ClassNotFoundException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(o);
oos.flush();
baos.flush();
byte[] bytes = baos.toByteArray();
private Object serializeAndDeserialize(Object o) throws IOException,
ClassNotFoundException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(o);
oos.flush();
baos.flush();
byte[] bytes = baos.toByteArray();
ByteArrayInputStream is = new ByteArrayInputStream(bytes);
ObjectInputStream ois = new ObjectInputStream(is);
Object o2 = ois.readObject();
ByteArrayInputStream is = new ByteArrayInputStream(bytes);
ObjectInputStream ois = new ObjectInputStream(is);
Object o2 = ois.readObject();
return o2;
}
return o2;
}
}

View File

@@ -7,13 +7,14 @@ import org.springframework.security.core.Authentication;
public class TestPermissionEvaluator implements PermissionEvaluator {
public boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission) {
return false;
}
public boolean hasPermission(Authentication authentication,
Object targetDomainObject, Object permission) {
return false;
}
public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType,
Object permission) {
return false;
}
public boolean hasPermission(Authentication authentication, Serializable targetId,
String targetType, Object permission) {
return false;
}
}

View File

@@ -29,20 +29,20 @@ import org.springframework.security.core.Authentication;
*
*/
public class JpaPermissionEvaluator implements PermissionEvaluator {
@Autowired
private EntityManager entityManager;
@Autowired
private EntityManager entityManager;
public JpaPermissionEvaluator() {
System.out.println("initializing "+this);
}
public JpaPermissionEvaluator() {
System.out.println("initializing " + this);
}
public boolean hasPermission(Authentication authentication,
Object targetDomainObject, Object permission) {
return true;
}
public boolean hasPermission(Authentication authentication,
Object targetDomainObject, Object permission) {
return true;
}
public boolean hasPermission(Authentication authentication,
Serializable targetId, String targetType, Object permission) {
return true;
}
public boolean hasPermission(Authentication authentication, Serializable targetId,
String targetType, Object permission) {
return true;
}
}

View File

@@ -29,8 +29,8 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@ContextConfiguration("sec2136.xml")
public class Sec2136Tests {
@Test
public void configurationLoads() {
@Test
public void configurationLoads() {
}
}
}

View File

@@ -25,26 +25,27 @@ import org.springframework.context.support.GenericXmlApplicationContext;
*
*/
public class Sec2499Tests {
private GenericXmlApplicationContext parent;
private GenericXmlApplicationContext parent;
private GenericXmlApplicationContext child;
private GenericXmlApplicationContext child;
@After
public void cleanup() {
if(parent != null) {
parent.close();
}
if(child != null) {
child.close();
}
}
@After
public void cleanup() {
if (parent != null) {
parent.close();
}
if (child != null) {
child.close();
}
}
@Test
public void methodExpressionHandlerInParentContextLoads() {
parent = new GenericXmlApplicationContext("org/springframework/security/config/method/sec2499/parent.xml");
child = new GenericXmlApplicationContext();
child.load("org/springframework/security/config/method/sec2499/child.xml");
child.setParent(parent);
child.refresh();
}
@Test
public void methodExpressionHandlerInParentContextLoads() {
parent = new GenericXmlApplicationContext(
"org/springframework/security/config/method/sec2499/parent.xml");
child = new GenericXmlApplicationContext();
child.load("org/springframework/security/config/method/sec2499/child.xml");
child.setParent(parent);
child.refresh();
}
}

View File

@@ -25,49 +25,49 @@ import org.springframework.security.util.InMemoryResource;
* @author Luke Taylor
*/
public class InMemoryXmlApplicationContext extends AbstractXmlApplicationContext {
private static final String BEANS_OPENING =
"<b:beans xmlns='http://www.springframework.org/schema/security'\n" +
" xmlns:context='http://www.springframework.org/schema/context'\n" +
" xmlns:b='http://www.springframework.org/schema/beans'\n" +
" xmlns:aop='http://www.springframework.org/schema/aop'\n" +
" xmlns:websocket='http://www.springframework.org/schema/websocket'\n" +
" xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'\n" +
" xsi:schemaLocation='http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd\n" +
"http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd\n" +
"http://www.springframework.org/schema/websocket http://www.springframework.org/schema/websocket/spring-websocket.xsd\n" +
"http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd\n" +
"http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-";
private static final String BEANS_CLOSE = "</b:beans>\n";
private static final String BEANS_OPENING = "<b:beans xmlns='http://www.springframework.org/schema/security'\n"
+ " xmlns:context='http://www.springframework.org/schema/context'\n"
+ " xmlns:b='http://www.springframework.org/schema/beans'\n"
+ " xmlns:aop='http://www.springframework.org/schema/aop'\n"
+ " xmlns:websocket='http://www.springframework.org/schema/websocket'\n"
+ " xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'\n"
+ " xsi:schemaLocation='http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd\n"
+ "http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd\n"
+ "http://www.springframework.org/schema/websocket http://www.springframework.org/schema/websocket/spring-websocket.xsd\n"
+ "http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd\n"
+ "http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-";
private static final String BEANS_CLOSE = "</b:beans>\n";
Resource inMemoryXml;
Resource inMemoryXml;
public InMemoryXmlApplicationContext(String xml) {
this(xml, "4.0", null);
}
public InMemoryXmlApplicationContext(String xml) {
this(xml, "4.0", null);
}
public InMemoryXmlApplicationContext(String xml, ApplicationContext parent) {
this(xml, "4.0", parent);
}
public InMemoryXmlApplicationContext(String xml, ApplicationContext parent) {
this(xml, "4.0", parent);
}
public InMemoryXmlApplicationContext(String xml, String secVersion, ApplicationContext parent) {
String fullXml = BEANS_OPENING + secVersion + ".xsd'>\n" + xml + BEANS_CLOSE;
inMemoryXml = new InMemoryResource(fullXml);
setAllowBeanDefinitionOverriding(true);
setParent(parent);
refresh();
}
public InMemoryXmlApplicationContext(String xml, String secVersion,
ApplicationContext parent) {
String fullXml = BEANS_OPENING + secVersion + ".xsd'>\n" + xml + BEANS_CLOSE;
inMemoryXml = new InMemoryResource(fullXml);
setAllowBeanDefinitionOverriding(true);
setParent(parent);
refresh();
}
@Override
protected DefaultListableBeanFactory createBeanFactory() {
return new DefaultListableBeanFactory(getInternalParentBeanFactory()) {
@Override
protected boolean allowAliasOverriding() {
return true;
}
};
}
@Override
protected DefaultListableBeanFactory createBeanFactory() {
return new DefaultListableBeanFactory(getInternalParentBeanFactory()) {
@Override
protected boolean allowAliasOverriding() {
return true;
}
};
}
protected Resource[] getConfigResources() {
return new Resource[] {inMemoryXml};
}
protected Resource[] getConfigResources() {
return new Resource[] { inMemoryXml };
}
}

View File

@@ -18,105 +18,98 @@ import org.springframework.security.core.context.SecurityContextHolder;
* @author Ben Alex
*/
public class MethodSecurityInterceptorWithAopConfigTests {
static final String AUTH_PROVIDER_XML =
"<authentication-manager>" +
" <authentication-provider>" +
" <user-service>" +
" <user name='bob' password='bobspassword' authorities='ROLE_USER,ROLE_ADMIN' />" +
" <user name='bill' password='billspassword' authorities='ROLE_USER' />" +
" </user-service>" +
" </authentication-provider>" +
"</authentication-manager>";
static final String AUTH_PROVIDER_XML = "<authentication-manager>"
+ " <authentication-provider>"
+ " <user-service>"
+ " <user name='bob' password='bobspassword' authorities='ROLE_USER,ROLE_ADMIN' />"
+ " <user name='bill' password='billspassword' authorities='ROLE_USER' />"
+ " </user-service>" + " </authentication-provider>"
+ "</authentication-manager>";
static final String ACCESS_MANAGER_XML =
"<b:bean id='accessDecisionManager' class='org.springframework.security.access.vote.AffirmativeBased'>" +
" <b:constructor-arg>" +
" <b:list><b:bean class='org.springframework.security.access.vote.RoleVoter'/></b:list>" +
" </b:constructor-arg>" +
"</b:bean>";
static final String ACCESS_MANAGER_XML = "<b:bean id='accessDecisionManager' class='org.springframework.security.access.vote.AffirmativeBased'>"
+ " <b:constructor-arg>"
+ " <b:list><b:bean class='org.springframework.security.access.vote.RoleVoter'/></b:list>"
+ " </b:constructor-arg>" + "</b:bean>";
static final String TARGET_BEAN_AND_INTERCEPTOR =
"<b:bean id='target' class='org.springframework.security.TargetObject'/>" +
"<b:bean id='securityInterceptor' class='org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor' autowire='byType' >" +
" <b:property name='securityMetadataSource'>" +
" <method-security-metadata-source>" +
" <protect method='org.springframework.security.ITargetObject.makeLower*' access='ROLE_A'/>" +
" <protect method='org.springframework.security.ITargetObject.makeUpper*' access='ROLE_A'/>" +
" <protect method='org.springframework.security.ITargetObject.computeHashCode*' access='ROLE_B'/>" +
" </method-security-metadata-source>" +
" </b:property>" +
"</b:bean>";
static final String TARGET_BEAN_AND_INTERCEPTOR = "<b:bean id='target' class='org.springframework.security.TargetObject'/>"
+ "<b:bean id='securityInterceptor' class='org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor' autowire='byType' >"
+ " <b:property name='securityMetadataSource'>"
+ " <method-security-metadata-source>"
+ " <protect method='org.springframework.security.ITargetObject.makeLower*' access='ROLE_A'/>"
+ " <protect method='org.springframework.security.ITargetObject.makeUpper*' access='ROLE_A'/>"
+ " <protect method='org.springframework.security.ITargetObject.computeHashCode*' access='ROLE_B'/>"
+ " </method-security-metadata-source>"
+ " </b:property>"
+ "</b:bean>";
private AbstractXmlApplicationContext appContext;
private AbstractXmlApplicationContext appContext;
@Before
public void clearContext() {
SecurityContextHolder.clearContext();
}
@Before
public void clearContext() {
SecurityContextHolder.clearContext();
}
@After
public void closeAppContext() {
SecurityContextHolder.clearContext();
if (appContext != null) {
appContext.close();
appContext = null;
}
}
@After
public void closeAppContext() {
SecurityContextHolder.clearContext();
if (appContext != null) {
appContext.close();
appContext = null;
}
}
@Test(expected=AuthenticationCredentialsNotFoundException.class)
public void securityInterceptorIsAppliedWhenUsedWithAopConfig() {
setContext(
"<aop:config>" +
" <aop:pointcut id='targetMethods' expression='execution(* org.springframework.security.TargetObject.*(..))'/>" +
" <aop:advisor advice-ref='securityInterceptor' pointcut-ref='targetMethods' />" +
"</aop:config>" +
TARGET_BEAN_AND_INTERCEPTOR +
AUTH_PROVIDER_XML + ACCESS_MANAGER_XML);
@Test(expected = AuthenticationCredentialsNotFoundException.class)
public void securityInterceptorIsAppliedWhenUsedWithAopConfig() {
setContext("<aop:config>"
+ " <aop:pointcut id='targetMethods' expression='execution(* org.springframework.security.TargetObject.*(..))'/>"
+ " <aop:advisor advice-ref='securityInterceptor' pointcut-ref='targetMethods' />"
+ "</aop:config>" + TARGET_BEAN_AND_INTERCEPTOR + AUTH_PROVIDER_XML
+ ACCESS_MANAGER_XML);
ITargetObject target = (ITargetObject) appContext.getBean("target");
ITargetObject target = (ITargetObject) appContext.getBean("target");
// Check both against interface and class
try {
target.makeLowerCase("TEST");
fail("AuthenticationCredentialsNotFoundException expected");
} catch (AuthenticationCredentialsNotFoundException expected) {
}
// Check both against interface and class
try {
target.makeLowerCase("TEST");
fail("AuthenticationCredentialsNotFoundException expected");
}
catch (AuthenticationCredentialsNotFoundException expected) {
}
target.makeUpperCase("test");
}
target.makeUpperCase("test");
}
@Test(expected=AuthenticationCredentialsNotFoundException.class)
public void securityInterceptorIsAppliedWhenUsedWithBeanNameAutoProxyCreator() {
setContext(
"<b:bean id='autoProxyCreator' class='org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator'>" +
" <b:property name='interceptorNames'>" +
" <b:list>" +
" <b:value>securityInterceptor</b:value>" +
" </b:list>" +
" </b:property>" +
" <b:property name='beanNames'>" +
" <b:list>" +
" <b:value>target</b:value>" +
" </b:list>" +
" </b:property>" +
" <b:property name='proxyTargetClass' value='false'/>" +
"</b:bean>" +
TARGET_BEAN_AND_INTERCEPTOR +
AUTH_PROVIDER_XML + ACCESS_MANAGER_XML);
@Test(expected = AuthenticationCredentialsNotFoundException.class)
public void securityInterceptorIsAppliedWhenUsedWithBeanNameAutoProxyCreator() {
setContext("<b:bean id='autoProxyCreator' class='org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator'>"
+ " <b:property name='interceptorNames'>"
+ " <b:list>"
+ " <b:value>securityInterceptor</b:value>"
+ " </b:list>"
+ " </b:property>"
+ " <b:property name='beanNames'>"
+ " <b:list>"
+ " <b:value>target</b:value>"
+ " </b:list>"
+ " </b:property>"
+ " <b:property name='proxyTargetClass' value='false'/>"
+ "</b:bean>"
+ TARGET_BEAN_AND_INTERCEPTOR + AUTH_PROVIDER_XML + ACCESS_MANAGER_XML);
ITargetObject target = (ITargetObject) appContext.getBean("target");
ITargetObject target = (ITargetObject) appContext.getBean("target");
try {
target.makeLowerCase("TEST");
fail("AuthenticationCredentialsNotFoundException expected");
} catch (AuthenticationCredentialsNotFoundException expected) {
}
try {
target.makeLowerCase("TEST");
fail("AuthenticationCredentialsNotFoundException expected");
}
catch (AuthenticationCredentialsNotFoundException expected) {
}
target.makeUpperCase("test");
target.makeUpperCase("test");
}
}
private void setContext(String context) {
appContext = new InMemoryXmlApplicationContext(context);
}
private void setContext(String context) {
appContext = new InMemoryXmlApplicationContext(context);
}
}