spring security oauth2 使用说明
spring security oauth2实现了oauth2协议,可搭建client(客户端)、resource server(资源服务器)、authorization server(认证服务器),
其中client(客户端)可用来实现三方登陆,spring-security-oauth2-client默认集成了github、google、facebook、okta,也提供了一些接口,可实现支付宝、qq、微信等三方授权登录
**************************
相关 jar 包
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
<version>2.2.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-client</artifactId>
<version>5.3.1.RELEASE</version>
</dependency>
**************************
配置类
OAuth2ClientAutoConfiguration:客户端自动配置类
@Configuration(
proxyBeanMethods = false
)
@AutoConfigureBefore({SecurityAutoConfiguration.class})
@ConditionalOnClass({EnableWebSecurity.class, ClientRegistration.class})
@ConditionalOnWebApplication(
type = Type.SERVLET
)
@Import({OAuth2ClientRegistrationRepositoryConfiguration.class, OAuth2WebSecurityConfiguration.class})
public class OAuth2ClientAutoConfiguration {
public OAuth2ClientAutoConfiguration() {
}
}
说明:该自动配置类导入OAuth2ClientRegistrationRepositoryConfiguration、OAuth2WebSecurityConfiguration
OAuth2ClientRegistrationRepositoryConfiguration:客户端配置类
@Configuration(
proxyBeanMethods = false
)
@EnableConfigurationProperties({OAuth2ClientProperties.class})
@Conditional({ClientsConfiguredCondition.class})
class OAuth2ClientRegistrationRepositoryConfiguration {
OAuth2ClientRegistrationRepositoryConfiguration() {
}
@Bean
@ConditionalOnMissingBean({ClientRegistrationRepository.class})
InMemoryClientRegistrationRepository clientRegistrationRepository(OAuth2ClientProperties properties) {
List<ClientRegistration> registrations = new ArrayList(OAuth2ClientPropertiesRegistrationAdapter.getClientRegistrations(properties).values());
return new InMemoryClientRegistrationRepository(registrations);
}//如果不存在ClientRegistrationRepository实例,则创建InMemoryClientRegistrationRepository实例
}
OAuth2ClientProperties:自动配置属性
@ConfigurationProperties(
prefix = "spring.security.oauth2.client"
)
public class OAuth2ClientProperties {
private final Map<String, OAuth2ClientProperties.Provider> provider = new HashMap();
private final Map<String, OAuth2ClientProperties.Registration> registration = new HashMap();
*****************
内部类
public static class Provider {
private String authorizationUri;
private String tokenUri;
private String userInfoUri;
private String userInfoAuthenticationMethod;
private String userNameAttribute;
private String jwkSetUri;
private String issuerUri;
*****************
内部类
public static class Registration {
private String provider;
private String clientId;
private String clientSecret;
private String clientAuthenticationMethod;
private String authorizationGrantType;
private String redirectUri;
private Set<String> scope;
private String clientName;
ClientRegistrationRepository:根据registrationId查找ClientRegistration类
public interface ClientRegistrationRepository {
ClientRegistration findByRegistrationId(String var1);
}
InMemoryClientRegistrationRepository:使用内存保存客户端配置
public final class InMemoryClientRegistrationRepository implements ClientRegistrationRepository, Iterable<ClientRegistration> {
private final Map<String, ClientRegistration> registrations;
public InMemoryClientRegistrationRepository(ClientRegistration... registrations) {
this(Arrays.asList(registrations));
}
public InMemoryClientRegistrationRepository(List<ClientRegistration> registrations) {
this(createRegistrationsMap(registrations));
}
private static Map<String, ClientRegistration> createRegistrationsMap(List<ClientRegistration> registrations) {
Assert.notEmpty(registrations, "registrations cannot be empty");
return toUnmodifiableConcurrentMap(registrations);
}
private static Map<String, ClientRegistration> toUnmodifiableConcurrentMap(List<ClientRegistration> registrations) {
ConcurrentHashMap<String, ClientRegistration> result = new ConcurrentHashMap();
Iterator var2 = registrations.iterator();
while(var2.hasNext()) {
ClientRegistration registration = (ClientRegistration)var2.next();
if (result.containsKey(registration.getRegistrationId())) {
throw new IllegalStateException(String.format("Duplicate key %s", registration.getRegistrationId()));
}
result.put(registration.getRegistrationId(), registration);
}
return Collections.unmodifiableMap(result);
}
public InMemoryClientRegistrationRepository(Map<String, ClientRegistration> registrations) {
Assert.notNull(registrations, "registrations cannot be null");
this.registrations = registrations;
}
public ClientRegistration findByRegistrationId(String registrationId) {
Assert.hasText(registrationId, "registrationId cannot be empty");
return (ClientRegistration)this.registrations.get(registrationId);
}
public Iterator<ClientRegistration> iterator() {
return this.registrations.values().iterator();
}
}
OAuth2WebSecurityConfiguration:oauth2客户端安全配置
@Configuration(
proxyBeanMethods = false
)
@ConditionalOnBean({ClientRegistrationRepository.class})
class OAuth2WebSecurityConfiguration {
OAuth2WebSecurityConfiguration() {
}
@Bean
@ConditionalOnMissingBean
OAuth2AuthorizedClientService authorizedClientService(ClientRegistrationRepository clientRegistrationRepository) {
return new InMemoryOAuth2AuthorizedClientService(clientRegistrationRepository);
}//不存在 OAuth2AuthorizedClientService,则创建该类
@Bean
@ConditionalOnMissingBean
OAuth2AuthorizedClientRepository authorizedClientRepository(OAuth2AuthorizedClientService authorizedClientService) {
return new AuthenticatedPrincipalOAuth2AuthorizedClientRepository(authorizedClientService);
}//不存在授权客户端,则创建AuthenticatedPrincipalOAuth2AuthorizedClientRepository
@Configuration(
proxyBeanMethods = false
)
@ConditionalOnMissingBean({WebSecurityConfigurerAdapter.class})
static class OAuth2WebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
OAuth2WebSecurityConfigurerAdapter() {
}
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests((requests) -> {
((AuthorizedUrl)requests.anyRequest()).authenticated();
});
http.oauth2Login(Customizer.withDefaults());
http.oauth2Client();
}//配置默认的安全策略
}
}
OAuth2AuthorizedClientService:授权客户端操作接口
public interface OAuth2AuthorizedClientService {
<T extends OAuth2AuthorizedClient> T loadAuthorizedClient(String var1, String var2); //加载授权客户端
void saveAuthorizedClient(OAuth2AuthorizedClient var1, Authentication var2); //保存授权客户端
void removeAuthorizedClient(String var1, String var2); //删除授权客户端
}
InMemoryOAuth2AuthorizedClientService:授权客户端操作类
public final class InMemoryOAuth2AuthorizedClientService implements OAuth2AuthorizedClientService {
private final Map<OAuth2AuthorizedClientId, OAuth2AuthorizedClient> authorizedClients; //保存授权客户端
private final ClientRegistrationRepository clientRegistrationRepository;
public InMemoryOAuth2AuthorizedClientService(ClientRegistrationRepository clientRegistrationRepository) {
Assert.notNull(clientRegistrationRepository, "clientRegistrationRepository cannot be null");
this.clientRegistrationRepository = clientRegistrationRepository;
this.authorizedClients = new ConcurrentHashMap();
}
public InMemoryOAuth2AuthorizedClientService(ClientRegistrationRepository clientRegistrationRepository, Map<OAuth2AuthorizedClientId, OAuth2AuthorizedClient> authorizedClients) {
Assert.notNull(clientRegistrationRepository, "clientRegistrationRepository cannot be null");
Assert.notEmpty(authorizedClients, "authorizedClients cannot be empty");
this.clientRegistrationRepository = clientRegistrationRepository;
this.authorizedClients = new ConcurrentHashMap(authorizedClients);
}
public <T extends OAuth2AuthorizedClient> T loadAuthorizedClient(String clientRegistrationId, String principalName) {
Assert.hasText(clientRegistrationId, "clientRegistrationId cannot be empty");
Assert.hasText(principalName, "principalName cannot be empty");
ClientRegistration registration = this.clientRegistrationRepository.findByRegistrationId(clientRegistrationId);
return registration == null ? null : (OAuth2AuthorizedClient)this.authorizedClients.get(new OAuth2AuthorizedClient

最低0.47元/天 解锁文章
2480

被折叠的 条评论
为什么被折叠?



