Začnu tím nejjednodušším řešením. Potřebujeme ochránit přístup k naší aplikaci nebo její části. Začneme třeba u řadiče Listy řídicího zobrazení servisních listů. Chceme aby neautorizovaní uživatelé měli jen možnost založit nový servisní list a nikoliv si prohlížet již založené servisní listy.
V řadiči tedy definuji soukromou metodu login_required:
private
def login_required
unless session[:user_name]
flash[:error] = 'Pro přístup k této stráunce musíte být přihlášen(a).'
redirect_to :action => 'public_index'
end
endTato metoda nědělá nic jiného, než že zkontroluje jestli je uživatel přihlášený a v případě že nikoliv, připraví o tom zprávu a přesměruje jej na nějakou veřejnou stránku. Nějaká veřejná stránka se míní taková, která není kontrolována a kterou smí vidět i neutorizovaný uživatel. Může to být například přihlašovací stránka.
Nyní můžeme v řadiči definovat filtr který ochrání stránky. K tomu použijeme before_filter. V případě že chceme ochránít přístup jen k několika vybraným stránkám, definujeme filtr takto:
before_filter :login_required, :only => [:edit, :destroy, :secret]
Pokud naopak chceme uživateli zamezit přístup všude, s výjimkou několika „veřejných“ stránek, napíšeme filtr takto:
before_filter :login_required, :except => [:login, :public_index, :new, :show, :edit]
V tété chvíli nám již aplikace neumožní přístup na neveřejné stránky. Při přístupu na nevěřejnou stránku je připravena zpráva flash[:error], kterou zobrazíme v layoutu. Protože s oblibou používám layout aplikace, uvedu do něj mezi jinými:
Příklad 47.16. app/views/layouts/application.html.erb:
<div id="pagecontent">
<%= "<div class=\"error\">#{flash[:error]}</div>" if flash[:error] -%>
<%= "<div class=\"info\">#{flash[:info]}</div>" if flash[:info] -%>
<%= "<div class=\"notice\">#{flash[:notice]}</div>" if flash[:notice] -%>
< yield -%>
</div>
Dalším krokem je umožnit uživateli přihlášení, tedy implemetovat metodu login s její formulář.
Příklad 47.17. app/controllers/listy_controller.rb:
def login
if request.post?
if params[:login][:user_name] == 'admin' && params[:login][:password] == 'žížala'
session[:user_name] == params[:login][:user_name]
redirect_to :action => 'index'
else
@auth_error = 'Špatné jméno nebo heslo'
end
end
endTo be done.
Začnu úpravou datového modelu uživatelů aplikace. Tento model, jenž se často jmenuje User s v mém případě jmenuje Person. Ale na jménu nezáleží. Tento model rozšíříme o metody umožňující ověření uživatele. V první variantě nebudu ukládat hesla ani jména do tabulky, protože budu mít jen jednoho „administrátora“ jehož přístup k aplikaci nebude omezován.
Pokud chceme ověřovat uživatele podle databáze, provedeme pár úprav. Nejdříve musíme mít v databázi uživatelská jména a hesla.
Příklad 47.18. db/migrate/:999_add_credentials
class AddCredentials < ActiveRecord::Migration
def self.up
add_column :person, :login, :string, :limit => 16, …
add_column :person, :sha1hash, :string, :limit => 34 …
end
def self.down
remove_column :person, :login
remove_column :person, :sha1hash
end
endV modelu pak nejdříve definujeme metodu pro vytváření hashe z hesla. Tu jsem pojmenoval po metodě kterou používám, tedy sha1_digest. Metodě předávám jeden zatím nevyužitý parametr a to salt.
Příklad 47.19. app/models/person.rb:
require 'digest/sha1' class Person < ActiveRecord::Base def self.sha1_digest(password, salt=nil) '{SHA}'+Base64.encode64(Digest::SHA1.digest(password)).chomp end end
Metodu si odzkoušíme:
$script/consoleLoading development environment (Rails 2.0.2)>>Person.sha1_digest('heslo')=> "{SHA}bgF7VGT4IKbBu16fbXEaZnqA2Oo="
Nyní napíšeme metodu pro ověření uživatele authenticate
Příklad 47.20. app/models/person.rb:
def self.authenticate(login, password)
user = find(:first, :conditions => ['login = ?', login])
return nil if user.nil?
return user if (Person.sha1_digest(password) == user.sha1hash)
nil
end