首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Spring WebFlux安全OAuth 2.0用户服务

Spring WebFlux安全OAuth 2.0用户服务
EN

Stack Overflow用户
提问于 2021-04-06 17:40:11
回答 1查看 950关注 0票数 0

为了提供一些上下文,我目前正在从标准的Security 5(使用spring-boot-starter-web)迁移到spring-webflux --与Spring一起使用作为我的API -它不支持spring-boot-starter-web依赖关系。

除了我的OAuth 2.0用户服务(我在以前的实现中)之外,我还使用了所有其他使用Spring /Webflux的工具。因此,我已经复制了用户服务--但我现在无法从新的安全配置中引用该服务。

以下是我的新安全配置:

代码语言:javascript
运行
复制
@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自定义用户服务

代码语言:javascript
运行
复制
@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);
  }
}

这和我以前的配置的唯一区别是我可以用这个

代码语言:javascript
运行
复制
http
    .userInfoEndpoint()
    .userService(customOAuth2UserService)

但是,在新安全配置选项(据我所知)中没有使用此选项的选项--因此,如果您知道一种将Security指向我的自定义用户服务的方法,请回答。

非常感谢

EN

回答 1

Stack Overflow用户

发布于 2021-04-26 02:12:09

您的Service用于常规OAuth流。您真正想要的是WebFlux,也就是ReactiveOAuth2UserService

您可以通过在ReactiveOAuth2UserService::loadUser方法上设置一个断点,然后正常地进行身份验证来验证这一点。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66973760

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档