0

Security Configuration doesn't let me use antMatchers() on some pages. Below is a configuration code where I'm trying to let not signed in user access "/", "/entries", "/signup". With "/signup" there is no problem it let me visit that page, but it keeps redirecting me to login page if I'm trying to access "/" or "/entries". I've tried to write each uri in separate antMatchers() and switching orders, but no luck so far.

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
  @Autowired
  DetailService userDetailsService;

  @Override
  protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(userDetailsService).passwordEncoder(User.PASSWORD_ENCODER);
  }

  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http
        .authorizeRequests()
        .antMatchers("/", "/entries","/signup").permitAll()
        .antMatchers("/adminpanel/**")
        .access("hasRole('ROLE_ADMIN')")
        .and()
        .formLogin()
        .loginPage("/login")
        .permitAll()
        .successHandler(loginSuccessHandler())
        .failureHandler(loginFailureHandler())
        .and()
        .logout()
        .permitAll()
        .logoutSuccessUrl("/clearConnection")
        .and()
        .csrf();

    http.headers().frameOptions().disable();
  }

  public AuthenticationSuccessHandler loginSuccessHandler() {
    return (request, response, authentication) -> response.sendRedirect("/");
  }

  public AuthenticationFailureHandler loginFailureHandler() {
    return (request, response, exception) -> {
      response.sendRedirect("/login");
    };
  }

  @Bean
  public EvaluationContextExtension securityExtension() {
    return new EvaluationContextExtensionSupport() {
      @Override
      public String getExtensionId() {
        return "security";
      }

      @Override
      public Object getRootObject() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        return new SecurityExpressionRoot(authentication) {
        };
      }
    };
  }

}
Nick Nagorski
  • 135
  • 1
  • 3
  • 11

1 Answers1

0

Apparently I had a UserHandler class that has annotation @ControllerAdvice(basePackages = "myproject.web.controller"). That's means that it applies to all classes for provided package. My addUser() is trying to add User as an attribute and if there is no user it throwing one of exceptions defined in the same class which cause redirection. So, I created separate GuestController outside of the package provided for @ControllerAdvice and handle all logic for a guest in it. That solved my problem. Would appreciate any insights on my approach, if its good practice or not.

@ControllerAdvice(basePackages = "myproject.web.controller")
public class UserHandler {
    @Autowired
    private UserService users;

    @ExceptionHandler(AccessDeniedException.class)
    public String redirectNonUser(RedirectAttributes attributes) {
        attributes.addAttribute("errorMessage", "Please login before accessing website");
        return "redirect:/login";
    }

    @ExceptionHandler(UsernameNotFoundException.class)
    public String redirectNotFound(RedirectAttributes attributes) {
        attributes.addAttribute("errorMessage", "Username not found");
        return "redirect:/login";
    }

    @ModelAttribute("currentUser")
    public User addUser() {
        if(SecurityContextHolder.getContext().getAuthentication() != null) {
            String username = SecurityContextHolder.getContext().getAuthentication().getName();
            User user = users.findByUsername(username);
            if(user != null) {
                return user;
            } else {
                throw new UsernameNotFoundException("Username not found");
            }
        } else {
            throw new AccessDeniedException("Not logged in");
        }
    }
}    
Nick Nagorski
  • 135
  • 1
  • 3
  • 11