Home > Enterprise >  Why Spring Security getAuthentication() returns null on server
Why Spring Security getAuthentication() returns null on server

Time:11-14

I have a web application and use spring security for authentication.
All page need authentication, but Login page doesn't need authentication.
in my situation, I succeeded to access other page which need authentication after login on local environment. But I fail on server environment.Because the getAuthentication() returns null.

I don't know why the getAuthentication() returns null on server environment.

when move to /foo after login(local log)

[2021-11-11 15:20:05:32506][http-nio-8080-exec-7] DEBUG org.springframework.security.authentication.dao.DaoAuthenticationProvider.createSuccessAuthentication - Authenticated user
[2021-11-11 15:20:05:32507][http-nio-8080-exec-7] DEBUG org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter.successfulAuthentication - Set SecurityContextHolder to UsernamePasswordAuthenticationToken [Principal=LoginUser(loginInfo=com.bar.entity.LoginInfoEntity@12234790), Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=0:0:0:0:0:0:0:1, SessionId=null], Granted Authorities=[]]
[2021-11-11 15:20:06:33756][http-nio-8080-exec-7] WARN  org.apache.catalina.util.SessionIdGeneratorBase.log - Creation of SecureRandom instance for session ID generation using [SHA1PRNG] took [1,246] milliseconds.
[2021-11-11 15:20:06:33760][http-nio-8080-exec-7] DEBUG org.springframework.security.web.context.HttpSessionSecurityContextRepository.saveContext - Stored SecurityContextImpl [Authentication=UsernamePasswordAuthenticationToken [Principal=LoginUser(loginInfo=com.bar.entity.LoginInfoEntity@12234790), Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=0:0:0:0:0:0:0:1, SessionId=null], Granted Authorities=[]]] to HttpSession [org.apache.catalina.session.StandardSessionFacade@16178716]
[2021-11-11 15:20:06:33760][http-nio-8080-exec-7] DEBUG org.springframework.security.web.context.HttpSessionSecurityContextRepository.saveContext - Stored SecurityContextImpl [Authentication=UsernamePasswordAuthenticationToken [Principal=LoginUser(loginInfo=com.bar.entity.LoginInfoEntity@12234790), Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=0:0:0:0:0:0:0:1, SessionId=null], Granted Authorities=[]]] to HttpSession [org.apache.catalina.session.StandardSessionFacade@16178716]
[2021-11-11 15:20:06:33760][http-nio-8080-exec-7] DEBUG org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter - Cleared SecurityContextHolder to complete request
--move to foo
[2021-11-11 15:20:06:33769][http-nio-8080-exec-8] DEBUG org.springframework.security.web.FilterChainProxy.doFilterInternal - Securing GET /foo
[2021-11-11 15:20:06:33769][http-nio-8080-exec-8] DEBUG org.springframework.security.web.context.HttpSessionSecurityContextRepository.readSecurityContextFromSession - Retrieved SecurityContextImpl [Authentication=UsernamePasswordAuthenticationToken [Principal=LoginUser(loginInfo=com.bar.entity.LoginInfoEntity@12234790), Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=0:0:0:0:0:0:0:1, SessionId=null], Granted Authorities=[]]]
[2021-11-11 15:20:06:33769][http-nio-8080-exec-8] DEBUG org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter - Set SecurityContextHolder to SecurityContextImpl [Authentication=UsernamePasswordAuthenticationToken [Principal=LoginUser(loginInfo=com.bar.entity.LoginInfoEntity@12234790), Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=0:0:0:0:0:0:0:1, SessionId=null], Granted Authorities=[]]]
[2021-11-11 15:20:06:33769][http-nio-8080-exec-8] DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping.getHandler - Mapped to com.bar.view.controller.FooController#initalize()
--success
[2021-11-11 15:20:06:33770][http-nio-8080-exec-8] DEBUG org.springframework.security.web.access.intercept.FilterSecurityInterceptor.beforeInvocation - Authorized filter invocation [GET /foo] with attributes [authenticated]

when move to /foo after login(server log). sorry no method name on log

