Как реализовать аутентификацию в Rails-приложении?ruby-46

1. Выбор стратегии аутентификации

Вариант 1: Devise

Самый популярный гем для аутентификации в Rails:

# Добавляем в Gemfile
gem 'devise'
bundle install
rails generate devise:install
rails generate devise User
rails db:migrate

Вариант 2: Ручная реализация

rails generate model User email:string password_digest:string

2. Настройка Devise

Конфигурация :

config.mailer_sender = 'no-reply@example.com'
config.pepper = ENV['DEVISE_PEPPER']
config.sign_out_via = :delete

Модель User:

class User < ApplicationRecord
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable,
         :confirmable, :lockable, :trackable
end

3. Контроллеры и маршруты

Devise автоматически добавляет маршруты:

devise_for :users

Для кастомизации контроллеров:

rails generate devise:controllers users

4. Аутентификация через токены

Настройка:

class User < ApplicationRecord
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable

  before_create :generate_authentication_token

  private

  def generate_authentication_token
    self.authentication_token = Devise.friendly_token
  end
end

Контроллер сессий:

class Api::SessionsController < ApplicationController
  skip_before_action :verify_authenticity_token

  def create
    user = User.find_by(email: params[:email])
    if user&.valid_password?(params[:password])
      render json: { token: user.authentication_token }
    else
      render json: { error: 'Invalid credentials' }, status: :unauthorized
    end
  end
end

5. OAuth аутентификация

Пример с GitHub:

gem 'omniauth-github'

Конфигурация:

config.omniauth :github, ENV['GITHUB_KEY'], ENV['GITHUB_SECRET']

Добавляем в модель User:

devise :omniauthable, omniauth_providers: [:github]

def self.from_omniauth(auth)
  where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
    user.email = auth.info.email
    user.password = Devise.friendly_token[0,20]
  end
end

6. Защита контроллеров

Базовый подход:

class ApplicationController < ActionController::Base
  before_action :authenticate_user!
end

Кастомные политики :

gem 'pundit'

Настройка:

class ApplicationController < ActionController::Base
  include Pundit
  rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized

  private

  def user_not_authorized
    flash[:alert] = "You are not authorized to perform this action."
    redirect_to(request.referrer || root_path)
  end
end

7. Тестирование аутентификации

Системные тесты:

test "login with valid credentials" do
  visit new_user_session_path
  fill_in 'Email', with: users(:one).email
  fill_in 'Password', with: 'password'
  click_button 'Log in'
  assert_text 'Signed in successfully'
end

Контроллер-тесты:

setup do
  @user = users(:one)
  sign_in @user
end

test "should get index" do
  get posts_url
  assert_response :success
end

8. Безопасность

Обязательные меры:

  1. HTTPS для всех запросов
  2. Защита от brute-force атак:
    config.paranoid = true
    config.lock_strategy = :failed_attempts
    config.maximum_attempts = 5
    
  3. Валидация паролей:
    config.password_length = 8..128
    config.strip_whitespace_keys = [:email]
    

9. Дополнительные функции

JWT аутентификация:

gem 'jwt'

Двухфакторная аутентификация:

gem 'devise-two-factor'

Резюмируем: реализация аутентификации в Rails может варьироваться от простой Devise-интеграции до сложных кастомных решений с OAuth и JWT. Ключевые аспекты — безопасность, удобство пользователя и правильная интеграция с остальными компонентами приложения.