45

This is my main controller:

package org.demian.demibox.controllers;

import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
public class MainController {
    private String getUsername() {
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        if (auth.isAuthenticated())
            return auth.getName();
        else
            return null;
    }
    @RequestMapping(value = "/", method = RequestMethod.GET)
    public String showHome() {
        String username = getUsername();
        System.out.println(username);
        if (username == null || username.length() == 0)
            return "welcome";
        return "index";
    }
}

Even though I am not logged in, auth.isAuthenticated() always returns true. Why is that? And when would auth.isAuthenticated() return false? The name of the authenticated user is anonymousUser if I'm not logged in and username if I am logged in.

EDIT

This is my security-context.xml file:

<?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"
    xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <security:authentication-manager>
        <security:authentication-provider>
            <security:jdbc-user-service data-source-ref="dataSource" id="jdbcUserService" />
            <!-- <security:password-encoder ref="passwordEncoder" /> -->
        </security:authentication-provider>
    </security:authentication-manager>
    <security:http use-expressions="true">
        <security:intercept-url pattern="/" access="permitAll" />
        <security:intercept-url pattern="/login" access="permitAll" />
        <security:intercept-url pattern="/redeem" access="permitAll" />
        <security:intercept-url pattern="/redeem_code" access="permitAll" />
        <security:intercept-url pattern="/static/**" access="permitAll" />
        <security:intercept-url pattern="/*" access="isAuthenticated()" />
        <security:intercept-url pattern="/**" access="isAuthenticated()" />
        <security:intercept-url pattern="/**" access="denyAll" />
        <security:form-login login-page="/login" authentication-failure-url="/login?error=true" />
        <security:logout logout-success-url="/" />
        <security:remember-me key="offersAppKey" user-service-ref="jdbcUserService" />
    </security:http>
    <security:global-method-security secured-annotations="enabled" />
    <!-- <bean id="passwordEncoder" class="org.springframework.security.crypto.password.StandardPasswordEncoder" /> -->
</beans>

And the following lines are in the web.xml file:

<filter>
    <display-name>springSecurityFilterChain</display-name>
    <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>
</filter-mapping>

I am using Tomcat 8.0 and all the latest dependencies via Maven.

Ariel
  • 1,222
  • 2
  • 14
  • 25

1 Answers1

60

This is how spring-security works by default.

From the docs:

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.

If you need to check if it is an anonymousUser then you can check whether Authentication object is AnonymousAuthenticationToken instance or not.

Community
  • 1
  • 1
Aleksandr M
  • 24,264
  • 12
  • 69
  • 143
  • Thank you. I've seen this answer in other questions on the net but I was reticent to using it because I think it's best to avoid when possible `instanceof`. – Ariel Sep 30 '14 at 09:39
  • 4
    @Ariel: You can also check `authorities` from `Authentication` object for `ROLE_ANONYMOUS`. – Aleksandr M Sep 30 '14 at 09:46
  • The token 'ROLE_ANONYMOUS' is hardcoded as a String in several places of Spring Security lib. Is it reliable to use it? I mean, the compiler will not detect the error in case of typo or refactoring. – beemaster Mar 04 '16 at 07:54
  • @beemaster Spring security is an open source project you can provide patch for that. – Aleksandr M Mar 04 '16 at 09:24
  • 1
    well, I even didn't think about it. I used to think that Spring's team are 'top level' developers and I'll look humble on this background. – beemaster Mar 11 '16 at 15:50
  • Is it possible to disable this behavior? – Nic Aug 03 '18 at 16:38
  • @NicHartley yes, check [this](https://stackoverflow.com/a/31681783/2342529) answer, but in my opinion is better not to. – Alexandru Severin Oct 23 '18 at 12:06
  • When does spring does this ? In which case the returned Authentication is an anonymousUser ? – Nitish Kumar Jan 06 '19 at 08:43
  • @AlexandruSeverin Why is it better not to disable this behavior??? – Partho63 Jan 06 '20 at 09:52