Система аутентифікації і контролю доступу Padrino забезпечує простий спосіб створювати свої системи аутентифікації. У поєднанні з OmniAuth ви можете легко використовувати її для аутентифікації за допомогою різних методів. Читайте нижче для більш докладної інформації про те, як інтегрувати їх.
У цій статті ми розглянемо дві теми:
- Інтеграцію Padrino Admin Authentication в усі додатки вашого проекту
- Створення власних стратегій аутентифікації
На відміну від оригінальної статті, де у якості ORM використовується ActiveRecord, тут ми будемо використовувати DataMapper, про який я писав тут. Можливо вам необхідно познайомитись з фреймворком Padrino, про який я писав тут і тут. І про OmniAuth тут.
Перш ніж ми почнемо, важливо відзначити, що наша вбудована аутентифікація, що базується на ролях, може взаємодіяти з іншими системами. Потрібно лише внести зміни у файли session.rb і account.rb для того щоб додати свій власний код.
Отже, давайте почнемо зі створення проекту використовуючи DataMapper:
$ padrino g project omniauth_dm --orm datamapper --tiny
$ cd omniauth_dm/
$ bundle install
Додаємо модель Account:
$ padrino g model Account name:string email:string role:string uid:string provider:string
| name | ім'я користувача | 
|---|---|
| email користувача | |
| role | роль контролю доступу | 
| uid | ідентифікатор користувача omniauth | 
| provider | постачальник omniauth | 
Створюємо базу даних:
$ padrino rake dm:migrate
Відкриваємо файл Gemfile і додаємо рядок:
# Gemfile
gem 'omniauth'
Запускаємо bundle install щоб встановити залежності:
$ bundle install
Тепер потрібно додати OmniAuth middleware. Тут доступні два шляхи:
- Додати middleware для всьо проекту(таким чином всі піддодатки зможуть використовувати його)
- Додати middleware тільки для додатку, який його потребує
В нашому прикладі, нам потрібно просто змінити app/app.rb:
# app/app.rb
class OmniauthDm < Padrino::Application
# ...
  use OmniAuth::Builder do
    provider :vkontakte, 'application_id', 'secure_key'
    provider :facebook, 'app_id', 'app_secret'
  end
# ...
end
Якщо ви вибрали multiapp сценарій вам необхідно відредагувати config/boot.rb:
# config/boot.rb
Padrino.use OmniAuth::Builder do
  provider :vkontakte, 'application_id', 'secure_key'
  provider :facebook, 'app_id', 'app_secret'
end
# before the line
Padrino.load!
Для отримання app_id і app_secret для Facebook необхідно:
- Перейти до сторінки розробників Facebook
- Натиснути Створити новий додаток
- Вказати ім’я додатку і заповнити форму
- Закінчивши, ви зможете змінити налаштування. Перейдіть у розділ Website
- Додати до site url: http://localhost:3000
- Додати до domain: localhost
- Записати "Application ID" і "Application Secret" до OmniAuth::Builder
Для отримання application_id і secure_key для ВКонтакте необхідно:
- Перейти до сторінки для розробників ВКонтакте
- Натиснути Створити додаток
- Вказати ім’я додатку і заповнити форму
- Закінчивши, ви зможете змінити налаштування.
- Додати до "Адреса сайту": http://localhost:3000/
- Додати до "Базовий домен": localhost
- Записати "ID додатку" і "Захисний ключ" до OmniAuth::Builder
ПРИМІТКА: Для домену не важливо чи шлях існуючий, тому що OmniAuth змінює callback url.
Далі, ми можемо інтегрувати нашу системи аутентифікації у app/app.rb:
class OmniauthDm < Padrino::Application
  # ...
  register Padrino::Admin::AccessControl
  set :login_page, "/" # визначає URL для входу
  access_control.roles_for :any do |role|
    role.protect "/profile"
    role.protect "/admin"
  end
  # тепер додаємо роль для користувачів
  access_control.roles_for :users do |role|
    role.allow "/profile"
  end
  
  # ...
end
І додамо декілька маршрутів у app/controllers.rb:
OmniauthDm.controllers  do
# ...
  get :index do
    haml <<-HAML.gsub(/^ {6}/, '')
      - if !current_account.nil?
        Hello
        =link_to(current_account['name'], url(:profile))
        %br
        =button_to('Log Out', url(:destroy), :method => :delete)
      - else  
        Login with
        =link_to('Facebook', '/auth/facebook')
        or
        =link_to('Vk', '/auth/vkontakte')
    HAML
  end
  get :profile do
    content_type :text
    current_account.to_yaml
  end
  delete :destroy do
    set_current_account(nil)
    redirect url(:index)
  end
  get :auth, :map => '/auth/:provider/callback' do
    auth    = request.env["omniauth.auth"]
    account = Account.find_by_provider_and_uid(auth["provider"], auth["uid"]) || 
              Account.create_with_omniauth(auth)
    set_current_account(account)
    redirect "http://" + request.env["HTTP_HOST"] + url(:profile)
  end
# ...
end
Вище ми посилаємося до методу Account.create_with_omniauth. Крім того для забезпечення працездатності потрібно створити методи find_by_id та find_by_provider_and_uid, які в ActiveRecord визначаються автоматично завдяки так званим "Dynamic attribute-based finders". Відкрийте app/models/account.rb і додате:
class Account
# ...
  def self.find_by_id(id)
    get(id) rescue nil
  end
  def self.find_by_provider_and_uid(provider, uid)
    first(:provider => provider, :uid=> uid) rescue nil
  end
  def self.create_with_omniauth(auth)
    account = Account.new
    account.provider = auth["provider"]
    account.uid      = auth["uid"]
    account.name     = auth["user_info"]["name"] if auth["user_info"]
    account.email    = auth["user_info"]["email"] if auth["user_info"] # тільки для Facebook. ВКонтакте не повертає email користувача :(
    account.role     = "users"
    account.save
    return account
  end
# ...
end
Настрав час запустити сервер і подивитись, що у нас вийшло:
$ padrino start
Перейдіть до http://localhost:3000/profile
Це приведе вас до початкової сторінки login_page, в нашому випадку /.
Тепер ви можете увійти тут http://localhost:3000
Це все, що вам потрібно для налаштувати скелету системи аутентифікації в Padrino.
 
Немає коментарів:
Дописати коментар