Сидя в Москве (как тут у вас многолюдно
, нашел время на написание серии статей по Rails.
Сегодняшняя тема навеяна печальным сообщением. Итак моя задача: показать как можно легко сделать авторизацию в Ruby on Rails. Задача новичков прочитать и попробовать, задача не новичков прочитать и написать как сделать лучше и/или указать на ошибки.
Использованные инструменты:
- Ruby 1.8.6
- Mac OS X 10.5.6
- Rails 2.2.2
- Mongrel 1.1.5
- MySQL 5.0.51b
Стандартные операции:
rails auth -d [любимая БД]
cd auth
rm public/index.html
[отредактировать config/database.yml]
rake db:create
Для авторизации в RoR существует куча плагинов. Я буду использовать restful-authentication.
Установка достаточно стандартна:
script/plugin install git://github.com/technoweenie/restful-authentication.git
Теперь нужно создать модель пользователя, в которой будет храниться логин пароль и другие пользователь-related данные. Так же понадобиться два контроллера. Один для регистрации, а другой для логина/логаута. Пусть модель пользователя будет user, а контроллер для логина логаута sessions, тогда выполнив такую команду:
script/generate authenticated user sessions
плагин все сделает за нас. У этого генератора есть несколько опций, например –include-activation, которая добавит активацию пользователя по e-mail. За более подробной информацией рекомендую обратиться к документации.
Генератор создаст два контроллера users и sessions, модель user, миграцию для модели user, записи в config/routes.rb и пару виюх которые скорей всего вы сразу же замените своими.
Роуты выглядят следующим образом:
Copy Source | Copy HTML
ActionController::Routing::Routes.draw do |map|
map.logout '/logout', :controller => 'sessions', :action => 'destroy'
map.login '/login', :controller => 'sessions', :action => 'new'
map.register '/register', :controller => 'users', :action => 'create'
map.signup '/signup', :controller => 'users', :action => 'new'
map.resources :users
map.resource :session
end
Как видно все довольно хорошо вписывается в REST:
sessions/new [GET] форма логина
sessions [POST] авторизация
sessions [DELETE] logout
users/new [GET] форма регистрации
users [POST] регистрация
Я рекомендую с помощью опций роутов(введенных не так давно, не помню с какой версии)
nly и :except, отредактировать запись map.resources :users (map.resources :users, :except => [:edit, :update, :destroy], for example). Например редактирование лучше перенести в отдельный роут: map.resource :profile, (редактирование в таком случае будет выглядить так: /profile/edit), так как скорей всего в вашем приложении одни пользователи других редактировать не должны.
Посмотрим на модель app/models/user.rb:
Copy Source | Copy HTML
require 'digest/sha1'class User < ActiveRecord::Base
include Authentication
include Authentication::ByPassword
include Authentication::ByCookieTokenvalidates_presence_of :login
validates_length_of :login, :within => 3..40
validates_uniqueness_of :login
validates_format_of :login, :with => Authentication.login_regex, :message => Authentication.bad_login_messagevalidates_format_of :name, :with => Authentication.name_regex, :message => Authentication.bad_name_message, :allow_nil => true
validates_length_of :name, :maximum => 100validates_presence_of :email
validates_length_of :email, :within => 6..100
validates_uniqueness_of :email
validates_format_of :email, :with => Authentication.email_regex, :message => Authentication.bad_email_messageattr_accessible :login, :email, :name, :password, :password_confirmation
def self.authenticate(login, password)
return nil if login.blank? || password.blank?
u = find_by_login(login.downcase) # need to get the salt
u && u.authenticated?(password) ? u : nil
enddef login=(value)
write_attribute :login, (value ? value.downcase : nil)
enddef email=(value)
write_attribute :email, (value ? value.downcase : nil)
end
end
В принципе ничего интересного разве что, мне не совсем нравится, что логином выступает не e-mail. Чтобы это поправить нужно сдеать следующее: удалить из миграции db/migrate/xxxx_users.rb запись t.column :login, :string, :limit => 40. Модель пользователя сделать такой:
Copy Source | Copy HTML
require 'digest/sha1'class User < ActiveRecord::Base
include Authentication
include Authentication::ByPassword
include Authentication::ByCookieTokenvalidates_format_of :name, :with => Authentication.name_regex, :message => Authentication.bad_name_message, :allow_nil => true
validates_length_of :name, :maximum => 100validates_presence_of :email
validates_length_of :email, :within => 6..100
validates_uniqueness_of :email
validates_format_of :email, :with => Authentication.email_regex, :message => Authentication.bad_email_messageattr_accessible :email, :name, :password, :password_confirmation
def self.authenticate(login, password)
return nil if login.blank? || password.blank?
u = find_by_email(login.downcase) # need to get the salt
u && u.authenticated?(password) ? u : nil
enddef email=(value)
write_attribute :email, (value ? value.downcase : nil)
end
end
Файл app/views/users/new.html.erb тоже придеться изменить:
<h1>Sign up as a new user</h1>
<% @user.password = @user.password_confirmation = nil %><%= error_messages_for :user %>
<% form_for :user, :url => users_path do |f| -%><p><%= label_tag ‘email’ %><br/>
<%= f.text_field :email %></p><p><%= label_tag ‘password’ %><br/>
<%= f.password_field :password %></p><p><%= label_tag ‘password_confirmation’, ‘Confirm Password’ %><br/>
<%= f.password_field :password_confirmation %></p><p><%= label_tag ‘name’ %><br/>
<%= f.text_field :name %></p><p><%= submit_tag ‘Sign up’ %></p>
<% end -%>* This source code was highlighted with Source Code Highlighter.
Все готово! Осталось выполнить миграции и запустить проект.
Для полноты можно добавить рутовый роут. Генерация рутового контроллера:
script/generate controller home index
в config/routes.rb добавить:
map.root :controller => 'home'
Добавить лайтаут (app/views/layouts/application.html.erb):
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<title>auth demo</title>
</head>
<body>
<%= render :partial => 'users/user_bar' %>
<%= yield %>
</body>
</html>* This source code was highlighted with Source Code Highlighter.
Некоторые пояснения. В контроллере/виюхе «залогиненность» нужно проверять функцией logged_in? (true/false) доступ к пользователю который сейчай авторизован осуществляется через current_user. Готовый проект, в котором есть несколько исправлений не отраженных в статье.
Апрель 2, 2009 в 3:22 дп |
первый раз не увидел спама в комментариях
Апрель 16, 2009 в 10:52 дп |
Нет поситителей – нет и спама