2016-08-16 162 views
1

获取在春季启动资源服务器主要我有一个单独的auth服务器和资源服务器 - 无论是春启动的应用程序。我正在使用OAuth2和JWT令牌进行身份验证和授权。从JWT令牌

我可以通过访问auth服务器获取令牌:

curl -X POST --user 'client:secret' -d 'grant_type=password&username=john&password=123' http://localhost:9000/auth-server/oauth/token 

和令牌附加到请求头从资源服务器获取资源(不同的服务器上运行)时使用它。

但是我不清楚的是,确定哪个用户在资源服务器上登录。

在auth服务器,我可以做这样的事情:

@RequestMapping("/user") 
public Principal user(Principal user) { 
    return user; 
} 

与此端点将得到我的当前用户基于使用的令牌。如果我试图在资源服务器上做同样的事情,我只会得到空的答复。

我需要得到验证用户的ID以某种方式在资源服务器,以决定是否我应该有的数据返回给他(我有一些资源只能被其所有者访问)。

我该怎么做?我认为通过使用JWT,我不需要共享相同的令牌存储。

我可以提供代码样本,如果我的问题是不清楚..我只是寻找一个确认我的假设是正确的,就可以实现这种行为 - 这是我第一次带弹簧的安全试验。

资源服务器链接到auth服务器在application.properties:

security.oauth2.resource.userInfoUri: http://localhost:9000/auth-server/user 
+0

没有你,不管怎样,这得到解决?我通过使用InMemoryTokenStore()而不是JwtTokenStore()来得到这个工作。不过,我想用JwtTokenStore()来达到同样的效果。 – Yasin

+0

不幸的是没有。我现在使用的方式是在auth服务器和资源服务器中共享相同的用户名,并使用在Principal对象中传递的唯一用户名来检索用户... – Smajl

回答

0

你的资源服务器不会自动奇迹般地摆脱了身份验证服务的主体。他们必须受到约束。将auth令牌插入标头是正确的方法。但是,资源服务器必须“验证”授权令牌。一旦您使用auth服务器验证auth令牌,将返回Principal。

因此,您的资源服务器需要在您的auth服务器上调用“/ user”。

下面是一个例子。 http://technicalrex.com/2015/02/20/stateless-authentication-with-spring-security-and-jwt

+0

只有在头部存在正确的令牌时(先前请求的表单auth服务器),资源服务器才会返回数据。我认为这个标记已经被验证过了,否则它会给我401,对吧?我通过将security.oauth2.resource.userInfoUri添加到属性来将资源服务器链接到auth服务器。 – Smajl

1

难道我建议另一种方式?

你需要实现自己的令牌生成,并包装成令牌的用户数据。所有你需要它将必要的用户信息放入索赔对象。然后在资源服务器上解开它。

private Map<String, Object> getClaims(UserEntity user) { 
    Map<String, Object> claims = new HashMap<>(); 
    OffsetDateTime now = OffsetDateTime.now(clock); 
    OffsetDateTime exp = now.plusMinutes(1); 

    //Standard claims 
    claims(Claims.ISSUED_AT, Date.from(now.toInstant()).getTime()); 
    claims(Claims.EXPIRATION, Date.from(exp.toInstant()).getTime()); 
    claims(Claims.ID, UUID.randomUUID()); 

    //Private claims 
    claims("user.auth", getRoles(user.getRoles())); 

    //Clear fields that should not be stored in the token 
    claims("user.data", stripUserFields(getApiUser(user))); 

    return claims; 
} 

private String buildJwtToken(Claims claims, String secretKey) throws ApplicationException { 
    DefaultJwsHeader header = new DefaultJwsHeader(); 
    if (secretKey != null) { 
     header.setAlgorithm(ALGORITHM); 
    } 
    String base64EncodedJsonHeader = Base64Util.encode(toJson("header", header), true); 
    String base64EncodedJsonBody = Base64Util.encode(toJson("body", claims), true); 
    String base64UrlEncodedBaseToken = base64EncodedJsonHeader + "." + base64EncodedJsonBody; 
    String hexDigest = createHexDigest(base64UrlEncodedBaseToken, secretKey); 
    return base64UrlEncodedBaseToken + "." + Base64Util.encode(hexDigest, true); 
} 

我们使用的是io.jsonwebtoken库。

+1

感谢您的建议。我正试图对此实施一些“标准”解决方案,在我看来,这是一个基本问题。我宁愿以某种'春天的方式'来实现它,而不使用这些变通办法 – Smajl