0

有没有办法在 Config.groovy 的列表中定义可以使用我的应用程序的用户?这将使用 Grails 2.2.3 和最新版本的 Spring Security Core 和 Spring Security LDAP。

我们使用 Active Directory 进行身份验证,只有 2 或 3 个人会使用这个小应用程序,所以似乎不值得为这个应用程序创建一个 AD 组。定义一个列表会更简单,只要有新员工而不是将他们添加到 AD 组,我所要做的就是将他们的名字添加到外部 Grails 配置中。

我想做类似以下的事情:

SomeController.groovy

@Secured("authentication.name in grailsApplication.config.my.app.usersList")
class SomeController {

}

然后在 Config.groovy 中放入以下代码:

my.app.usersList = ['Bill', 'Tom', 'Rick']

这可能吗?如果是这样,这是一个可怕的想法吗?非常感谢。

4

4 回答 4

1

这看起来真的很傻。为什么不在表中包含用户列表?然后,您可以在该表中添加/删除,而无需修改应用程序。

我目前正在这样做,并且在我UserDetailsContextMapper确保用户名已经存在于Users 表中。

于 2013-07-23T20:45:12.320 回答
1

您需要一个自定义身份验证器,该身份验证器将尝试访问您的 Active Directory,如果通过身份验证,将查看 Grails 属性以检查用户名是否允许登录。

这是我使用的类。我更改了代码以验证配置:

class ActiveDirectoryAuthenticator {

  private DefaultSpringSecurityContextSource contextFactory
  private String principalSuffix = ""

  def grailsApplication

  public DirContextOperations authenticate(Authentication authentication) {

    // Grab the username and password out of the authentication object.
    String principal = authentication.getName() + "@" + principalSuffix
    String password = ""
    if (authentication.getCredentials() != null) {
      password = authentication.getCredentials().toString()
    }

    // If we have a valid username and password, try to authenticate.
    if (!("".equals(principal.trim())) && !("".equals(password.trim()))) {

      try {

        String provider  = contextFactory.getUrls()[0]

        Hashtable authEnv = new Hashtable(11)
        authEnv.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory")
        authEnv.put(Context.PROVIDER_URL, provider)
        authEnv.put(Context.SECURITY_AUTHENTICATION, "simple")
        authEnv.put(Context.SECURITY_PRINCIPAL, principal)
        authEnv.put(Context.SECURITY_CREDENTIALS, password)
        javax.naming.directory.DirContext authContext = new InitialDirContext(authEnv)


        //here validate the user against your config.
        if(!authentication.getName() in grailsApplication.config.adUsersAllowed) {
          throw new BadCredentialsException("User not allowed.")
        }

        DirContextOperations authAdapter = new DirContextAdapter()
        authAdapter.addAttributeValue("ldapContext", authContext)
        return authAdapter

      } catch ( NamingException ex ) {
        throw new BadCredentialsException(ex.message)
      }

    } else {
      throw new BadCredentialsException("Incorrect username or password")
    }
  }

  public DefaultSpringSecurityContextSource getContextFactory() {
    return contextFactory
  }

  /**
   * Set the context factory to use for generating a new LDAP context.
   *
   * @param contextFactory
   */
  public void setContextFactory(DefaultSpringSecurityContextSource contextFactory) {
    this.contextFactory = contextFactory
  }

  public String getPrincipalSuffix() {
    return principalSuffix
  }

  /**
   * Set the string to be prepended to all principal names prior to attempting authentication
   * against the LDAP server.  (For example, if the Active Directory wants the domain-name-plus
   * backslash prepended, use this.)
   *
   * @param principalPrefix
   */
  public void setPrincipalSuffix(String principalSuffix) {
    if (principalSuffix != null) {
      this.principalSuffix = principalSuffix
    } else {
      this.principalSuffix = ""
    }
  }

}

在 resources.groovy 中将其声明为您的 ldapAuthenticator:

ldapAuthenticator(ActiveDirectoryAuthenticator) {
  contextFactory = ref('contextSource')
  principalSuffix = 'domain.local' //your domain suffix
  grailsApplication = ref('grailsApplication')
}

缺点是更改 config.groovy 时需要重新启动上下文

在您的控制器中,只需使用@Secured('IS_AUTHENTICATED_FULLY')

于 2013-07-23T22:13:32.733 回答
0

我认为您不能这样做,因为注释是在编译时解决的,而不是在运行时解决的。配置属性将在应用程序运行时读取,所以我担心你最终必须这样做:

@Secured(["authentication.name in ['Bill', 'Tom', 'Rick']"])
class SomeController {

}
于 2013-07-23T19:53:50.877 回答
0

如果我没记错的话,@Secured除了比较角色之外,注释不能用于其他用途。但是您应该能够使用 spring 证券@PreAuthorize@PostAuthorize注释来做到这一点。使用 grails 时,设置这些注释的最简单方法是安装 spring security ACL 插件。在内部@PreAuthorize@PostAuthorize您可以使用更灵活的 SPEL 表达式。不幸的是,SPEL 不提供in操作员。但是,您可以将安全检查委托给服务:

@PreAuthorize('@securityService.canAccess(authentication)')
public void test() {
    println "test?"
}

使用该@符号,您可以在表达式中引用其他 bean,例如服务。这里securityService.canAccess()调用该方法来评估登录用户是否可以访问该方法。要使用它,您必须配置一个BeanResolver. BeanResolver 我在这里写了一些关于配置 a 的更多细节。

securityService你现在可以在里面做:

class SecurityService {
    def grailsApplication
    public boolean canAccess(Authentication auth) {
        return grailsApplication.config.myList.contains(auth.name)
    }    
}

一般来说,我不建议在安全检查中使用配置值来验证用户。groovy 配置将被编译,因此您无法在不重新部署应用程序的情况下轻松添加新用户。

于 2013-07-23T20:03:10.447 回答