Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1024,7 +1024,7 @@ public HttpSecurity logout(Customizer<LogoutConfigurer<HttpSecurity>> logoutCust
* @return the {@link HttpSecurity} for further customizations @
*/
public HttpSecurity anonymous(Customizer<AnonymousConfigurer<HttpSecurity>> anonymousCustomizer) {
anonymousCustomizer.customize(getOrApply(new AnonymousConfigurer<>()));
anonymousCustomizer.customize(getOrApply(new AnonymousConfigurer<>(getContext())));
return HttpSecurity.this;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,14 @@
import java.util.List;
import java.util.UUID;

import org.springframework.context.ApplicationContext;
import org.springframework.security.authentication.AnonymousAuthenticationProvider;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.SecurityConfigurer;
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.core.GrantedAuthorityDefaults;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
Expand All @@ -40,6 +42,7 @@
*
* @author Rob Winch
* @author DingHao
* @author Ngoc Nhan
* @since 3.2
*/
public final class AnonymousConfigurer<H extends HttpSecurityBuilder<H>>
Expand All @@ -53,15 +56,20 @@ public final class AnonymousConfigurer<H extends HttpSecurityBuilder<H>>

private Object principal = "anonymousUser";

private List<GrantedAuthority> authorities = AuthorityUtils.createAuthorityList("ROLE_ANONYMOUS");
private List<GrantedAuthority> authorities;

private String computedKey;

/**
* Creates a new instance.
* @param context the {@link ApplicationContext} to use
* @see HttpSecurity#anonymous(Customizer)
*/
public AnonymousConfigurer() {
public AnonymousConfigurer(ApplicationContext context) {
GrantedAuthorityDefaults grantedAuthorityDefaults = context.getBeanProvider(GrantedAuthorityDefaults.class)
.getIfAvailable();
String rolePrefix = (grantedAuthorityDefaults != null) ? grantedAuthorityDefaults.getRolePrefix() : "ROLE_";
this.authorities = AuthorityUtils.createAuthorityList(rolePrefix + "ANONYMOUS");
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,15 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.authentication.AuthenticationDetailsSource;
import org.springframework.security.config.ObjectPostProcessor;
import org.springframework.security.config.annotation.SecurityContextChangedListenerConfig;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.core.GrantedAuthorityDefaults;
import org.springframework.security.config.test.SpringTestContext;
import org.springframework.security.config.test.SpringTestContextExtension;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
Expand All @@ -48,13 +51,15 @@
import static org.mockito.Mockito.verify;
import static org.springframework.security.config.Customizer.withDefaults;
import static org.springframework.security.config.annotation.SecurityContextChangedListenerArgumentMatchers.setAuthentication;
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.anonymous;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

/**
* @author Rob Winch
* @author Josh Cummings
* @author Ngoc Nhan
*/
@ExtendWith(SpringTestContextExtension.class)
public class AnonymousConfigurerTests {
Expand Down Expand Up @@ -116,6 +121,15 @@ public void anonymousAuthenticationWhenUsingAuthenticationDetailsSourceRefThenMa
verify(source).buildDetails(any(HttpServletRequest.class));
}

@Test
public void anonymousWithCustomAuthorityDefaults() throws Exception {
this.spring.register(AnonymousGrantedAuthorityDefaultsConfig.class, PrincipalController.class).autowire();
this.mockMvc.perform(get("/anonymous").with(anonymous())).andExpect(status().isForbidden());
this.mockMvc.perform(get("/anonymous").with(anonymous().authorities("my_roles_ANONYMOUS")))
.andExpect(status().isOk())
.andExpect(content().string("anonymous"));
}

@Configuration
@EnableWebSecurity
@EnableWebMvc
Expand Down Expand Up @@ -261,6 +275,31 @@ String principal(@AuthenticationPrincipal String principal) {
return principal;
}

@GetMapping("/anonymous")
@PreAuthorize("hasRole('ANONYMOUS')")
String getAnonymous(@AuthenticationPrincipal String principal) {
return principal;
}

}

@EnableWebMvc
@EnableWebSecurity
@EnableMethodSecurity
@Configuration
static class AnonymousGrantedAuthorityDefaultsConfig {

@Bean
GrantedAuthorityDefaults grantedAuthorityDefaults() {
return new GrantedAuthorityDefaults("my_roles_");
}

@Bean
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests((authorize) -> authorize.anyRequest().anonymous());
return http.build();
}

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@
* Security.
*
* @author Rob Winch
* @author Ngoc Nhan
* @since 4.0
*/
public final class SecurityMockMvcRequestPostProcessors {
Expand Down Expand Up @@ -346,7 +347,7 @@ public static RequestPostProcessor authentication(Authentication authentication)
* </code> </pre>
* @return the {@link RequestPostProcessor} to use
*/
public static RequestPostProcessor anonymous() {
public static AnonymousRequestPostProcessor anonymous() {
return new AnonymousRequestPostProcessor();
}

Expand Down Expand Up @@ -1020,16 +1021,64 @@ private User createUser() {

}

private static class AnonymousRequestPostProcessor extends SecurityContextRequestPostProcessorSupport
public static final class AnonymousRequestPostProcessor extends SecurityContextRequestPostProcessorSupport
implements RequestPostProcessor {

private AuthenticationRequestPostProcessor delegate = new AuthenticationRequestPostProcessor(
new AnonymousAuthenticationToken("key", "anonymous",
AuthorityUtils.createAuthorityList("ROLE_ANONYMOUS")));
private String key = "key";

private Object principal = "anonymous";

private Collection<? extends GrantedAuthority> authorities = AuthorityUtils
.createAuthorityList("ROLE_ANONYMOUS");

@Override
public MockHttpServletRequest postProcessRequest(MockHttpServletRequest request) {
return this.delegate.postProcessRequest(request);
AuthenticationRequestPostProcessor delegate = new AuthenticationRequestPostProcessor(
this.createAnonymous());
return delegate.postProcessRequest(request);
}

/**
* Creates a new {@link AnonymousAuthenticationToken}.
* @return the {@link AnonymousAuthenticationToken} for the principal
*/
private AnonymousAuthenticationToken createAnonymous() {
return new AnonymousAuthenticationToken(this.key, this.principal, this.authorities);
}

/**
* Populates the user's {@link GrantedAuthority}'s. The default is
* {@code ROLE_ANONYMOUS}.
* @param authorities the authorities to grant to the anonymous user
* @return the {@link AnonymousRequestPostProcessor} for further customizations
*/
public AnonymousRequestPostProcessor authorities(String... authorities) {
Assert.notNull(authorities, "authorities cannot be null");
this.authorities = AuthorityUtils.createAuthorityList(authorities);
return this;
}

/**
* Sets the key used to identify the anonymous user.
* @param key the key to use
* @return the {@link AnonymousRequestPostProcessor} for further customizations
*/
public AnonymousRequestPostProcessor key(String key) {
Assert.hasLength(key, "key cannot be null or empty");
this.key = key;
return this;
}

/**
* Sets the principal for the anonymous user.
* @param principal the principal to use
* @return the {@link AnonymousRequestPostProcessor} for further customizations
*/
public AnonymousRequestPostProcessor principal(Object principal) {
Assert.notNull(principal, "principal cannot be null");
Assert.isTrue(!"".equals(principal), "principal cannot be empty");
this.principal = principal;
return this;
}

}
Expand Down
Loading