diff --git a/test/src/test/java/org/springframework/security/test/context/showcase/CustomUserDetails.java b/test/src/test/java/org/springframework/security/test/context/showcase/CustomUserDetails.java new file mode 100644 index 0000000000..9e386e3854 --- /dev/null +++ b/test/src/test/java/org/springframework/security/test/context/showcase/CustomUserDetails.java @@ -0,0 +1,79 @@ +/* + * Copyright 2002-2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package org.springframework.security.test.context.showcase; + +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.AuthorityUtils; +import org.springframework.security.core.userdetails.UserDetails; + +import java.util.Collection; + +/** + * @author Rob Winch + */ +public class CustomUserDetails implements UserDetails { + private final String name; + private final String username; + private final Collection authorities; + + public CustomUserDetails(String name, String username) { + this.name = name; + this.username = username; + this.authorities = AuthorityUtils.createAuthorityList("ROLE_USER"); + } + + @Override + public Collection getAuthorities() { + return authorities; + } + + @Override + public String getPassword() { + return null; + } + + @Override + public String getUsername() { + return username; + } + + @Override + public boolean isAccountNonExpired() { + return true; + } + + @Override + public boolean isAccountNonLocked() { + return true; + } + + @Override + public boolean isCredentialsNonExpired() { + return true; + } + + @Override + public boolean isEnabled() { + return true; + } + + @Override + public String toString() { + return "CustomUserDetails{" + + "username='" + username + '\'' + + '}'; + } +} \ No newline at end of file diff --git a/test/src/test/java/org/springframework/security/test/context/showcase/WithMockCustomUser.java b/test/src/test/java/org/springframework/security/test/context/showcase/WithMockCustomUser.java new file mode 100644 index 0000000000..2eb5e0f928 --- /dev/null +++ b/test/src/test/java/org/springframework/security/test/context/showcase/WithMockCustomUser.java @@ -0,0 +1,46 @@ +/* + * Copyright 2002-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.security.test.context.showcase; + +import org.springframework.security.test.context.support.WithSecurityContext; + +/** + * @author Rob Winch + */ +@WithSecurityContext(factory = WithMockCustomUserSecurityContextFactory.class) +public @interface WithMockCustomUser { + /** + * The username to be used. The default is rob + * @return + */ + String username() default "rob"; + + /** + * The roles to use. The default is "USER". A {@link org.springframework.security.core.GrantedAuthority} will + * be created for each value within roles. Each value in roles will + * automatically be prefixed with "ROLE_". For example, the default will + * result in "ROLE_USER" being used. + * + * @return + */ + String[] roles() default { "USER" }; + + /** + * The name of the user + * @return + */ + String name() default "Rob Winch"; +} diff --git a/test/src/test/java/org/springframework/security/test/context/showcase/WithMockCustomUserSecurityContextFactory.java b/test/src/test/java/org/springframework/security/test/context/showcase/WithMockCustomUserSecurityContextFactory.java new file mode 100644 index 0000000000..4b6f82eaae --- /dev/null +++ b/test/src/test/java/org/springframework/security/test/context/showcase/WithMockCustomUserSecurityContextFactory.java @@ -0,0 +1,44 @@ +/* + * Copyright 2002-2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package org.springframework.security.test.context.showcase; + +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.AuthorityUtils; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.context.SecurityContext; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.test.context.support.WithSecurityContextFactory; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author Rob Winch + */ +public class WithMockCustomUserSecurityContextFactory implements WithSecurityContextFactory { + @Override + public SecurityContext createSecurityContext(WithMockCustomUser customUser) { + SecurityContext context = SecurityContextHolder.createEmptyContext(); + + CustomUserDetails principal = new CustomUserDetails(customUser.name(), customUser.username()); + Authentication auth = + new UsernamePasswordAuthenticationToken(principal, "password", principal.getAuthorities()); + context.setAuthentication(auth); + return context; + } +} diff --git a/test/src/test/java/org/springframework/security/test/context/showcase/WithMockUserTests.java b/test/src/test/java/org/springframework/security/test/context/showcase/WithMockUserTests.java new file mode 100644 index 0000000000..9ebb590a45 --- /dev/null +++ b/test/src/test/java/org/springframework/security/test/context/showcase/WithMockUserTests.java @@ -0,0 +1,83 @@ +/* + * Copyright 2002-2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package org.springframework.security.test.context.showcase; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; +import org.springframework.security.test.context.DefaultSecurityTestExecutionListeners; +import org.springframework.security.test.context.showcase.service.HelloMessageService; +import org.springframework.security.test.context.showcase.service.MessageService; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import static org.fest.assertions.Assertions.assertThat; + +/** + * @author Rob Winch + */ + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = WithMockUserTests.Config.class) +@DefaultSecurityTestExecutionListeners +public class WithMockUserTests { + @Autowired + private MessageService messageService; + + @Test(expected = AuthenticationCredentialsNotFoundException.class) + public void getMessageUnauthenticated() { + messageService.getMessage(); + } + + @Test + @WithMockUser + public void getMessageWithMockUser() { + String message = messageService.getMessage(); + assertThat(message).contains("user"); + } + + @Test + @WithMockUser("customUsername") + public void getMessageWithMockUserCustomUsername() { + String message = messageService.getMessage(); + assertThat(message).contains("customUsername"); + } + + @Test + @WithMockUser(username="admin",roles={"USER","ADMIN"}) + public void getMessageWithMockUserCustomUser() { + String message = messageService.getMessage(); + assertThat(message).contains("admin").contains("ROLE_USER").contains("ROLE_ADMIN"); + } + + @Configuration + @EnableGlobalMethodSecurity(prePostEnabled = true) + @ComponentScan(basePackageClasses = HelloMessageService.class) + static class Config { + @Autowired + public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { + auth + .inMemoryAuthentication() + .withUser("user").password("password").roles("USER"); + } + } +} \ No newline at end of file diff --git a/test/src/test/java/org/springframework/security/test/context/showcase/WithUserDetailsTests.java b/test/src/test/java/org/springframework/security/test/context/showcase/WithUserDetailsTests.java new file mode 100644 index 0000000000..1cea82ea2c --- /dev/null +++ b/test/src/test/java/org/springframework/security/test/context/showcase/WithUserDetailsTests.java @@ -0,0 +1,99 @@ +/* + * Copyright 2002-2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package org.springframework.security.test.context.showcase; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.security.test.context.DefaultSecurityTestExecutionListeners; +import org.springframework.security.test.context.showcase.service.HelloMessageService; +import org.springframework.security.test.context.showcase.service.MessageService; +import org.springframework.security.test.context.support.WithUserDetails; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import static org.fest.assertions.Assertions.assertThat; + +/** + * @author Rob Winch + */ + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = WithUserDetailsTests.Config.class) +@DefaultSecurityTestExecutionListeners +public class WithUserDetailsTests { + @Autowired + private MessageService messageService; + + @Test(expected = AuthenticationCredentialsNotFoundException.class) + public void getMessageUnauthenticated() { + messageService.getMessage(); + } + + @Test + @WithUserDetails + public void getMessageWithUserDetails() { + String message = messageService.getMessage(); + assertThat(message).contains("user"); + assertThat(getPrincipal()).isInstanceOf(CustomUserDetails.class); + } + + @Test + @WithUserDetails("customUsername") + public void getMessageWithUserDetailsCustomUsername() { + String message = messageService.getMessage(); + assertThat(message).contains("customUsername"); + assertThat(getPrincipal()).isInstanceOf(CustomUserDetails.class); + } + + @Configuration + @EnableGlobalMethodSecurity(prePostEnabled = true) + @ComponentScan(basePackageClasses = HelloMessageService.class) + static class Config { + @Autowired + public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { + auth + .userDetailsService(userDetailsService()); + } + + @Bean + public UserDetailsService userDetailsService() { + return new CustomUserDetailsService(); + } + } + + private Object getPrincipal() { + return SecurityContextHolder.getContext().getAuthentication().getPrincipal(); + } + + static class CustomUserDetailsService implements UserDetailsService { + + @Override + public UserDetails loadUserByUsername(final String username) throws UsernameNotFoundException { + return new CustomUserDetails("name", username); + } + } +} diff --git a/test/src/test/java/org/springframework/security/test/context/showcase/service/HelloMessageService.java b/test/src/test/java/org/springframework/security/test/context/showcase/service/HelloMessageService.java new file mode 100644 index 0000000000..87c2611a7a --- /dev/null +++ b/test/src/test/java/org/springframework/security/test/context/showcase/service/HelloMessageService.java @@ -0,0 +1,34 @@ +/* + * Copyright 2002-2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package org.springframework.security.test.context.showcase.service; + +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Component; + +/** + * @author Rob Winch + */ +@Component +public class HelloMessageService implements MessageService { + + @PreAuthorize("authenticated") + public String getMessage() { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + return "Hello " + authentication; + } +} diff --git a/test/src/test/java/org/springframework/security/test/context/showcase/service/MessageService.java b/test/src/test/java/org/springframework/security/test/context/showcase/service/MessageService.java new file mode 100644 index 0000000000..05026a8a4a --- /dev/null +++ b/test/src/test/java/org/springframework/security/test/context/showcase/service/MessageService.java @@ -0,0 +1,10 @@ +package org.springframework.security.test.context.showcase.service; + +import org.springframework.security.access.prepost.PreAuthorize; + +/** + * @author Rob Winch + */ +public interface MessageService { + String getMessage(); +}