Rails 下添加阿里(alipay)快捷登录简易案例

示例项目地址 https://github.com/kai209209/alipay-login-example

  • 申请获得阿里alipay的pid和key,并申请快捷登录功能
  • 在运行之前先把你的hosts文件修改一下,设置本地使用的域名指向本机(ubuntu 14.04)
sudo vim /etc/hosts
0.0.0.0         alipay-login-test.com

~                                                                               
~                                                                               
~                                                                               
~                                                                               
~                                                                               
~                                                                               
~                                                                               
~                                                                               
"/etc/hosts" 15L, 408C                                        1,1          全部

然后重启你的网卡使域名生效.

/etc/init.d/networking restart

 

  • 登录管理设置和路由设置

本例登录管理使用的是devise.

路由设置如下:

rotues.rb

Rails.application.routes.draw do
  resource :user, only: :show
  devise_for :users, controllers: { sessions: "users/sessions" } 
  devise_scope :user do
    get 'alipay_login', to: redirect(User.redirect_to_alipay_login_gateway)   #重定向路由
    get 'sign_from_alipay', to: 'users/sessions#sign_from_alipay'             #支付宝登录后返回的接口 
  end
  root 'static#index'
end

 

  • 登录

在所需要的页面添加登录按钮

= link_to "登录", alipay_login_path, class: "btn btn-primary"

当用户点击登录按钮以后,路由将会重定向到User model的self.redirect_to_alipay_login_gateway方法.

在之前本来是想直接定义一个helper,然后直接通过helper产生一个链接直接链接到alipay的快捷登录页面的,但是由于直接使用helper有可能会暴露申请的pid和key,所以使用路由重定向的方式进行快捷登录.

self.redirect_to_alipay_login_gateway方法是根据快捷登录文档的解读,对需要的信息进行对于拼接,最后生成返回一个地址进行跳转登录

  def self.redirect_to_alipay_login_gateway
    options = { "service" => "alipay.auth.authorize",
                "partner" => "xxxxxxxxxxx", #申请的alipay id
                "_input_charset" => "utf-8", 
                "return_url" =>  "xxxxxxxxxxxx", #回调的接口,处理登录, 例如开发环境alipay-login-test:3000/sign_from_alipay
                "target_service" => "user.auth.quick.login" }
    options.merge!("sign_type" => "MD5", 
                   "sign" => Digest::MD5.hexdigest(options.sort.map{|k, v| "#{k}=#{v}"}.join("&") + "xxxxxxxxxxxxx(#申请的alipay key)"))
    "https://mapi.alipay.com/gateway.do?#{options.sort.map{|k,v|"#{CGI::escape(k.to_s)}=#{CGI::escape(v.to_s)}"}.join("&")}"
  end

 

 跳转至支付宝,且登录成功后,支付宝会根据return_url的地址将所需的信息拼接打包返回到该接口,返回的大致如下

Started GET "/sign_from_alipay?is_success=T&notify_id=xxxxxxxxxxxxxxxxxxxxxx&real_name=xxxxxxxxxxxxx&token=xxxxxxxxxxxxxxxxxxxxxxxxxxxx&user_id=xxxxxxxxxxxxxxxxxxxxxxxxxx&sign=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&sign_type=MD5" for 127.0.0.1 at 2015-09-08 15:48:23 +0800
Processing by Users::SessionsController#sign_from_alipay as HTML
  Parameters: {"is_success"=>"T", "notify_id"=>"xxxxxxxxxxxxxxxxxxxxxxxxxxx", "real_name"=>"xxxxxxxxxxxxxxxxxxx", "token"=>"xxxxxxxxxxxxxxxxxxxxxxx", "user_id"=>"xxxxxxxxxxxxxxxxxxxxx1", "sign"=>"xxxxxxxxxxxxxxxxxxxxxxxxxx", "sign_type"=>"MD5"}

 

返回访问 sign_from_alipay接口

  def sign_from_alipay
    notify_params = params.except(*request.path_parameters.keys)
    if User.alipay_valid_check(notify_params[:notify_id])    #根据文档,对返回信息进行校验以确保该信息是从alipay返回的
      @user = User.from_alipay(params)                       #登录前对数据库进行查找
      sign_in(:user, @user)                                  #devise的方法sign_in(resource_name, resource),使用该方法登录@user
      redirect_to user_path
    else
      render text: 'error'                                   #如果校验错误进行下一步操作
    end
  end

 

信息返回校验方法

  def self.alipay_valid_check(notify_id)
    uri = URI("https://mapi.alipay.com/gateway.do")
    uri.query = URI.encode_www_form(
      'service' => 'notify_id',
      'partner' => "xxxxxxxxxxx", #申请的alipay id
      'notify_id' => notify_id
    )
    Net::HTTP.get(uri) == "true"
  end

 

登录前对数据库进行查找

 数据库进行查找是否有该用户,如果有则从数据库取出,如果没有则创建该用户

def self.from_alipay(params)
    where(uid: params[:user_id]).first_or_create do |user| 
      user.uid = params[:user_id]
      user.name = params[:real_name]
    end
end

 

 

  • 总结

这一整个过程看似简单,就几个方法就能完成这整个登录的过程,但是这阿里快捷登录rails用的比较少,网上关于rails下阿里快捷登录的资料比较少,所以还是花了几天时间来摸索完成该功能的,其中很多代码参照https://github.com/chloerei/alipay的源码来写的.非常感谢写该alipay库的前辈.

 

 

 

 

 

 

posted @ 2015-09-08 17:51  慕斯bevan  阅读(671)  评论(0编辑  收藏  举报