Search code examples
spring-mvcspring-security

Spring SecurityContext returning null authentication


I am using Spring Security for user authentication , but the SecurityContext is null when the user is not logged in.

In my web.xml I have:

 <filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>
        org.springframework.web.filter.DelegatingFilterProxy
    </filter-class>
</filter>
<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>REQUEST</dispatcher>
    <dispatcher>ERROR</dispatcher>
</filter-mapping>

In my security.xml I have

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:security="http://www.springframework.org/schema/security"
       xmlns:http="http://www.springframework.org/schema/security"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd">

    <!-- Static resources such as CSS and JS files are ignored by Spring Security -->
    <security:http pattern="/resources/**" security="none" />

    <security:http use-expressions="true">
        <!-- Enables Spring Security CSRF protection -->
        <security:csrf/>
        <!-- Configures the form login -->
        <security:form-login
                login-page="/login"
                login-processing-url="/login/authenticate"
                authentication-failure-url="/login?error=bad_credentials"
                username-parameter="username"
                password-parameter="password"/>
        <!-- Configures the logout function -->
        <security:logout
                logout-url="/logout"
                logout-success-url="/home"
                delete-cookies="JESSIONID"/>

        <security:intercept-url pattern="/**" method="GET" access="permitAll"/>
        <security:intercept-url pattern="/user/register" method="POST" access="permitAll"/>

        <!-- These operations are protected. -->
        <security:intercept-url pattern="/product/**" access="hasAnyRole('ROLE_USER','ROLE_ADMIN')"/>
        <security:intercept-url pattern="/admin/**" access="hasRole('ROLE_ADMIN')"/>
        <security:access-denied-handler error-page="/login"/>

        <!-- Adds social authentication filter to the Spring Security filter chain. -->
        <security:custom-filter ref="socialAuthenticationFilter" before="PRE_AUTH_FILTER" />
    </security:http>

... other config...

The code where I am getting null is:

HttpSession session = request.getSession(true);
SecurityContext securityContext =(SecurityContext) session.getAttribute("SPRING_SECURITY_CONTEXT");
Authentication authentication = securityContext.getAuthentication();
user = (Object) authentication.getPrincipal();

But I am getting null securityContext when no user is logged in. Any help where I am doing wrong


Solution

  • From http://docs.spring.io/spring-security/site/docs/3.0.x/reference/anonymous.html:

    ...Note that there is no real conceptual difference between a user who is “anonymously authenticated” and an unauthenticated user. Spring Security's anonymous authentication just gives you a more convenient way to configure your access-control attributes. Calls to servlet API calls such as getCallerPrincipal, for example, will still return null even though there is actually an anonymous authentication object in the SecurityContextHolder.

    There are other situations where anonymous authentication is useful, such as when an auditing interceptor queries the SecurityContextHolder to identify which principal was responsible for a given operation. Classes can be authored more robustly if they know the SecurityContextHolder always contains an Authentication object, and never null.

    So a setup like (also from cited page):

    <bean id="anonymousAuthFilter"
      class="org.springframework.security.web.authentication.AnonymousAuthenticationFilter">
      <property name="key" value="foobar"/>
      <property name="userAttribute" value="anonymousUser,ROLE_ANONYMOUS"/>
    </bean>
    <bean id="anonymousAuthenticationProvider"
      class="org.springframework.security.authentication.AnonymousAuthenticationProvider">
      <property name="key" value="foobar"/>
    </bean>
    

    ..and adjusting your security.xml entries from:

    permitAll
    

    ..to:

    ROLE_ANONYMOUS
    

    should provide you always with a Securitycontext/Authentication object (but not necessarily with a "Principal").