请求OAuth微服务服务器接口**oauth/login** 验证信息返回token,并将token进行缓存持久化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 @RequestMapping(value = "/oauth/login", method = RequestMethod.POST) public ModelAndView postLogin (Principal principal, @RequestParam Map<String, String> parameters) throws HttpRequestMethodNotSupportedException { return MVF.filterData(handleAccessToken(principal, parameters)); } private OAuth2AccessToken handleAccessToken (Principal principal, Map<String, String> parameters) { if (!(principal instanceof Authentication)) { throw new InsufficientAuthenticationException ("There is no client authentication. Try adding an appropriate authentication filter." ); } String clientId = getClientId(principal); ClientDetails authenticatedClient = getClientDetailsService().loadClientByClientId(clientId); TokenRequest tokenRequest = getDefaultOAuth2RequestFactory().createTokenRequest(parameters, authenticatedClient); if (clientId != null && !clientId.equals("" )) { if (!clientId.equals(tokenRequest.getClientId())) { throw new InvalidClientException ("Given client ID does not match authenticated client" ); } } if (authenticatedClient != null ) { oAuth2RequestValidator.validateScope(tokenRequest, authenticatedClient); } 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" ); } if (isAuthCodeRequest(parameters)) { if (!tokenRequest.getScope().isEmpty()) { logger.debug("Clearing scope of incoming token request" ); tokenRequest.setScope(Collections.emptySet()); } } if (isRefreshTokenRequest(parameters)) { tokenRequest.setScope(OAuth2Utils.parseParameterList(parameters.get(OAuth2Utils.SCOPE))); } OAuth2AccessToken token = getTokenGranter().grant(tokenRequest.getGrantType(), tokenRequest); if (token == null ) { throw new UnsupportedGrantTypeException ("Unsupported grant type: " + tokenRequest.getGrantType()); } return token; }
重点是这段:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 ... OAuth2AccessToken token = getTokenGranter().grant(tokenRequest.getGrantType(), tokenRequest);...
执行实现 继承AbstractEndpoint的getTokenGranter()方法实现的TokenGranter接口 的 grant 方法,具体gettokenGranter方法可以自己查看源码,先来看看grant实现是在哪个位置。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 @Configuration @EnableAuthorizationServer @EnableDefinitionGranter("ru.reimu.akariserver.auth.granter") public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter { ... @Autowired private List<TokenGranter> TokenGranters; @Override public void configure (AuthorizationServerEndpointsConfigurer endpoints) { endpoints .allowedTokenEndpointRequestMethods(HttpMethod.GET, HttpMethod.POST) .tokenStore(redisTokenStore()) .tokenEnhancer(jwtAccessTokenConverter()) .authenticationManager(authenticationManager) .reuseRefreshTokens(false ) .userDetailsService(userDetailsService) .tokenServices(defaultTokenServices()) .exceptionTranslator(webResponseExceptionTranslator) .tokenGranter(new TokenGranter () { private CompositeTokenGranter delegate; @Override public OAuth2AccessToken grant (String grantType, TokenRequest tokenRequest) { if (this .delegate == null ) { this .delegate = new CompositeTokenGranter (TokenGranters); } return this .delegate.grant(grantType, tokenRequest); } }); } ... }
可以开到这里我们装配了一个TokenGranter的List的Beans,但是这些TokenGranter又是从哪里注入的呢?
自定义 @Granter 注解 我们将借助ImportBeanDefinitionRegistrar接口实现granter bean的动态注入,即使用@Granter注解的类将在运行时时注入到容器,则上面授权服务器则能自动装配到实现TokenGranter的所有实现类了。
@Granter 1 2 3 4 5 6 7 8 9 10 11 @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface Granter { String granterType () ; }
@EnableDefinitionGranter value值即上面授权服务器的自定义granter包 @EnableDefinitionGranter(“ru.reimu.akariserver.auth.granter”)
1 2 3 4 5 6 7 8 9 10 11 12 13 @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Import({GranterDefinitionBeanRegister.class}) public @interface EnableDefinitionGranter { String value () ; }
动态注入代码实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 public class GranterDefinitionBeanRegister implements ImportBeanDefinitionRegistrar , BeanFactoryAware { private final Logger log = LoggerFactory.getLogger(this .getClass()); private BeanFactory beanFactory; @Override public void setBeanFactory (BeanFactory beanFactory) throws BeansException { this .beanFactory = beanFactory; } @Override public void registerBeanDefinitions (AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) { AnnotationAttributes annoAttrs = AnnotationAttributes.fromMap(annotationMetadata.getAnnotationAttributes(EnableDefinitionGranter.class.getName())); String scanPackage = annoAttrs.getString("value" ); try { Set<Class<?>> granterSet = ReflectionUtility.loadClassesByAnnotationClass(Granter.class, scanPackage.split("," )); granterSet.forEach(granter -> { Granter annotation = granter.getAnnotation(Granter.class); String granterType = annotation.granterType(); BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(granter); beanDefinitionBuilder.addConstructorArgValue(granterType); beanDefinitionRegistry.registerBeanDefinition(granter.getSimpleName(), beanDefinitionBuilder.getBeanDefinition()); }); } catch (IOException e) { log.error("Granter register error" , e); } catch (ClassNotFoundException e) { log.error("Granter register error" , e); } } }
选择对应的grant type的tokenGranter 接上面授权服务器,这里实例化了一个CompositeTokenGranter类,我们将执行这个grant方法。下面是代码实现,具体看注释。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 @Override public OAuth2AccessToken grant (String grantType, TokenRequest tokenRequest) { if (this .delegate == null ) { this .delegate = new CompositeTokenGranter (TokenGranters); } return this .delegate.grant(grantType, tokenRequest); } public OAuth2AccessToken grant (String grantType, TokenRequest tokenRequest) { Iterator var3 = this .tokenGranters.iterator(); OAuth2AccessToken grant; do { if (!var3.hasNext()) { return null ; } TokenGranter granter = (TokenGranter)var3.next(); grant = granter.grant(grantType, tokenRequest); } while (grant == null ); return grant; } public OAuth2AccessToken grant (String grantType, TokenRequest tokenRequest) { if (!this .grantType.equals(grantType)) { return null ; } else { String clientId = tokenRequest.getClientId(); ClientDetails client = this .clientDetailsService.loadClientByClientId(clientId); this .validateGrantType(grantType, client); if (this .logger.isDebugEnabled()) { this .logger.debug("Getting access token for: " + clientId); } return this .getAccessToken(client, tokenRequest); } }
最后调用同包下的this.getAccessToken(ClientDetails client, TokenRequest tokenRequest)方法
1 2 3 protected OAuth2AccessToken getAccessToken (ClientDetails client, TokenRequest tokenRequest) { return this .tokenServices.createAccessToken(this .getOAuth2Authentication(client, tokenRequest)); }
this.getOAuth2Authentication(ClientDetails client, TokenRequest tokenRequest)就将执行我们选择的自定义授权者重载的代码
自定的授权者PasswordGranter类 先来看看里面的代码,到这里先不记录后续
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 @Granter(granterType = "password") public class PasswordGranter extends AbstractGranter { @Autowired private AuthenticationManager authenticationManager; protected PasswordGranter (String grantType, AuthorizationServerTokenServices tokenServices, ClientDetailsService clientDetailsService, OAuth2RequestFactory requestFactory, RabbitMQSender mqSender) { super (grantType, tokenServices, clientDetailsService, requestFactory, mqSender); } @Override protected OAuth2Authentication getOAuth2Authentication (ClientDetails client, TokenRequest tokenRequest) { Map<String, String> parameters = new LinkedHashMap <>(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 = this .authenticationManager.authenticate(userAuth); } catch (AccountStatusException var8) { throw new InvalidGrantException (var8.getMessage()); } catch (BadCredentialsException var9) { throw new InvalidGrantException (var9.getMessage()); } if (userAuth != null && userAuth.isAuthenticated()) { OAuth2Request storedOAuth2Request = this .getRequestFactory().createOAuth2Request(client, tokenRequest); return new OAuth2Authentication (storedOAuth2Request, userAuth); } else { throw new InvalidGrantException ("Could not authenticate user: " + username); } } @Override protected UserDetails access (ClientDetails client, TokenRequest tokenRequest) { return null ; } }
未完待续