有没有办法在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']
这可能吗?如果是这样,这是一个可怕的想法吗?非常感谢。
答案 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配置,因此您无法在不重新部署应用程序的情况下轻松添加新用户。