我正在尝试使用 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()
}
}
}
}