Spring Security OAuth2 源码分析1 - TokenEndpoint

通过请求 oauth/token 来获取 token。大致为以下流程:

  1. 从 principal 中获取 clientId, 进而装载 ClientDetails
  2. 从 parameters 中获取 clientId、scope、grantType 以组装 TokenRequest
  3. 校验 Client 信息。
  4. 根据 grantType 设置 TokenRequest 的 scope。
  5. 通过令牌授予者获取 Token

下面我们通过源码来学习整个流程。

@FrameworkEndpoint
public class TokenEndpoint extends AbstractEndpoint {
	// 以下是核心部分代码...
	@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.");
		}

		// 1. 从 principal 中获取 clientId, 进而 load client 信息
		String clientId = getClientId(principal);
		ClientDetails authenticatedClient = getClientDetailsService().loadClientByClientId(clientId);

		// 2. 从 parameters 中拿 clientId、scope、grantType 组装 TokenRequest
		TokenRequest tokenRequest = getOAuth2RequestFactory().createTokenRequest(parameters, authenticatedClient);

		// 3. 校验 client 信息
		if (clientId != null && !clientId.equals("")) {
			if (!clientId.equals(tokenRequest.getClientId())) {
				// 双重校验: 确保从 principal 拿到的 client 信息与根据 parameters 得到的 client 信息一致
				throw new InvalidClientException("Given client ID does not match authenticated client");
			}
		}
		if (authenticatedClient != null) {
			oAuth2RequestValidator.validateScope(tokenRequest, authenticatedClient);
		}

		// 4. 根据 grantType 设置 TokenRequest 的 scope。
		// 授权类型有: password 模式、authorization_code 模式、refresh_token 模式、client_credentials 模式、implicit 模式
		if (!StringUtils.hasText(tokenRequest.getGrantType())) {
			throw new InvalidRequestException("Missing grant type");
		}
		if (tokenRequest.getGrantType().equals("implicit")) {
			throw new InvalidGrantException("Implicit grant type not supported from token endpoint");
		}

		// 如果是授权码模式, 则清空 scope。 因为授权请求过程会确定 scope, 所以没必要传
		if (isAuthCodeRequest(parameters)) {
			if (!tokenRequest.getScope().isEmpty()) {
				logger.debug("Clearing scope of incoming token request");
				tokenRequest.setScope(Collections.<String> emptySet());
			}
		}

		// 如果是刷新 Token 模式, 解析并设置 scope
		if (isRefreshTokenRequest(parameters)) {
			tokenRequest.setScope(OAuth2Utils.parseParameterList(parameters.get(OAuth2Utils.SCOPE)));
		}

		// 5. 通过令牌授予者获取 token
		OAuth2AccessToken token = getTokenGranter().grant(tokenRequest.getGrantType(), tokenRequest);
		if (token == null) {
			throw new UnsupportedGrantTypeException("Unsupported grant type: " + tokenRequest.getGrantType());
		}

		return getResponse(token);
	}
	// ...
}
复制代码

该系列文章:

Spring Security OAuth2 源码分析1 - TokenEndpoint

Spring Security OAuth2 源码分析2 - TokenGranter

// 持续更新中...

转载于:https://juejin.im/post/5bb048acf265da0acb13a3e8

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值