登录后 Spring Boot 重定向到请求的 URL
Posted
技术标签:
【中文标题】登录后 Spring Boot 重定向到请求的 URL【英文标题】:Spring Boot Redirect to requested URL after login 【发布时间】:2018-11-16 20:04:24 【问题描述】:我有一个 Spring Boot UI 应用程序。我正在尝试在登录后将用户重定向到最初请求的 URL。
当用户请求http://www.example.com/myapp/user/22 时,应用程序会适当地重定向到http://www.example.com/myapp/login。用户登录后,应用程序将重定向到http://www.example.com/myapp/dashboard。我希望应用程序重定向到http://www.example.com/myapp/user/22。
我浏览了几个链接,感觉我的配置正确,但是重定向没有按预期工作。
我的安全配置是
public class SecurityConfig extends WebSecurityConfigurerAdapter
.....
....
@Autowired
private MyAuthenticationSuccessHandler authenticationSuccessHandler;
@Override
protected void configure(HttpSecurity http) throws Exception
http.
authorizeRequests()
.antMatchers("/user/**").authenticated()
.and().csrf().disable().formLogin()
.successHandler(authenticationSuccessHandler)
......
我的成功处理程序是
@Component
public class MyAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler
...
public MyAuthenticationSuccessHandler()
super();
this.setDefaultTargetUrl("/myapp/dashboard");
this.setUseReferer(true);
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) throws IOException, ServletException
//Do something ..........
........
.........
super.onAuthenticationSuccess(request, response, authentication);
我也尝试过使用 SavedRequestAwareAuthenticationSuccessHandler。
我注意到我的成功处理程序被调用,但目标 URL 始终是 /user/login 并且我的登录控制器被调用..
@RequestMapping("/login")
public ModelAndView login(@ModelAttribute()
if(!userIdentified)
//go to login page
else
new ModelAndView("redirect:/myapp/dashboard");
并且用户被重定向到“仪表板”。
我还缺少什么?
【问题讨论】:
【参考方案1】:使用会话属性中的“Referer”获取最新的请求 URL。在我的应用程序上,我使用这个
public class CustomAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler
public static final String REDIRECT_URL_SESSION_ATTRIBUTE_NAME = "REDIRECT_URL";
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) throws IOException, ServletException
Object redirectURLObject = request.getSession().getAttribute(REDIRECT_URL_SESSION_ATTRIBUTE_NAME);
if(redirectURLObject != null)
setDefaultTargetUrl(redirectURLObject.toString());
else
setDefaultTargetUrl("/");
request.getSession().removeAttribute(REDIRECT_URL_SESSION_ATTRIBUTE_NAME);
super.onAuthenticationSuccess(request, response, authentication);
编辑:
对不起,我忘了显示登录控制器
@RequestMapping(method = RequestMethod.GET, value = "/login")
String login(Model model, Principal principal, HttpServletRequest request) throws Exception
String referer = request.getHeader("Referer"); //Get previous URL before call '/login'
//save referer URL to session, for later use on CustomAuthenticationSuccesshandler
request.getSession().setAttribute(CustomAuthenticationSuccessHandler.REDIRECT_URL_SESSION_ATTRIBUTE_NAME, referer);
return principal == null ? "login" : "redirect:/";
【讨论】:
嗯……重定向 url 对象始终为空。我是否缺少其他配置?该属性是如何/在哪里设置的? 抱歉,刚刚更新了答案,如果有效请告诉我 Referer 也是 null :( 触发失败 URL... .failureUrl("/myapp/login?error=true") 我猜这就是 /login 的调用方式。 我的运行良好,可能只是缺少安全配置。查看here 和here 啊!!!想通了这个问题。我们有一个带有 @ExceptionHandler(AccessDeniedException.class) 注释方法的 ExceptionResolver,它重定向到 /myapp/login。因此,我得到了一个 302 重定向,它将引用者设置为 /login。现在,我在这个方法的 session 中设置了 referer,并在 MyAuthenticationSuccessHandler 中使用它来重定向。我也这样做了。setUseReferer(false);现在一切都按预期工作。谢谢辛吉。【参考方案2】:虽然Singgih S 回答有效,但但是有一个更好的方法如下: 参考: https://www.baeldung.com/spring-security-redirect-login
Spring Security 中这些易于使用的功能没有什么神奇之处。 当请求安全资源时,请求将是 由一系列不同的过滤器过滤。身份验证主体和 权限将被检查。如果请求会话不是 尚未通过身份验证,将抛出 AuthenticationException。
AuthenticationException 将在 ExceptionTranslationFilter,其中将进行身份验证过程 开始,导致重定向到登录页面。
因此:
1. 当重定向到“/login”页面时,您的安全请求 url 在会话中保存为 DefaultSavedRequest
对象。
2. 我们还知道,当基于表单的登录成功发生时,会调用 AuthenticationSuccessHandler
的实现之一。
因此我们可以创建一个自定义类并在其中获取 DefaultSavedRequest
,如下所示:
public class CustomAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException
DefaultSavedRequest defaultSavedRequest = (DefaultSavedRequest) request.getSession().getAttribute("SPRING_SECURITY_SAVED_REQUEST");
if(defaultSavedRequest != null)
getRedirectStrategy().sendRedirect(request, response, defaultSavedRequest.getRedirectUrl());
else
super.onAuthenticationSuccess(request, response, authentication);
3. 我们要在 WebSecurityConfigurerAdapter 中引入这个类:
@Override
protected void configure(HttpSecurity http) throws Exception
http.(...).anyRequest().authenticated().and()
.formLogin()
.loginPage("/login")
.loginProcessingUrl("/login")
.successHandler(new CustomAuthenticationSuccessHandler());
所以你可以在上面的 onAuthenticationSuccess
方法中实现你的逻辑。
最好的祝福
【讨论】:
【参考方案3】:Spring 路由,扩展 SavedRequestAwareAuthenticationSuccessHandler
或 SimpleUrlAuthenticationSuccessHandler
可能有点笨拙。在控制器中(例如处理登录的 POST 方法),您可以自己进行标头请求;例如:
HttpServletRequest request =null;
String priorUrl = request.getHeader("Referer");
您会注意到,在手动(由用户启动)注销或会话超时(由 Spring 会话处理)之前,您将拥有该 URL:您将获得一个 https://iAmPriorUrl.com/...
。然后你可以用它做任何你想做的事情。
【讨论】:
以上是关于登录后 Spring Boot 重定向到请求的 URL的主要内容,如果未能解决你的问题,请参考以下文章
成功登录后 Spring Boot Security 重定向 - 未定义
会话超时后,Spring 安全性不会重定向到上次请求的页面登录