Spring不想使用我的PrincipalExtractor
bean。相反,它使用默认的FixedPrincipalExtractor
。
我试图按照Spring的OAuth2教程进行操作: https://spring.io/guides/tutorials/spring-boot-oauth2/
直到我决定将经过身份验证的用户保存到我的数据库之前,一切都差不多了。该教程只是说:“这太简单了,所以我们将不展示如何做到这一点”。当然,那是我被困几天的时刻。
有WebSecurityConfig
类。这是一团糟,但用于教育目的。
@Configuration
@EnableWebSecurity
@EnableOAuth2Client
@RestController
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
OAuth2ClientContext oauth2ClientContext;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/**")
.authorizeRequests()
.antMatchers("/", "/login**", "/js/**", "/error**", "/webjars/**").permitAll()
.anyRequest().authenticated()
.and().logout().logoutSuccessUrl("/").permitAll()
.and()
.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
.and()
.addFilterBefore(ssoFilter(), BasicAuthenticationFilter.class);
}
private Filter ssoFilter() {
CompositeFilter filter = new CompositeFilter();
List<Filter> filters = new ArrayList<>();
filters.add(ssoFilter(google(), "/login/google"));
filter.setFilters(filters);
return filter;
}
private Filter ssoFilter(ClientResources client, String path) {
OAuth2ClientAuthenticationProcessingFilter oAuth2ClientAuthenticationFilter = new OAuth2ClientAuthenticationProcessingFilter(path);
OAuth2RestTemplate oAuth2RestTemplate = new OAuth2RestTemplate(client.getClient(), oauth2ClientContext);
oAuth2ClientAuthenticationFilter.setRestTemplate(oAuth2RestTemplate);
UserInfoTokenServices tokenServices = new UserInfoTokenServices(client.getResource().getUserInfoUri(),
client.getClient().getClientId());
tokenServices.setRestTemplate(oAuth2RestTemplate);
oAuth2ClientAuthenticationFilter.setTokenServices(tokenServices);
return oAuth2ClientAuthenticationFilter;
}
@Bean
@ConfigurationProperties("google")
public ClientResources google() {
return new ClientResources();
}
@Bean
public FilterRegistrationBean<OAuth2ClientContextFilter> oauth2ClientFilterRegistration(OAuth2ClientContextFilter filter) {
FilterRegistrationBean<OAuth2ClientContextFilter> registration = new FilterRegistrationBean<OAuth2ClientContextFilter>();
registration.setFilter(filter);
registration.setOrder(-100);
return registration;
}
@Bean
public PrincipalExtractor principalExtractor(UserDetailsRepo userDetailsRepo) {
return map -> {
String id = (String) map.get("sub");
User user = userDetailsRepo.findById(id).orElseGet(() -> {
User newUser = new User();
newUser.setId(id);
newUser.setEmail((String) map.get("email"));
// and so on...
return newUser;
});
return userDetailsRepo.save(user);
};
}
}
class ClientResources {
@NestedConfigurationProperty
private AuthorizationCodeResourceDetails client = new AuthorizationCodeResourceDetails();
@NestedConfigurationProperty
private ResourceServerProperties resource = new ResourceServerProperties();
public AuthorizationCodeResourceDetails getClient() {
return client;
}
public ResourceServerProperties getResource() {
return resource;
}
}
还有application.yml
:
spring:
datasource:
url: jdbc:postgresql://localhost/my_db
username: postgres
password: password
jpa:
generate-ddl: true
properties:
hibernate:
jdbc:
lob:
non_contextual_creation: true
google:
client:
clientId: 437986124027-7072jmbsba04d11fft0h9megkqcpem2t.apps.googleusercontent.com
clientSecret: ${clientSecret}
accessTokenUri: https://www.googleapis.com/oauth2/v4/token
userAuthorizationUri: https://accounts.google.com/o/oauth2/v2/auth
clientAuthenticationScheme: form
scope: openid,email,profile
resource:
userInfoUri: https://www.googleapis.com/oauth2/v3/userinfo
preferTokenInfo: true
如上所述,Spring并不想使用我的PrincipalExtractor
bean,而是使用默认的FixedPrincipalExtractor
。我花了很多时间尝试解决此问题,但没有任何帮助。除了像这样更改application.yml
:
security:
oauth2:
client:
clientId: 620652621050-v6a9uqrjq0ejspm5oqbek48sl6od55gt.apps.googleusercontent.com
clientSecret: ${clientSecret}
[...]
resource:
userInfoUri: https://www.googleapis.com/oauth2/v3/userinfo
preferTokenInfo: true
有google.client.clientId
,您将看到它变为security.oauth2.client.clientId
。
如果您删除所有过滤器方法以及与它们相关的所有内容,那么它将起作用,是的。它确实使用了我的PrincipleExtractor
。但是,现在如何添加更多身份验证提供程序(Facebook,GitHub等)和本地身份验证?
最后,我有几个问题:
PrincipalExtractor
?PrincipalExtractor
吗?也许还有另一种方法可以做到这一点?application.yml
有问题吗?我尝试过的事情:
什么都没有改变。
Spring找不到UserInfoRestTemplateFactory。我猜手动添加bean是不对的,而且根本行不通。
答案 0 :(得分:1)
在定义ssoFilter
时,请添加以下内容:
tokenServices.setPrincipalExtractor(myCustomPrincipalExtractor());
奖金:AuthorityExtractor
也是如此。