验证rails中的网站所有权

时间:2009-12-03 19:47:12

标签: ruby-on-rails

有关类似主题的最新讨论,请检查this提问。

验证特定用户是否拥有网站所有权的最佳方法是什么?

假设你有这个模型:

class User < ActiveRecord::Base
   has_many :websites
end

为了确保用户确实拥有该网站,我考虑过进行电子邮件验证。示例:用户将example.com列为其网站,并将电子邮件发送至username@example.com。如果用户从example.com发送响应消息,则该网站将进行验证。

问题在于,如果有一个网站,一大群人可以从具有该域名的网站发送电子邮件,例如gmail.com。我不希望用户将gmail注册为他们的个人网站。

因此,最好的方法是让用户在HTML中嵌入一些代码,rails应用程序确保代码存在。

你会怎么做呢?

5 个答案:

答案 0 :(得分:8)

这是您使用RESTful样式的Google子域方法验证域的方法。您将允许用户创建站点记录,该记录将保持未验证状态,直到用户稍后单击链接/按钮以在稍后验证域(以允许DNS传播)。

此代码未经测试,但可以帮助您入门。

型号:

class Site < ActiveRecord::Base
  # schema
  # create_table "sites", :force => true do |t|
  #  t.string   "domain"
  #  t.string   "cname"
  #  t.integer  "user_id"
  #  t.boolean  "verified"
  #  t.datetime "created_at"
  #  t.datetime "updated_at"
  # end

  require "resolv"

  YOUR_DOMAIN = "example.com"

  belongs_to :user
  before_create :generate_cname

  attr_accessible :domain
  …

  # Validate unless already validated
  def validate!
    validate_cname unless self.verifed == true
  end

  protected

  # Generate a random string for cname
  def generate_cname
    chars = ('a'..'z').to_a
    self.cname = 10.times.collect { chars[rand(chars.length)] }.join
  end

  # Sets verifed to true if there is a CNAME record matching the cname attr and it points to this site.
  def validate_cname
    Resolv::DNS.open do |domain|
      @dns = domain.getresources("#{cname}.#{domain}", Resolv::DNS::Resource::IN::CNAME)
     self.verified = !@dns.empty? && @dns.first.name.to_s == YOUR_DOMAIN
    end
  end

end

控制器

class SitesController < ActionController::Base
  # Usual RESTful controller actions
  # …

  def validate
    @site = current_user.sites.find(params[:id])
    @site.validate!

    respond_to do |format|
      if @site.save && @site.verified
        flash[:notice] = 'Site verified!'
        format.html { redirect_to(@site) }
        format.xml  { head :ok }
      else
        flash[:Error] = 'Site verification failed!'
        format.html { redirect_to(@site) }
        format.xml  { render :status => :unprocessable_entity }
      end
    end

  end
end

把它放在routes.rb:

map.resources :sites, :member => { :validate => :put }

我会把观点作为练习留给你。

答案 1 :(得分:3)

您可以通过让他们在他们的网站上放置一些您可以用来确认的javascript /代码,以类似于谷歌分析的方式进行确认。或者,您可以让他们创建一个您可以检查的DNS记录 - 这两个记录都会显示网站的实际所有权,而不仅仅是域的一部分。

答案 2 :(得分:2)

Google网站工具可让您只上传具有特定名称的文件。所以,你可以要求用户创建一个文件,以便你验证他们拥有网站

require 'digest/sha1'
require 'net/http'

# you may want to store a unique value in the website table instead
unique_id = Digest::SHA1.hexdigest("#{website.id}/#{website.created_at}")
response = Net::HTTP.start(website.url, 80) {|http| http.head("/verify_#{unique_id}.html") }
website.verified = true if response.code == "200"

答案 3 :(得分:0)

特定代码嵌入的特殊代码(如Google Analytics)。

您还可以请求用户必须在给定域内提供具有指定内容的URL。例如,用户表示在域 www.foo.com 的网址 / vali / date / me 下,您可以找到生成“有效”的页面文本。

答案 4 :(得分:0)

非常感谢你们。我使用了Steve和Amiel的建议,找到了一个有效的解决方案:

在网站模型中:

class Website < ActiveRecord::Base
  require 'net/http'

  belongs_to :user
  before_create :generate_unique_id

  # Validate unless already validated
  def verify!
    verify_unique_id unless self.verified == true
  end

  protected

  # Generate a random string for unique_id
  def generate_unique_id
    self.unique_id = ActiveSupport::SecureRandom.hex(10)
  end

  def verify_unique_id
  response = Net::HTTP.start(self.domain, 80) {|http| http.head("/#   {unique_id}.html") }
    self.verified = true if response.code == "200"
  end

end

除了应用程序找到网站ID的部分外,控制器与史蒂夫的建议几乎没有变化:

    def verify
    @website = Website.find_by_id(params[:website])
    @website.verify!

    respond_to do |format|
      if @website.save && @website.verified == true
        flash[:notice] = 'Site verified!'
        format.html { redirect_to(websites_path) }
        format.xml  { head :ok }
      else
        flash[:notice] = 'Site verification failed!'
        format.html { redirect_to(websites_path) }
        format.xml  { render :status => :unprocessable_entity }
      end
    end
end

最后,我有一个用户网站的索引视图(这很丑陋,但它完成了工作):

<% for website in @websites %>
<%= link_to "#{website.domain}", website %> | 
<% if website.verified? %> VERIFIED |  
<% else %> NOT VERIFIED 
<%= link_to "Verify your website", verify_website_path(:website => website.id), :id => website.id %>
Verification key: <%= website.unique_id %>
<% end %><% end %>
<%= link_to "Add a website", new_website_path %>

无论如何,我通过我现有的一个网站进行了一些手动测试,它没有问题。我当然还要实施其他验证,但这是我真正需要帮助的。谢谢你们!

贤治