Spring Boot 中有没有办法限制对某个端点的访问,除非提交了前一页的表单?

Posted

技术标签:

【中文标题】Spring Boot 中有没有办法限制对某个端点的访问,除非提交了前一页的表单?【英文标题】:Is there a way in Spring Boot to restrict access to a certain endpoint unless a form from a previous page is submitted? 【发布时间】:2021-11-17 12:53:08 【问题描述】:

这是我的 Spring Boot 应用程序的正常行为:

用户可以在其中填写包含一般信息的表单的登录页面 (http://localhost:8085/customers/generalInfo/)。提交后,用户将被重定向到财务详细信息页面 (http://localhost:8085/customers/financialDetails),他可以在其中填写另一个表单并提交结果。

我的控制器类如下:

GeneralInfoController.java

@Controller
@RequestMapping("/customers/generalInfo")
public class CustomerController 

    @GetMapping
    public String openCustomerForm(Model model) 

        model.addAttribute("mainContact", new MainContact());

        return "general-info"; // general-info.html
    
    
    @PostMapping("/saveInfo")
    public String saveCustomerForm(@Valid MainContact mainContact, Model model) 
        /*
         *  something
         */
        return "redirect:/customers/financialDetails";
    

financialDetailsController.java

@Controller
@RequestMapping("/customers/financialDetails")
public class CustomerController 

    @GetMapping
    public String openFinDetailsForm(Model model) 
        model.addAttribute("financialDetails", new FinancialDetails());
        return "financial-details"; // financial-details.html
    
    
    @PostMapping("/saveFinancialDetails")
    public String saveFinancialForm(@Valid FinancialDetails financialDetails, Model model) 
        /*
         *  something
         */
        return "redirect:/done";
    

我的问题是我可以通过 http://localhost:8085/customers/financialDetails 访问财务详细信息表单,甚至无需填写一般信息表单,这是完全可以预料的。但就我而言,除非填写并提交了“一般信息”表单,否则我不希望用户访问“财务详细信息”页面。

我尝试使用 Spring-boot 的安全性。如果我明确授权某些端点(这意味着默认情况下所有其他端点都受到限制),那么即使提交以前的表单,“/customers/financialDetails”端点也将无法访问。(预期行为)

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter 
    
    @Override
    protected void configure(HttpSecurity http) throws Exception 
        
            http.authorizeRequests()
                .antMatchers("/customers/generalInfo",
                             "/assets/**",
                             "/common/**",
                             "/images/**",
                             "/js/**",
                             "/styles/**")
                .permitAll()
                .anyRequest().authenticated();
    


换句话说,我不希望此应用程序的用户能够通过输入 URL 直接从浏览器访问第二个表单。他应该有权访问“/customers/generalInfo”,并且只有在填写并提交表单时才被重定向到“/customers/financialDetails”。这甚至可以在 Spring-boot 中实现吗?

【问题讨论】:

您可以简单地在openFinDetailsForm...中添加条件重定向? @slauth 感谢您的回复。有没有办法检查openFinDetailsForm 是否被saveCustomerForm() 调用? 我认为您应该只关注所需数据是否可用。最后,您必须将其存储在某个地方,不是吗?如果数据丢失,重定向到起点。 @slauth 确实如此。数据存储在 Oracle DB 中。我将尝试检查您提到的表单数据是否可用,并希望它有效。感谢您的帮助! 【参考方案1】:

首先,确保在提交表单并重定向到财务之前填写用户信息页面上的每个字段

生成一个ID以及用户详细信息页面,如果填写并提交了用户详细信息页面,则可以在您的数据库中生成该ID。

然后将该 ID 作为参数传递到您的财务详细信息的 URL 中,并在您的控制器中将其作为请求参数,将其置于一个条件是否为空,然后通过重定向传递它或在没有用户的情况下无法访问详细信息。

【讨论】:

感谢您的回复@Pranay,我会试一试。我想出了一种不需要在我的数据库上执行任何 CRUD 操作的方法。在我的财务控制器中,我只是从HttpServletRequest 的标题中读取referrer 属性并检查它是否为空。 (在我的openFinDetailsForm() 方法中将HttpServletRequest 添加到我的参数列表中) 这样看起来更有意义、更紧凑。

以上是关于Spring Boot 中有没有办法限制对某个端点的访问,除非提交了前一页的表单?的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法使用spring boot starter app graphql-spring-boot-starter公开2个graphql端点?

关于spring-boot-actuator的httptrace端点不生效问题解决办法

如何在 /info 执行器端点中获取 Spring Boot 的版本

如何在 Spring(Boot)中装饰 REST 响应?

没有 REST 端点在 Spring Boot 应用程序中工作

IDEA中添加spring-boot-configuration-processor依赖但yml文件对自己创建的类没有提示的解决办法