2

我正在尝试使用 shiro 插件保护 grails 应用程序。我有一个简单的身份验证系统,可以在简单app-run的开发模式下正常工作。但是,一旦我在生产模式下运行应用程序 ( grails prod run-app --stacktrace) 任何登录或注册尝试都会引发以下错误并拒绝运行:

| Error 2012-12-03 05:35:15,081 [http-bio-8080-exec-9] ERROR databasesession.GormPersisterService  - [Assertion failed] - this String argument must have length; it must not be null or empty
Message: [Assertion failed] - this String argument must have length; it must not be null or empty
   Line | Method
->>  45 | deleteBySessionId in grails.plugin.databasesession.PersistentSessionAttributeValue
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
|   111 | invalidate        in grails.plugin.databasesession.GormPersisterService
|    90 | proxySession . .  in grails.plugin.databasesession.SessionProxyFilter
|    42 | getSession        in grails.plugin.databasesession.SessionProxyFilter$1
|   147 | getSession . . .  in org.apache.shiro.web.servlet.ShiroHttpServletRequest
|   188 | getSession        in     ''
|   108 | createSession . . in org.apache.shiro.web.session.mgt.ServletContainerSessionManager
|    64 | start             in     ''
|   121 | start . . . . . . in org.apache.shiro.mgt.SessionsSecurityManager
|   336 | getSession        in org.apache.shiro.subject.support.DelegatingSubject
|   314 | getSession . . .  in     ''
|   182 | mergePrincipals   in org.apache.shiro.mgt.DefaultSubjectDAO
|   163 | saveToSession . . in     ''
|   144 | save              in     ''
|   383 | save . . . . . .  in org.apache.shiro.mgt.DefaultSecurityManager
|   350 | createSubject     in     ''
|   183 | createSubject . . in     ''
|   283 | login             in     ''
|   257 | login . . . . . . in org.apache.shiro.subject.support.DelegatingSubject
|    68 | register          in pfm.SignupController
|   195 | doFilter . . . .  in grails.plugin.cache.web.filter.PageFragmentCachingFilter
|    63 | doFilter          in grails.plugin.cache.web.filter.AbstractFilter
|    55 | doFilter . . . .  in org.apache.shiro.grails.SavedRequestFilter
|   449 | executeChain      in org.apache.shiro.web.servlet.AbstractShiroFilter
|   365 | call . . . . . .  in org.apache.shiro.web.servlet.AbstractShiroFilter$1
|    90 | doCall            in org.apache.shiro.subject.support.SubjectCallable
|    83 | call . . . . . .  in     ''
|   380 | execute           in org.apache.shiro.subject.support.DelegatingSubject
|   362 | doFilterInternal  in org.apache.shiro.web.servlet.AbstractShiroFilter
|   125 | doFilter          in org.apache.shiro.web.servlet.OncePerRequestFilter
|    51 | doFilterInternal  in grails.plugin.databasesession.SessionProxyFilter
|   886 | runTask           in java.util.concurrent.ThreadPoolExecutor$Worker
|   908 | run . . . . . . . in     ''
^   680 | run               in java.lang.Thread

由于数据库会话在开发模式下被禁用并且堆栈跟踪包含databasesession我假设这就是问题所在。我不知道是什么原因造成的,也不知道如何解决。

一些可能有用的规格:

Grails 2.1.1
compile ":shiro:1.1.4"

让我知道我是否可以提供更多信息并提前致谢

更新:这是在身份验证控制器中触发它的代码:

  def signIn = {
        def authToken = new UsernamePasswordToken(params.username, params.password as String)

        // Support for "remember me"
        if (params.rememberMe) {
            authToken.rememberMe = true
        }

        // If a controller redirected to this page, redirect back
        // to it. Otherwise redirect to the root URI.
        def targetUri = params.targetUri ?: "/"

        // Handle requests saved by Shiro filters.
        def savedRequest = WebUtils.getSavedRequest(request)
        if (savedRequest) {
            targetUri = savedRequest.requestURI - request.contextPath
            if (savedRequest.queryString) targetUri = targetUri + '?' + savedRequest.queryString
        }

        try{
            // Perform the actual login. An AuthenticationException
            // will be thrown if the username is unrecognised or the
            // password is incorrect.
            SecurityUtils.subject.login(authToken)

            log.info "Redirecting to '${targetUri}'."
            redirect(uri: targetUri)
        }
        catch (AuthenticationException ex){
            // Authentication failed, so display the appropriate message
            // on the login page.
            log.info "Authentication failure for user '${params.username}'."
            flash.message = message(code: "login.failed")

            // Keep the username and "remember me" setting so that the
            // user doesn't have to enter them again.
            def m = [ username: params.username ]
            if (params.rememberMe) {
                m["rememberMe"] = true
            }

            // Remember the target URI too.
            if (params.targetUri) {
                m["targetUri"] = params.targetUri
            }

            // Now redirect back to the login page.
            redirect(action: "login", params: m)
        }
    }

相关的域类:

class User {
    String username
    String passwordHash
    byte[] passwordSalt
    Manager manager

    static hasMany = [ roles: Role, permissions: String ]

    static constraints = {
        username(nullable: false, blank: false, unique: true)
        manager(nullable: true)
    }
}

最后是安全过滤器:

class SecurityFilters {

    def publicActions = [
        signup: ['index','register'],
        auth:['*','*']
    ]

    private boolean findAction(controllerName, actionName){
        def c = publicActions[controllerName]
        return(c)?c.find{(it==actionName||it=='*')}!=null:false
    }

    def filters = {

        all(uri: "/**"){
            before = {
                //Check for public controller/actions
                def isPublic=findAction(controllerName,actionName)

                if(isPublic) return true

                // Ignore direct views (e.g. the default main index page).
                if (!controllerName) return true

                accessControl()
            }
        }
    }
}
4

1 回答 1

1

嗯。刚刚看了一下数据库会话插件的来源。我无法将您的异常的行号与源匹配。您使用的是哪个版本的插件?

对我来说,看起来数据库会话插件错过了一个 sessionId 并试图用无效的会话 ID 使会话无效。

对我来说,您似乎偶然发现了插件 V1.12 中的一个错误:http: //jira.grails.org/browse/GPDATABASESESSION-1

这似乎已经修复但未在 grails.org 上发布。

要获取最新版本,请从https://github.com/burtbeckwith/grails-database-session/archive/master.zip下载,解压缩并将目录重命名为grails-database-session.

打开一个 shell 并 cd 进入该grails-database-session目录。执行一个grails package-plugin. 如果它抱怨错误的 grails 版本,要么切换到正确的版本,要么再做grails upgrade一次grails package-plugin

现在 cd 到您的项目并执行grails install-plugin /path/to/grails-database-session/grails-database-session-1.2.zip.

至少,这对我有用......

于 2012-12-04T08:46:59.853 回答