2009-01-29 37 views
4

我写Grails中一个小的web应用,并确保所有用户都我用下面的筛选认证从过滤器定义控制器访问的变量:Grails中

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}"   
    } 
} 
0

我认为你可以做到这一点,但它真的值得麻烦?在我看来,你唯一的优势是输入“user”而不是“request.user”。收益不大。无论如何,我认为您可以按照用户指南的“12.7在运行系统中添加动态方法”中的说明进行操作。我认为,如果您创建了一个动态方法“getUser(){return request.user}”,那么Groovy JavaBeans getter/setter访问将允许您以您想要的方式简单引用“user”。

如果您确实添加了动态方法,您可能需要跳过筛选器并在动态方法中完成所有操作。

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

然后使用过滤器重定向如果未通过身份验证,也许拦截器,用于存储本地参考user = authenticationService.loggedInUser。但我也不认为这是最好的方式。我建议你创建一个抽象AuthenticationAwareController作为在SRC/Groovy中所有的控制器基类,并有有像user

class AuthenticationAwareController { 
    def authenticationService 
    def getUser() { return authenticationService.loggedInUser() } 
} 

这样的简便方法,你可以改变你介意存储用户,但是你喜欢,不必更改您的代码。此外,您还可以从Hibernate中的缓存中受益,该缓存在不同会话之间共享已检索的用户对象实例,因此可避免数据库往返。

您仍然应该检查检索到的用户对象的有效性,如果检索不成功,则会抛出AuthenticationException。 (也许像AuthenticationService.getLoggedInUser(failOnError = false)。)

你甚至可以使这个Service/ControllerBase成为一个小插件,在每个应用程序上重复使用或直接使用spring安全插件... ;-)