Spring安全重定向到登录并恢复之前输入的表单数据
Posted
技术标签:
【中文标题】Spring安全重定向到登录并恢复之前输入的表单数据【英文标题】:Spring security redirect to login and restore form data previously entered 【发布时间】:2015-11-07 16:34:32 【问题描述】:概览
-
我使用 Spring Security 保护了 Spring Web 应用程序
网站上有一个表格可以输入一些数据,这个表格是公开的,但是数据只会为经过身份验证的用户处理
如果用户按下提交按钮但尚未登录,他将被委派到登录页面。如果登录成功,用户将被重定向到数据处理结果可见的站点
问题
在标准配置中,用户设置的所有数据在登录过程后都会丢失。据我了解,这是因为在登录后为重定向创建了一个新的 HttpRequest。
解决方案
-
我必须编写一个自定义的 LoginUrlAuthenticationEntryPoint,它将表单数据存储在会话中
我必须编写一个自定义的 SavedRequestAwareAuthenticationSuccessHandler,它从会话中读取日期并将它们作为参数添加到 url
网络应用配置
@Configuration
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter
@Autowired
private SecurityProperties security;
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception
auth.inMemoryAuthentication()
.withUser("admin")
.password("admin")
.roles("ADMIN", "USER")
.and()
.withUser("user")
.password("user")
.roles("USER");
@Override
protected void configure(HttpSecurity http) throws Exception
http.authorizeRequests()
.antMatchers("/", "/inputForm")
.permitAll()
.anyRequest()
.authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.successHandler(new SavedRequestAwareAuthenticationSuccessHandlerCustom())
.and()
.csrf()
.and()
.logout()
.logoutUrl("/logout")
.logoutSuccessUrl("/")
.invalidateHttpSession(true)
.and()
.exceptionHandling()
.authenticationEntryPoint(new LoginUrlAuthenticationEntryPointCustom("/login"));
自定义 SuccessHandler
public class SavedRequestAwareAuthenticationSuccessHandlerCustom extends SavedRequestAwareAuthenticationSuccessHandler
@Override
public void onAuthenticationSuccess(
HttpServletRequest request,
HttpServletResponse response,
Authentication authentication) throws IOException, ServletException
String text = (String) request.getSession().getAttribute("text");
if (text != null)
request.getSession().removeAttribute("text");
setDefaultTargetUrl("/user/dashboard/?text=" + text);
super.onAuthenticationSuccess(request, response, authentication);
自定义入口点
public class LoginUrlAuthenticationEntryPointCustom extends LoginUrlAuthenticationEntryPoint
public LoginUrlAuthenticationEntryPointCustom(String loginFormUrl)
super(loginFormUrl);
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException)
throws IOException,
ServletException
String text = request.getParameter("text");
request.getSession().setAttribute("text", text);
super.commence(request, response, authException);
你会说,这是恢复表单数据的有效方法,是更好/其他解决方案,也许是春季的标准方法?
更新
看来我的配置还是有问题,因为从调试消息中可以看出,请求没有被“HttpSessionRequestCache”保存。如果我得到这个工作,我就不必使用自定义实现。
o.s.s.w.util.matcher.AndRequestMatcher : Trying to match using Ant [pattern='/**', GET]
o.s.s.w.u.matcher.AntPathRequestMatcher : Request 'POST /user/dashboard' doesn't match 'GET /**
o.s.s.w.util.matcher.AndRequestMatcher : Did not match
o.s.s.w.s.HttpSessionRequestCache : Request not saved as configured RequestMatcher did not match
【问题讨论】:
已保存请求感知包装器的全部意义在于,先前的请求(或导致登录的请求)在登录后被保存和恢复。如果这不起作用,则说明您的设置有问题。 这也是我的预期,但似乎 org.springframework.security.web.savedrequest.HttpSessionRequestCache.saveRequest(HttpServletRequest, HttpServletResponse) 中的匹配器不起作用。匹配器只包含“requestMatchers=[Ant [pattern='/**'”而不是我配置的内容......调试消息还说“尝试使用 Ant [pattern='/**', GET] " -> "请求 'POST /user/dashboard' 不匹配 'GET /**" -> "不匹配" -> "请求未保存为配置的 RequestMatcher 不匹配" 看看:github.com/spring-projects/spring-security/blob/master/web/src/… 你也可以实现自己的 RequestMatcher 来解决这个问题。可能与csrf过滤器有关? 请确保表单方法是这样发布的 【参考方案1】:请确保表单方法是 post 像这样
<form th:action="@/login" method="post">
<!-- form input -- >
</form>
【讨论】:
对不起,但这个解决方案根本与问题无关,我想你甚至没有理解问题......但无论如何,这是5年前的问题,这是我设置的问题,正如 M. Deinum 所说,保存的请求感知包装器负责执行我想要的操作以上是关于Spring安全重定向到登录并恢复之前输入的表单数据的主要内容,如果未能解决你的问题,请参考以下文章
Spring Oauth和安全性在登录成功后重定向到/ login
通过 JSF 表单成功登录后 Spring Security 不会重定向到登录页面