0

我目前正在研究 Grails 中的解决方案,并且我已经安装了以下安全插件:

  • Spring 安全核心
  • 弹簧安全用户界面

我基本上会有一个具有以下安全结构的解决方案:

  • 超级用户
  • 管理员(针对不同的业务领域)
  • 用户(不同业务领域内)

所以基本上我安装了 Spring Security UI 是为了让各个 Business Area Admins 管理他们自己的区域,他们应该能够使用 UI 以便让他们只搜索自己区域中的用户,在他们自己的区域中创建用户区域和编辑用户只在他们自己的区域。然而,spring security UI 让有权访问一揽子访问权限的人可以做任何事情。

我在 spring 安全域模型中添加了一个额外的字段,即“区域”,所以我在想当管理员搜索用户时,他们只会看到与他们在同一区域中的用户,当他们创建一个用户时,他们只能这样做所以对于他们自己的区域,他们只能编辑自己区域的用户。

下面是 Spring Security UI 用于搜索用户的一些代码,我可以修改它以便只返回与当前登录的管理员位于同一区域的用户吗?或者,还有更好的方法?

def userSearch = {

    boolean useOffset = params.containsKey('offset')
    setIfMissing 'max', 10, 100
    setIfMissing 'offset', 0

    def hql = new StringBuilder('FROM ').append(lookupUserClassName()).append(' u WHERE 1=1 ')
    def queryParams = [:]

    def userLookup = SpringSecurityUtils.securityConfig.userLookup
    String usernameFieldName = userLookup.usernamePropertyName

    for (name in [username: usernameFieldName]) {
        if (params[name.key]) {
            hql.append " AND LOWER(u.${name.value}) LIKE :${name.key}"
            queryParams[name.key] = params[name.key].toLowerCase() + '%'
        }
    }

    String enabledPropertyName = userLookup.enabledPropertyName
    String accountExpiredPropertyName = userLookup.accountExpiredPropertyName
    String accountLockedPropertyName = userLookup.accountLockedPropertyName
    String passwordExpiredPropertyName = userLookup.passwordExpiredPropertyName

    for (name in [enabled: enabledPropertyName,
                  accountExpired: accountExpiredPropertyName,
                  accountLocked: accountLockedPropertyName,
                  passwordExpired: passwordExpiredPropertyName]) {
        Integer value = params.int(name.key)
        if (value) {
            hql.append " AND u.${name.value}=:${name.key}"
            queryParams[name.key] = value == 1
        }
    }

    int totalCount = lookupUserClass().executeQuery("SELECT COUNT(DISTINCT u) $hql", queryParams)[0]

    Integer max = params.int('max')
    Integer offset = params.int('offset')

    String orderBy = ''
    if (params.sort) {
        orderBy = " ORDER BY u.$params.sort ${params.order ?: 'ASC'}"
    }

    def results = lookupUserClass().executeQuery(
            "SELECT DISTINCT u $hql $orderBy",
            queryParams, [max: max, offset: offset])
    def model = [results: results, totalCount: totalCount, searched: true]

    // add query params to model for paging
    for (name in ['username', 'enabled', 'accountExpired', 'accountLocked',
                  'passwordExpired', 'sort', 'order']) {
        model[name] = params[name]
    }

    render view: 'search', model: model
}

编辑....

我相信这可能与下面的代码有关:

def results = lookupUserClass().executeQuery(
            "SELECT DISTINCT u $hql $orderBy",
            queryParams, [max: max, offset: offset])

我想我只需要更改此语句,以便它查找当前登录的用户“区域”与用户相同的区域的用户列表。谁能帮我解决这个问题??

编辑 2……

我现在已经对此进行了研究,并且已经能够获取用户区域,现在我需要做的就是修改对数据库的查询,以查找与管理员搜索具有相同区域的用户。我试过以下没有运气,有人可以帮我解决这个问题,因为我知道这一定很简单,只是似乎无法到达那里:-S

        def user = springSecurityService.currentUser
        def userArea = user.area

        def hql = new StringBuilder('FROM ').append(lookupUserClassName()).append(' u WHERE 1=1 AND u.area = userArea')

编辑 3.......

非常感谢我的问题解决了一半,现在只是 Ajax 部分:

我尝试了以下代码,以修改对 Ajax 函数的搜索,使其仅返回用户区域与当前登录用户相同的结果:

String username = params.term
            String usernameFieldName = SpringSecurityUtils.securityConfig.userLookup.usernamePropertyName
            def user = springSecurityService.currentUser

            setIfMissing 'max', 10, 100

            def results = lookupUserClass().executeQuery(
                    "SELECT DISTINCT u.$usernameFieldName " +
                    "FROM ${lookupUserClassName()} u " +
                    "WHERE LOWER(u.$usernameFieldName) LIKE :name AND LOWER(u.area) = :area " +
                    "ORDER BY u.$usernameFieldName",
                    [name: "${username.toLowerCase()}%"],
                    [area: "user.area"],
                    [max: params.max])

还尝试更改参数如下:

[area: user.area]
4

1 回答 1

1

控制器正在构建 HQL 查询,因此您不能只说“ WHERE u.area = userArea”,您需要使用命名参数并将值放入queryParams映射中

    def user = springSecurityService.currentUser

    def hql = new StringBuilder('FROM ').append(lookupUserClassName()).append(
        ' u WHERE u.area = :userArea ')
    def queryParams = [userArea:user.area]

对于问题的第二部分(Ajax 位),我怀疑您是否需要LOWER转换,并且您还需要将所有查询参数放入一个地图中(第二个地图参数仅用于分页设置):

def results = lookupUserClass().executeQuery(
   "SELECT DISTINCT u.$usernameFieldName " +
   "FROM ${lookupUserClassName()} u " +
   "WHERE LOWER(u.$usernameFieldName) LIKE :name AND u.area = :area " +
   "ORDER BY u.$usernameFieldName",
   [name: "${username.toLowerCase()}%", area:user.area],
   [max: params.max])

如果您确实希望area检查不区分大小写,请将其保留为,LOWER(u.area) = :area但您还需要将要测试的值转换为小写:

   [name: "${username.toLowerCase()}%", area:user.area.toLowerCase()],
于 2012-09-28T11:27:00.820 回答