`
qiezi
  • 浏览: 497158 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

[RoR] Post/Get分派

    博客分类:
  • Ruby
阅读更多
一、前言

出于数据安全性考虑,某些破坏性链接应该使用post请求,比如一个删除记录的请求。

除了脚本确认以外,服务端还需要post验证,因为脚本是可以绕过的。想像你的页面上有一个删除链接,只作了客户端脚本确认(老的scaffold生成代码有这问题),被google找到了,它一个请求就会让你的数据丢失。

rails对于这类请求的处理,是通过verify方法,默认的scaffold生成代码有如下内容:

<!---->  # GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html)
  verify :method => :post, :only => [ :destroy, :create, :update ],
         
:redirect_to => { :action => :list }

只有post请求时,destroy才会被允许,如果是get,就会被重定向到list。

二、实现

我自己实现了一个method_dispatch,当请求一个/test/a时,如果是get,则会直接执行TestController#a;如果是post,则会执行TestController#a_post,a_post应该是protected,这样不会直接暴露给客户,get/post就严格区分开来了。

method_dispatch现在是直接实现在ApplicationController中的,代码如下:

<!---->class ApplicationController < ActionController::Base
  protected
  def self
.method_dispatch(*methods)
    before_filter 
:do_method_dispatch, :only => methods.flatten.map(&:to_sym)
  end

  private
  def do_method_dispatch
    
if request.post? && respond_to?("#{action_name}_post")
      
eval("#{action_name}_post")
      
return false
    end
  end
end

由于ApplicationController里面的方法会被子类继承到,所以必须严格处理访问级别。

使用如下:

<!---->class TestController < ApplicationController
  method_dispatch 
:a

  def 
index
  end

  def a
    render 
:text => 'get a'
  end
  def b
    render 
:text => 'get b'
  end
  protected
  def a_post
    render 
:text => 'post a'
  end
  def b_post
    render 
:text => 'post b'
  end
end

注意a_post,b_post要被保护起来防止直接调用。

index.rhtml里面演示了使用get和post的情况:

<!----><%= link_to "Get a", :action => 'a' %>
<%= link_to "Post a", {:action => 'a'}, {:post => true} %><br />

<%= link_to "Get b", :action => 'b' %>
<%= link_to "Post b", {:action => 'b'}, {:post => true} %><br />

rails在处理有:post => true参数的link_to时,生成的代码如下:

<!----><href="/test/a" onclick="var f = document.createElement('form');
       this.parentNode.appendChild(f); f.method = 'POST'; f.action = this.href; f.submit();return false;"
>Post a</a>

经测试上面代码工作情况良好,使用get访问/test/a时,显示get a;使用post访问时,显示post a。使用get访问/test/b时,显示get b;使用post时,显示get b,因为b并没有使用method_dispatch。

三、应用

下面的posts_controller.rb是scaffold生成的:

<!---->class PostsController < ApplicationController
  def 
index
    list
    render 
:action => 'list'
  end

  
# GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html)
  verify :method => :post, :only => [ :destroy, :create, :update ],
         
:redirect_to => { :action => :list }

  def list
    
@post_pages, @posts = paginate :posts, :per_page => 10
  end

  def show
    
@post = Post.find(params[:id])
  end

  def new
    
@post = Post.new
  end

  def create
    
@post = Post.new(params[:post])
    
if @post.save
      flash[
:notice] = 'Post was successfully created.'
      redirect_to 
:action => 'list'
    
else
      render 
:action => 'new'
    end
  end

  def edit
    
@post = Post.find(params[:id])
  end

  def update
    
@post = Post.find(params[:id])
    
if @post.update_attributes(params[:post])
      flash[
:notice] = 'Post was successfully updated.'
      redirect_to 
:action => 'show', :id => @post
    
else
      render 
:action => 'edit'
    end
  end

  def destroy
    Post
.find(params[:id]).destroy
    redirect_to 
:action => 'list'
  end
end

可以看到,它添加了verify,但action过多,需要在verify中维护一份对应方法名,稍不留神就容易出现漏洞。

我把它修改如下:

<!---->class PostsController < ApplicationController
  method_dispatch 
:new, :edit, :destroy

  def 
index
    list
    render 
:action => 'list'
  end

  def list
    
@post_pages, @posts = paginate :posts, :per_page => 10
  end

  def show
    
@post = Post.find(params[:id])
  end

  def new
    
@post = Post.new
  end

  def edit
    
@post = Post.find(params[:id])
  end

  def destroy
    render 
:inline => <<-EOS
      Are you sure?
      
<%= link_to "Yes", {}, :post => true %>
      
<%= link_to "No", :action => 'edit', :id => params[:id]%>
    EOS
  end

  protected
  def destroy_post
    Post
.find(params[:id]).destroy
    redirect_to 
:action => 'list'
  end
  def edit_post
    
@post = Post.find(params[:id])
    
if @post.update_attributes(params[:post])
      flash[
:notice] = 'Post was successfully updated.'
      redirect_to 
:action => 'show', :id => @post
    
else
      render 
:action => 'edit'
    end
  end
  def new_post
    
@post = Post.new(params[:post])
    
if @post.save
      flash[
:notice] = 'Post was successfully created.'
      redirect_to 
:action => 'list'
    
else
      render 
:action => 'new'
    end
  end
end

相应地,还需要把new.rhtml中的action从create修改到new,把edit.rhtml中的action从update修改到edit。

这样的修改把必须使用post请求的action隐藏起来,而相应的get操作是不修改或删除记录的,如果以post请求,才会自动调用这些保护的方法。
分享到:
评论

相关推荐

    ROR绿色最新环境(2013/3/10)

    ROR环境 Ruby version 1.9.3 (java) RubyGems version 1.8.24 Rack version 1.4 Rails version 3.2.12 JavaScript Runtime therubyrhino (Rhino) Active Record version 3.2.12 Action Pack version 3.2.12 ...

    RoR性能优化经验谈

    Lighttpd在完全接收POST数据后才一次性转发,同时在接收应用服务器响应时也不限制Buffer大小,从而减少了应用服务器的延迟,提高了资源利用率。 除了部署层面的优化,RoR自身的代码优化也很重要。这可能涉及数据库...

    ror

    NULL 博文链接:https://xuxiangpan888.iteye.com/blog/266696

    ror-api:ROR火

    单个组织记录由以下JSON结构表示: { "id":"https://ror.org/013cjyk83", "name":"PSL Research University", "email_address":null, "ip_addresses":[ ], "established":2010, "types":[ "Education" ], ...

    ror实例

    7. **RESTful设计**:Rails鼓励使用REST(Representational State Transfer)原则来构建资源导向的API,通过HTTP动词(GET、POST、PUT、DELETE等)实现资源的操作。 8. **Scaffolding**:快速生成基本CRUD(创建、...

    從 PL/SQL 中調用 ROR 创建的 Web 服务

    你可以使用这个模块发送 GET 或 POST 请求到 ROR API,并接收响应。 - `UTL_HTTP.SET_WIRE_DEBUG(TRUE)` 可以开启调试,查看发送和接收的 HTTP 报文。 - `UTL_HTTP.BEGIN_REQUEST` 初始化一个 HTTP 请求,指定 ...

    ror中文资料

    **Ruby on Rails(简称RoR)中文资料** Ruby on Rails(RoR)是一个基于Ruby编程语言的开源Web应用框架,遵循MVC(Model-View-Controller)架构模式,旨在简化Web开发过程,提高开发效率。RoR强调“约定优于配置”...

    神经网络ror resenet模型

    **神经网络Ror ResNet模型详解** 在深度学习领域,ResNet(残差网络)模型是具有里程碑意义的创新,由He et al.在2015年提出。该模型解决了深度神经网络训练中的梯度消失问题,允许构建非常深的网络结构。而“Ror”...

    RoR选题方向—源代码

    Ruby on Rails(RoR)是一种基于Ruby语言的开源Web应用程序框架,它遵循MVC(Model-View-Controller)架构模式,旨在简化Web开发过程。在这个选题方向中,我们主要探讨的是与RoR相关的源代码分析和学习。源代码是...

    ROR安装必备所有架包

    在Ruby on Rails(ROR)开发环境中,安装和配置正确的依赖包是至关重要的。这个压缩包包含了一系列用于ROR框架的基础组件,但不包括Ruby本身。让我们深入了解一下这些包的作用和重要性。 首先,`actionpack`是Rails...

    初探ROR

    **初探ROR** Ruby on Rails(简称ROR)是一个基于Ruby编程语言的开源Web应用程序框架,它遵循MVC(模型-视图-控制器)架构模式,旨在促进开发过程的简洁性和效率。Ruby on Rails的核心理念是“Don't Repeat ...

    RoRBlog 基于RoR的博客系统

    基于RoR的博客系统,代码风格简单清晰,前后太完善,适合初学者。

    Windows 上搭建 ROR环境

    ### Windows上搭建Ruby on Rails(ROR)环境详解 #### 一、引言 随着Web开发技术的不断发展,Ruby on Rails(简称Rails或ROR)作为一种高效、简洁且优雅的Web开发框架,受到了广大开发者的青睐。然而,在Windows...

    ROR 文件的上传与下载

    2. **文件下载**:`get_file`方法用于提供用户下载或直接查看文件(如图片)。它从数据库中检索最新的记录(即最新上传的文件),并使用`send_data`方法发送文件数据。`send_data`的`type`参数应根据文件类型设定...

    RoR,十分钟做Blog

    【RoR,十分钟做Blog】这篇教程主要介绍了如何使用Ruby on Rails(RoR)框架在NetBeans IDE上快速创建一个简单的博客程序。RoR是一个基于MVC(模型-视图-控制器)架构的Web开发框架,它使得开发过程更加高效且简洁。...

    ROR环境配置

    你需要下载适合你操作系统的Ruby版本,例如,对于Windows用户可以从Ruby官方网站下载安装包,而对于Linux或Mac用户,可以通过包管理器如apt-get、yum或brew进行安装。确保在安装过程中勾选添加Ruby到系统路径选项,...

    RoR 培训课程PPT

    ### RoR培训课程PPT知识点概述 #### 一、课程概览与背景介绍 - **课程性质**:本课程为为期五天的Ruby on Rails(简称RoR)入门级培训,适合初学者快速掌握RoR的基本概念和技术要点。 - **讲师信息**:由Peter ...

    freemis 基于ror框架的mis

    FreeMIS是一个基于Ruby on Rails(RoR)框架构建的管理信息系统(MIS)。RoR是由David Heinemeier Hansson开发的一个开源Web应用程序框架,它遵循“Don't Repeat Yourself”(DRY)原则,强调简洁和生产力。RoR使用...

    机遇ROR 的图书管理系统

    《机遇ROR的图书管理系统》是一份以Ruby on Rails(简称ROR)技术为核心,旨在构建高效、便捷的图书管理解决方案的学习资料。Ruby on Rails,是基于Ruby编程语言的开源Web应用框架,它遵循MVC(Model-View-...

Global site tag (gtag.js) - Google Analytics