dev
dev

Reputation: 11

Springboot security: not find SecurityContext in HttpSession. Role anonymous. Access denied

My hello world war file (Spring boot 3.1.1, jdk 17, jsf) was deployed in Tomcat 10.1.x. My xhtml files are under WEB-INF. Though I used correct username/password (log trace) to login at login.xhtml, the app just stayed at login screen instead of going to a default success url (test.xhtml). The security log trace had "Created SecurityContextImpl [Null authentication]", "HttpSessionSecurityContextRepository : Did not find SecurityContext in HttpSession using the SPRING_SECURITY_CONTEXT session attribute." It caused Granted Authorities=[ROLE_ANONYMOUS], then Access Denied. Security log trace:

533-04:00 DEBUG 3980 --- [nio-8080-exec-8] o.s.security.web.FilterChainProxy : Secured POST /login 543-04:00 DEBUG 3980 --- [nio-8080-exec-8] o.s.web.servlet.DispatcherServlet : POST "/sbwar2/login", parameters={username:[user], password:[password], _csrf:[9cqHDzmNlsgTvrwCjfBK1gKrEB8YVEBLfuM0Te5Q3Lhh1DjTwq-yPA-49Pk-2t007t1-4TqbPScvN3FmG4YMfNpiut5Rtlvi]} 549-04:00 DEBUG 3980 --- [nio-8080-exec-8] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped to ResourceHttpRequestHandler [classpath [META-INF/resources/], classpath [resources/], classpath [static/], classpath [public/], ServletContext [/]] 604-04:00 DEBUG 3980 --- [nio-8080-exec-8] o.s.w.s.r.ResourceHttpRequestHandler : Resource not found 604-04:00 TRACE 3980 --- [nio-8080-exec-8] o.s.s.w.header.writers.HstsHeaderWriter : Not injecting HSTS header since it did not match request to [Is Secure] 608-04:00 DEBUG 3980 --- [nio-8080-exec-8] o.s.web.servlet.DispatcherServlet : Completed 404 NOT_FOUND 609-04:00 TRACE 3980 --- [nio-8080-exec-8] w.c.HttpSessionSecurityContextRepository : Did not find SecurityContext in HttpSession 1204F5B756E65B39DA16CFE184630C21 using the SPRING_SECURITY_CONTEXT session attribute 610-04:00 TRACE 3980 --- [nio-8080-exec-8] .s.s.w.c.SupplierDeferredSecurityContext : Created SecurityContextImpl [Null authentication] 610-04:00 TRACE 3980 --- [nio-8080-exec-8] .s.s.w.c.SupplierDeferredSecurityContext : Created SecurityContextImpl [Null authentication] 614-04:00 TRACE 3980 --- [nio-8080-exec-8] o.s.s.w.a.AnonymousAuthenticationFilter : Set SecurityContextHolder to AnonymousAuthenticationToken [Principal=anonymousUser, Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=0:0:0:0:0:0:0:1, SessionId=1204F5B756E65B39DA16CFE184630C21], Granted Authorities=[ROLE_ANONYMOUS]] ............................
651-04:00 TRACE 3980 --- [nio-8080-exec-8] o.s.s.w.a.ExceptionTranslationFilter : Sending AnonymousAuthenticationToken [Principal=anonymousUser, Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=0:0:0:0:0:0:0:1, SessionId=1204F5B756E65B39DA16CFE184630C21], Granted Authorities=[ROLE_ANONYMOUS]] to authentication entry point since access is denied ...................
org.springframework.security.access.AccessDeniedException: Access Denied at org.springframework.security.web.access.intercept.AuthorizationFilter.doFilter(AuthorizationFilter.java:98) ~[spring-security-web-6.1.1.jar:6.1.1] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374) ......................................

WebSecurityConfig.java

@Configuration
@EnableWebSecurity
public class WebSecurityConfig {
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests((requests) -> requests
                .requestMatchers("/", "/home","/jakarta.faces.resource/**", "/login", "/login.xhtml").permitAll()               
                .anyRequest().authenticated()
            )
            .formLogin((form) -> form
                    .loginPage("/login.xhtml")
                    .permitAll()
                    .defaultSuccessUrl("/test.xhtml", true)
                    .failureUrl("/login.xhtml?error-true")      
            )
            .cors(cors -> cors.disable())
            .logout((logout) -> logout.permitAll());
        return http.build();
    }
    @Bean
    public UserDetailsService users() {
        UserDetails user = User.builder()
            .username("user")
            .password("password")
            .roles("USER")
            .build();
        return new InMemoryUserDetailsManager(user);
    }   
}

login.xhtml

    <form action="${request.contextPath}/login" method="POST">
    <div align="center"><h:outputLabel styleClass="fa fa-2x" value="Sign in"/></div><br/>                       
    <div align="center">
        <h:outputLabel class="alert alert-danger" value="Invalid user name or password" rendered="${not empty SPRING_SECURITY_LAST_EXCEPTION.message}"/>
    </div>                          
    <div class="input-group input-sm">
        <label class="input-group-addon" for="username"><i class="fa fa-user"></i></label>
        <input type="text" class="form-control" id="username" name="username" placeholder="Username" required="true"  autofocus="true"/>
    </div>
    <div class="input-group input-sm">
        <label class="input-group-addon" for="password"><i class="fa fa-lock"></i></label> 
        <input type="password" class="form-control" id="password" name="password" placeholder="Password" required="true"/>
    </div>
    <input type="hidden" name="${_csrf.parameterName}"  value="${_csrf.token}" />
    <div class="form-group">
        <input type="submit" class="btn btn-block btn-primary btn-default" value="Log in"/>
    </div>
</form>

test.xhtml

<h:body>
This is a test
</h:body>

I did some research: Spring Session - Security Context not found in session after redirect to target url

Spring boot Resource Not Found 404 error html

Make JSF resources publicly accessible with Spring Security

SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession and Principal of logged in user is never filled

https://docs.spring.io/spring-security/reference/servlet/authentication/passwords/in-memory.html

Update: I tried to add a registry for /login. And rename login.xhtml to signin.xhtml

@Configuration
public class MvcConfig implements WebMvcConfigurer {
   @Override
   public void addViewControllers(ViewControllerRegistry registry) {
      registry.addViewController("/login").setViewName("login");
   }
}

However, I got 405 METHOD_NOT_ALLOWED for /login

DEBUG 11512 --- [nio-8080-exec-7] o.s.security.web.FilterChainProxy : Secured POST /login DEBUG 11512 --- [nio-8080-exec-7] o.s.web.servlet.DispatcherServlet : POST "/sbwar2/login", parameters={username:[user], password:[password], ...... WARN 11512 --- [nio-8080-exec-7] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'POST' is not supported] DEBUG 11512 --- [nio-8080-exec-7] o.s.web.servlet.DispatcherServlet : Completed 405 METHOD_NOT_ALLOWED

Update: I added this class. It worked.

   @Controller
   public class LoginController {
      @GetMapping("/login")
      String login() {
         return "signin.xhtml";
      } 
    }

Upvotes: 0

Views: 3670

Answers (1)

Martin P.
Martin P.

Reputation: 820

I got a similar issue. After comparing with a working example, I found out the bean ChangeSessionIdAuthenticationStrategy was not executed. So, within flow exchange it cannot find the session and associate the user to Anonymous.

In my case I created a custom UsernamePasswordAuthenticationFilter which cause issue. Instead I created an AuthenticationProvider Bean to use the user/password differently.

I found this answer useful: StackOverflow

Upvotes: 0

Related Questions