Grails spring安全登录问题:/ auth?login_error = 1

时间:2011-07-28 12:37:54

标签: grails spring-security grails-plugin

我成功安装了SpringSecurity,在用户注册并使用Spring Security UI'RegisterController闭包验证用户后,我可以看到用户使用springSecurityService.reauthenticate成功登录。

但是,如果我注销并尝试使用spring security提供的auth屏幕登录,我总是得到http://:port / spoofsecurity / login / auth?login_error = 1

我可以在数据库中看到用户在那里并解锁并启用。

感谢任何想法,为什么我登录失败。

由于

我的Config.groovy条目

    grails.plugins.springsecurity.userLookup.userDomainClassName = 'com.srisris.spoofsecurity.auth.SchemeUser'
grails.plugins.springsecurity.userLookup.authorityJoinClassName = 'com.srisris.spoofsecurity.auth.SchemeUserRole'
grails.plugins.springsecurity.authority.className = 'com.srisris.spoofsecurity.auth.SchemeRole'
//grails.plugins.springsecurity.password.algorithm='SHA-512'
grails.plugins.springsecurity.securityConfigType = SecurityConfigType.Annotation
//grails.plugins.springsecurity.securityConfigType = SecurityConfigType.Requestmap
//grails.plugins.springsecurity.requestMap.className = 'com.srisris.spoofsecurity.auth.Requestmap' 
//grails.plugins.springsecurity.useSwitchUserFilter = true
grails.plugins.springsecurity.securityConfigType = SecurityConfigType.Annotation

LoginController.groovy

    import grails.converters.JSON

import javax.servlet.http.HttpServletResponse

import org.codehaus.groovy.grails.plugins.springsecurity.SpringSecurityUtils

import org.springframework.security.authentication.AccountExpiredException
import org.springframework.security.authentication.CredentialsExpiredException
import org.springframework.security.authentication.DisabledException
import org.springframework.security.authentication.LockedException
import org.springframework.security.core.context.SecurityContextHolder as SCH
import org.springframework.security.web.WebAttributes
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter

class LoginController {

    /**
     * Dependency injection for the authenticationTrustResolver.
     */
    def authenticationTrustResolver

    /**
     * Dependency injection for the springSecurityService.
     */
    def springSecurityService

    /**
     * Default action; redirects to 'defaultTargetUrl' if logged in, /login/auth otherwise.
     */
    def index = {
        if (springSecurityService.isLoggedIn()) {
            redirect uri: SpringSecurityUtils.securityConfig.successHandler.defaultTargetUrl
        }
        else {
            redirect action: auth, params: params
        }
    }

    /**
     * Show the login page.
     */
    def auth = {

        def config = SpringSecurityUtils.securityConfig

        if (springSecurityService.isLoggedIn()) {
            redirect uri: config.successHandler.defaultTargetUrl
            return
        }

        String view = 'auth'
        String postUrl = "${request.contextPath}${config.apf.filterProcessesUrl}"
        render view: view, model: [postUrl: postUrl,
                                   rememberMeParameter: config.rememberMe.parameter]
    }

    /**
     * The redirect action for Ajax requests. 
     */
    def authAjax = {
        response.setHeader 'Location', SpringSecurityUtils.securityConfig.auth.ajaxLoginFormUrl
        response.sendError HttpServletResponse.SC_UNAUTHORIZED
    }

    /**
     * Show denied page.
     */
    def denied = {
        if (springSecurityService.isLoggedIn() &&
                authenticationTrustResolver.isRememberMe(SCH.context?.authentication)) {
            // have cookie but the page is guarded with IS_AUTHENTICATED_FULLY
            redirect action: full, params: params
        }
    }

    /**
     * Login page for users with a remember-me cookie but accessing a IS_AUTHENTICATED_FULLY page.
     */
    def full = {
        def config = SpringSecurityUtils.securityConfig
        render view: 'auth', params: params,
            model: [hasCookie: authenticationTrustResolver.isRememberMe(SCH.context?.authentication),
                    postUrl: "${request.contextPath}${config.apf.filterProcessesUrl}"]
    }

    /**
     * Callback after a failed login. Redirects to the auth page with a warning message.
     */
    def authfail = {

        def username = session[UsernamePasswordAuthenticationFilter.SPRING_SECURITY_LAST_USERNAME_KEY]
        String msg = ''
        def exception = session[WebAttributes.AUTHENTICATION_EXCEPTION]
        if (exception) {
            if (exception instanceof AccountExpiredException) {
                msg = SpringSecurityUtils.securityConfig.errors.login.expired
            }
            else if (exception instanceof CredentialsExpiredException) {
                msg = SpringSecurityUtils.securityConfig.errors.login.passwordExpired
            }
            else if (exception instanceof DisabledException) {
                msg = SpringSecurityUtils.securityConfig.errors.login.disabled
            }
            else if (exception instanceof LockedException) {
                msg = SpringSecurityUtils.securityConfig.errors.login.locked
            }
            else {
                msg = SpringSecurityUtils.securityConfig.errors.login.fail
            }
        }

        if (springSecurityService.isAjax(request)) {
            render([error: msg] as JSON)
        }
        else {
            flash.message = msg
            redirect action: auth, params: params
        }
    }

