在Spring Security中认证成功后重定向到原始URL

问题描述 投票:0回答:3

我在 Spring Cloud Gateway 应用程序中有以下安全配置类。该网关充当处理用户身份验证的 OAuth2 客户端。身份验证成功后,我想重定向到用户最初来自的单页应用程序的 URL。

示例
如果用户位于

http://localhost:8093/profile
,那么这应该是重定向 URL。

目前我仅使用用于测试目的的硬编码值。有没有办法获取“原始URL”并将其用作重定向URL?

@Configuration
@EnableWebFluxSecurity
public class SecurityConfiguration {

    @Bean
    public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity httpSecurity) {
        httpSecurity
                .csrf().disable()
                .authorizeExchange()
                .anyExchange().authenticated()
                .and()
                .oauth2Login()
                // Use original URL here?
                .authenticationSuccessHandler(new RedirectServerAuthenticationSuccessHandler("http://localhost:8093"))
                .and()
                .exceptionHandling().authenticationEntryPoint(new HttpStatusServerEntryPoint(HttpStatus.UNAUTHORIZED))
                .and()
                .oauth2ResourceServer().jwt();
        return httpSecurity.build();
    }
}
spring-boot spring-security spring-oauth2
3个回答
3
投票

您可以尝试下面提供的组合来实现您正在寻找的:

首先,您需要创建身份验证成功处理程序:

public class MySimpleUrlAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
    protected Log logger = LogFactory.getLog(this.getClass());

    private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();

    @Override
    public void onAuthenticationSuccess(
        HttpServletRequest request, 
        HttpServletResponse response, 
        Authentication authentication
    ) throws IOException {
        handle(request, response, authentication);
        clearAuthenticationAttributes(request);
    }

    // Then handle Method implementation:
    protected void handle(
        HttpServletRequest request,
        HttpServletResponse response, 
        Authentication authentication
    ) throws IOException {
        //This will provide you last URL
        String targetUrl = request.getHeader("referer");

        if (response.isCommitted()) {
            logger.debug(
                    "Response has already been committed. Unable to redirect to "
                            + targetUrl);
            return;
        }

        redirectStrategy.sendRedirect(request, response, targetUrl);
    }
}

仅供参考:

注意HTTP Referer 是客户端控制的值,因此可以被欺骗为完全不同的东西,甚至被删除。该值不应用于任何关键操作。


2
投票

也许为时已晚,但我也遇到了和你一样的问题。 Jayesh 说过,您需要创建一个“身份验证成功处理程序”类,以在成功的 Oauth2 身份验证后添加一些逻辑和重定向。 但是这个新类必须扩展 SavedRequestAwareAuthenticationSucessHandler 并重写方法 onAuthenticationSucess(),而不是扩展 SimpleUrlAuthenticationSucessHandler。

public class OAuth2LoginSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {

@Autowired
private UserService userService;

@Autowired
private MessageSource messageSource;

@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
        Authentication authentication) throws IOException, ServletException {

    CustomOAuth2User oAuth2User = (CustomOAuth2User) authentication.getPrincipal();

    User existingUser = userService.findByUsername(oAuth2User.getEmail());

    if (existingUser != null) {

        // update of user with providerId and authenticationProvider if not already done
        log.info(messageSource.getMessage("global.existing-user.oauth2-authenticated",
                new Object[] { existingUser }, LocaleContextHolder.getLocale()));

        if (existingUser.getAuthenticationProvider() == AuthProvider.LOCAL) {

            userService.updateUserFromOAuth2Authentication(oAuth2User, existingUser);

        } else if ((!Objects.equals(existingUser.getIdProvider(), oAuth2User.getproviderId())
                || existingUser.getAuthenticationProvider() != oAuth2User.getClientProvider())) {

            throw new OAuth2AuthenticationException("a problem occured with Oauth2Authentication!");
        }

    } else {

        // creation of new user
        log.info(messageSource.getMessage("global.not-existing-user.oauth2-authenticated",
                new Object[] { "createdUser" }, LocaleContextHolder.getLocale()));
        userService.saveUserFromOAuth2Authentication(oAuth2User);
    }   
    super.onAuthenticationSuccess(request, response, authentication);
}
}

在安全性配置类中,您只需调用 Oauth2Login 的 successHandler() 方法即可使用新类“身份验证成功处理程序”,当然无需使用方法 defaultSucessUrl() ,如下所示

  http.oauth2Login()
                .loginPage("/app/login")
                .userInfoEndpoint()
                .userService(oauth2UserService)
                .and()
                .successHandler(oAuth2LoginSuccessHandler)
            ;

抱歉我的英语不好,我在读完这篇文章后就找到了这个解决方案https://www.baeldung.com/spring-security-redirect-login


0
投票

我的解决方案(spring boot,maven,spring data jdbc)与Dorian的非常相似,但有一些差异。

// @formatter:off
@Bean
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http.authorizeHttpRequests(
                (authorize) -> authorize
                .requestMatchers("/", "/login").permitAll()
                .anyRequest().authenticated())
            .formLogin().loginPage("/login")
            .and()
            .oauth2Login(oauth2 -> oauth2
                .loginPage("/login")
                    .userInfoEndpoint()
                    .userService(oauth2UserService)
                .and()
                    .successHandler(oAuth2LoginSuccessHandler)
            );

    return http.build();
}
// @formatter:on

@Autowired
private OAuth2LoginSuccessHandler oAuth2LoginSuccessHandler;

这是 OAuth2LoginSuccessHandler 类:

@Component
public class OAuth2LoginSuccessHandler
        extends SavedRequestAwareAuthenticationSuccessHandler {
    @Autowired
    private CustomOAuth2UserService userService;

    @Autowired
    private UserRepository userRepo;

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request,
            HttpServletResponse response, Authentication authentication)
            throws IOException, ServletException {

        CustomOAuth2User user = (CustomOAuth2User) authentication.getPrincipal();

        User existingUser = userRepo.findByUsername(user.getEmail());

        if (existingUser == null) {
            userService.processOAuthPostLogin(user.getEmail());
        }
        super.onAuthenticationSuccess(request, response, authentication);
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.