Spring security + sendRedirect not working

2019-08-05 06:44发布

问题:

Currently my spring-security.xml looks like this:

<global-method-security pre-post-annotations="enabled" />

    <http pattern="/login" security="none"/>
    <http pattern="/assets/**" security="none"/>

    <http auto-config="false" entry-point-ref="authenticationEntryPoint" disable-url-rewriting="true">
        <intercept-url pattern="/**" access="ROLE_USER"/>
        <intercept-url pattern="/admin/**" access="ROLE_ADMIN"/>
        <intercept-url pattern="/tadmin/**" access="ROLE_TENANT_ADMIN"/>
        <form-login login-page="/login" authentication-success-handler-ref="authenticationSuccessHandler" authentication-failure-url="/login?error"/>
        <logout logout-url="/logout" logout-success-url="/login"/>
        <remember-me/>
    </http>

    <beans:bean id="authenticationSuccessHandler" class="com.dj.LoginSuccessHandler">
        <beans:property name="useReferer" value="true"/>
    </beans:bean>

    <beans:bean id="authenticationEntryPoint"
        class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
        <beans:property name="loginFormUrl" value="/login" />
    </beans:bean>

    <authentication-manager alias="authenticationManager">
        <authentication-provider>
            <!-- <password-encoder hash="md5"/> -->
            <user-service>
                <user name="user" password="123" authorities="ROLE_USER"/>
                <user name="admin" password="123" authorities="ROLE_ADMIN,ROLE_USER"/>
                <user name="tadmin" password="123" authorities="ROLE_TENANT_ADMIN,ROLE_USER"/>
            </user-service>
        </authentication-provider>
    </authentication-manager>

My custom AuthenticationSuccessHandler:

package com.dj;

import java.io.IOException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;

import com.dj.UserRole;

public class LoginSuccessHandler extends
    SavedRequestAwareAuthenticationSuccessHandler {
    // getters and setters for injected services

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request,
        HttpServletResponse response, Authentication authentication) {

    try {
        String redirectUrl = "/login";
        if (hasRole(authentication, UserRole.ROLE_ADMIN)) {
        redirectUrl = "/app/admin/secure";
        } else if (hasRole(authentication, UserRole.ROLE_TENANT_ADMIN)) {
        redirectUrl = "/app/tadmin/secure";
        } else if (hasRole(authentication, UserRole.ROLE_USER)) {
        redirectUrl = "/app/USER/";
        }
        response.sendRedirect(redirectUrl);
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    }

    /**
     * Check if a role is present in the authorities of current user
     * 
     * @param authorities
     *            all authorities assigned to current user
     * @param role
     *            required authority
     * @return true if role is present in list of authorities assigned to
     *         current user, false otherwise
     */
    private boolean hasRole(Authentication auth, UserRole role) {
    boolean hasRole = false;
    for (GrantedAuthority grantedAuthority : auth.getAuthorities()) {
        hasRole = grantedAuthority.getAuthority().equals(role.name());
        if (hasRole)
        break;
    }
    return hasRole;
    }
}

When I try to log in i can see by intercepting network traffic:

  1. A POST from my custom login form sending username,password,remember me to j_spring_security_check
  2. A GET from the app/admin/secure page

However, I am never getting redirected to the correct page given the type of user that has just been logged in, stuck forever on the login page.

When entering the redirect url manually everything works fine and I am logged in properly. Seems to me security is set up properly, however the redirecting is just not working.

Any help on this matter would be appreciated.

回答1:

Your intercept-url declarations are in the wrong order. You need to put the most-specific ones first. You have /** at the top, so that will always match. It should be the last in the list.

You should be able to track the successful login and a subsequent access-denied exception in the debug log.