Shiro在启用数据库会话时爆炸

时间:2012-12-03 13:48:43

标签: grails shiro

我正在尝试使用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"

如果我能提供更多信息并提前致谢,请告诉我

更新: 以下是在auth控制器中触发它的代码:

  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()
            }
        }
    }
}

1 个答案:

答案 0 :(得分:1)

HM。刚看了一下数据库会话插件的来源。我无法将您的例外情况与来源相匹配。您使用的是哪个版本的插件?

对我来说,看起来数据库会话插件错过了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并进入grails-database-session目录。执行grails package-plugin。如果它抱怨错误的grails版本,请切换到正确的版本或再次执行grails upgradegrails package-plugin

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

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