Skip to content

Commit df5febe

Browse files
authored
Exception Handler for Spring Security Resource Server (eugenp#12085)
* Exception Handler implemented for Spring Security Resource Server * Renamed test class name to solve PMD Failure * Code formatting
1 parent e9409e8 commit df5febe

15 files changed

Lines changed: 306 additions & 0 deletions

File tree

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package com.baeldung.exceptionhandler;
2+
3+
import org.springframework.boot.SpringApplication;
4+
import org.springframework.boot.autoconfigure.SpringBootApplication;
5+
6+
@SpringBootApplication
7+
public class AppInitializer {
8+
public static void main(String[] args) {
9+
SpringApplication.run(AppInitializer.class, args);
10+
}
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package com.baeldung.exceptionhandler.controller;
2+
3+
import org.springframework.stereotype.Controller;
4+
import org.springframework.web.bind.annotation.GetMapping;
5+
import org.springframework.web.bind.annotation.RequestMapping;
6+
7+
@Controller
8+
@RequestMapping("/access-denied")
9+
public class AccessDeniedController {
10+
11+
@GetMapping
12+
public String accessDenied() {
13+
return "/denied.html";
14+
}
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package com.baeldung.exceptionhandler.controller;
2+
3+
import org.springframework.stereotype.Controller;
4+
import org.springframework.web.bind.annotation.GetMapping;
5+
import org.springframework.web.bind.annotation.RequestMapping;
6+
7+
@Controller
8+
@RequestMapping
9+
public class CustomErrorController {
10+
11+
@GetMapping("/customError")
12+
public String customErrorController() {
13+
return "/error";
14+
}
15+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package com.baeldung.exceptionhandler.controller;
2+
3+
import org.springframework.stereotype.Controller;
4+
import org.springframework.web.bind.annotation.GetMapping;
5+
import org.springframework.web.bind.annotation.RequestMapping;
6+
7+
@Controller
8+
@RequestMapping("/home")
9+
public class HomeController {
10+
11+
@GetMapping
12+
public String home() {
13+
return "/index.html";
14+
}
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package com.baeldung.exceptionhandler.controller;
2+
3+
import org.springframework.stereotype.Controller;
4+
import org.springframework.web.bind.annotation.GetMapping;
5+
import org.springframework.web.bind.annotation.RequestMapping;
6+
7+
@Controller
8+
@RequestMapping("/secured")
9+
public class SecuredResourceController {
10+
11+
@GetMapping
12+
public String secureResource() {
13+
return "/admin.html";
14+
}
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package com.baeldung.exceptionhandler.security;
2+
3+
import java.io.IOException;
4+
5+
import javax.servlet.http.HttpServletRequest;
6+
import javax.servlet.http.HttpServletResponse;
7+
8+
import org.springframework.security.access.AccessDeniedException;
9+
import org.springframework.security.web.access.AccessDeniedHandler;
10+
11+
public class CustomAccessDeniedHandler implements AccessDeniedHandler {
12+
13+
@Override
14+
public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException exc) throws IOException {
15+
response.sendRedirect("/access-denied");
16+
}
17+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package com.baeldung.exceptionhandler.security;
2+
3+
import java.io.IOException;
4+
5+
import javax.servlet.http.HttpServletRequest;
6+
import javax.servlet.http.HttpServletResponse;
7+
8+
import org.springframework.security.core.AuthenticationException;
9+
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
10+
11+
public class CustomAuthenticationFailureHandler implements AuthenticationFailureHandler {
12+
13+
@Override
14+
public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException {
15+
httpServletResponse.sendRedirect("/customError");
16+
}
17+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package com.baeldung.exceptionhandler.security;
2+
3+
import java.io.IOException;
4+
5+
import javax.servlet.ServletException;
6+
import javax.servlet.http.HttpServletRequest;
7+
import javax.servlet.http.HttpServletResponse;
8+
import javax.servlet.http.HttpSession;
9+
10+
import org.springframework.security.core.Authentication;
11+
import org.springframework.security.core.context.SecurityContextHolder;
12+
import org.springframework.security.core.userdetails.User;
13+
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
14+
15+
public class CustomAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
16+
17+
@Override
18+
public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
19+
20+
HttpSession session = httpServletRequest.getSession();
21+
User authUser = (User) SecurityContextHolder.getContext()
22+
.getAuthentication()
23+
.getPrincipal();
24+
session.setAttribute("username", authUser.getUsername());
25+
session.setAttribute("authorities", authentication.getAuthorities());
26+
27+
httpServletResponse.setStatus(HttpServletResponse.SC_OK);
28+
29+
httpServletResponse.sendRedirect("/home");
30+
}
31+
}
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
package com.baeldung.exceptionhandler.security;
2+
3+
import org.springframework.context.annotation.Bean;
4+
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
5+
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
6+
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
7+
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
8+
import org.springframework.security.core.userdetails.User;
9+
import org.springframework.security.core.userdetails.UserDetails;
10+
import org.springframework.security.core.userdetails.UserDetailsService;
11+
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
12+
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
13+
import org.springframework.security.web.access.AccessDeniedHandler;
14+
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
15+
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
16+
17+
@EnableWebSecurity
18+
public class SecurityConfig extends WebSecurityConfigurerAdapter {
19+
20+
@Bean
21+
public UserDetailsService userDetailsService() {
22+
23+
UserDetails user = User.withUsername("user")
24+
.passwordEncoder(PasswordEncoderFactories.createDelegatingPasswordEncoder()::encode)
25+
.password("password")
26+
.roles("USER")
27+
.build();
28+
29+
UserDetails admin = User.withUsername("admin")
30+
.passwordEncoder(PasswordEncoderFactories.createDelegatingPasswordEncoder()::encode)
31+
.password("password")
32+
.roles("ADMIN")
33+
.build();
34+
35+
InMemoryUserDetailsManager userDetailsManager = new InMemoryUserDetailsManager();
36+
37+
userDetailsManager.createUser(user);
38+
userDetailsManager.createUser(admin);
39+
40+
return userDetailsManager;
41+
}
42+
43+
@Override
44+
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
45+
auth.inMemoryAuthentication()
46+
.withUser("user")
47+
.password("{noop}password")
48+
.roles("USER")
49+
.and()
50+
.withUser("admin")
51+
.password("{noop}password")
52+
.roles("ADMIN");
53+
}
54+
55+
@Override
56+
protected void configure(HttpSecurity http) throws Exception {
57+
http.csrf()
58+
.disable()
59+
.httpBasic()
60+
.disable()
61+
.authorizeRequests()
62+
.antMatchers("/login")
63+
.permitAll()
64+
.antMatchers("/customError")
65+
.permitAll()
66+
.antMatchers("/access-denied")
67+
.permitAll()
68+
.antMatchers("/secured")
69+
.hasRole("ADMIN")
70+
.anyRequest()
71+
.authenticated()
72+
.and()
73+
.formLogin()
74+
.failureHandler(authenticationFailureHandler())
75+
.successHandler(authenticationSuccessHandler())
76+
.and()
77+
.exceptionHandling()
78+
.accessDeniedHandler(accessDeniedHandler())
79+
.and()
80+
.logout();
81+
}
82+
83+
@Bean
84+
public AuthenticationFailureHandler authenticationFailureHandler() {
85+
return new CustomAuthenticationFailureHandler();
86+
}
87+
88+
@Bean
89+
public AuthenticationSuccessHandler authenticationSuccessHandler() {
90+
return new CustomAuthenticationSuccessHandler();
91+
}
92+
93+
@Bean
94+
public AccessDeniedHandler accessDeniedHandler() {
95+
return new CustomAccessDeniedHandler();
96+
}
97+
98+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
spring.thymeleaf.prefix=classpath:/templates/

0 commit comments

Comments
 (0)