[2021-11-11 06:17:15:126723][foo] DEBUG org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter - Set SecurityContextHolder to UsernamePasswordAuthenticationToken [Principal=LoginUser(loginInfo=com.bar.entity.LoginInfoEntity@708afefc), Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=39.110.214.222, SessionId=null], Granted Authorities=[]]
[2021-11-11 06:17:15:126740][foo] DEBUG org.springframework.security.web.context.HttpSessionSecurityContextRepository - Stored SecurityContextImpl [Authentication=UsernamePasswordAuthenticationToken [Principal=LoginUser(loginInfo=com.bar.entity.LoginInfoEntity@708afefc), Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=39.110.214.222, SessionId=null], Granted Authorities=[]]] to HttpSession [org.apache.catalina.session.StandardSessionFacade@4d6cfed4]
[2021-11-11 06:17:15:126740][foo] DEBUG org.springframework.security.web.context.HttpSessionSecurityContextRepository - Stored SecurityContextImpl [Authentication=UsernamePasswordAuthenticationToken [Principal=LoginUser(loginInfo=com.bar.entity.LoginInfoEntity@708afefc), Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=39.110.214.222, SessionId=null], Granted Authorities=[]]] to HttpSession [org.apache.catalina.session.StandardSessionFacade@4d6cfed4]
[2021-11-11 06:17:15:126741][foo] DEBUG org.springframework.security.web.context.SecurityContextPersistenceFilter - Cleared SecurityContextHolder to complete request
-- move to foo
[2021-11-11 06:17:15:126766][foo] DEBUG org.springframework.security.web.FilterChainProxy - Securing GET /foo
[2021-11-11 06:17:15:126766][foo] DEBUG org.springframework.security.web.context.SecurityContextPersistenceFilter - Set SecurityContextHolder to empty SecurityContext
[2021-11-11 06:17:15:126766][foo] DEBUG org.springframework.security.web.authentication.AnonymousAuthenticationFilter - Set SecurityContextHolder to anonymous SecurityContext
[2021-11-11 06:17:15:126767][foo] DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped to com.bar.view.controller.RobotSelectController#initalize()
-- fail
[2021-11-11 06:17:15:126780][foo] DEBUG org.springframework.security.web.access.intercept.FilterSecurityInterceptor - Failed to authorize filter invocation [GET /foo] with attributes [authenticated]

My source code

I have only Config and for Spring Security

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {


    @Override
    public void configure(WebSecurity web) throws Exception {
      web
        .ignoring()
        .antMatchers("/images/**", "/js/**", "/css/**");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
              .mvcMatchers(loginPage).permitAll()
              .anyRequest().authenticated()
             .and()
              .formLogin()
               .loginPage(loginPage)
               .loginProcessingUrl(loginSuccessUrl)
               .successHandler(new AuthenticationSuccessHandler() {
                    @Override
                    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
                            Authentication authentication) throws IOException, ServletException {
                        //add Session
                        request.getSession().setMaxInactiveInterval(180000);
                        //move page
                        response.sendRedirect(fooPage);
                    }
                });

    }

}

Login implement UserDetailsService

@Service
public class Login implements UserDetailsService{
    
    
    private final LoginInfoRepository loginRepo;
    
    @Autowired
    public Login(LoginInfoRepository loginRepo) {
        this.loginRepo = loginRepo;
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        LoginInfoEntity entity = loginRepo.findById(username)
                .orElseThrow(() -> new UsernameNotFoundException("not exist user"));
        
        UserDetails userDetails = new LoginUser(entity);
        
        return userDetails; 
    }
    
}

loginUser use for session information

public class LoginUser extends User {

    @SuppressWarnings("unchecked")
    public LoginUser(LoginInfoEntity loginInfo) {
        super(loginInfo.getUserId(), loginInfo.getPassword(), 
                loginInfo.isAvailable(), true, true, true, Collections.EMPTY_SET);
    }
}

Thank you for reading it.

CodePudding user response:

[2021-11-11 06:17:15:126766][foo] DEBUG org.springframework.security.web.authentication.AnonymousAuthenticationFilter - Set SecurityContextHolder to anonymous SecurityContext

This is the key line to understand the issue. When you are doing the redirect you are redirecting the user, yes. However, his session information ( cookie ) or some other thing is not part of this redirected request.

Therefore, to the /foo endpoints point of view, it does not get any credential information and its treating the request as anonymous.

If you can get rid of this piece of code ...

successHandler(.. do redirect ...)

And don't do the redirect like this and do it like this instead, it will likely fix the problem.

Redirect via defaultSuccessUrl

 http.formLogin().defaultSuccessUrl("/success.html", true);

Does this solve your problem ? Tell me in the comments.

You can also enable HTTP request tracing and see exactly which request with which headers and payloads are coming to the /foo endpoint and this will make it easier to diagnose the problem.

Are you using cookies or JWT for authentication ? Tell me in the comments.

CodePudding user response:

I solved the problem. Thank you Arthur Klezovich. The cause is contextpath not redirect. I thought local environment is equal to server environment. but Server environment had contextpath Beacuse I don't set for contextpath. It causes url to be involved contextpath.

For example)

  • Succeed to get session after login in local - http://99.99.99/foo

  • Failed to get session after login in server - http://99.99.99/foo(question's url)

  • Succeed to get session after login in server -http://99.99.99/contextpath/foo

There are several ways remove url of contextpath. I choosed easiest way change file of war name

foo.war -> root.war

after Spring-security is working well, no modify code

  • Related