我的Grails应用程序正在使用Spring Security插件。我需要以编程方式登录用户,而且我无法访问他们的密码。我尝试了以下,当使用Acegi插件(Spring Security插件的祖先)时,它应该有效:
// automatically login a user and assign them the USER role.
// In my app, the email address is also the username
GrantedAuthority[] auths = [new GrantedAuthorityImpl('USER')]
SecurityContextHolder.context.authentication
= new UsernamePasswordAuthenticationToken(email, 'unknown', auths)
看起来这几乎有效,因为如果我在执行上述操作后调用springSecurityService.principal
,我会找回自动登录用户的电子邮件地址。但是,如果我拨打springSecurityService.currentUser
,我会收到错误消息。此错误的根本原因是:
SpringSecurityUtils.securityConfig.userLookup.userDomainClassName
返回“Person”,它不是我的用户类的名称。诸如<sec:loggedInUser>
之类的各种标签也不起作用,大概是出于同样的原因。
我想知道这个问题是否与我使用pre-existing domain classes for user and role(而不是插件生成的类)的事实有某种关系?如果用户通过在表单中输入用户名和密码(而不是以编程方式)登录,则一切似乎都正常。
关注Burt's advice后,我将上面的代码替换为:
springSecurityService.reauthenticate(email)
但我仍然在SpringSecurityService.getCurrentUser()
String className = SpringSecurityUtils.securityConfig.userLookup.userDomainClassName
grailsApplication.getClassForName(className).get(principal.id)
因为className
设置为“Person”,而不是我的User类的名称。
答案 0 :(得分:18)
如果用户存在于数据库中,请使用springSecurityService.reauthenticate()
- 请参阅Grails 2的this link或Grails 3的this link。
此方法旨在在用户更改使其与数据库不同步时更新身份验证,但对于您希望强制对现有用户进行有效身份验证但不知道的情况,此方法也很有用。密码。
答案 1 :(得分:1)
也许这个代码来自我写的webapp会有所帮助。我们必须使用RESTful API授权用户,并且他们提供了用户名和API密钥。此代码中的关键部分是设置权限和经过身份验证的布尔值。
class CustomAppTokenAuthenticationProvider implements AuthenticationProvider {
def userDetailsService
Authentication authenticate(Authentication customAuth) {
def userDetails = userDetailsService.loadUserByUsername(customAuth.principal)
def user = User.get(userDetails.id)
if (user?.apiKey.equals(customAuth.credentials)) {
customAuth.authorities = userDetails.authorities
customAuth.authenticated = true
return customAuth
} else {
return customAuth
}
}
boolean supports(Class authentication) {
return CustomAppTokenAuthentication.class.isAssignableFrom(authentication)
}
}
以下是来自过滤器的代码,用于拦截API调用以处理身份验证
def userId = request.getHeader("x-user-external-id")
def apiKey = request.getHeader("x-user-api-key")
if (userId && apiKey) {
def user = User.findByExternalId(userId)
def myAuth = new CustomAppTokenAuthentication(
name: userId,
credentials: apiKey,
principal: user.username,
authenticated: false
)
def auth = authenticationManager.authenticate(myAuth);
if (auth?.authorities?.size() >= 0) {
log.info "Successfully Authenticated ${userId} in object ${auth}"
// Store to SecurityContextHolder
SecurityContextHolder.getContext().setAuthentication(myAuth);
} else {
SecurityContextHolder.getContext().setAuthentication(null)
}
答案 2 :(得分:1)
reauthenticate()
方法有两个限制: