从 Grails 中的过滤器定义控制器可访问变量
Posted
技术标签:
【中文标题】从 Grails 中的过滤器定义控制器可访问变量【英文标题】:Defining controller accessible variables from filters in Grails 【发布时间】:2010-10-04 09:10:30 【问题描述】:我正在 Grails 中编写一个小型 Web 应用程序,为了确保所有用户都经过身份验证,我使用了以下过滤器:
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 框架似乎能够在幕后创造相当多的魔力,所以我认为这可能值得一问。
【问题讨论】:
【参考方案1】:在控制器中使用 beforeInterceptor 可能会有所帮助:
class LoginController
def user
def beforeInterceptor =
user = request.user
def index =
render text:"index: $user"
def test =
render text:"test: $user"
【讨论】:
【参考方案2】:我认为每次都将用户对象插入到请求对象中通常不是一个好主意:
请求的生命周期非常短,因此您最终可能会在每个 http-request 中往返于缓存,甚至更糟地访问数据库以检索对象,您甚至可能不需要这些对象,并且之后会立即将其删除。因此,如果必须,最好将整个对象存储在会话中,而不仅仅是 id。
一般来说,我建议您编写一个 AuthenticationService
,其中包含在用户通过身份验证时返回 true 的方法 isLoggedIn()
和返回此对象的方法 getLoggedInUser()
。
class AuthenticationService
def transactional = false
boolean isLoggedIn() return session.user_id
def getLoggedInUser() return User.get(session.user_id)
然后,如果未通过身份验证,则使用过滤器进行重定向,并且可能使用拦截器来存储本地引用 user = authenticationService.loggedInUser
。但我也不认为这是最好的方法。我建议您为 src/groovy 中的所有控制器创建一个抽象的 AuthenticationAwareController
作为基类,并且有像 user
这样的便捷方法
class AuthenticationAwareController
def authenticationService
def getUser() return authenticationService.loggedInUser()
这样,您以后可以改变主意,按照自己的喜好存储用户,而不必更改代码。此外,您还受益于 Hibernate 中的缓存,它在不同会话之间共享已检索到的用户对象实例,因此避免了数据库往返。
您仍然应该检查检索到的用户对象的有效性或抛出AuthenticationException
,以防检索不成功。 (可能类似于AuthenticationService.getLoggedInUser(failOnError = false)
。)
您甚至可以将此 Service/ControllerBase 制作为一个小插件,以便在每个应用程序上重复使用,或者直接使用 spring 安全插件... ;-)
【讨论】:
【参考方案3】:我认为你可以做到这一点,但这真的值得吗?在我看来,您唯一的优势是输入“user”而不是“request.user”。收获不大。无论如何,我认为您可以按照用户指南的“12.7 在运行时添加动态方法”中的说明进行操作。我认为如果您创建了一个动态方法“getUser() return request.user”,Groovy JavaBeans getter/setter 访问将允许您以您想要的方式简单地引用“用户”。
如果您确实添加了动态方法,您可能希望跳过过滤器并在动态方法中完成所有操作。
【讨论】:
以上是关于从 Grails 中的过滤器定义控制器可访问变量的主要内容,如果未能解决你的问题,请参考以下文章