springsecurity源码(oauth2)

一,先看流程图
在这里插入图片描述

二,步骤解析
1,首先从获取授权码的请求路径/oauth/token入手
主要流程为获取ClientDetails-》认证并返回授权信息-》返回获取到的token

@RequestMapping(value = "/oauth/token", method=RequestMethod.POST)
	public ResponseEntity<OAuth2AccessToken> postAccessToken(Principal principal, @RequestParam
	Map<String, String> parameters) throws HttpRequestMethodNotSupportedException {
。。。
		String clientId = getClientId(principal);
		ClientDetails authenticatedClient = getClientDetailsService().loadClientByClientId(clientId);
		//获取ClientDetails(第三方应用)
		//loadClientByClientId 的 sql语句 :select client_id, client_secret,。。。   from oauth_client_details  where client_id = ?
		
		TokenRequest tokenRequest = getOAuth2RequestFactory().createTokenRequest(parameters, authenticatedClient);//组装tokenRequest
。。。
	   //这里根据传过来的认授权模式(密码模式,授权码模式等),认证并返回授权信息
		OAuth2AccessToken token = getTokenGranter().grant(tokenRequest.getGrantType(), tokenRequest);
		if (token == null) {
			throw new UnsupportedGrantTypeException("Unsupported grant type: " + tokenRequest.getGrantType());
		}
		return getResponse(token);//返回获取到的token
	}

2,查看认证并返回授权信息的方法, getTokenGranter().grant(tokenRequest.getGrantType(), tokenRequest);

public class CompositeTokenGranter implements TokenGranter {

	private final List<TokenGranter> tokenGranters; 
	
	public OAuth2AccessToken grant(String grantType, TokenRequest tokenRequest) {
		for (TokenGranter granter : tokenGranters) {
			OAuth2AccessToken grant = granter.grant(grantType, tokenRequest);//找到对应的生成token授权模式,并认证
			if (grant!=null) {
				return grant;
			}
		}
		return null;
	}

	public OAuth2AccessToken grant(String grantType, TokenRequest tokenRequest) {
      。。。
  		String clientId = tokenRequest.getClientId();
		ClientDetails client = clientDetailsService.loadClientByClientId(clientId);
		validateGrantType(grantType, client); 
		return getAccessToken(client, tokenRequest); //这里
	}
	protected OAuth2AccessToken getAccessToken(ClientDetails client, TokenRequest tokenRequest) {
		return tokenServices.createAccessToken(getOAuth2Authentication(client, tokenRequest));// 不同的授权模式getOAuth2Authentication
	}

3,上面的tokenServices.createAccessToken(getOAuth2Authentication(client, tokenRequest)); 有两个方法
首先看内层方法getOAuth2Authentication(client, tokenRequest),该方法不同的授权模式有不同的实现
以密码授权模式ResourceOwnerPasswordTokenGranter 为例,
进入该类的getOAuth2Authentication方法

@Override
	protected OAuth2Authentication getOAuth2Authentication(ClientDetails client, TokenRequest tokenRequest) {

		Map<String, String> parameters = new LinkedHashMap<String, String>(tokenRequest.getRequestParameters());
		String username = parameters.get("username");
		String password = parameters.get("password");
		parameters.remove("password");

		Authentication userAuth = new UsernamePasswordAuthenticationToken(username, password);
		((AbstractAuthenticationToken) userAuth).setDetails(parameters);
		try {
			userAuth = authenticationManager.authenticate(userAuth);//这里
		}
	。。。
		OAuth2Request storedOAuth2Request = getRequestFactory().createOAuth2Request(client, tokenRequest);		 
		return new OAuth2Authentication(storedOAuth2Request, userAuth);  //生成OAuth2Authentication
	}

4,上面的 userAuth = authenticationManager.authenticate(userAuth); 就是账号密码登陆的逻辑,取得认证信息。详看springsecurity源码(密码登陆) 第三步
5,取得认证信息后,返回再看 tokenServices.createAccessToken(getOAuth2Authentication(client, tokenRequest)); 的外层方法createAccessToken方法
跟进DefaultTokenServices的createAccessToken方法

@Transactional
	public OAuth2AccessToken createAccessToken(OAuth2Authentication authentication) throws AuthenticationException {

		OAuth2AccessToken existingAccessToken = tokenStore.getAccessToken(authentication);// 获取OAuth2AccessToken 从jdbc,jwt,redis,inmemory
		if (existingAccessToken != null) {
		 。。。。。
				return existingAccessToken; //如果存在就返回
		}
		OAuth2RefreshToken refreshToken = null; 
	  。。。
		OAuth2AccessToken accessToken = createAccessToken(authentication, refreshToken);//不存在就进入这里
		tokenStore.storeAccessToken(accessToken, authentication);
	 。。。
		refreshToken = accessToken.getRefreshToken();
		if (refreshToken != null) {
			tokenStore.storeRefreshToken(refreshToken, authentication);
		}
		return accessToken;
	}

6,查看 createAccessToken(authentication, refreshToken);
该方法生成最终的OAuth2AccessToken,并返回,
回到第1步的return getResponse(token); 返回给客户端

private OAuth2AccessToken createAccessToken(OAuth2Authentication authentication, OAuth2RefreshToken refreshToken) {
		DefaultOAuth2AccessToken token = new DefaultOAuth2AccessToken(UUID.randomUUID().toString());
		int validitySeconds = getAccessTokenValiditySeconds(authentication.getOAuth2Request());
		if (validitySeconds > 0) {
			token.setExpiration(new Date(System.currentTimeMillis() + (validitySeconds * 1000L)));
		}
		token.setRefreshToken(refreshToken);
		token.setScope(authentication.getOAuth2Request().getScope());

		return accessTokenEnhancer != null ? accessTokenEnhancer.enhance(token, authentication) : token;//自定义token
	}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值