我正在Grails中编写一个小型webapp,并确保所有用户都经过身份验证我正在使用以下过滤器:
class LoginFilters {
static filters = {
loginCheck(controller:'*', action:'*') {
before = {
if (session.user_id) {
request.user = User.get(session.user_id)
} else if (!actionName.equals("login")) {
redirect(controller: "login", action: "login")
return false
}
}
}
}
}
所有控制器方法都从读取请求对象的用户属性开始:
def actionName = {
def user = request.user
...
}
上面的代码可行,但我宁愿避免所有控制器方法中的重复代码。过滤器是否可以将用户对象绑定到名为“user”而不是“request.user”的变量,该变量可以从所有控制器访问?
我知道可能会有一些范围问题使得这个问题变得不可能,但Grails框架似乎能够在幕后制造相当多的魔力,所以我认为它可能值得一试。
答案 0 :(得分:1)
在控制器中使用beforeInterceptor可能会有所帮助:
class LoginController {
def user
def beforeInterceptor = {
user = request.user
}
def index = {
render text:"index: ${user}"
}
def test = {
render text:"test: ${user}"
}
}
答案 1 :(得分:1)
我认为每次将用户对象插入请求对象通常不是一个好主意:
请求的生命周期非常短,因此您最终可能会在每个http请求上进行缓存往返,甚至更糟糕的是访问数据库以检索对象,您可能甚至不需要这些对象,之后会立即将其删除。因此,如果必须,最好将整个对象存储在会话中,而不仅仅是id。
通常,我建议您编写一个AuthenticationService
方法isLoggedIn()
,该方法在用户通过身份验证时返回true,并返回返回此对象的方法getLoggedInUser()
。
class AuthenticationService {
def transactional = false
boolean isLoggedIn() { return session.user_id }
def getLoggedInUser() { return User.get(session.user_id) }
}
然后,如果未经过身份验证,则使用Filter进行重定向,也可以使用Interceptor来存储本地引用user = authenticationService.loggedInUser
。但我也不认为这是最好的方式。我建议你为src / groovy中的所有控制器创建一个抽象的AuthenticationAwareController
作为基类,并且有一些方便的方法,比如user
class AuthenticationAwareController {
def authenticationService
def getUser() { return authenticationService.loggedInUser() }
}
通过这种方式,您可以随后改变您的想法,无论您喜欢如何存储用户,也无需更改代码。您还可以从Hibernate中的Caches中受益,它们在不同的会话之间共享已经检索过的用户对象实例,因此可以避免数据库往返。
您仍应检查检索到的用户对象的有效性,或者在检索失败的情况下抛出AuthenticationException
。 (也许像AuthenticationService.getLoggedInUser(failOnError = false)
。)
你甚至可以将这个Service / ControllerBase作为一个小插件,在每个应用程序上重用,或直接使用spring security插件......; - )
答案 2 :(得分:0)
我认为你可以做到这一点,但这真的值得吗?在我看来,你唯一的优势是键入“user”而不是“request.user”。没有大的收获。无论如何,我认为您可以按照“用户指南”中的“12.7在运行时添加动态方法”中的说明进行操作。我认为如果你创建了一个动态方法“getUser(){return request.user}”,那么Groovy JavaBeans getter / setter访问将允许你以你想要的方式简单地引用“user”。
如果您确实添加了动态方法,则可能需要跳过过滤器并在动态方法中完成所有操作。