为了提供一些上下文,我目前正在从标准的Security 5(使用spring-boot-starter-web
)迁移到spring-webflux
--与Spring一起使用作为我的API -它不支持spring-boot-starter-web
依赖关系。
除了我的OAuth 2.0用户服务(我在以前的实现中)之外,我还使用了所有其他使用Spring /Webflux的工具。因此,我已经复制了用户服务--但我现在无法从新的安全配置中引用该服务。
以下是我的新安全配置:
@Configuration
@EnableWebFluxSecurity
@EnableReactiveMethodSecurity
public class SecurityConfig {
private final OAuth2SuccessHandler oAuth2SuccessHandler;
private final OAuth2FailureHandler oAuth2FailureHandler;
private final OAuth2UserService customOAuth2UserService;
public SecurityConfig(OAuth2SuccessHandler oAuth2SuccessHandler, OAuth2FailureHandler oAuth2FailureHandler, OAuth2UserService customOAuth2UserService) {
this.oAuth2SuccessHandler = oAuth2SuccessHandler;
this.oAuth2FailureHandler = oAuth2FailureHandler;
this.customOAuth2UserService = customOAuth2UserService;
}
@Bean
public TokenAuthenticationFilter tokenAuthenticationFilter() {
return new TokenAuthenticationFilter();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public ReactiveAuthenticationManager reactiveAuthenticationManager(
UserDetailsService userDetailsService, PasswordEncoder passwordEncoder) {
UserDetailsRepositoryReactiveAuthenticationManager authenticationManager =
new UserDetailsRepositoryReactiveAuthenticationManager(userDetailsService);
authenticationManager.setPasswordEncoder(passwordEncoder);
return authenticationManager;
}
@Bean
public SecurityWebFilterChain springWebFilterChain(
ServerHttpSecurity http) {
http
.requestCache()
.requestCache(NoOpServerRequestCache.getInstance())
.and()
.securityContextRepository(NoOpServerSecurityContextRepository.getInstance())
.authorizeExchange()
.pathMatchers(
"/",
"/error",
"/favicon.ico",
"/*/*.png",
"/*/*.gif",
"/*/*.svg",
"/*/*.jpg",
"/*/*.html",
"/*/*.css",
"/*/*.js")
.permitAll()
.pathMatchers("/login/*", "/auth/*", "/oauth2/*")
.permitAll()
.anyExchange()
.authenticated()
.and()
.oauth2Login()
.authenticationSuccessHandler(oAuth2SuccessHandler)
.authenticationFailureHandler(oAuth2FailureHandler)
.and()
.formLogin()
.disable()
.exceptionHandling()
.authenticationEntryPoint(new AuthenticationEntryPoint())
.and()
.oauth2Client();
http.addFilterBefore(tokenAuthenticationFilter(), SecurityWebFiltersOrder.AUTHENTICATION);
return http.build();
}
}
这是我的OAuth 2.0自定义用户服务
@Service
public class OAuth2UserService extends DefaultOAuth2UserService {
private final UserDao userDao;
public OAuth2UserService(UserDao userDao) {
this.userDao = userDao;
}
@Override
public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
OAuth2User oAuth2User = super.loadUser(userRequest);
OAuth2UserInfo oAuth2UserInfo =
OAuth2UserInfoFactory.getOAuth2UserInfo(
userRequest.getClientRegistration().getRegistrationId(), oAuth2User.getAttributes());
if (StringUtils.isEmpty(oAuth2UserInfo.getEmail())) {
throw new OAuth2AuthenticationProcessingException("Email not found from any providers");
}
/* Find the user by email */
User user = userDao.findUserByEmail(oAuth2UserInfo.getEmail());
try {
if (user == null) throw new OAuth2AuthenticationProcessingException("You must sign up!");
if (!user.getProvider().equals(AuthProvider.valueOf(userRequest.getClientRegistration().getRegistrationId()))) {
throw new OAuth2AuthenticationProcessingException(
"Woah! Looks like you're already signed up with your "
+ user.getProvider().getValue()
+ ". Please use your "
+ user.getProvider().getValue()
+ " account to login.");
}
user = registerNewUser(userRequest, oAuth2UserInfo);
} catch (Exception e) {
}
return UserPrincipal.create(user, oAuth2User.getAttributes());
}
private User registerNewUser(OAuth2UserRequest oAuth2UserRequest, OAuth2UserInfo oAuth2UserInfo) {
User user = new User();
user.setProvider(
AuthProvider.valueOf(oAuth2UserRequest.getClientRegistration().getRegistrationId()));
user.setProviderId(oAuth2UserInfo.getId());
user.setUsername(oAuth2UserInfo.getName());
user.setEmail(oAuth2UserInfo.getEmail());
user.setProfilePicture(oAuth2UserInfo.getImageUrl());
return userDao.save(user);
}
}
这和我以前的配置的唯一区别是我可以用这个
http
.userInfoEndpoint()
.userService(customOAuth2UserService)
但是,在新安全配置选项(据我所知)中没有使用此选项的选项--因此,如果您知道一种将Security指向我的自定义用户服务的方法,请回答。
非常感谢
发布于 2021-04-26 02:12:09
您的Service用于常规OAuth流。您真正想要的是WebFlux,也就是ReactiveOAuth2UserService
。
您可以通过在ReactiveOAuth2UserService::loadUser
方法上设置一个断点,然后正常地进行身份验证来验证这一点。
https://stackoverflow.com/questions/66973760
复制相似问题