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 end
Tato 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 end
To 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 end
V 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