【问题标题】:block a direct call to a controller阻止对控制器的直接调用
【发布时间】:2015-01-29 21:22:32
【问题描述】:

我正在使用 JAVA Spring mvc 开发一个网站。我有一个需要两个控制器的功能。首先,请求由控制器 1 处理,控制器使用返回的新 ModelAndView(“redirect:controller2.htm”)将请求重定向到控制器 2。一切正常。但是,我想阻止对控制器 2 的直接访问(阻止来自 url“controller2.htm”的调用),因为控制器 2 的表单需要来自控制器 1 的数据。我希望使用控制器 2 的唯一情况是重定向来自控制器 1。我想要一个没有注释的解决方案。在此先感谢您的帮助。 这是代码: 控制器1:

public class controller1 extends SimpleFormController implements Serializable {
private PersonManager pManager ;   
@Override
public ModelAndView onSubmit(Object command) {
    CommandPerson cmd = (CommandPerson) command;
    Person p = null;
        String viewName = "redirect:controller2.htm";
        try {
            p = pManager.getPersonbyID(cmd.getID());
        } catch (EmptyResultDataAccessException ex) {
      viewName="NosuchPerson";
        }
       ModelAndView mav = new ModelAndView(viewName);
        mav.addObject("ID",cmd.getID());   
        return mav;
 }

控制器2:

  public class controller2 extends SimpleFormController implements Serializable {
    private PersonManager pManager ;   
    @Override
    public ModelAndView onSubmit (Object command) throws ServletException, IOException { 

          Person p = (Person) command;
         Map<String,Object> model = new HashMap<String,Object>();
                pManager.UpdatePerson(p);
                model.put("person", p);
               return new ModelAndView("SuccesfulUpdate","model",model);

        }

    protected Object formBackingObject(HttpServletRequest request,HttpServletResponse response)
             throws ServletException, IOException {
                        String  id = request.getParameter("ID");
                        if(id==null) {
                            response.sendRedirect("controller1.htm");
                            return null;
                        } else{
                    Personne p = pManager.getPersonbyID(id);
                          return p;
                }}

如果直接调用 url “controller2.htm”,则 ID 参数将为 null,并且由于 formBackingObject() 是处理请求时执行的第一个方法,我想我可以在其中进行重定向,但它没有工作,因为我被重定向到 controller2 的表单为空。

【问题讨论】:

  • 重定向会导致 浏览器 发出对重定向 URL 的请求。您希望如何实现这种差异化?
  • 解决这个问题的方法太多了。也许最简单的方法是在网络级别限制访问。
  • 该功能是一种更新功能。第一个表单是用户在表单的字段中填写一个 id ,然后第一个控制器检查具有指定 ID 的对象是否存在于数据库中。如果存在,则重定向到第二个控制器,该控制器使用 ID 从数据库中提取对象,然后使用 formBackingmethod() 用对象的当前值填充第二个表单。我只是想阻止对控制器 2 的直接访问,因为如果用户直接从浏览器调用 url “controller2.htm”,他将不会得到预先填写的表单。
  • 你能显示重定向代码吗?

标签: java spring-mvc


【解决方案1】:

您的问题非常接近跨站点请求伪造保护,因此应该应用相同的通用解决方案。

您只需要在Controller1 中生成一个随机令牌,将其以任意名称(例如"_csrf")放入模型中,并将其值存储在会话中。然后在Controller2 中测试:

  • 参数请求_csrf存在于请求中
  • 它等于存储在会话中的值

并立即从会话中删除 _csrf 值。

如果满足这两个要求,则很有可能Controller2 是通过来自Controller1 的重定向调用的,因为没有其他人应该能够猜到该值

【讨论】:

  • 感谢您的回答。实际上,我想阻止通过 url "controller2.htm" 直接访问 controller2。所以,我不知道这是否可能,只要直接从浏览器调用“controller2.htm”,就将请求重定向到“controller1”。我想让控制器2依赖于控制器1,所以调用“控制器2 .htm”就像我们调用“controller1.htm”一样,因为更新功能需要由controller1然后controller2处理。因此,最好阻止对controller2的直接访问,因为它也必须在controller1之后使用。
【解决方案2】:

我终于找到了解决办法。我重写了 showForm 方法。在这种方法中,我可以测试请求中是否存在参数。如果存在,则调用 formBackingObject 方法并显示控制器 2 的表单,否则将重定向到控制器 1。

控制器1:

 public class controller1 extends SimpleFormController implements Serializable {
private PersonManager pManager ;   
@Override
public ModelAndView onSubmit(Object command) {
    CommandPerson cmd = (CommandPerson) command;
    Person p = null;
        String viewName = "redirect:controller2.htm";
        try {
            p = pManager.getPersonbyID(cmd.getID());
        } catch (EmptyResultDataAccessException ex) {
      viewName="NosuchPerson";
        }
       ModelAndView mav = new ModelAndView(viewName);
        mav.addObject("ID",cmd.getID());   
        return mav;
 }

控制器2:

 public class controller2 extends SimpleFormController implements Serializable {
        private PersonManager pManager ;   
        @Override
        public ModelAndView onSubmit (Object command) throws ServletException, IOException { 

              Person p = (Person) command;
             Map<String,Object> model = new HashMap<String,Object>();
                    pManager.UpdatePerson(p);
                    model.put("person", p);
                   return new ModelAndView("SuccesfulUpdate","model",model);

            }

        protected Object formBackingObject(HttpServletRequest request,HttpServletResponse response)
                 throws ServletException, IOException {
                            String  id = request.getParameter("ID");
                            if(id==null) {
                                response.sendRedirect("controller1.htm");
                                return null;
                            } else{
                        Personne p = pManager.getPersonbyID(id);
                              return p;
                    }}

     protected ModelAndView showForm(HttpServletRequest request, HttpServletResponse response, BindException errors)throws Exception {
        String id = request.getParameter("ID");
    if (id==null) return new ModelAndView("redirect:controller1.htm");
    else{
            Personn p = (Personne) formBackingObject(request, response);
        return new ModelAndView("UpdatePersonForm","Person",p);
        }}

【讨论】:

    猜你喜欢
    • 2016-08-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-02
    • 2016-04-20
    相关资源
    最近更新 更多