How to setup a remote json API for Rails for authe

2019-04-13 14:54发布

问题:

I'm new to rails and are have a pretty basic understanding of the Devise Gem. Besides the CRUD and views I'm not clear on what it provides that could help me for a AngularJs app talking to a Rails Json Api.

At the moment I'm hand rolling things ie. for security I have I exchange a HTTP Header token between client (js) and server. I'm also using the Railscast #250 for user authentication - but as I don't see how to apply the SessionController for a remote client.

Are there any strategies I could employ for authentication and managing session via a remote json API?

Thanks!

回答1:

I personally wouldn't use devise for something like this because there's only a small part of it you'd be using anyways

Dont

You pretty much just don't use a session. All you need to do is pass in basic authentication each time, and in the application controller you determine if its valid, if not just send them back an auth error.

Example request: http://username:password@example.com/api/endpoint

class ApplicationController
  before_filter :check_auth!

  private
  def check_auth!
    username, password = ActionController::HttpAuthentication::Basic::user_name_and_password(request)
    user = User.find_by(username: username)
    if user && user.encrypted_password == SomeEncryptFunction(params[:password])
      @current_user = user
    else
      raise "error"
    end
  end
end

But if you want to...

Then what you can do is update a DateTime field on the user when they first auth (which starts their session), then on subsequent calls they can just pass a token you give them that you you check for each time they sign in. You also check that only a certain amount of time has passed since they first authed, otherwise their session is invalid.

class SessionsController < ApplicationController
  skip_before_filter :check_auth!
  before_filter :login!

  private
  # Note: I don't remember the actual devise method for validating username + password
  def login!
    user = User.find_by(username: params[:username])
    if user && user.valid_password(params[:password])
      current_user = user
      current_user.update_attributes(
        authenticated_at: DateTime.now,
        authentication_token: Devise.friendly_token
      )
    else
      raise "error"
    end
  end
end

class ApplicationController
  before_filter :check_auth!

  private
  def check_auth!
    if valid_token(params[:token])
      current_user = User.find_by(authentication_token: params[:token])
    else
      raise "error"
    end
  end

  # Returns true if token belongs to a user and is recent enough
  def valid_token(token)
    user = User.find_by(authentication_token: params[:token])
    user && user.authenticated_at < DateTime.now - 1.day
  end
end