什么是JWT?为什么选择JWT?如何在Spring Cloud Security集成使用?

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

什么是JWT?

Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准,详情可以参考什么是 JWT -- JSON WEB TOKEN。其特点如下:

  1. 具体时效性,包含失效时间。
  2. 具有安全性,基于密钥机制的签发和验证机制。

为什么选择JWT?

基于oauth2协议认证过程中,以密码类型认证方式为例,包括认证和授权两个步骤。分别如下:

  1. 客户端通过客户端用户名和密码,密码授权方式,以及用户名和密码,向授权服务器认证,如果有效则返回token(访问令牌)。
  2. 客户端携带token(访问令牌)访问资源服务器,资源服务器验证token,如果有效则返回受保护的资源。 

一般在资源服务验证token时,需要通过token向授权服务器调用认证服务,并且,需要通过token向授权服务器获取用户信息。在服务的相互调用过程中,会频繁地调用授权服务器,如果使用JWT有如下几个优势:

  1. 由于JWT具有时效性,如果token失效则直接校验失败
  2. 在资源服务可以基于密钥对token进行校验,而无需调用授权服务器的认证服务,避免频繁调用认证服务器
  3. 在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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值