Spring Security Oauth2 - InsufficientAuthenticationException:需要身份验证才能获取访问令牌(匿名不允许)

时间:2016-12-29 13:28:11

标签: spring spring-security oauth oauth-2.0 spring-security-oauth2

我试图理解为什么客户端中的匿名用户无法获取访问令牌。

我在这个主题上找到了这个post on the Spring Blog,Dave Syer回答了这个问题:

  

请记住这是与客户端应用程序有关的问题,而不是auth   服务器,所以尝试从cllient的角度来看它。在   步骤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。

包含accessToken的OAuth2ClientContext是一个会话作用域的Spring bean。由于匿名用户有一个HttpSession,他们有独立的OAuth2ClientContext,所以他们可以存储单独的accessTokens。

有人可以解释这是否有意义或我不理解?

1 个答案:

答案 0 :(得分:1)

我认为这并不是真正受约束的会议。戴夫可能意味着你可以在spring语境中只拥有一个匿名用户。对我来说,为什么这个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来获取令牌(因此第一步是询问代码,只有在授权用户后才会提供 - 用户可能会重定向到让步)。第二步是通过提供token来获取codecode在db中具有有限的授权,因此spring知道谁是新令牌的所有者:

\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范围sessionrequest将无法帮助您。