我正在尝试使用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()
}
}
}
}
答案 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 upgrade
和grails package-plugin
。
现在转到您的项目并执行grails install-plugin /path/to/grails-database-session/grails-database-session-1.2.zip
。
至少,这对我有用......