Rails API: Найкращий спосіб реалізації автентифікації?


78

Я пишу додаток Rails 4, який розкриє API для мобільного додатка, який ще не розроблений. Користувачі автентифікуються за допомогою електронної пошти та пароля з мобільного додатка.

Хоча я знайшов досить багато інформації по цій темі. Важко розрізнити, що датоване чи неоптимальне. Я читав про HTTP Basic Auth, який здається не надто захищеним, та Auth Authen на основі HTTP, але я не впевнений у тому, як поєднати це із звичайною автентифікацією електронної пошти та паролем (я використовую Devise by шлях).

Я просто хотів би знати, яка на сьогодні найкраща практика, як це реалізувати, тому я впевнений, що піду правильним шляхом.


1
Не знаючи специфіки, моя думка - OAuth2. Використовуйте привратника або самоцвіти oauth2.
Джо Ессі,

Відповіді:


49

З точки зору безпеки, важливим моментом є обмін електронною поштою та паролем користувача на маркер один раз, а потім використання цього маркера для подальших запитів. Це відбувається тому:

  1. Ви не хочете, щоб клієнтська програма відповідала за утримання пароля користувача, де помилка або атака може призвести до його витоку; і
  2. Виданий сервером маркер дає вам (і вашим користувачам) можливість закінчити термін дії маркера, якщо це необхідно, наприклад, заблокувати викрадений пристрій або заблокувати неправильний клієнт API.

Є багато способів досягти цього з різним рівнем складності.

Ось навчальний посібник, який був нещодавно нещодавній та містить детальний покроковий посібник для створення API у Rails з автентифікацією на основі токенів (не використовуючи Devise, але все ще важливий для розуміння концепцій): https://labs.kollegorna.se/blog/ 2015/04 / build-an-api-now /


Дякую! Це те, що мені потрібно було зрозуміти.
Roma149

Окрім маркера пристрою, ви також можете використовувати маркер пристрою. Маркер цієї відповіді може допомогти вам правильно визначити пристрій; він може допомогти у випадку доступу іншого пристрою до вашого веб-сайту.
duykhoa

5

Інший варіант - включити модуль нижче до вашої розробленої МОДЕЛІ та додати auth_token до вашої таблиці.

додаток / моделі / проблеми / token_authenticable.rb

module TokenAuthenticatable
  extend ActiveSupport::Concern

  included do
    before_save :ensure_auth_token
  end

  module ClassMethods
    def find_by_token(token)
      find_by(auth_token: token)
    end
  end

  def ensure_auth_token
    self.auth_token = generate_auth_token if auth_token.blank?
  end

  private

  def generate_auth_token
    loop do
      token = Devise.friendly_token
      break token unless self.class.exists?(auth_token: token)
    end
  end
end

app / controllers / api / v1 / login_controller.rb

...
 def login_user(params)
    if params[:authentication]
      @user = User.find_by(auth_token: params[:authentication])
      if @user.nil?
        render json: err('login user by token failed', ERR_USER_NOT_FOUND), status: :not_found
        event('login_user_by_auth_failed', 'token', params[:authentication])
        return
      else
        render status: :ok, json: @user
        return
      end
    else
      user = user.find_by(email: params[:email])
      if user.nil?
        event('login_user_failed_not_found', 'user_email', params[:email])
        render json: err("login user not found #{params[:email]}", ERR_USER_NOT_FOUND), status: :not_found
        return
      end
      if user.access_locked?
        event('login_user_blocked', 'user_id', user.id)
        render json: err("login user account is locked : #{user.id}", ERR_USER_LOCKED), status: :unauthorized
        return
      end
      unless user.try(:valid_password?, params[:password])
        event("login_user_password_does_not_match #{user.id}", 'user_id',  user.id)
        render json: err('login user password does not match', ERR_PASSWORD_NOT_MATCH), status: :unauthorized
        return
      end
      event('login_user_succeeded', 'user_id', user.id)
      @user= user
      if @user.save
        response.headers['authentication'] = @user.auth_token
        render status: :ok, json: @user
        return
      else
        render json: @user.errors, status: :unprocessable_entity
        return
      end
    end
  end
...

Редагувати: Виправлена ​​помилка, що порушує код


на додачу подивіться на has_secured_password особливість рейок
ілюзіоніст

Я вважаю, що token_authenticable застарілий.
Kelsey Hannan

4

@ Roma149 це більше особисті уподобання, але більшість людей, які тільки починають використовувати Devise, оскільки це найпростіший IMO. OAuth2 - також хороший варіант. Як більш важливу примітку, ви завжди можете перейти до The Ruby Toolbox

Там є багато корисної інформації про дорогоцінні камені, і вони навіть говорять вам про вік та популярність самоцвіту. Це також дозволить вам розрізнити, які саме дорогоцінні камені зараз справді вироджує спільнота, або що занепало.

Пам’ятайте, що в Ruby та Ruby On Rails не завжди краще, ніж краще, але що найкраще відповідає вашому проекту!


3

Камінь Tiddle надає стратегію розробки автентифікації маркерів у програмах Ruby on Rails, призначених лише для API. Основною його особливістю є підтримка декількох токенів на користувача .

https://github.com/adamniedzielski/tiddle

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.