войти автоматически с Grails Spring Security - PullRequest
14 голосов
/ 19 августа 2011

Приложение 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

возвращает "Person", который не является именем моего пользовательского класса. Различные теги, такие как <sec:loggedInUser>, также не работают, предположительно по той же причине.

Интересно, связана ли эта проблема с тем, что я использую существующие классы доменов для пользователя и роли (а не классы, созданные плагином)? Если пользователь входит в систему, вводя свое имя пользователя и пароль в форму (а не программно), кажется, что все работает нормально.

Обновление

Следуя Совету Берта , я заменил код выше:

springSecurityService.reauthenticate(email)

Но я все еще получаю сообщение об ошибке в этих строках в SpringSecurityService.getCurrentUser()

String className = SpringSecurityUtils.securityConfig.userLookup.userDomainClassName
grailsApplication.getClassForName(className).get(principal.id)

Потому что className имеет значение «Персона», а не имя моего класса пользователя.

Ответы [ 3 ]

18 голосов
/ 19 августа 2011

Если пользователь существует в базе данных, используйте springSecurityService.reauthenticate() - см. эту ссылку для Grails 2 или эту ссылку для Grails 3.

Этот метод предназначенобновить аутентификацию, когда изменение пользователя сделало его не синхронизированным с базой данных, но это также полезно для этого сценария, когда вы хотите принудительно установить действительную аутентификацию для существующего пользователя, но не знаете пароль.

1 голос
/ 25 октября 2013

Метод reauthenticate() имеет два ограничения:

  • Пароль не проверяется
  • Это не вызывает события. Вот почему многие плагины, которые прослушивают события, могут не работать. Например плагин для грубой силы.
1 голос
/ 19 августа 2011

Может быть, этот фрагмент кода из написанного мною веб-приложения поможет. Мы должны были авторизовать пользователей, используя 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)
      }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...