OAuth2.0和C++ REST SDK使用示例

目標(biāo)

現(xiàn)在各大網(wǎng)站均可以使用一些已有其它賬戶(微信骇钦、微博等)登錄消痛,而不需要為其申請賬戶和密碼侥猬,其中使用的授權(quán)協(xié)議有一種是OAuth谆吴。
以下將演示如何使用C++ REST SDK和OAuth2.0協(xié)議仗岸,實現(xiàn)一個console客戶端谷遂,進行Windows Live身份驗證忧勿,并獲取一些用戶的基本信息挟秤。

OAuth2.0

關(guān)于OAuth的基本知識可以閱讀以下鏈接的內(nèi)容:

準(zhǔn)備環(huán)境

本文開發(fā)環(huán)境為Visual Studio 2015,C++ REST SDK;

使用Vcpkg安裝C++ REST SDK:

//下載vcpkg
git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
//構(gòu)造
powershell -exec bypass scripts\bootstrap.ps1
//整合到Visual Studio 2015
vcpkg integrate install
//安裝C++ REST SDK
vcpkg install cpprestsdk

客戶端準(zhǔn)備

編寫客戶端使用OAuth授權(quán)時粘昨,需要到對應(yīng)的服務(wù)商申請客戶端ID和密鑰垢啼,一般在谷歌中搜索類似" Windows Live OAuth2"即可得到對應(yīng)的服務(wù)商說明;
我們需要查閱服務(wù)商的開發(fā)者文檔來查看其是否支持OAuth张肾,如何通過其進行授權(quán)芭析,譬如微軟對應(yīng)的 OAuth 2.0即描述了其對OAuth2.0的支持,以及開發(fā)說明;而Registering Your Application with Windows Live則描述了如何注冊客戶端到"Windows Live"捌浩。

實現(xiàn)流程

采用的是客戶端授權(quán)模式中的授權(quán)碼模式放刨,授權(quán)流程如下:

來自阮一峰博客的授權(quán)流程

客戶端(Windows Live 應(yīng)用程序)配置

  • 應(yīng)用程序ID
  • 應(yīng)用程序密碼
  • 平臺:Web
  • 重定向URI:http://localhost:8890
  • 勾選Live SDK支持

如何實現(xiàn)

OAuth2.0配置信息

C++ REST SDK中關(guān)于OAuth2的所有配置及最終獲取到的訪問令牌均存儲在oauth2_config中,構(gòu)造時需要的信息有:

  • client_key:客戶端ID
  • client_secret:客戶端密碼
  • auth_endpoint:認(rèn)證服務(wù)器端口
  • token_endpoint:令牌服務(wù)器端口
  • redirect_uri:重定向URI
  • scope :授權(quán)請求范圍

構(gòu)造示例如下:

static const utility::string_t s_live_key(U("40654b2b-feda-4733-8499-584017f37c4e"));
static const utility::string_t s_live_secret(U("zL4fsEUOTHr8b8Ppm6bJhM9"));

oauth2_config config(s_live_key,
    s_live_secret,
    U("https://login.live.com/oauth20_authorize.srf"),
    U("https://login.live.com/oauth20_token.srf"),
    U("http://localhost:8890/"));

導(dǎo)向認(rèn)證服務(wù)器

客戶端需要構(gòu)造申請認(rèn)證的URI尸饺,并將用戶導(dǎo)向認(rèn)證服務(wù)器进统;
構(gòu)造申請認(rèn)證所需的URI,可以直接使用oauth2_configbuild_authorization_uri方法浪听;

打開瀏覽器的實現(xiàn)如下:

//used to open browser
#include <Windows.h>
#include <shellapi.h>
static void open_browser(utility::string_t auth_uri)
{
    auto r = ::ShellExecuteA(nullptr,"open",
        conversions::utf16_to_utf8(auth_uri).c_str(),NULL,NULL,SW_SHOWNORMAL);
}

對應(yīng)流程實現(xiàn)如下:

void open_browser_auth()
{
    auto auth_uri(m_oauth2_config.build_authorization_uri(true));
    ucout<<"Opening browser in URI:" << std::endl;
    ucout<<auth_uri<<std::endl;
    open_browser(auth_uri);
}

獲取用戶授權(quán)碼

