Получение «Невозможно вызвать метод loadUserByUsername() для нулевого объекта» в безопасности grails spring rest

Я пытался внедрить Facebook OAuth отсюда: http://alvarosanchez.github.io/grails-spring-security-rest/latest/docs/index.html#_delegating_authentication_to_oauth_providers

Я могу интегрировать OAuth и получить токен доступа от Facebook, но столкнулся с проблемой реализации пользовательского OAuthUserDetailsService. Я создал пользовательский сервис:

FacebookOauthUserDetails.groovy

class FacebookOauthUserDetailsService implements OauthUserDetailsService{

@Delegate
UserDetailsService userDetailsService
UserDetailsChecker preAuthenticationChecks

@Override
OauthUser loadUserByUserProfile(CommonProfile userProfile, Collection<GrantedAuthority> defaultRoles) throws UsernameNotFoundException {
    UserDetails userDetails
    OauthUser oauthUser
    println("adss")
    try {
        println("Trying to fetch user details for user profile: ${userProfile}")
        userDetails = userDetailsService.loadUserByUsername(userProfile.id)
        log.debug("Checking user details with ${preAuthenticationChecks.class.name}")
        preAuthenticationChecks?.check(userDetails)
        Collection<GrantedAuthority> allRoles = userDetails.authorities + defaultRoles
        oauthUser = new OauthUser(userDetails.username, userDetails.password, allRoles, userProfile)
    } catch (UsernameNotFoundException unfe) {
        println("User not found. Creating a new one with default roles: ${defaultRoles}")
        oauthUser = new OauthUser(userProfile.id, 'N/A', defaultRoles, userProfile)
    }

    return oauthUser
}
}

в официальной документации упоминается, что для переопределения поведения по умолчанию необходимо определить его в resources.groovy с именем bean-компонента oauthUserDetailsService. Вот как выглядит мой файл resources.groovy:

resources.groovy:

import hungr.FacebookOauthUserDetailsService
import hungr.UserPasswordEncoderListener

beans =
{
    userPasswordEncoderListener(UserPasswordEncoderListener)
    oauthUserDetailsService(FacebookOauthUserDetailsService)
}

Я попытался сослаться на этот документ здесь о том, как определить bean-компонент: https://docs.grails.org/latest/guide/spring.html, но у меня это тоже не сработало. Что я делаю неправильно?


person Aditya Gurjar    schedule 25.12.2017    source источник
comment
'userDetailsService' может быть неправильно введен/не разрешен, вы используете Grails3?   -  person Nitin Dhomse    schedule 26.12.2017
comment
Да, я использую Grails 3.   -  person Aditya Gurjar    schedule 26.12.2017
comment
Вы нашли нулевую проблему и почему ваш сервис не внедряется?   -  person Nitin Dhomse    schedule 26.12.2017


Ответы (1)


GrailsUserDetailsService — это интерфейс, который в основном находится в пакете org.springframework.security.core.userdetails. Вы можете реализовать метод loadUserByUsername вышеуказанного сервиса (интерфейса) в своем сервисе (классе) и написать код (реализация), чтобы получить нужные данные/детали пользователя, вы можете получить данные пользователя как объект/список/карту в любом формате, который вы хотите, вы можете найти там данные с помощью метода поиска GORM по заданному имени пользователя и вернуть эти данные. Ниже приведен пример примера,

Код услуги:

class Your_service_name implements GrailsUserDetailsService {

      Map loadUserByUsername(String username) throws UsernameNotFoundException {
        Map userDetails = [:]
        User.withTransaction { status ->

        User user = User.findByUsername(username, ["readOnly": true])
        if (!user) throw new UsernameNotFoundException('User not found', username)
        // you can also return the whole user object here instead of map keep method return type as UserDetails  and return user object, you also return the user roles along with other details in Map.
        userDetails["username"] = user.username
        userDetails["emailAddress"] = user.emailAddress
        userDetails["userFullName"] = user.userFullName
        return userDetails
   }
}

Теперь вы можете внедрить вышеуказанную службу в свой контроллер и вызвать метод, как показано ниже:

class YourController{
  Your_service_name myService // injected above created service which contains the loadUserByUsername method implementation

  def getUserDetails(){
    Map userdetails = myService.loadUserByUsername("username_to_find")
    println userdetails
  }
}

Ваш resources.groovy будет следующим:

beans = {
    userDetailsService(Your_service_name)
}

Примечание. Очистите и перезапустите приложение после этого изменения.

person Nitin Dhomse    schedule 26.12.2017
comment
Официальная документация здесь (alvarosanchez.github.io /grails-spring-security-rest/latest/docs/) говорит, что мне нужно реализовать интерфейс OAuthUserDetailsService, чтобы переопределить поведение по умолчанию. Извините, если я веду себя глупо. Я новичок, и мои знания о groovy/grails довольно ограничены. Ограниченные ресурсы, доступные в Интернете, также не помогают моему делу. - person Aditya Gurjar; 26.12.2017
comment
@AdityaGurjar: смотрите, я обновил ответ с примером кода, надеюсь, это поможет вам. - person Nitin Dhomse; 26.12.2017
comment
Я создал пользовательскую службу, реализующую GrailsUserDetailsService. Я все еще сталкиваюсь с той же проблемой. Я чувствую, что делаю что-то неправильно с определением bean-компонента в файле resources.groovy. - person Aditya Gurjar; 26.12.2017
comment
Я предлагаю вам просмотреть пример проекта Grails, доступный на github сообщества Grails, а также найти, как создавать bean-компоненты, надеюсь, что документация и проект github помогут вам. - person Nitin Dhomse; 26.12.2017
comment
Образец проекта для Oauth в grails rest отсутствует. Только документация. - person Aditya Gurjar; 26.12.2017