Idiomati c способ регистрации пользовательской аутентификации в Spring Security - PullRequest
0 голосов
/ 29 января 2020

Мой пример использования: я использую вход в Oauth2 в Spring Security 5.2, но хотел бы, чтобы класс пользователя моей базы данных был доступен вместе с Oauth2AuthenticationToken в Authentication. Это сделано для того, чтобы мой класс пользователя базы данных кэшировался SecurityContextHolder.

В псевдокоде:

  1. Пользователь входит в систему с помощью Google или Github Oauth2
  2. Мое приложение находит (или создает) пользователя базы данных с возвращенной информацией
  3. Мое приложение сохраняет в SecurityContextHolder специальную оболочку аутентификации, которая оборачивает как Oauth2AuthenticationToken, так и пользовательский класс базы данных
  4. При последующих запросах пользовательский Оболочка аутентификации доступна для методов контроллера

Вот мои попытки обертки:

class MyAuthenticationWrapper implements Authentication {

        public MyAuthenticationWrapper(User user, Authentication underlyingAuth1) {
            this.user = user;
            this.underlyingAuth = underlyingAuth1;
        }

        private final User user;
        private final Authentication underlyingAuth;

        @Override
        public Collection<? extends GrantedAuthority> getAuthorities() {
            return underlyingAuth.getAuthorities();
        }

        @Override
        public void setAuthenticated(boolean isAuthenticated) {
            underlyingAuth.setAuthenticated(isAuthenticated);
        }

        @Override
        public String getName() {
            return underlyingAuth.getName();
        }

        @Override
        public Object getCredentials() {
            return underlyingAuth.getCredentials();
        }

        @Override
        public Object getPrincipal() {
            return underlyingAuth.getPrincipal();
        }

        @Override
        public boolean isAuthenticated() {
            return underlyingAuth.isAuthenticated();
        }

        @Override
        public Object getDetails() {
            return underlyingAuth.getDetails();
        }

    public User getUser() {
        return user;
    }
}

И пользовательский Oauth2AuthenticationFilter:

@Component
class CustomLoginAuthenticationFilter extends OAuth2LoginAuthenticationFilter {

    @Autowired
    private UserDAO userDAO;

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
    Authentication auth = super.attemptAuthentication(request, response);
    if (auth instanceof OAuth2AuthenticationToken) {
        switch (((OAuth2AuthenticationToken) auth).authorizedClientRegistrationId) {
            case "google":
                Optional<User> user = userDAO.findByEmail(username);
                if (!user.isPresent()) {
                    throw new NotFoundException("!");
                }
                return MyAuthenticationWrapper(auth, user.get());
            }
        }
        return auth;
    }
}

У меня нет ' У меня не получилось применить этот подход к работе, и мне интересно, действительно ли это правильный подход.

Существует ли другой, более идиоматический c подход к объединению пользовательских данных базы данных с пользовательскими данными Oauth2 в Весна безопасности?

1 Ответ

2 голосов
/ 29 января 2020

Возможно, изучение OAuth2UserService может помочь. Он вызывается после успешного получения токена OAuth. Вот как это будет работать:

  1. Пользователь входит в систему с помощью Google или Github Oauth2

Не нужно ничего добавлять. Пусть фильтры по умолчанию позаботятся об этом.

Мое приложение находит (или создает) пользователя базы данных с возвращенной информацией

Создайте свой OAuth2UserService в виде компонента (он будет выбран автоматически), который позаботится работы с базой данных:

@Component
public class CustomService implements OAuth2UserService<OAuth2UserRequest, OAuth2User> {

    @Override
    public OAuth2User loadUser(OAuth2UserRequest userRequest)
        throws OAuth2AuthenticationException {
        // ... DB logic goes here
    }
}

В loadUser(...), OAuth2UserRequest дает вам доступ к соответствующим ClientRegistration и OAuth2AccessToken, которые затем можно использовать для запроса или обновления базы данных. .

Мое приложение сохраняет в SecurityContextHolder пользовательскую оболочку аутентификации, которая оборачивает как Oauth2AuthenticationToken, так и пользовательский класс базы данных

Нет необходимости иметь дело с оболочкой! Пользовательский OAuth2User, который вы строите из информации из базы данных, будет Principal в OAuth2LoginAuthenticationToken, который в итоге будет Authentication, поэтому он будет доступен для вашего приложения. Поскольку вы не имеете дело с Authentication самостоятельно, вам не придется беспокоиться о сохранении его в SecurityContextHolder.

При последующих запросах пользовательская оболочка аутентификации доступна для методов контроллера

Ваш Authentication будет иметь тип OAuth2LoginAuthenticationToken. Вы можете получить свой пользовательский OAuth2User, например:

OAuth2LoginAuthenticationToken auth = //...
OAuth2User user = auth.getPrincipal();

Для получения дополнительной информации об основных классах, с которыми вы имеете дело, они могут быть полезны:

Для готовых реализаций OAuth2UserService проверьте:

...