我在 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();
}
}
您可以尝试下面提供的组合来实现您正在寻找的:
首先,您需要创建身份验证成功处理程序:
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 是客户端控制的值,因此可以被欺骗为完全不同的东西,甚至被删除。该值不应用于任何关键操作。
也许为时已晚,但我也遇到了和你一样的问题。 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
我的解决方案(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);
}
}