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

认证后Spring安全重定向到静态资源

已登录用户的 Spring 安全重定向问题

通过 JSF 表单成功登录后 Spring Security 不会重定向到登录页面

Spring security *always* 重定向到登录表单

Grails Spring Security - 登录后总是重定向到特定页面?