After successful login spring redirects to /error
page with the following content
{
"timestamp" : 1586002411175,
"status" : 999,
"error" : "None",
"message" : "No message available"
}
I'm using spring-boot 2.2.4
spring.mvc.view.prefix=/WEB-INF/views/
spring.mvc.view.suffix=.jsp
spring.mvc.servlet.load-on-startup=1
spring.mvc.throw-exception-if-no-handler-found=true
spring.resources.add-mappings=false
@Configuration
public class DispatcherContextConfig implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
}
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class AppSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
public void configure(WebSecurity web) {
web.ignoring().antMatchers("/favicon.ico", "/resources/**");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/api/**").permitAll()
.antMatchers("/registration/**").anonymous()
.anyRequest().authenticated()
.and()
.headers()
.defaultsDisabled()
.cacheControl()
.and()
.and()
.exceptionHandling()
.accessDeniedPage("/errors/403")
.and()
.formLogin()
.loginPage("/login")
.loginProcessingUrl("/login")
.failureUrl("/login?error")
.defaultSuccessUrl("/log") // I don't want to use force redirect here
.permitAll()
.and()
.logout()
.logoutUrl("/logout")
.deleteCookies("JSESSIONID")
.invalidateHttpSession(true)
.logoutSuccessUrl("/login?logout")
.permitAll()
.and()
.rememberMe()
.rememberMeParameter("remember-me")
.key("myKey");
}
// ...
}
Turns out that error is caused by failed request to one of my static resources. Login page has <script src="/resources/my-js-file.js"></script>
that is missing in the project.
I can fix this by removing missing resource import, but the problem can reappear in future so it's not a fix.
I know I can force redirect to starting page with .defaultSuccessUrl("/log", true)
but I don't want this.
Also I want redirect to work properly despite of any not found resources.
After wasting a lot of time I figured out what's happening.
So spring can't find one of static resources that is used on login page. But instead of returning status 404
for this resource it tries to render error page and forwards request to /error
. Then spring security denies this request because user is not authorized. It saves /error
request to session (for redirecting after successful login) and redirects user to login page.
Of course user can't see this redirect because status 302
returns for request that is done in background. But the main issue is /error
request saved in session.
Then user logins successfully and spring checks session for this attribute and makes redirect to /error
page. By default spring assumes that you have such page somewhere in static resources. If you doesn't have this page you will see this weird error with status code 999.
Ignore /error
page in security config:
web.ignoring().antMatchers("/favicon.ico", "/resources/**", "/error");
So this request will not be saved to session for user redirection after successful login. You will see that on login page status code of request to static resource will change from 302
to 404
.
Ignore part of spring boot autoconfig:
spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration
This gives same result but disables some beans from config ErrorMvcAutoConfiguration
so be careful.