如何在Grails应用程序中存储/加载用户名?

时间:2014-06-26 14:33:44

标签: session grails shiro

我有一个Grails(2.3.6)应用程序,要求用户在访问应用程序之前登录。一旦他们成功登录,他们就会被重定向到一个在右上角显示其用户名的登录页面。我通过以下3段代码很好地工作(或者我认为):

// myapp/grails-app/realms/myapp/MyAppRealm.groovy:
class MyAppRealm {
    def onSuccessfulLogin(Principal principal) {
        // Lots of code

        // If I logged in successfully with a username of "user1", then principal.name will be "user1" here.
        UserHolder.name = principal.name

        // Lots more code
    }
}

在上面的代码中,如果身份验证层确定他们已成功登录,则会执行onSuccessfulLogin()方法。 principal.name值是他们登录的经过身份验证的用户名。如您所见,我将此值存储在UserHolder POGO中,如下所示:

class UserHolder {
    static String name = null

    static String getName() {
        name
    }

    static void setName(String n) {
        name = n
    }
}

然后,在我的GSP文件中:

// myapp/grails-app/views/page.gsp
You are logged in as ${UserHolder?.name}.

我刚刚向我报告说,测试人员成功登录,几分钟后,他们点击了F5并刷新了他们的屏幕,却发现他们的用户名属于另一个测试人员!查看代码后,原因很明显:UserHolder.name是一个静态变量;在任何给定的时间点,它只有1个实例存在于服务器上。因此,如果user1登录,他们会在用户界面中看到user1作为用户名。但是,如果user2然后登录,User.name现在等于user2,如果user1刷新他们的屏幕,他们会看到user2作为他们的用户名。

所以我的下一个想法是尝试将principal.name存储在像session.name = principal.name这样的会话变量中:

// myapp/grails-app/realms/myapp/MyAppRealm.groovy:
class MyAppRealm {
    def onSuccessfulLogin(Principal principal) {
        // Lots of code

        // If I logged in successfully with a username of "user1", then principal.name will be "user1" here.
        session.name = principal.name

        // Lots more code
    }
}

...然后在GSP中引用它You are logged in as ${session.name}.。问题在于我无法从session内部访问MyAppRealm.groovy,而且不容易注射(除非有人能想到如何)。所以我问:我怎样才能记录" principal.name结束MyAppRealm,然后在GSP内指定正确的用户名?

3 个答案:

答案 0 :(得分:1)

我的Groovy和Grails应用程序中有类似的要求。对您的解决方案并不是真正直接的答案,但您可以尝试类似的东西。这就是我所做的:

class UserController {

def register() {
    if(request.method == 'POST') {
        def u = new User()
        u.properties[
                    'login',
                    'password',
                    'firstName',
                    'lastName',
                    ] = params

         if(u.save()) {
            session.user = u
            session.setMaxInactiveInterval(-1)
            redirect(controller: "myController", action: "welcome")
                }
}

在我看来,我用它如下:

Welcome ${session?.user?.firstName}

我的用户域类如下:

class User {
    String login
    String password
    String firstName
    String lastName
}

希望有所帮助:)

答案 1 :(得分:0)

我认为最简单的是使用TagLib。这是documentation

下面,您将找到一个使用Spring Security Core的小例子:

class ProfileTagLib {

    def springSecurityService
    static namespace = "prf"
    static defaultEncodeAs = 'none'

    def username = { attrs, body ->

    def loggedInUser = springSecurityService.currentUser
    if(loggedInUser) {
        loggedInUser.attach()
        out << loggedInUser.firstName
    }
}

在我的gsp上,下一个标签是我唯一需要显示firstName:

<prf:username />

希望这有帮助

答案 2 :(得分:0)

上面已经发布了答案,但您可以在您的领域内访问会话。在这种情况下,您无法访问文件中某个位置的会话。

// Import this package.
import org.springframework.web.context.request.RequestContextHolder

// And then get the current session
def session = RequestContextHolder.currentRequestAttributes().getSession()