Войти автоматически с помощью Grails Spring Безопасность
Приложение My 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
возвращает "Лицо", которое не является именем моего пользовательского класса. Различные теги, такие как <sec:loggedInUser>
, также не работают, по-видимому, по той же причине.
Интересно, связана ли эта проблема с тем, что я использую ранее существовавшие классы домена для пользователя и роли (а не классы, созданные плагином )? Если пользователь входит в систему, введя свое имя пользователя и пароль в форму (а не программно), все работает нормально.
Update
Следуя советам Burt, я заменил код выше:
springSecurityService.reauthenticate(email)
Но я все еще получаю ошибку на этих строках в пределах SpringSecurityService.getCurrentUser()
String className = SpringSecurityUtils.securityConfig.userLookup.userDomainClassName
grailsApplication.getClassForName(className).get(principal.id)
Потому что className
установлен на "Person", а не на имя моего класса User.
Ответы
Ответ 1
Если пользователь существует в базе данных, используйте springSecurityService.reauthenticate()
- см. Эту ссылку для Grails 2 или эту ссылку для Grails 3.
Этот метод предназначен для обновления аутентификации, когда изменение пользователя сделало его не синхронизированным с базой данных, но он также полезен для этого сценария, когда вы хотите принудительно установить действительную аутентификацию для существующего пользователя, но не знаете пароль.
Ответ 2
Возможно, этот снимок кода из 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)
}
Ответ 3
Метод reauthenticate()
имеет два ограничения:
- Не проверять пароль
- Это не вызывает события. Вот почему многие плагины, которые прослушивают события, могут не работать. Например плагин для грубой силы.