如何在GSP中使用Spring Security Grails插件获取当前用户

6

我是Grails的新手。我正在使用Spring Security Grails插件进行身份验证。我想在我的视图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 ......

Please help.

4个回答

15
你可以使用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>

如果你发现需要经常进行这种检查,我建议将其放入自定义标签库中。

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>

1
在我的情况下,标签<sec:ifLoggedIn>是有效的。我遵循了你的代码。现在,“编辑此帖子”不会显示在任何帖子中。 - Free-Minded
很好的工作。但是你有什么想法为什么 sec.username == 'my user' 不起作用呢? - Vishnoo Rath

7
尝试使用Spring Security插件提供的标签,类似于以下内容:
<sec:isLoggedIn>

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

</sec:isLoggedIn>

实际上,您正在尝试在GSP页面上注入服务,您可以通过在页面上使用一些导入语句来完成,但我认为这不是良好的编程实践。我认为您应该从控制器向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>

这只是告诉你是否已登录?实际上我正在使用关注功能,用户可以查看关注者的帖子。现在他不能编辑其他帖子。但是现在它显示“编辑此帖子”按钮。我只想向当前用户创建的那些人展示此按钮。 - Free-Minded
我已根据您的需求编辑了答案,请查看。 - Saurabh Dixit
2
在Grails 2.4.4中,正确的标签是:<sec:ifLoggedIn> - MAGx2

0
另一种方法是创建一个过滤器,并将用户作为过滤器的一部分放入请求范围中,就像这样:
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>

0

看起来现有的标签,作为Spring Security插件的一部分,对您来说不够用,是吗?请参见文档

我的建议是向Person实体添加一个新方法,该方法以Post为参数并返回true/false,如果可以编辑它(或者反过来向Post实体添加新方法,该方法以Person为参数,这取决于您的决定)。

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接