Checking website ownership on rails

For a later discussion on a similar topic, check this box.

What is the best way to check if a particular user owns a website?

Say you had this model:

class User < ActiveRecord::Base
   has_many :websites
end

To make sure that the user actually owns this site, I thought about doing email checks. Example: example.com user lists as their website, and an email is sent to username@example.com. If the user sends a response message from example.com, the site checks.

The problem with this is that there is a website where a large group of people could send an email from a website with that domain name, for example gmail.com. I would not want the user to register gmail as their personal site.

Thus, the best way to do this is to force the user to embed some code in the HTML, and rails applications are sure that this code is.

How would you do that?

+3
source share
5 answers

This is how you can verify a domain using the google subdomain approach in a RESTful style. You will allow the user to create a site record that will remain unverified until the user later clicks on the link / button to check the domain later in order to allow DNS distribution.

, .

:

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 }

.

+8

, , Google, javascript/, . DNS, , - , .

+3

Google Website . , , , -.

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"
+2

, (, Google Analytics).

, URL- . , , URL /vali/date/me www.foo.com VALIDATED " .

0

, . , , :

-:

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

, , -:

    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 %>

In any case, I conducted this through several manual tests with one of my existing websites, and it works without problems. I still, of course, have to perform other checks, but this was the one I really need help with. Thanks guys!

Kenji

0
source

Source: https://habr.com/ru/post/1724670/


All Articles