首页 文章

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

提问于
浏览
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 回答

  • 0

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

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

  • 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')

  • 0

    我不认为你可以这样做,因为注释在编译时解决,而不是在运行时解决 . 在应用程序运行时将读取配置属性,因此您担心必须最终执行以下操作:

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

    如果我没记错的话, @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 here的更多细节 .

    securityService 内,您现在可以:

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

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

相关问题