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¬ify_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库的前辈.