什么是JWT?
Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准,详情可以参考什么是 JWT -- JSON WEB TOKEN。其特点如下:
- 具体时效性,包含失效时间。
- 具有安全性,基于密钥机制的签发和验证机制。
为什么选择JWT?
基于oauth2协议认证过程中,以密码类型认证方式为例,包括认证和授权两个步骤。分别如下:
- 客户端通过客户端用户名和密码,密码授权方式,以及用户名和密码,向授权服务器认证,如果有效则返回token(访问令牌)。
- 客户端携带token(访问令牌)访问资源服务器,资源服务器验证token,如果有效则返回受保护的资源。
一般在资源服务验证token时,需要通过token向授权服务器调用认证服务,并且,需要通过token向授权服务器获取用户信息。在服务的相互调用过程中,会频繁地调用授权服务器,如果使用JWT有如下几个优势:
- 由于JWT具有时效性,如果token失效则直接校验失败
- 在资源服务可以基于密钥对token进行校验,而无需调用授权服务器的认证服务,避免频繁调用认证服务器
- 在JWT中携带非敏感的认证信息,同样避免了频繁调用授权服务器获取用户相关信息,方便了在服务之间传递
如何在Spring Cloud Security集成使用?
授权服务器生成JWT
- 授权服务器生成token的流程分析如下:
通过向授权服务TokenEndpoint的/oauth/token POST 请求生成访问令牌。TokenEndpoint部分源码如下:
@RequestMapping(value = "/oauth/token", method=RequestMethod.POST)
public ResponseEntity<OAuth2AccessToken> postAccessToken(Principal principal, @RequestParam
Map<String, String> parameters) throws HttpRequestMethodNotSupportedException {
if (!(principal instanceof Authentication)) {
throw new InsufficientAuthenticationException(
"There is no client authentication. Try adding an appropriate authentication filter.");
}
// 通过客户端id获取客户端信息
String clientId = getClientId(principal);
ClientDetails authenticatedClient = getClientDetailsService().loadClientByClientId(clientId);
TokenRequest tokenRequest = getOAuth2RequestFactory().createTokenRequest(parameters, authenticatedClient);
// 省略授权模式校验
... ...
// 生成token访问授权码
OAuth2AccessToken token = getTokenGranter().grant(tokenRequest.getGrantType(), tokenRequest);
if (token == null) {
throw new UnsupportedGrantTypeException("Unsupported grant type: " + tokenRequest.getGrantType());
}
return getResponse(token);
}
根据源码可知,security通过TokenGranter生成OAuth2AccessToken,在一般的实现中会使用CompositeTokenGranter组合生成token。分析TokenGranter的公共类AbstractTokenGranter可知,TokenGranter通过调用AuthorizationServerTokenServices的createAccessToken方法生成token,AbstractTokenGranter源码如下:
// TokenGranter 公共实现类
public abstract class AbstractTokenGranter implements TokenGranter {
// 生成OAuth2AccessToken
public OAuth2AccessToken grant(String grantType, TokenRequest tokenRequest) {
if (!this.grantType.equals(grantType)) {
return null;
}
String clientId = tokenRequest.getClientId();
ClientDetails client = clientDetailsService.loadClientByClientId(clientId);
validateGrantType(grantType, client);
if (logger.isDebugEnabled()) {
logger.debug("Getting access token for: " + clientId);
}
return getAccessToken(client, tokenRequest);
}
// 通过AuthorizationServerTokenServices 生成token
protected OAuth2AccessToken getAccessToken(ClientDetails client, TokenRequest tokenRequest) {
return tokenServices.createAccessToken(getOAuth2Authentication(client, tokenRequest));
}
}
在security中默认的AuthorizationServerTokenServices实现类为DefaultTokenServices,在调用createAccessToken生成token时,会调用TokenEnhancer的enhance对OAuth2AccessToken进行包装。在实现JWT的TokenEnhancer实现类JwtAccessTokenConverter时,会按照JWT的规范生成OAuth2AccessToken,并且可以自定义TokenEnhancer在OAuth2AccessToken的additionalInformat

本文介绍JWT的概念及其在Spring Cloud Security中的集成方法。详细讲述了JWT的特点、选择JWT的原因,以及如何在授权服务器和资源服务器中使用JWT。此外,还提供了具体的代码实现。

1578

被折叠的 条评论
为什么被折叠?