當(dāng)用戶給予授權(quán)后螟碎,認(rèn)證服務(wù)器會將用戶導(dǎo)向客戶端事先指定的“重定向URI”并附上授權(quán)碼,我們需要創(chuàng)建一個臨時的HTTP Listener來監(jiān)控返回的信息拿到授權(quán)碼:

一個簡單的HTTP Listener實現(xiàn)如下:

class OAuth2_listener
{
public:
    OAuth2_listener(uri listen_uri):
        m_listener(new http_listener(listen_uri))
    {
        m_listener->support([this](http_request request)->void {
            //處理HTTP 請求
            if (request.request_uri().path() == U("/") &&
                request.request_uri().query() != U(""))
            {
                m_lock.lock();
                
                //處理返回的授權(quán)碼,并設(shè)置為完成
                m_tce.set(true);
 
                request.reply(status_codes::OK, U("Ok."));
                m_lock.unlock();
            }
            else
            {
                request.reply(status_codes::NotFound, U("Not found"));
            }
        });
        m_listener->open().wait();//打開HTTP 監(jiān)聽
    }
 
    ~OAuth2_listener()
    {
        m_listener->close().wait();//關(guān)閉HTTP Listener
    }
 
    pplx::task<bool> listen_for_code()
    {
        return pplx::create_task(m_tce); //等待認(rèn)證服務(wù)器的授權(quán)碼
    }
private:
    std::unique_ptr<http_listener> m_listener; //HTTP監(jiān)聽
    pplx::task_completion_event<bool> m_tce;//收到授權(quán)碼的確認(rèn)事件
    std::mutex m_lock;
};

使用OAuth2_listener.listen_for_code().get()即可得到授權(quán)碼迹栓。

獲取訪問令牌

拿到授權(quán)碼之后掉分,則需要向認(rèn)證服務(wù)器申請令牌;在oauth2_config中有方法實現(xiàn)了這樣的操作:

根據(jù)重定向URI獲取令牌

其操作步驟是獲取URI中的CODE,然后請求令牌酥郭,并將獲取的令牌保存到oauth2_config中,調(diào)整HTTP Listener中處理授權(quán)碼的部分:

//處理返回的授權(quán)碼
//m_tce.set(true);
m_config.token_from_redirected_uri(request.request_uri()).then(
    [this, request](pplx::task<void> token_task)->void {
    try
    {
        token_task.wait();
        m_tce.set(true);
    }
    catch (const oauth2_exception& e)
    {
        ucout << "Error: " << e.what() << std::endl;
        m_tce.set(false);
    }
    catch (const http_exception& he)
    {
        ucout << "Error: " << he.what() << std::endl;
        m_tce.set(false);
    }
});

經(jīng)過這樣的處理之后华坦,訪問令牌就保存到了oauth2_config中。

集成授權(quán)流程

經(jīng)過上述操作不从,即可拿到令牌惜姐,而在http_client_config中有接口set_oauth2可以將之前的存有令牌的oauth2_config保存到客戶端配置中,之后就可以按照常規(guī)的HTTP/HTTPS操作獲取用戶信息了:

public:
    http_client_config m_http_config;
    oauth2_config m_oauth2_config;
    std::unique_ptr<OAuth2_listener> m_listener_;
    void work()
    {
        if (!m_oauth2_config.client_key().empty() &&
            !m_oauth2_config.client_secret().empty())
        {
            if (!m_oauth2_config.token().is_valid_access_token())
            {
                if (m_listener_->listen_for_code().get())
                {
                    m_http_config.set_oauth2(m_oauth2_config);//保存令牌及信息到http配置
                }
                else
                {
                    //授權(quán)失敗
                }
            }
            else
            {
                //令牌已有效
            }
 
            //發(fā)起獲取用戶信息請求
        }
        else
        {
            //沒有有效的客戶端信息
        }
    }

獲取用戶信息

以下是獲取Windows Live上用戶信息的簡單示例:

http_client api(U("https://apis.live.net/v5.0/"),m_http_config);
ucout << "Requesting account information:"<<std::endl;
ucout << api.request(methods::GET,U("me")).get().extract_json().get() << std::endl;

輸出結(jié)果如圖:

用戶信息

收獲

