现在的位置: 首页 > 综合 > 正文

利用OAuth2协议将网站接入到新浪微博

2017年11月14日 ⁄ 综合 ⁄ 共 4427字 ⁄ 字号 评论关闭

利用OAuth2协议将网站接入到新浪微博

2012-06-22 Fri DeviseOAuth2weibo 

前段时间收到了新浪微博客开放平台发来的邮件,宣布要在9月份停止使用OAuth1协议,这点让我感到意外,以下是邮件原文:

尊敬的开发者您好:

新浪微博开放平台预计2012年九月份停止旧版接口和OAuth1.0的使用,请尽快将您的应用迁移至新版接口和OAuth2.0。

新版接口更高效,包含更丰富的功能,为帮助您迁移,请参考以下链接:

...

希望您能够做好相关准备,技术问题可咨询 @微博API,由此造成诸多不便,请开发者给予谅解。

这个9月份的截止时间可谓是一记重磅炸弹,让所有还停留在Oauth1上的网站面临不得不面临升级的尴尬。

之前花了点时间把新浪微博的一整套流程都给研究清楚了,其实时间主要都花在研究他的审核机制了,OAuth2调用相对来说还是相当简单的。下面我来讲一下如何使用OAuth2做授权。

开发之前其实需要做一些准备,比如创建新浪微博开放平台的帐号,其实也就是微博帐号,登录后访问http://open.weibo.com,点击"网站接入",会引导进入添加新网站表单,这里有一点需要注意,目前来说新浪微博的网站接入得验证域名的所有权了,所以必须得输入正确的域名而且要在网站首页添加相应的meta标签才能通过。完成之后可以不用立即提交审核,因为这个步骤需要提供备案密码,没有备案是通过不了的,但是验证域名的前提就是服务器的80端口能被访问,而且是解析好的域名,所以备案这关其实在这之前已经过了,没问题的情况下可以提交审核,一般在2-5个工作日之间。

网站接入后所得到的App Key 和 App Secret 需要保存起来,代码中将会使用到。

由于本人比较喜欢使用 devise, 所以OAuth2的集成也是基于devise的,在Gemfile加入相应的gem:

Gemfile

1
2
3
# Weibo support
gem 'devise'
gem 'omniauth-weibo-oauth2', '~> 0.2.0'

在项目根目录执行 bundle 来安装相应的gem

使用 devise的朋友都应该清楚,user.rb模型中会默认存在功能模块配置,将模块做以下的修改:

app/models/user.rb

1
2
3
4
5
6
7
8
9
10
11
12
class User < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :token_authenticatable, :encryptable, :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable,
         :registerable,
         :recoverable,
         :rememberable,
         :trackable,
         :validatable,
         :confirmable,
         :omniauthable, omniauth_providers: [:weibo]
end

加入了以上devise的omniauthable的配置后, 就能通过devise自带的方法来调出可授权的第三方服务

>> User.omniauth_providers
=> [:weibo]

到这里,我们可以来配置之前做好的网站接入了,新建一个service.yml来存放第三方的App
Key和 App Secret:

app/config/services.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
common: &common
  weibo:
    api_key: "这里填写你获取到的api key"
    api_secret: "这里填写你获取到的api secret"
    redirect_uri: "http://www.yourdomain.com/users/auth/weibo/callback"

production:
  <<: *common

development:
  <<: *common

test:
  <<: *common

当然,还需要将此配置用到devise和omniauth的集成中:

app/config/initializers/devise.rb

1
2
3
4
5
6
7
SERVICES = YAML.load_file(Rails.root.join("config", "services.yml")).fetch(Rails.env)
Devise.setup do |config|
  # ==> OmniAuth
  # Add a new OmniAuth provider. Check the wiki for more information on setting
  # up on your models and hooks.
  config.omniauth :weibo, SERVICES['weibo']['api_key'], SERVICES['weibo']['api_secret']
end

配置完成后我们就可以生成一个controller专门来处理回调的逻辑,我们以authentications_controller.rb为例:

$ rails g controller authentications

既然我们用到了Devise的Omniauth模块,将authenticationsc controller做个集成即可,父类为Devise::OmniauthCallbacksController,请参考以下代码:

app/controllers/authentications_controller.rb

1
2
3
4
5
class AuthenticationsController < Devise::OmniauthCallbacksController
  def weibo
    # TODO
  end
end

因为我们利用authentications controller集成了Devise自己的controller,所以我们需要来修改下默认的路由:

app/config/routes.rb

1
2
3
devise_for :users, controllers: {
  omniauth_callbacks: :authentications
}

我们可以通过打印路由的方法来看看weibo的回调路由是否已经存在:

$ rake routes |grep authentications
user_omniauth_callback /users/auth/:action/callback(.:format) authentications#(?-mix:weibo)

不难看出,weibo的设置已经生效,剩下的事情其实就是来写回调逻辑了,就逻辑而言,想必都应该很清楚,会存在三种情况:

  1. 用户没有登录的情况下授权新浪微博:这个时候其实就是新用户注册,但是新浪微博客是不提供email的,在一些以email为必须字段的情况下,需要另外来处理,比如将授权信息存入session,然后跳转到让用户补充email的界面,必须让用户绑定一个email才能完成授权。这一点国内的其他网站也都差不多,基本都不会提供emial,不像facebook等国外主流网站。

  2. 用户已经登录,但是还未进行新浪微博帐号绑定:这步比较简单,只要将获得的授权信息和当前用户进行绑定即可。

  3. 用户未登录,但是之前已经授权过了:先要根据获得的收钱信息中的uid和provider取出来,数据库中一查便知。

请参考以下的代码:

app/controllers/authentications_controller.rb

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class AuthenticationsController < Devise::OmniauthCallbacksController
  def weibo
    omniauth_process
  end
  protected
  def omniauth_process
    omniauth = request.env['omniauth.auth']
    authentication = Authentication.where(provider: omniauth.provider, uid: omniauth.uid.to_s).first

    if authentication
      set_flash_message(:notice, :signed_in)
      sign_in(:user, authentication.user)
      redirect_to root_path
    elsif current_user
      authentication = Authentication.create_from_hash(current_user.id, omniauth)
      set_flash_message(:notice, :add_provider_success)
      redirect_to authentications_path
    else
      session[:omniauth] = omniauth.except("extra")
      set_flash_message(:notice, :fill_your_email)
      redirect_to new_user_registration_url
    end
  end

  def after_omniauth_failure_path_for(scope)
    new_user_registration_path
  end
end
app/models/authentication.rb

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Authentication < ActiveRecord::Base
  attr_accessible :user_id, :provider, :uid, :access_token

  belongs_to :user

  validates :provider, :uid, :access_token, presence: true
  validates :provider, uniqueness: { scope: :user_id }

  def self.create_from_hash(user_id, omniauth)
    self.create!(
      user_id:      user_id,
      provider:     omniauth.provider,
      uid:          omniauth.uid,
      access_token: omniauth.credentials.token
    )
  end
end

代码堆砌完成,我们需要在登录页面或者注册页面加入微博授权的链接:

1
2
%ul
  %li= link_to '微博帐号登录', '/users/auth/weibo', class: 'weibo'

本地测试的话可以添加一个host, 将域名绑定到本机,大家可以尝试以下,下次再讲下如何利用OAuth2来实现微博的主要接口。

抱歉!评论已关闭.