Android Rails api和本机移动应用程序身份验证

Android Rails api和本机移动应用程序身份验证,android,ios,ruby-on-rails,devise,oauth-2.0,Android,Ios,Ruby On Rails,Devise,Oauth 2.0,我知道关于这个话题有很多信息,但我找不到任何最新的。 我看到像这样的话题,但我看到了 我的问题很简单:有没有一种好方法可以使用Rails4对本地Android和iPhone应用程序的用户进行身份验证?有人知道提供解决方案的好教程或文章吗 亚当·韦特添加赏金: 我刚刚就这个问题提出了500悬赏,因为我找不到从iOS应用程序到Rails API的用户身份验证的正确方法。这就是我正在考虑做的,但不知道它是否安全 假设我们有一个用户记录。用户已注册一个帐户,该帐户在数据库中创建了一个user记录,其中包

我知道关于这个话题有很多信息,但我找不到任何最新的。 我看到像这样的话题,但我看到了

我的问题很简单:有没有一种好方法可以使用Rails4对本地Android和iPhone应用程序的用户进行身份验证?有人知道提供解决方案的好教程或文章吗

亚当·韦特添加赏金:

我刚刚就这个问题提出了500悬赏,因为我找不到从iOS应用程序到Rails API的用户身份验证的正确方法。这就是我正在考虑做的,但不知道它是否安全

假设我们有一个
用户
记录。用户已注册一个帐户,该帐户在数据库中创建了一个
user
记录,其中包含
email
列和
password\u digest

当用户登录时,我希望该用户在移动应用程序上保持身份验证,直到明确注销

我想我们需要一个基于令牌的身份验证。我可能会在创建
用户
时创建一个ApiKey记录,并将其保存为
用户
记录上的关联

当用户登录/注册时,响应将包含一个API令牌(类似于
SecureRandom.hex
),该令牌将保存在iOS密钥链中,并与所有后续请求一起使用,以通过在标头中传递该令牌并使用类似于:

before_filter :restrict_access

private

def restrict_access
authenticate_or_request_with_http_token do |token, options|
  ApiKey.exists?(access_token: token)
end
这安全吗?我是否应该在每个请求中刷新令牌并将其包含在响应中

我还有其他选择吗?像Facebook、Twitter和Pinterest这样的公司做什么

我知道OAuth2.0,但它不是用于授予外部应用程序的吗

有没有一个gem可以管理这些

对不起,这里完全不确定


最佳答案为500。

您的思路是正确的,但用户的令牌应仅用于识别发出请求的用户。您仍然需要某种身份验证,因为正如您在每次请求中更改令牌时推测的那样,黑客可以拦截数据流,获取令牌,然后在后续请求中“成为”该用户

通过在每个请求上更改令牌,可以消除拦截问题,但一旦有人拦截了令牌,他们就可以通过继续拦截甚至修改响应来进一步利用系统。一个解决方案是使用HMAC(AmazonWeb服务使用HMAC)。它是一种为您的请求提供签名(哈希)的算法,该签名对于每个请求都是唯一的,不需要更改密钥,并且无法预测未来的请求

有一个rubygemforrails,它在服务器端实现HMAC,用于签署HMAC请求以及在进行服务器到服务器通信时生成它们。对于像您这样的客户端到服务器请求,您需要在iOS或Android端生成签名,并在服务器上对其进行身份验证

考虑使用gem在服务器端完成工作。在IOS客户端,考虑生成签名的库。看看ApiAuth的具体实现,因为它向数据添加了时间戳以防止重播攻击,所以在将数据传递给HBHMAC之前,您可能需要向数据添加一个字段


综上所述,使用HMAC认证将避免中间人攻击和重放攻击,利用单向散列算法,防止攻击者产生真实的请求,即使它们能够拦截有效请求。

< P>我有这个问题,我是API开发者。您可以使用令牌和自定义授权来完成这项任务,但我将告诉您我们如何使用我们的应用程序,它为六位数的用户提供服务

至少对于iOS,该设备将为您处理会话,这意味着如果iOS应用程序上的用户使用参数向
/users/sign_>发出POST请求

user: { 
  password: 'mypassword',
  email: 'testuser@example.com',
  remember_me: true # optional
}
iOS设备将安全持久地为您存储会话

现在,如果您想使用OAuth 2路线,我实际上维护了一个名为OAuth 2 Providerable的rails 4的gem,我在其中添加了一个非常酷的功能,允许用户通过“授权”屏幕,因为显然,如果您开发了软件,您不需要用户确认他们信任您

如果您决定使用OAuth 2,则需要使用所谓的隐式访问令牌。

rails 4项目可以在github上找到

如果您不在rails 4上,可以使用原始的gem


顺便说一句,gem需要改进,所以如果有人读到这篇文章想让它变得更好,请务必从我的研究中提出解决方案的要点。可以随意编辑、更正、作废等

SessionsController < ApplicationController
  skip_before_filter :authenticate_user, :only => [:create]
  def create
    user = User.where("username = ? OR email = ?", params[:username_or_email], params[:username_or_email]).first
    if user && user.authenticate(params[:password])
      api_key = user.find_api_key
      if !api_key.secret_key || api_key.is_expired?
        api_key.set_expiry_date
        api_key.generate_secret_key
      end
      api_key.save
      render json: api_key, status: 201     
    else
      status: 401
    end
  end
sessioncontroller[:create]
def创建
user=user。其中(“username=?或email=?”,params[:username\u或\u email],params[:username\u或\u email])。首先
如果用户&&user.authenticate(参数[:密码])
api\u key=user.find\u api\u key
如果!api_key.secret_key.api_key.过期了吗?
api\u key.set\u到期日期
api_key.generate_secret_key
结束
api_key.save
呈现json:api_键,状态:201
其他的
状况:401
结束
结束
注意ApiAuth.authentic?方法和请求对象。请求必须在客户端上使用HMAC算法签名

ApplicationController < ActionController::Base
  respond_to :json
  force_ssl
  protect_from_forgery with: :null_session 
  before_filter :authenticate_user
  private
  def authenticate_user
    if authenticate_user_from_secret_key
      return true
    else
      head :unauthorized 
    end
  end
  def authenticate_user_from_secret_key
    userid = ApiAuth.access_id(request)
    currentuser = userid && User.find_by_id(userid)
    if ApiAuth.authentic?(request, currentuser.find_api_key.secret_key)
      return true
    else
      return false
    end
    false
  end
ApplicationControllerUsersController < ApplicationController
  skip_before_filter :authenticate_user, :only => [:create]
  def create
      user = User.create(user_params)
      if !user.new_record?
        render json: user.find_apit_key, status: 201

      else
       # error
      end
  end
class ApiKey < ActiveRecord::Base
  before_create :generate_secret_key, :set_expiry_date
  belongs_to :user   
  def generate_secret_key
    begin
    self.secret_key = ApiAuth.generate_secret_key
    end while self.class.exists?(secret_key: secret_key)
  end
class User < ActiveRecord::Base
  has_secure_password
  before_save :ensure_api_key 
  has_many :api_keys 
  def find_api_key
   self.api_keys.active.ios.first_or_create
  end