Answer the question
In order to leave comments, you need to log in
Why doesn't accessDaniedHandler work in Spring Security?
Hello everyone, such a situation, I want to set up security in spring so that when someone climbs onto non-existent pages or closed pages, redirects to the page - access is closed. But the fact is that when I try to make a request to some left path, I am redirected to the login page, as if I entered the wrong data during authentication! I added a page to the settings in the case of "access is denied" I also added a Hadler, but the logs do not work in it, that is, it does not work ... Why is that?
Maybe I don't understand how it should work? I understand this in such a way that when entering a left or forbidden path, that is, where the user does not have rights, I should be redirected to the error page, but for some reason it redirects to the login page ...
little update:
accessDeniedHandler only fires if I'm logged in and trying to access an existing denied page. Why doesn't it work if I'm logged out and trying to access an existing forbidden page and redirects to the login page?
Spring Security Settings
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
public AuthenticationSuccessHandler myAuthenticationSuccessHandler() {
return new MyAuthenticationSuccessHandler();
}
@Bean
public UserDetailsServiceImpl userDetailsService() {
return new UserDetailsServiceImpl();
}
@Bean
public AccessDeniedHandler accessDeniedHandler() {
return new MyAccessDeniedHandler();
}
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public DaoAuthenticationProvider daoAuthenticationProvider () {
DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
authenticationProvider.setUserDetailsService(userDetailsService());
authenticationProvider.setPasswordEncoder(bCryptPasswordEncoder());
return authenticationProvider;
}
@Override
protected void configure(AuthenticationManagerBuilder amb) throws Exception {
amb.authenticationProvider(daoAuthenticationProvider());
}
@Override
public void configure(WebSecurity web) throws Exception {
// web.debug(true);
web.ignoring()
.antMatchers("/resources/**")
.antMatchers("/resources/bootstrapComponent/**")
.antMatchers("/resources/css/**")
.antMatchers("/resources/patternViews/**");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.headers()
.defaultsDisabled()
.contentTypeOptions().and()
.frameOptions().and()
.xssProtection()
.block(true).and()
.contentSecurityPolicy ( "script-src 'self'").and()
.cacheControl();
http.authorizeRequests()
.antMatchers("/main", "/signin", "/signUp"/*, "/error"*/).permitAll()
.antMatchers("/home").hasAnyRole("CEO", "Manager", "User")
.antMatchers("/control").hasAnyRole("CEO", "Manager")
.antMatchers("/ceo").hasAnyRole("CEO")
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/signin")
.usernameParameter("username")
.passwordParameter("password")
.loginProcessingUrl("/signin")
// .defaultSuccessUrl("/processSignIn")
// .successForwardUrl("/processSignIn")
.successHandler(myAuthenticationSuccessHandler())
.and()
.logout()
.logoutUrl("/signout")
.logoutSuccessUrl("/signin")
.and()
// .exceptionHandling().accessDeniedPage("/error");
.exceptionHandling().accessDeniedHandler(accessDeniedHandler());
}
}
@Component
public class MyAccessDeniedHandler implements AccessDeniedHandler {
private final Logger logger = LogManager.getLogger(MyAccessDeniedHandler.class);
@Override
public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AccessDeniedException e) throws IOException, ServletException {
logger.debug("DEBUG from MyAccessDeniedHandler --> " + e.getMessage());
httpServletResponse.sendRedirect( httpServletRequest.getContextPath() + "/error");
}
}
Answer the question
In order to leave comments, you need to log in
accessDeniedHandler only fires if I'm logged in and trying to access an existing denied page. Why doesn't it work if I'm logged out and trying to access an existing forbidden page and redirects to the login page?
permitAll()
, going further down the chain it stumbles upon .anyRequest().authenticated()
and throws an Access Denied Exception. /error
commented out. It is possible that it is trying to show an error, but since this page is not available being unauthorized, it first redirects to the authorization page... @Controller
public class HttpErrorController implements ErrorController {
private final MessageSource messageSource;
@Autowired
public HttpErrorController(MessageSource messageSource) {
this.messageSource = messageSource;
}
@RequestMapping("/error")
public String handleError(
Locale locale,
Model model,
HttpServletRequest request,
Exception ex
) {
Object status = request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE);
if (status != null) {
int statusCode = Integer.valueOf(status.toString());
Map<String, String> metaData = new HashMap<>();
// 403
if (statusCode == HttpStatus.FORBIDDEN.value()) {
//do somthing
}
// 404
else if (statusCode == HttpStatus.NOT_FOUND.value()) {
//do somthing
}
// 405
else if (statusCode == HttpStatus.NOT_FOUND.value()) {
//do somthing
}
// 500
else if (statusCode == HttpStatus.INTERNAL_SERVER_ERROR.value()) {
//do somthing
}
}
return "errors/httperrors";
}
@Override
public String getErrorPath() {
return "/error";
}
}
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question