    /**
     * The Ajax success redirect url.
     */
    def ajaxSuccess = {
        render([success: true, username: springSecurityService.authentication.name] as JSON)
    }

    /**
     * The Ajax denied redirect url.
     */
    def ajaxDenied = {
        render([error: 'access denied'] as JSON)
    }
}

auth.jsp

 <head>
    <meta name='layout' content='main'/>
    <title>Login</title>
    <style type='text/css' media='screen'>

    #auth .flashMessage {
        text-align: center;
        margin: 5px 0 0 0;
    }

    #auth {
        padding: 5px 10px;
        text-align: left;
        width: 300px;
        border-width: 1px;
        border-style: dashed none;
        border-color: #49d;
    }

    #auth table {
        width: 100%;
    }

    #auth table tr:first-child td {
        border: 0;
    }

    #auth h1 {
        font-size: 1.4em;
        margin-bottom: 0;
        text-align: center;
    }

    #auth td {
        border-top: 1px dashed gray;
        vertical-align: middle;
        padding: 5px 0;
    }

    #auth label {
        font-weight: bold;
    }

    #auth input[type="submit"] {
        font-size: 1em;
        width: 100px;
        height: 2em;
    }

    #auth .submit {
        text-align: center;
    }

    .forgot{
        margin: 0;
        text-align: center;
    }
    </style>
</head>

<body>
    <div id='auth'>
        <cap:flashMessage/>
        <form action='${postUrl}' method='POST' id='loginForm' autocomplete='off' onsubmit="return formSubmit();">
            <table cellpadding="0" cellspacing="0">
                <tr>
                    <td colspan="2"><h1>Please Login</h1></td>
                </tr>
                <tr>
                    <td><label for='username'>Email</label></td>
                    <td><input type='text' name='j_username' id='username'/></td>
                </tr>
                <tr>
                    <td><label for='password'>Password</label></td>
                    <td><input type='password' name='j_password' id='password'/></td>
                </tr>
                <tr>
                    <td><label for='remember_me'>Remember Me</label></td>
                    <td><input type='checkbox' name='${rememberMeParameter}'
                            id='remember_me' ${hasCookie ? "checked='checked'" : ''}/></td>
                </tr>
                <tr>
                    <td colspan="2" class="submit"><input type='submit' value='Login'/></td>
                </tr>
            </table>
        </form>
        <p class="forgot"><g:link action="forgotPassword">Forgot your password?</g:link></p>
    </div>
    <script type='text/javascript'>

        (function() {
            document.forms['loginForm'].elements['j_username'].focus();
        })();
        function formSubmit() {
            var e = document.getElementById("username");
            e.value = e.value.toLowerCase();
            return true;
        }
    </script>
</body>

更新1:

好的,当我调试时,这是我在stacktrace中看到的。无法理解我使用的是在注册用户时使用的相同密码。

2011-07-31 10:09:55,463 [http-8090-1] DEBUG dao.DaoAuthenticationProvider  - Authentication failed: password does not match stored value 
2011-07-31 10:09:55,463 [http-8090-1] DEBUG rememberme.TokenBasedRememberMeServices  - Interactive login attempt was unsuccessful. 
2011-07-31 10:09:55,463 [http-8090-1] DEBUG rememberme.TokenBasedRememberMeServices  - Cancelling cookie 
2011-07-31 10:09:55,504 [http-8090-1] DEBUG web.DefaultRedirectStrategy  - Redirecting to '/wr/login/authfail?login_error=1' 
2011-07-31 10:09:55,504 [http-8090-1] DEBUG context.SecurityContextPersistenceFilter  - SecurityContextHolder now cleared, as request processing completed 
2011-07-31 10:09:55,537 [http-8090-1] DEBUG web.FilterChainProxy  - Converted URL to lowercase, from: '/login/authfail'; to: '/login/authfail' 
2011-07-31 10:09:55,537 [http-8090-1] DEBUG web.FilterChainProxy  - Candidate is: '/login/authfail'; pattern is /**; matched=true 

2 个答案:

答案 0 :(得分:7)

很难说,可能有几个原因。首先要尝试的是加速记录 - 添加

debug 'org.springframework.security'

Config.groovy中的Log4j配置,您可能会在输出中看到一条有用的错误消息。

答案 1 :(得分:2)

我发现了我的错误,我希望我知道如何在log4j中使用这些调试。它是如此微不足道,但花费了我很多时间和精力。

问题是我使用springSecurityService.encrypt(密码)加密了密码,但没有在我创建的User对象中设置密码,因此密码比较不匹配并失败。