Issue
I have a Spring Boot 2
application with some controllers.
I wat to add Spring Security
and allow some urls for only authenticated users, whereas others should be accessible for all.
But when I use WebSecurityConfigurerAdapter
to configure cecurity per-url, auto-generated pages for "/login" and "/error" disappear.
If I try to add the simplest possible configuration, it works and protects all urls:
application.yml
spring:
security:
user:
name: "admin"
password: "1234"
roles: "ADMIN"
pom.xml
:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
</dependencies>
And every action redirects me to /login
page with login form, until I log in with credentials I configured.
However, If I add a configuration class to customize the behavior, the default login form seems to be missing, and I keep getting /error
page instead because there is no such resource as /login
:
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("admin").password("1234").roles("ADMIN");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/private").hasRole("ADMIN")
.antMatchers("/public").permitAll()
.antMatchers("/", "/login", "/logout", "/error").permitAll()
.antMatchers("/**").denyAll();
}
}
Here are some debug logs (the rest is omitted for readability):
DEBUG o.s.s.w.a.AnonymousAuthenticationFilter - Populated SecurityContextHolder with anonymous token: 'org.springframework.security.authentication.AnonymousAuthenticationToken@e4de2840: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: ROLE_ANONYMOUS'
...
DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Checking match of request : '/login'; against '/login'
DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - Secure object: FilterInvocation: URL: /login; Attributes: [permitAll]
DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - Previously Authenticated: org.springframework.security.authentication.AnonymousAuthenticationToken@e4de2840: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: ROLE_ANONYMOUS
DEBUG o.s.s.access.vote.AffirmativeBased - Voter: org.springframework.security.web.access.expression.WebExpressionVoter@2a3c0a9c, returned: 1
DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - Authorization successful
DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - RunAsManager did not change Authentication object
DEBUG o.s.security.web.FilterChainProxy - /login reached end of additional filter chain; proceeding with original chain
DEBUG o.s.web.servlet.DispatcherServlet - GET "/login", parameters={}
DEBUG o.s.w.s.h.SimpleUrlHandlerMapping - Mapped to ResourceHttpRequestHandler ["classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/", "/"]
DEBUG o.s.o.j.s.OpenEntityManagerInViewInterceptor - Opening JPA EntityManager in OpenEntityManagerInViewInterceptor
DEBUG o.s.w.s.r.ResourceHttpRequestHandler - Resource not found
DEBUG o.s.s.w.h.writers.HstsHeaderWriter - Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@27581ee6
DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository - SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.
DEBUG o.s.o.j.s.OpenEntityManagerInViewInterceptor - Closing JPA EntityManager in OpenEntityManagerInViewInterceptor
DEBUG o.s.web.servlet.DispatcherServlet - Completed 404 NOT_FOUND
DEBUG o.s.s.w.a.ExceptionTranslationFilter - Chain processed normally
DEBUG o.s.s.w.c.SecurityContextPersistenceFilter - SecurityContextHolder now cleared, as request processing completed
DEBUG o.s.security.web.FilterChainProxy - /error at position 1 of 11 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
...
DEBUG o.s.security.web.FilterChainProxy - /error reached end of additional filter chain; proceeding with original chain
DEBUG o.s.web.servlet.DispatcherServlet - "ERROR" dispatch for GET "/error", parameters={}
DEBUG o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped to org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController#errorHtml(HttpServletRequest, HttpServletResponse)
DEBUG o.s.o.j.s.OpenEntityManagerInViewInterceptor - Opening JPA EntityManager in OpenEntityManagerInViewInterceptor
DEBUG o.s.w.s.v.ContentNegotiatingViewResolver - Selected 'text/html' given [text/html, text/html;q=0.8]
DEBUG o.s.o.j.s.OpenEntityManagerInViewInterceptor - Closing JPA EntityManager in OpenEntityManagerInViewInterceptor
DEBUG o.s.web.servlet.DispatcherServlet - Exiting from "ERROR" dispatch, status 404
DEBUG o.s.s.w.a.ExceptionTranslationFilter - Chain processed normally
DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository - SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.
DEBUG o.s.s.w.c.SecurityContextPersistenceFilter - SecurityContextHolder now cleared, as request processing completed
At the end I get error page in browser, saying that there is no /error
page either.
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.
Tue Jan 21 14:53:17 CET 2020
There was an unexpected error (type=Not Found, status=404).
Not Found
For some reason, auto-generated pages for "/login" and "/error" disappear when I use WebSecurityConfigurerAdapter
configuration class. Where are they gone?
Moreover, this Previously Authenticated:
looks suspicious to me, because It was a fresh app start. But if I try to disable anonymous users with http.anonymous().disable()
, I start getting 403 error for any url. Can it be related?
Solution
You are missing: .formLogin().loginPage("/login")
Something like:
http
.authorizeRequests()
.antMatchers("/private").hasRole("ADMIN")
.antMatchers("/public").permitAll()
.antMatchers("/", "/login", "/logout", "/error").permitAll()
.antMatchers("/**").denyAll()
.and().formLogin().loginPage("/login");
Answered By - user10871691
Answer Checked By - Marie Seifert (JavaFixing Admin)