Rails API: Der beste Weg, um die Authentifizierung zu implementieren?


78

Ich schreibe eine Rails 4-App, die eine API für eine mobile App bereitstellt, die noch entwickelt werden muss. Benutzer authentifizieren sich mit einer E-Mail und einem Passwort von der mobilen App.

Ich habe zwar einige Informationen zu diesem Thema gefunden. Es ist schwer zu erkennen, was veraltet oder nicht optimal ist. Ich habe über HTTP Basic Auth, das nicht allzu sicher zu sein scheint, und HTTP Token-based Auth gelesen, bin mir aber nicht sicher, wie ich das mit der regulären E-Mail- und Kennwortauthentifizierung koppeln soll (ich verwende Devise by der Weg).

Ich möchte nur wissen, was die derzeitige Best Practice für die Implementierung ist, damit ich sicher bin, dass ich den richtigen Weg gehe.


1
Ohne die Einzelheiten zu kennen, ist mein Gedanke OAuth2. Verwenden Sie den Türhüter oder oauth2 Edelsteine.
Joe Essey

Antworten:


49

Aus Sicherheitsgründen ist es wichtig, die E-Mail-Adresse und das Kennwort des Benutzers einmal gegen ein Token auszutauschen und dieses Token dann für nachfolgende Anforderungen zu verwenden. Das ist weil:

  1. Sie möchten nicht, dass die Client-App dafür verantwortlich ist, das Kennwort des Benutzers beizubehalten, wenn ein Fehler oder Angriff dazu führen kann, dass es durchgesickert ist. und
  2. Mit einem vom Server ausgestellten Token können Sie (und Ihre Benutzer) bei Bedarf ein Token ablaufen lassen, z. B. ein gestohlenes Gerät sperren oder einen sich schlecht benehmenden API-Client blockieren.

Es gibt viele Möglichkeiten, dies mit unterschiedlicher Komplexität zu erreichen.

Hier ist ein Tutorial, das sehr aktuell ist und eine ausführliche Anleitung zum Erstellen einer API in Rails mit tokenbasierter Authentifizierung enthält (nicht mit Devise, aber immer noch relevant für das Verständnis der Konzepte): https://labs.kollegorna.se/blog/ 2015/04 / build-an-api-now /


Vielen Dank! Das musste ich verstehen.
Roma149

Neben dem Gerätetoken können Sie auch das Gerätetoken verwenden. Das Gerätetoken mit dieser Antwort kann Ihnen helfen, das Gerät korrekt zu identifizieren. Es kann hilfreich sein, wenn ein anderes Gerät auf Ihre Website zugreift.
Duykhoa

5

Eine andere Möglichkeit besteht darin, das unten stehende Modul in Ihr MODELL aufzunehmen und das auth_token zu Ihrer Tabelle hinzuzufügen.

App / Modelle / Anliegen / 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 / controller / 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
...

Bearbeiten: Tippfehler korrigiert


Schauen Sie sich außerdem die Funktion has_secured_password von Rails an
Illusionist

Ich glaube, token_authenticable ist veraltet.
Kelsey Hannan

4

@ Roma149 Dies ist eher eine persönliche Präferenz, aber die meisten Leute, die gerade erst anfangen, verwenden Devise, da es die einfachste IMO ist. OAuth2 ist ebenfalls eine gute Option. Als wichtigerer Hinweis können Sie jederzeit zur Ruby Toolbox gehen

Es gibt dort viele gute Informationen über Edelsteine ​​und sie geben sogar Auskunft über das Alter und die Beliebtheit des Edelsteins. Auf diese Weise können Sie auch unterscheiden, auf welche Edelsteine ​​sich die Community gerade wirklich konzentriert oder welche veraltet sind.

Denken Sie daran, dass es in Ruby und Ruby On Rails nicht immer besser ist, was Edelsteine ​​sind, sondern was am besten zu Ihrem Projekt passt!


Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.