Search code examples
javaspring-mvcservlet-filtersshiro

Can't understand Shiro behavior on custom login page request


I'm using Apache Shiro to secure my Spring MVC application. This is my config:

<!-- Shiro -->
<bean id = "hibernateRealm" class = "com.bidapp.presentation.shiro.HibernateRealm" />

<bean id = "securityManager" class = "org.apache.shiro.web.mgt.DefaultWebSecurityManager">
    <property name = "realm" ref = "hibernateRealm" />
</bean>

<bean id = "lifecycleBeanPostProcessor" class = "org.apache.shiro.spring.LifecycleBeanPostProcessor" />

<bean id = "shiroFilter" class = "org.apache.shiro.spring.web.ShiroFilterFactoryBean">
    <property name = "securityManager" ref = "securityManager" />
</bean>
<!-- Shiro -->

In web.xml (among other things)

<filter>
    <filter-name>shiroFilter</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    <init-param>
        <param-name>targetFilterLifecycle</param-name>
        <param-value>true</param-value>
    </init-param>
</filter>

<filter-mapping>
    <filter-name>shiroFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

My login page is at context/account/login. When I try to submit the form, I get a 400 HTTP error code with message The request sent by the client was syntactically incorrect (). and the following is logged by Shiro

365348 [http-bio-8080-exec-5] TRACE o.a.s.w.s.OncePerRequestFilter - Filter 'shiroFilter' not yet executed.  Executing now. 
365349 [http-bio-8080-exec-5] TRACE o.a.s.mgt.DefaultSecurityManager - Context already contains a SecurityManager instance.  Returning. 
365349 [http-bio-8080-exec-5] TRACE o.a.s.mgt.DefaultSecurityManager - No identity (PrincipalCollection) found in the context.  Looking for a remembered identity. 
365349 [http-bio-8080-exec-5] TRACE o.a.shiro.web.servlet.SimpleCookie - No 'rememberMe' cookie value 
365349 [http-bio-8080-exec-5] TRACE o.a.s.mgt.DefaultSecurityManager - No remembered identity found.  Returning original context. 
365349 [http-bio-8080-exec-5] TRACE o.a.s.s.support.DelegatingSubject - attempting to get session; create = false; session is null = true; session has id = false 
365349 [http-bio-8080-exec-5] TRACE o.a.s.s.support.DelegatingSubject - attempting to get session; create = false; session is null = true; session has id = false 
365349 [http-bio-8080-exec-5] TRACE o.a.s.s.support.DelegatingSubject - attempting to get session; create = false; session is null = true; session has id = false 
365349 [http-bio-8080-exec-5] TRACE o.a.s.s.support.DelegatingSubject - attempting to get session; create = false; session is null = true; session has id = false 
365349 [http-bio-8080-exec-5] TRACE org.apache.shiro.util.ThreadContext - Bound value of type [org.apache.shiro.web.subject.support.WebDelegatingSubject] for key [org.apache.shiro.util.ThreadContext_SUBJECT_KEY] to thread [http-bio-8080-exec-5] 
365349 [http-bio-8080-exec-5] TRACE org.apache.shiro.util.ThreadContext - Bound value of type [org.apache.shiro.web.mgt.DefaultWebSecurityManager] for key [org.apache.shiro.util.ThreadContext_SECURITY_MANAGER_KEY] to thread [http-bio-8080-exec-5] 
365349 [http-bio-8080-exec-5] TRACE o.a.s.w.servlet.AbstractShiroFilter - No FilterChain configured for the current request.  Using the default. 
365351 [http-bio-8080-exec-5] TRACE org.apache.shiro.util.ThreadContext - get() - in thread [http-bio-8080-exec-5] 
365351 [http-bio-8080-exec-5] TRACE org.apache.shiro.util.ThreadContext - Retrieved value of type [org.apache.shiro.web.subject.support.WebDelegatingSubject] for key [org.apache.shiro.util.ThreadContext_SUBJECT_KEY] bound to thread [http-bio-8080-exec-5] 
365351 [http-bio-8080-exec-5] TRACE o.a.s.s.support.DelegatingSubject - attempting to get session; create = false; session is null = true; session has id = false 

The really weird thing is that I can click back and then forward on my browser and it brings me to the correct authenticated web page. I tried debugging and my Controller never even gets called. But how can that be if clicking back and the forward bring me to the correct page?

I don't have any other filters in my web.xml and don't use any of Shiro's default filters, not knowingly anyway.

What is going on?

Not that it makes any difference I'm developing on Eclipse Indigo. And this is the code that should be called but isn't (in debug mode).

    @RequestMapping(value = "/account/login", method = RequestMethod.POST, params = "login")
    public String login(@RequestParam("username") String username, 
            @RequestParam("password") String password,
            @RequestParam("remember") boolean rememberMe,
            Model model) {
        Subject currentUser = SecurityUtils.getSubject();

        if (!currentUser.isAuthenticated()) {

            UsernamePasswordToken token = new UsernamePasswordToken(username, password);
            token.setRememberMe(rememberMe);
            currentUser.login(token);

            return "redirect:/account/profile";
        }

        return "home";

    }

Solution

  • So I still can't explain the forward and back button behavior, but this wasn't a Shiro problem. The issue was with the remember me checkbox I have. In the handler method for login, I have @RequestParam("remember") boolean rememberMe but it should be @RequestParam(value = "remember", required = false) boolean rememberMe. The required means that you don't need it there. By default, Spring makes it true, so it will say that this is the correct method to call but it can't call it because it doesn't have the information it needs, thus 400.