如何在 GSP 中使用 Spring Security Grails 插件获取 current_user

Posted

技术标签:

【中文标题】如何在 GSP 中使用 Spring Security Grails 插件获取 current_user【英文标题】:How to get current_user by using Spring Security Grails plugin in GSP 【发布时间】:2013-07-05 18:30:58 【问题描述】:

我是 Grails 的新手。我使用Spring Security Grails plugin 进行身份验证。我想在我的视图 gsp 文件中获取当前用户。

我正在尝试这样......

<g:if test="$post.author == Person.get(springSecurityService.principal.id).id ">
      <g:link controller="post" action="edit" id="$post.id">
            Edit this post
      </g:link>
</g:if>

在这里,我想仅显示 编辑此帖子 链接到由已登录用户创建的帖子。但它显示错误 -

Error 500: Internal Server Error

 URI
    /groovypublish/post/list
 Class
   java.lang.NullPointerException
 Message
   Cannot get property 'principal' on null object

这是我的 Post.groovy --

class Post 

static hasMany = [comments:Comment]

String title
String teaser
String content
Date lastUpdated
Boolean published = false
SortedSet comments
Person author

....... more code ....

这是我的 Person.groovy 域类文件 --

class Person 

transient springSecurityService

String realName
String username
String password
boolean enabled
boolean accountExpired
boolean accountLocked
boolean passwordExpired
byte[] avatar
String avatarType

static hasMany = [followed:Person, posts:Post]
static searchable = [only: 'realName']
    ........ more code ......

请帮忙。

【问题讨论】:

【参考方案1】:

您可以使用Spring Security Taglibs。对于您想要做的事情,检查登录用户是否是帖子的所有者,您可以执行以下操作:

<sec:isLoggedIn>
<g:if test="$post.author.id == sec.loggedInUserInfo(field: 'id')">
      <g:link controller="post" action="edit" id="$post.id">
            Edit this post
      </g:link>
</g:if>
</sec:isLoggedIn>

如果你发现你需要做这个检查很多,我建议把它放到一个自定义的 taglib 中

class AuthTagLib 

  def springSecurityService

  def isOwner =  attrs, body ->
    def loggedInUser = springSecurityService.currentUser
    def owner = attrs?.owner

    if(loggedInUser?.id == owner?.id) 
      out << body()
    
  

那就这样用吧

<g:isOwner owner="$post?.author">
  <g:link controller="post" action="edit" id="$post.id">
    Edit this post
  </g:link>
</g:isOwner>

【讨论】:

在我的例子中,标签是 &lt;sec:ifLoggedIn&gt; 工作。我遵循你的代码。现在Edit this Post 没有显示在任何帖子中 不错的作品。但是知道为什么 sec.username == 'my user' 不起作用。【参考方案2】:

试试 springSecurity 插件提供的标签,比如:

<sec:isLoggedIn>

  <g:link controller="post" action="edit" id="$post.id">
            Edit this post
      </g:link>

</sec:isLoggedIn>

实际上你正试图在你的 GSP 页面上注入服务,你可以在页面上使用一些 import 语句来做到这一点,但我会说这不是一个好的编程习惯,我认为你应该发送当前登录用户的实例从控制器到 GSP 页面,然后对其进行检查:

假设你有控制器方法:

def showPostPage()
Person currentLoggedInUser = springSecurityService.getCurrentUser();
[currentLoggedInUser:currentLoggedInUser]

在您的 GSP 页面上:

<g:if test="$post.author == currentLoggedInUser ">
      <g:link controller="post" action="edit" id="$post.id">
            Edit this post
      </g:link>
</g:if>

【讨论】:

这只告诉你是singed_in还是不是?实际上我正在使用关注功能,用户也可以看到关注者的帖子。现在他不能编辑其他帖子。但现在它显示编辑此帖子按钮。我只想将这个按钮显示给那些由 current_user 创建的人。 我已经根据您的需要编辑了答案,请看一下 在 Grails 2.4.4 中,正确的标签是:&lt;sec:ifLoggedIn&gt;【参考方案3】:

另一种方法是创建一个过滤器并将用户作为过滤器的一部分放在请求范围内,如下所示:

class SetCurrentUserFilters 
    def springSecurityService
    def filters = 
        all(controller: '*', action: '*') 
            before = 
                if (springSecurityService.isLoggedIn())
                    request.setAttribute("current_user", springSecurityService.currentUser);
                
            
            after =  Map model ->

            
            afterView =  Exception e ->

            
        
    

那么您的 GSP 只需要查找 'current_user' 属性,如下所示:

<g:if test="$current_user.property"> ... </g:if>

【讨论】:

【参考方案4】:

看起来现有的标签,它们是 Spring Security 插件的一部分,对你来说还不够,对吗?见documentation

我的建议是向 Person 实体添加一个新方法,它以 Post 作为参数并返回 true/false,如果它可以编辑(反之亦然,向 Post 实体添加新方法,它将 Person 作为论据,这取决于你的决定)。

然后您可以创建自己的标签,利用此方法使您的 GPS 更好,即使这不是强制性步骤。

【讨论】:

以上是关于如何在 GSP 中使用 Spring Security Grails 插件获取 current_user的主要内容,如果未能解决你的问题,请参考以下文章

Grails Spring Security 插件和 GSP 标签不起作用

如何知道用户是不是登录(在 GSP 中)

在 grails gsp 中调用标签不起作用

使用 grails spring security core 插件保护 URL 映射

在脚手架模板中使用 gsp 导入

如何从 gsp 调用 Grails 服务?