将用户保留在Grails的Config.groovy列表中

时间:2013-07-23 19:04:59

标签: grails spring-security config

有没有办法在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 个答案:

答案 0 :(得分:1)

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

我目前正在执行此操作,在我的UserDetailsContextMapper中,我确保User表中已存在用户名。

答案 1 :(得分: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')

答案 2 :(得分:0)

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

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

}

答案 3 :(得分:0)

如果我没记错的话,@Secured注释除了比较角色之外不能用于其他事情。但是你应该能够使用春季证券@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 here的详细信息。

securityService内你现在可以做到:

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

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