Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Spring安全重定向到登录并恢复以前输入的表单数据_Spring_Redirect_Login_Spring Security_Restore - Fatal编程技术网

Spring安全重定向到登录并恢复以前输入的表单数据

Spring安全重定向到登录并恢复以前输入的表单数据,spring,redirect,login,spring-security,restore,Spring,Redirect,Login,Spring Security,Restore,概述 我使用Spring安全性保护Spring Web应用程序 在站点上有一个表单可以输入一些数据,这个表单是公共的,但是数据将只为经过身份验证的用户处理 如果用户按下提交按钮但尚未登录,他将被委派到登录页面。如果登录成功,用户将被重定向到数据处理结果可见的站点 问题 在标准配置中,用户设置的所有数据在登录过程后丢失。据我所知,这是因为登录后为重定向创建了一个新的HttpRequest 解决方案 @Configuration @Order(SecurityProperties.ACCESS_OV

概述

  • 我使用Spring安全性保护Spring Web应用程序
  • 在站点上有一个表单可以输入一些数据,这个表单是公共的,但是数据将只为经过身份验证的用户处理
  • 如果用户按下提交按钮但尚未登录,他将被委派到登录页面。如果登录成功,用户将被重定向到数据处理结果可见的站点
  • 问题

    在标准配置中,用户设置的所有数据在登录过程后丢失。据我所知,这是因为登录后为重定向创建了一个新的HttpRequest

    解决方案

    @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"));
        }
    }
    
  • 我必须编写一个自定义的LoginUrauThenticationEntryPoint,它将表单数据存储在会话中
  • 我必须编写一个自定义的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);
        }
    }
    
    您会怎么说,这是恢复表单数据的有效方法吗?更好的/其他的解决方案是否是spring中的标准方法

    更新

    似乎我的配置仍然有问题,因为在调试消息中可以看到,请求没有被“HttpSessionRequestCache”保存。如果我能做到这一点,我就不必使用自定义实现

    o.s.s.w.util.matcher.AndRequestMatcher:尝试使用Ant[pattern='/**',GET]进行匹配
    o、 s.s.w.u.matcher.AntPathRequestMatcher:请求“POST/user/dashboard”与“GET”不匹配/**
    o、 s.s.w.util.matcher.AndRequestMatcher:不匹配
    
    o、 s.s.w.s.HttpSessionRequestCache:未保存为配置的RequestMatcher的请求不匹配

    请确保表单方法为post
    像这样

    <form th:action="@{/login}" method="post"> 
             <!-- form input -- >
    </form>
    
    
    
    请确保表单方法为post
    像这样

    <form th:action="@{/login}" method="post"> 
             <!-- form input -- >
    </form>
    
    
    
    保存的请求感知包装的全部要点是,在登录后保存并还原上一个请求(或导致登录的请求)。如果这不起作用,那么您的设置也有问题。这也是我所期望的,但是org.springframework.security.web.savedrequest.HttpSessionRequestCache.saveRequest(HttpServletRequest,HttpServletResponse)中的匹配器似乎有些问题不起作用。匹配程序只包含“requestMatchers=[Ant[pattern='/**',而不是我所配置的…”调试消息还显示“正在尝试使用Ant[pattern='/**',GET]进行匹配”->“请求”POST/user/dashboard“不匹配”“GET/**”“不匹配”->“未保存为配置的请求匹配”看一看:您也可以实现自己的RequestMatcher来解决这个问题。可能与csrf筛选器有关?请确保表单方法是这样post的。保存的请求感知包装的全部要点是前一个请求(或导致登录的请求)登录后保存并还原。如果这不起作用,您的设置中会出现错误。这也是我所期望的,但似乎org.springframework.security.web.savedrequest.HttpSessionRequestCache.saveRequest(HttpServletRequest,HttpServletResponse)中的匹配程序出现问题。匹配程序只包含“requestMatchers=[Ant[pattern='/**'”而不是我所配置的…调试消息也会说“尝试使用Ant[pattern='/**',GET]进行匹配”->“请求”POST/user/dashboard“不匹配”“GET/**”“不匹配”->“保存为已配置RequestMatcher的请求不匹配”"看一看:你也可以实现你自己的RequestMatcher来解决这个问题。可能与csrf过滤器有关?请确保表单方法是这样发布的抱歉,但这个解决方案根本与问题无关,我认为你甚至没有解决这个问题…但无论如何,这是5年前的事,在我的设置中是一个问题,正如M.Deinum所说,保存的请求感知包装器负责完成我想要的事情对不起,但是这个解决方案与问题根本没有关系,我想你甚至没有解决这个问题……但无论如何,这是5年前的事了,在我的设置中是个问题,正如M.Deinum所说,保存的请求感知包装器负责完成所有的事情我想要的