上述源代碼主要來自于C++ REST SDK中的OAuth2.0示例椿息,但是在具體分析和使用的過程中還是遇到了很多問題:申請Application時的配置歹袁,無法獲取令牌,運行時崩潰等等寝优;

為了定位無法獲取令牌的問題条舔,重寫了一遍 token_from_redirected_uri,梳理了實現(xiàn)流程乏矾,最終發(fā)現(xiàn)是設(shè)置了HTTP Client的proxy所致孟抗,最新的代碼應(yīng)該不存在這個問題。

實際上OAuth2就是通過HTTP進行多次交互獲取訪問令牌钻心,C++ REST SDK提供了HTTP通信功能夸浅,自己也可以完成整個OAuth2的授權(quán)流程。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末扔役,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子警医,更是在濱河造成了極大的恐慌亿胸,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,185評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件预皇,死亡現(xiàn)場離奇詭異侈玄,居然都是意外死亡,警方通過查閱死者的電腦和手機吟温,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評論 3 393
  • 文/潘曉璐 我一進店門序仙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人鲁豪,你說我怎么就攤上這事潘悼。” “怎么了爬橡?”我有些...
    開封第一講書人閱讀 163,524評論 0 353
  • 文/不壞的土叔 我叫張陵治唤,是天一觀的道長。 經(jīng)常有香客問我糙申,道長宾添,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,339評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮缕陕,結(jié)果婚禮上粱锐,老公的妹妹穿的比我還像新娘。我一直安慰自己扛邑,他們只是感情好怜浅,可當(dāng)我...
    茶點故事閱讀 67,387評論 6 391
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著鹿榜,像睡著了一般海雪。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上舱殿,一...
    開封第一講書人閱讀 51,287評論 1 301
  • 那天奥裸,我揣著相機與錄音,去河邊找鬼沪袭。 笑死湾宙,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的冈绊。 我是一名探鬼主播侠鳄,決...
    沈念sama閱讀 40,130評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼死宣!你這毒婦竟也來了伟恶?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,985評論 0 275
  • 序言:老撾萬榮一對情侶失蹤毅该,失蹤者是張志新(化名)和其女友劉穎博秫,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體眶掌,經(jīng)...
    沈念sama閱讀 45,420評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡挡育,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,617評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了朴爬。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片即寒。...
    茶點故事閱讀 39,779評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖召噩,靈堂內(nèi)的尸體忽然破棺而出母赵,到底是詐尸還是另有隱情,我是刑警寧澤具滴,帶...
    沈念sama閱讀 35,477評論 5 345
  • 正文 年R本政府宣布市咽,位于F島的核電站,受9級特大地震影響抵蚊,放射性物質(zhì)發(fā)生泄漏施绎。R本人自食惡果不足惜溯革,卻給世界環(huán)境...
    茶點故事閱讀 41,088評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望谷醉。 院中可真熱鬧致稀,春花似錦、人聲如沸俱尼。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,716評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽遇八。三九已至矛绘,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間刃永,已是汗流浹背货矮。 一陣腳步聲響...
    開封第一講書人閱讀 32,857評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留斯够,地道東北人囚玫。 一個月前我還...
    沈念sama閱讀 47,876評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像读规,于是被迫代替她去往敵國和親抓督。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,700評論 2 354

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理束亏,服務(wù)發(fā)現(xiàn)铃在,斷路器,智...
    卡卡羅2017閱讀 134,654評論 18 139
  • 以下是官網(wǎng)直譯:https://oauth.net/ 1. 首頁 OAuth是一種開放協(xié)議(注:協(xié)議是公開的碍遍,任何...
    TooYummyToThrow閱讀 11,233評論 0 20
  • 原文地址:http://www.sanjinbest.com/blog/b6ec839d56c04ca387b95...
    木子小三金閱讀 8,567評論 0 37
  • 什么是三方授權(quán)? 第三方授權(quán)就是涌穆,委托第三方來對既定的用戶進行鑒定,鑒定成功之后雀久,下發(fā)信任憑證,信任憑證和用戶掛鉤...
    一只小哈閱讀 32,565評論 2 21
  • 我不敢去打破現(xiàn)在的格局趁舀,我怕我連最后的你我都會失去掉赖捌,如果可以靜靜地看著你,我內(nèi)心也是很心滿意足的矮烹,夢里越庇,和你表白...
    小小鐘閱讀 189評論 0 0