Gem 为 devise 添加 token 认证

qingxp9 · 2014年11月25日 · 最后由 flowerwrong 回复于 2014年11月26日 · 4700 次阅读

前不久用 rails 作一个 iOS 应用的后端,因为传递的是 json 得用到 token,在处理用户验证上花了些时间找资料,因为 devise 在某次更新中把 token 认证模块去掉了。 花了点小时整理了下为 devise 添加 token 认证的方法,不过怕使用的方法在某些方面存在一点问题或者是不够成熟,还请各位帮我看看,有问题能指点下。在更改完后我再将文章弄过来分享给其他需要的人。

目前暂时放在我的博客上 http://www.flincllck.com/use-json-authentication-api-on-rails4/

toke 放 header 里传比较好。

https://github.com/gonzalo-bulnes/simple_token_authentication or https://github.com/lynndylanhurley/devise_token_auth

前者提供了基本的验证功能,后者原本针对 angularjs 开发,但也可以用在普通的 token 场景,但须自己重写接口

只用 token 做用户查询不好吧 一般的做法不是靠 id 和 token 去查么

之前搞得:

module Concerns
  module TokenAuthenticatable
    extend ActiveSupport::Concern

    included do

      # Generate new authentication token (a.k.a. "single access token").
      def reset_authentication_token
        self.authentication_token = self.class.authentication_token
      end

      # Generate new authentication token and save the record.
      def reset_authentication_token!
        reset_authentication_token
        save(validate: false)
      end

      # Generate authentication token unless already exists.
      def ensure_authentication_token
        reset_authentication_token if authentication_token.blank?
      end

      # Generate authentication token unless already exists and save the record.
      def ensure_authentication_token!
        reset_authentication_token! if authentication_token.blank?
      end

      # Hook called after token authentication.
      def after_token_authentication
      end

      def expire_auth_token_on_timeout
        self.class.expire_auth_token_on_timeout
      end

    end

    module ClassMethods

      # Generate a token checking if one does not already exist in the database.
      def authentication_token
        generate_token("authentication_token")
      end

      # Generate a token by looping and ensuring does not already exist.
      def generate_token(column)
        loop do
          token = Devise.friendly_token
          break token unless User.find_by(column => token)
        end
      end
    end
  end
end

对比 token 时,别少了计时攻击的防护措施。:)

#2 楼 @everett 两个不错的例子,谢谢分享

最简单的是添加一个 warden strategy (例如叫做 my_token_strategy ), 然后

initializers/devise.rb:

config.warden do |manager|
  manager[:default_strategies][:user].unshift :my_token_strategy
end

正常的用 authenticate_user! 就好了

#6 楼 @qingxp9 请问有没有对应的 iOS 的例子?

建议内存数据库存token application_controller.rb中加一个前置过滤器处理是否带token以及权限等 覆写session_controller.rb保存token到 redis

无法使用session,这里得注意下。

需要 登录 后方可回复, 如果你还没有账号请 注册新账号