Я создаю приложение, используя Spring с Oauth2 в качестве бэкэнда для двух приложений (приложение провайдера и приложение потребителя). У меня есть два разных типа пользователей; Поставщики и потребители, каждый со своей таблицей БД. Проблема, с которой я сталкиваюсь, заключается в том, что я не могу найти способ узнать, исходит ли запрос от поставщика или клиента, поскольку каждый из них будет находиться в отдельной таблице БД.

Имя пользователя не является уникальным для двух таблиц. Таким образом, поставщик и потребитель могут иметь одно и то же имя пользователя (и пароль). Я думаю, что одного из следующих решений будет достаточно, однако я не могу найти способ реализовать любое из них.

  • Наличие двух разных конечных точек для каждого пользовательского класса. например "/ provider / oauth / token" и "/ consumer / oauth / token". У каждого свой менеджер аутентификации.
  • Или: Наличие двух серверов авторизации в одном приложении Spring, а затем сопоставление их «/ oauth / token» с разными конечными точками.
  • Или: отправка пользовательских данных в запросе oauth, чтобы узнать, откуда поступил запрос, а затем динамический выбор диспетчера аутентификации.
  • Или: связывание разных менеджеров аутентификации с разными клиентами OAuth, а затем обеспечение того, чтобы у каждого приложения был соответствующий идентификатор клиента.

Если какое-либо из этих решений возможно, или если есть другой способ сделать это, пожалуйста, дайте мне знать. Любая помощь приветствуется.

Изменить - решение

Следуя ответу ниже, я добавил другого клиента с другим идентификатором клиента, проверил идентификатор в UserDetailsService и затем решил, какой БД использовать. Вот код:

  public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
            UsernamePasswordAuthenticationToken authentication = (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
            User user = (User) authentication.getPrincipal();
            String username = user.getUsername();
            if (username.equals(OAuth2Configuration.provider_app))
                   // Load from provider db
            else if (username.equals(OAuth2Configuration.consumer_app))
                  // Load from consumer db
            else
                throw new UsernameNotFoundException("ClientID " + username + " not found.");
        }
    };
}

UsernamePasswordAuthenticationToken используется, поскольку / oauth / token защищен с помощью Basic Oauth с использованием идентификатора клиента и секрета.

2
Islam Abdalla 5 Апр 2017 в 22:55

2 ответа

Лучший ответ

Я думаю, вы должны заглянуть внутрь SecurityContextHolder.getContext().getAuthentication. Это должен быть экземпляр OAuth2Authentication, из которого вы можете (после того как вы произнесете) вызвать getOAuth2Request (), чтобы получить оригинал Oauth2Request Подробнее.

С этой информацией у вас может быть один UserDetailsService, который может делегировать поиск нужным таблицам БД. Вы можете использовать области или resourceIds, чтобы определить, какую таблицу БД использовать.

1
ninj 5 Апр 2017 в 22:37

Вы можете использовать третий вариант. но это не хороший принцип для подражания. Вы можете отправить пользовательский параметр в конечной точке oauth / token. Доступ к нему можно получить с помощью AutoWiring HttpServletRequest в userDetailsService.

sample postman request

UserDetailsService

@Autowired
private HttpServletRequest httpServletRequest;

@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    try {
        String userType = httpServletRequest.getParameter("user_type");
        LOGGER.info("Load user method \n Username : " + username + "\nuser_type : " + userType);
        if (userType == null) {
            throw new CustomOauthException("User type is required !");
        }
        if (userType.equals(String.valueOf(MOBILE_USER))) {
            //get user..

        } else if (userType.equals(String.valueOf(DRIVER))) {
            //get driver..

        } else if (userType.equals(String.valueOf(ADMIN))) {
            //get admin
        }
        throw new CustomOauthException("User type is not valid !");
    } catch (Exception e) {
        e.printStackTrace();
        LOGGER.error("Exception : " + e.getMessage());
        throw new CustomOauthException(e.getMessage());
    }
}
0
Tharindu Eranga 30 Дек 2019 в 09:23