1

Я пытаюсь понять, почему анонимные пользователи в клиенте не могут получить токен доступа.Spring Security Oauth2 - InsufficientAuthenticationException: для получения токена доступа требуется анонимность (анонимно не разрешено)

Я нашел post on the Spring Blog по этой теме, где Дэйв Syer отвечает так:

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

Однако я не понимаю, почему анонимные пользователи будут один и той же фишка:

Authentication auth = SecurityContextHolder.getContext().getAuthentication(); 

    if (auth instanceof AnonymousAuthenticationToken) { 
     if (!resource.isClientOnly()) { 
      throw new InsufficientAuthenticationException(
        "Authentication is required to obtain an access token (anonymous not allowed)"); 
     } 
    } 

Хотя они не полностью идентифицированы, они имеют JSESSIONID связаны с каждым отдельным анонимным пользователем.

OAuth2ClientContext, который будет содержать accessToken, представляет собой сессионный компонент Spring bean. Поскольку у анонимных пользователей есть HttpSession, у них есть независимые OAuth2ClientContext, так что они могут хранить отдельные accessTokens.

Может ли кто-нибудь объяснить, если это имеет смысл или что я не понимаю?

ответ

0

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

Посмотрите на код метода getAccessToken в JdbcClientTokenServices классе

public OAuth2AccessToken getAccessToken(OAuth2ProtectedResourceDetails resource, Authentication authentication) { 

    OAuth2AccessToken accessToken = null; 

    try { 
     accessToken = jdbcTemplate.queryForObject(selectAccessTokenSql, new RowMapper<OAuth2AccessToken>() { 
      public OAuth2AccessToken mapRow(ResultSet rs, int rowNum) throws SQLException { 
       return SerializationUtils.deserialize(rs.getBytes(2)); 
      } 
     }, keyGenerator.extractKey(resource, authentication)); 
    } 
    catch (EmptyResultDataAccessException e) { 
     if (LOG.isInfoEnabled()) { 
      LOG.debug("Failed to find access token for authentication " + authentication); 
     } 
    } 

    return accessToken; 
} 

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

В authorization_code поток oauth2 вам нужен code, чтобы получить токен (так что 1-й шаг - запросить код, который будет указан только после того, как авторизация пользователя-пользователя может быть перенаправлена, чтобы можно было сказать facebook на этом этапе). Второй этап - выбор token, давая code. code имеет ограниченное разрешение в дБ, поэтому весной знает, кто является владельцем новых маркеров:

\d+ oauth_code; 
                Table "mydb.oauth_code" 
    Column  |   Type   |      Modifiers      | Storage | Stats target | Description 
----------------+------------------------+--------------------------------- ------------------------+----------+--------------+------------- 
id    | integer    | not null default  nextval('oauth_code_id_seq'::regclass) | plain |    | 
authentication | bytea     |               | extended |    | 
code   | character varying(255) |               | extended |    | 

Таким образом, чтобы подвести итог, имея OAuth2ClientContext с областью session или request не поможет вам, если вы собираетесь заполнить его то же самое.

+0

Благодарим вас за то, что нашли время, чтобы прояснить это. Вы абсолютно правы, с того момента, как мы настраиваем 'JdbcClientTokenServices' для сохранения токенов, поскольку запрос' selectAccessTokenSql' использует 'Authentication.getName()' (который был бы анонимнымUser), все пользователи будут делиться токеном. Однако, пока мы не сохраняем токены, проблем не будет, я дважды проверил, что «OAuth2ClientContext» является областью сеанса, и каждый клиент сохраняет свой собственный доступ к Token в HttpSession.Запрос мог быть реализован для использования session.id вместо 'Authorization.getName()' ... – codependent

+0

, может быть, это к раннему. Я не помню, что серверы oauth2 auth без слоя сохранения сохраняются. Без сохранения токена, как бы вы проверили, что токен, отправленный с клиента, действителен? Как бы вы сравнили это с чем-нибудь? Как бы вы отменили его/обновили? Может быть, вам нужен токен JWT, а не oauth2 bearer :) – freakman

+0

Возможно, я не объяснил это хорошо ... конечно, нам нужен сервер для хранения токенов, я имел в виду постоянство токена клиента, которое выполняется через 'JdbcClientTokenServices', и это необязательно. – codependent

Смежные вопросы