package com.kidgrow.oauth2.config; import com.kidgrow.oauth2.handler.SingleTokenServices; import com.kidgrow.oauth2.service.impl.RedisClientDetailsService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Primary; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.AuthenticationProvider; import org.springframework.security.authentication.ProviderManager; import org.springframework.security.authentication.dao.DaoAuthenticationProvider; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.oauth2.common.exceptions.InvalidTokenException; import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter; import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer; import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer; import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.code.RandomValueAuthorizationCodeServices; import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator; import org.springframework.security.oauth2.provider.token.TokenEnhancer; import org.springframework.security.oauth2.provider.token.TokenEnhancerChain; import org.springframework.security.oauth2.provider.token.TokenStore; import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter; import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider; import javax.annotation.Resource; import java.util.Arrays; /** * 石家庄喜高科技有限责任公司 版权所有 © Copyright 2020
* * @Description: OAuth2 授权服务器配置
* @Project:
* @CreateDate: Created in 2020/2/20 09:19
* @Author: liuke */ @Configuration @EnableAuthorizationServer @AutoConfigureAfter(AuthorizationServerEndpointsConfigurer.class) public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter { /** * 注入authenticationManager 来支持 password grant type */ // @Autowired // private AuthenticationManager authenticationManager; @Resource private UserDetailsService userDetailsService; @Autowired private TokenStore tokenStore; // @Autowired // private CustomRedisTokenStore tokenStore; @Autowired(required = false) private JwtAccessTokenConverter jwtAccessTokenConverter; @Autowired(required = false) private TokenEnhancer tokenEnhancer; @Autowired private WebResponseExceptionTranslator webResponseExceptionTranslator; @Autowired private RedisClientDetailsService clientDetailsService; @Autowired private RandomValueAuthorizationCodeServices authorizationCodeServices; @Autowired private AuthenticationProvider daoAuhthenticationOauthProvider; // @Autowired // private SingleTokenServices tokenServices; /** * 配置身份认证器,配置认证方式,TokenStore,TokenGranter,OAuth2RequestFactory * @param endpoints */ @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) { if (jwtAccessTokenConverter != null) { if (tokenEnhancer != null) { TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain(); tokenEnhancerChain.setTokenEnhancers( Arrays.asList(tokenEnhancer, jwtAccessTokenConverter)); endpoints.tokenEnhancer(tokenEnhancerChain); } else { endpoints.accessTokenConverter(jwtAccessTokenConverter); } } endpoints //扩展tokenServices .tokenServices(KidgrowTokenServices()) .authenticationManager(new AuthenticationManager(){ @Override public Authentication authenticate(Authentication authentication) throws AuthenticationException { String token = (String) authentication.getPrincipal(); OAuth2Authentication auth = KidgrowTokenServices().loadAuthentication(token); if (auth == null) { throw new InvalidTokenException("Invalid token: " + token); } return daoAuhthenticationOauthProvider.authenticate(authentication); } }) .userDetailsService(userDetailsService) .authorizationCodeServices(authorizationCodeServices) .exceptionTranslator(webResponseExceptionTranslator); } @Bean DaoAuthenticationProvider daoAuthenticationProvider(){ DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider(); daoAuthenticationProvider.setPasswordEncoder(new BCryptPasswordEncoder()); daoAuthenticationProvider.setUserDetailsService(userDetailsService); return daoAuthenticationProvider; } @Bean @Primary @Lazy public SingleTokenServices KidgrowTokenServices(){ SingleTokenServices tokenServices = new SingleTokenServices(); tokenServices.setTokenStore(tokenStore); tokenServices.setSupportRefreshToken(true);//支持刷新token tokenServices.setReuseRefreshToken(true); addUserDetailsService(tokenServices, this.userDetailsService); return tokenServices; } // private SingleTokenServices tokenServices(AuthorizationServerEndpointsConfigurer endpoints) { // SingleTokenServices tokenServices = new SingleTokenServices(); // tokenServices.setTokenStore(tokenStore); // tokenServices.setSupportRefreshToken(true);//支持刷新token // tokenServices.setReuseRefreshToken(true); // tokenServices.setClientDetailsService(endpoints.getClientDetailsService()); // tokenServices.setTokenEnhancer(endpoints.getTokenEnhancer()); // addUserDetailsService(tokenServices, this.userDetailsService); // return tokenServices; // } // private void addUserDetailsService(SingleTokenServices tokenServices, UserDetailsService userDetailsService) { // if (userDetailsService != null) { // PreAuthenticatedAuthenticationProvider provider = new PreAuthenticatedAuthenticationProvider(); // provider.setPreAuthenticatedUserDetailsService(new UserDetailsByNameServiceWrapper<>( // userDetailsService)); // tokenServices.setAuthenticationManager(new ProviderManager(Arrays.asList(provider))); // } // } private void addUserDetailsService(SingleTokenServices tokenServices, UserDetailsService userDetailsService) { if (userDetailsService != null) { PreAuthenticatedAuthenticationProvider provider = new PreAuthenticatedAuthenticationProvider(); provider.setPreAuthenticatedUserDetailsService(new UserDetailsByNameServiceWrapper<>( userDetailsService)); tokenServices.setAuthenticationManager(new ProviderManager(Arrays.asList(provider))); } } /** * 配置应用名称 应用id * 配置OAuth2的客户端相关信息 * @param clients * @throws Exception */ @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { clients.withClientDetails(clientDetailsService); clientDetailsService.loadAllClientToCache(); } /** * 对应于配置AuthorizationServer安全认证的相关信息,创建ClientCredentialsTokenEndpointFilter核心过滤器 * @param security */ @Override public void configure(AuthorizationServerSecurityConfigurer security) { security .tokenKeyAccess("isAuthenticated()") .checkTokenAccess("permitAll()") //让/oauth/token支持client_id以及client_secret作登录认证 .allowFormAuthenticationForClients(); } }