Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save MWhyte/e6a5204190ae6d631bd99e2e4c3d65fc to your computer and use it in GitHub Desktop.
Save MWhyte/e6a5204190ae6d631bd99e2e4c3d65fc to your computer and use it in GitHub Desktop.
A Post: Spring Security - Redirect based on User Roles
Post: TBD
Repo - https://github.com/mwhyte-dev/spring-security/tree/3.redirect-based-on-role
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head>
<title>codenerve.com - Welcome!</title>
<meta charset="UTF-8">
<title>Admin</title>
<link href="https://fonts.googleapis.com/css?family=Open+Sans:400,700" rel="stylesheet">
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<h1 th:inline="text">Hello [[${#httpServletRequest.remoteUser}]]!</h1>
<div>
Custom administrator page.
</div>
<br/>
<form th:action="@{/logout}" method="post">
<input type="submit" value="Sign Out"/>
</form>
</body>
</html>
package dev.mwhyte.spring.sec;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
package dev.mwhyte.spring.sec;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders.FormLoginRequestBuilder;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.servlet.MockMvc;
import static org.hamcrest.core.StringContains.containsString;
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders.formLogin;
import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.authenticated;
import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.unauthenticated;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
@ExtendWith(SpringExtension.class)
@SpringBootTest
@AutoConfigureMockMvc
public class ApplicationTests {
@Autowired
private MockMvc mockMvc;
@Test
public void loginWithValidUserThenAuthenticated() throws Exception {
FormLoginRequestBuilder login = formLogin()
.user("user")
.password("pass");
mockMvc.perform(login)
.andExpect(authenticated().withUsername("user"));
}
@Test
public void loginWithInvalidUserThenUnauthenticated() throws Exception {
FormLoginRequestBuilder login = formLogin()
.user("invalid")
.password("invalidpassword");
mockMvc.perform(login)
.andExpect(unauthenticated());
}
@Test
public void accessUnsecuredResourceThenOk() throws Exception {
mockMvc.perform(get("/css/style.css"))
.andExpect(status().isOk());
}
@Test
public void accessSecuredResourceUnauthenticatedThenRedirectsToLogin() throws Exception {
mockMvc.perform(get("/hello"))
.andExpect(status().is3xxRedirection())
.andExpect(redirectedUrlPattern("**/login"));
}
@Test
@WithMockUser
public void accessSecuredResourceAuthenticatedThenOk() throws Exception {
mockMvc.perform(get("/index"))
.andExpect(status().isOk());
}
@Test
@WithMockUser(roles = "USER")
public void loginWithRoleUserThenExpectAdminPageForbidden() throws Exception {
mockMvc.perform(get("/admin"))
.andExpect(status().isForbidden());
}
@Test
@WithMockUser(roles = "ADMIN")
public void loginWithRoleAdminThenExpectAdminContent() throws Exception {
mockMvc.perform(get("/admin"))
.andExpect(status().isOk())
.andExpect(content().string(containsString("Custom administrator page.")));
}
@Test
public void loginWithRoleUserThenExpectIndexPageRedirect() throws Exception {
FormLoginRequestBuilder login = formLogin()
.user("user")
.password("pass");
mockMvc.perform(login)
.andExpect(authenticated().withUsername("user"))
.andExpect(redirectedUrl("/index"));
}
@Test
public void loginWithRoleAdminThenExpectAdminPageRedirect() throws Exception {
FormLoginRequestBuilder login = formLogin()
.user("admin")
.password("pass");
mockMvc.perform(login)
.andExpect(authenticated().withUsername("admin"))
.andExpect(redirectedUrl("/admin"));
}
}
package dev.mwhyte.spring.sec.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Set;
@Configuration
public class CustomAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
@Override
public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
Set<String> roles = AuthorityUtils.authorityListToSet(authentication.getAuthorities());
if (roles.contains("ROLE_ADMIN")) {
httpServletResponse.sendRedirect("/admin");
} else {
httpServletResponse.sendRedirect("/index");
}
}
}
package dev.mwhyte.spring.sec.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class MvcConfig implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("login");
registry.addViewController("/index").setViewName("index");
registry.addViewController("/admin").setViewName("admin");
registry.addViewController("/login").setViewName("login");
}
}
package dev.mwhyte.spring.sec.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
private AuthenticationSuccessHandler authenticationSuccessHandler;
@Autowired
public WebSecurityConfig(AuthenticationSuccessHandler authenticationSuccessHandler) {
this.authenticationSuccessHandler = authenticationSuccessHandler;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers( "/css/**", "/images/**", "/favicon.ico").permitAll()
.antMatchers("/admin").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.successHandler(authenticationSuccessHandler)
.permitAll()
.and()
.logout()
.permitAll()
.and().csrf().disable(); // we'll enable this in a later blog post
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("{noop}pass").roles("USER")
.and()
.withUser("admin").password("{noop}pass").roles("ADMIN");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment