本篇承接上一篇《从0到1 手把手搭建spring cloud alibaba 微服务大型应用框架(八)saas平台篇-解决不同租户针定制化开发问题(2) -挂载自定义登陆以及业务端完整代码》,上一篇中具体说明了如何创建租户个性化工程以及详细代码,这里说明代码上如何在认证中心添加tenantId属性
目前登陆返回信息并没有tenantId字段
oauth2 框架认证流程源码分析
详细泳道图
关键代码以及分析
1 客户端请求/oauth/token 进行认证
2 AbstractAuthenticationProcessingFilter 过滤器优先执行调用providerManager 进行校验
3 如果providerManager 的authenticate 没问题,则进入TokenEndpoint 执行postAccessToken 方法
4 TokenEndpoint postAccessToken 内部
4.1 通过 ClientDetailsService获取clientDetails 进行client信息校验 这个是关键点,需要首先数据库添加tenantId字段
4.2 然后将clientDetails 传入ResourceOwnerPasswordTokenGranter 获取OAuth2Authentication
4.3 Granter内部通过OAuth2RequestFactory 获取OAuth2Request 这个是关键点,需要拼装tenantId字段
4.4 DefaultTokenServices 通过OAuth2Request 信息拼装成返回结果返回给客户端 这个是关键点,需要拼装tenantId字段
如何扩展oauth2 框架添加tenantId字段
扩展部分关键点
具体源码
数据库部分添加tenantId 属性
MiniCloudAuthorizationServerConfig添加requestFactory
/** * @desc: 主要是对endpoints(框架本身的url路径)注入自定义service * 这里对注入了默认的userDetailsService,authenticationManager, */ @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { endpoints .allowedTokenEndpointRequestMethods(HttpMethod.GET, HttpMethod.POST,HttpMethod.DELETE,HttpMethod.PUT) .tokenStore(tokenStore()) .tokenEnhancer(miniCloudTokenEnhancer) .userDetailsService(userDetailsService) .requestFactory(oauth2RequestFactory(ClientDetailServiceImpl)) .authenticationManager(authenticationManager); } public OAuth2RequestFactory oauth2RequestFactory(ClientDetailsService clientDetailsService){ MiniCloudOAuth2RequestFactory miniCloudOAuth2RequestFactory = new MiniCloudOAuth2RequestFactory(clientDetailsService); return miniCloudOAuth2RequestFactory; }
MiniCloudOAuth2RequestFactory.java
public class MiniCloudOAuth2RequestFactory extends DefaultOAuth2RequestFactory { public MiniCloudOAuth2RequestFactory(ClientDetailsService clientDetailsService) { super(clientDetailsService); } @Override public OAuth2Request createOAuth2Request(ClientDetails client, TokenRequest tokenRequest) { OAuth2Request oAuth2Request = super.createOAuth2Request(client, tokenRequest); oAuth2Request.getExtensions().put("tenantId",(Integer)client.getAdditionalInformation().get("tenantId")); return oAuth2Request; } }
MiniCloudTokenEnhancer.java
/** * 扩展auth 认证中map 存放token 内容,client 模式不处理 * */ @Override public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) { if (CLIENT_CREDENTIALS.equals(authentication.getOAuth2Request().getGrantType())) { return accessToken; } final Map<String, Object> additionalInfo = new HashMap<>(8); MiniCloudUserDetails miniCloudUserDetails = (MiniCloudUserDetails) authentication.getUserAuthentication().getPrincipal(); additionalInfo.put(DETAILS_USER, miniCloudUserDetails); additionalInfo.put(DETAILS_LICENSE, "made by mini-cloud"); additionalInfo.put(ACTIVE, Boolean.TRUE); additionalInfo.put("tenantId",authentication.getOAuth2Request().getExtensions().get("tenantId")); ((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInfo); return accessToken; }
MiniCloudUserAuthenticationConverter.java
/** * * 将check_token 中返回的OAuth2Authentication的getPrincipal 重写为我们自己的miniclouddetail * */ @Override @Cacheable(value = "mini_cloud_cache:extractAuthentication:authentication", key = "#responseMap['user_name']", unless = "#result == null") public Authentication extractAuthentication(Map<String, ?> responseMap) { if (responseMap.containsKey(USERNAME)) { Map<String, ?> map = MapUtil.get(responseMap, "user_info", Map.class); List<Map> authorities = MapUtil.get(map,"miniCloudGrantedAuthorities",List.class); List<MiniCloudGrantedAuthority> miniCloudGrantedAuthorities = authorities.stream().map(authoritity->{ String method = MapUtil.getStr((Map)authoritity,"method"); String url = MapUtil.getStr((Map)authoritity,"url"); return new MiniCloudGrantedAuthority(method,url); }).collect(Collectors.toList()); MiniCloudUserDetails miniCloudUserDetails = new MiniCloudUserDetails(MapUtil.getInt(map,"id"),MapUtil.getStr(map,"username"),N_A,miniCloudGrantedAuthorities,MapUtil.getInt(responseMap,"tenantId")); return new UsernamePasswordAuthenticationToken(miniCloudUserDetails, N_A, miniCloudGrantedAuthorities); } return null; }
重新启动,结果展示,已经有了tenantId字段