【问题标题】:How to store/load username in Grails app?如何在 Grails 应用程序中存储/加载用户名?
【发布时间】:2014-08-17 11:17:08
【问题描述】:

我有一个 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 登录,他们将在 UI 中看到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}.。那里的问题是我无法从MyAppRealm.groovy 内部访问session,而且它不容易注入(除非有人能想到如何注入)。所以我问:我怎样才能在MyAppRealm中“记录”principal.name,然后从GSP中指定正确的用户名?

【问题讨论】:

    标签: session grails shiro


    【解决方案1】:

    我觉得最简单的就是用一个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 上,下一个标签是我唯一需要显示名字的东西:

    <prf:username />
    

    希望对你有帮助

    【讨论】:

    • 可以直接使用spring-security-core标签库&lt;sec:loggedInUserInfo field="username"/&gt;访问用户名
    • 没错,但在我的项目中,我必须显示名字,而不是用户名。
    【解决方案2】:

    我在我的 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
    }
    

    希望对你有帮助:)

    【讨论】:

      【解决方案3】:

      上面已经发布了答案,但是您几乎可以访问您领域内的会话。这是您无权访问文件中某处的会话的情况。

      // Import this package.
      import org.springframework.web.context.request.RequestContextHolder
      
      // And then get the current session
      def session = RequestContextHolder.currentRequestAttributes().getSession()
      

      【讨论】:

        猜你喜欢
        • 2011-10-21
        • 2015-05-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-31
        • 1970-01-01
        • 2013-06-07
        相关资源
        最近更新 更多