实现了Spring OAuth2,从不同的设备获取相同的访问令牌

时间:2015-09-08 14:12:07

标签: spring spring-security spring-security-oauth2

实施Spring OAuth2安全性并在使用相同用户但从不同设备进行日志记录时获取相同的访问令牌。当我从这些设备中的任何一个注销(撤销令牌)时,其他设备也会被注销。这是预期的行为还是我错过了什么?希望共享大量代码不会有太大帮助,所以这个问题简短而简单。

3 个答案:

答案 0 :(得分:3)

  

DefaultTokenServices的默认行为是重用现有令牌(基于现有TokenStore实现的行为)

http://forum.spring.io/forum/spring-projects/security/oauth/121797-multiple-valid-oauth-access-tokens-for-same-client

如果您希望为每台设备分配不同的access_token,请创建自己的AuthenticationKeyGenerator,例如在授权流程中发送您的设备ID,并让您的AuthenticationKeyGenerator流程设备ID为该设备创建access_token

答案 1 :(得分:3)

(请阅读org.springframework.security.oauth2.provider.token.DefaultAuthenticationKeyGenerator代码,将以下解决方案纳入上下文)

DefaultAuthenticationKeyGenerator可在春季推出。我刚刚创建了一个自定义版本,其中包含一个扩展名相同的代码,即从device_id检索请求参数时从客户端发送的OAuth2Authentication,如下所示;

String deviceId = authentication.getOAuth2Request().getRequestParameters().get("device_id")

然后放入values地图(最后用于生成令牌)。因此,device_id成为token的一部分,从而为每个设备生成唯一的令牌。

以下是完整的解决方案,除了上面解释的位之外,主要是DefaultAuthenticationKeyGenerator

public class CustomAuthenticationKeyGenerator implements AuthenticationKeyGenerator
{
    private static final String CLIENT_ID = "client_id";

    private static final String SCOPE = "scope";

    private static final String USERNAME = "username";

    @Override
    public String extractKey(OAuth2Authentication authentication) {
        Map<String, String> values = new LinkedHashMap<String, String>();
        OAuth2Request authorizationRequest = authentication.getOAuth2Request();
        if (!authentication.isClientOnly()) {
            values.put(USERNAME, authentication.getName());
        }
        values.put(CLIENT_ID, authorizationRequest.getClientId());
        if (authorizationRequest.getScope() != null) {
            values.put(SCOPE, OAuth2Utils.formatParameterList(authorizationRequest.getScope()));
        }

        String deviceId = authorizationRequest.getRequestParameters().get(CustomHeader.device_id.name());
        if(deviceId != null && !deviceId.isEmpty()) {
            values.put("device_id", deviceId);
        }

        MessageDigest digest;
        try {
            digest = MessageDigest.getInstance("MD5");
        }
        catch (NoSuchAlgorithmException e) {
            throw new IllegalStateException("MD5 algorithm not available.  Fatal (should be in the JDK).");
        }

        try {
            byte[] bytes = digest.digest(values.toString().getBytes("UTF-8"));
            return String.format("%032x", new BigInteger(1, bytes));
        }
        catch (UnsupportedEncodingException e) {
            throw new IllegalStateException("UTF-8 encoding not available.  Fatal (should be in the JDK).");
        }
    }
}

答案 2 :(得分:1)

对于那些面临同样问题的人,可以使用MangEngkus的回复解决方案,为了获得精确的解决方案,您也可以参考此链接Spring OAuth2 Generate Access Token per request to the Token Endpoint