我也想聊聊 OAuth 2.0 —— Access Token


這是一篇待在草稿箱半年之久的文章

連我自己都不知道我的草稿箱有多少未發布的文章了。這應該是我在上一家公司未解散之前寫的,記得當時是要做一個開發者中心,很不幸。
今天,打開草稿箱有種莫名的傷感,看到這個一系列關於 OAuth 的草稿(其實也就兩篇而已),我決定重新發表出來。因為,我看到之前簡單寫的一個一行代碼,發送郵件的小工具,放到Github上以后,好多大的企業在免費使用,如:某某新聞網、某某雲服務和一家硬件公司等,其實我非常高興的,因為我一直在免費使用好多開源社區的福利。有機會做一點微薄的貢獻,這個世界會更好。

上一篇:我也想聊聊 OAuth 2.0 —— 基本概念

你在北方的寒夜里瑟瑟如狗,我在南方的艷陽里看你發抖

我的朋友圈反正今天早上是被「雪」爆了,而我依然穿着短袖。看到老三拍了兩張帶有老家標志建築物的雪景照,發了條朋友圈說我有點想家了,老二回復說:回來唄。突然,鼻子一酸...回復他:老子在擠地鐵!!!回屁家。然后,我喝了口涼水后心情大好!
回到正題,你肯定已經了解到什么是 OAuth 2.0 了,你說它不就是一個協議么,但是那些第三方接口都有什么ClientIdClientSecretAccess TokenRefresh Token等等之類的,看着都頭暈,這些到底是什么阿阿阿?。是這樣的,我也如你一樣苦惱,這些到底都是什么鬼、干什么的?這篇文章就講清道明這些東西到底是什么鬼!!!

一個開發者中心的授權流程是怎樣的

上文好像說到我們要開發一個「開發者中心」,所以,我想先講一下這個所謂的「開發者中心」是怎樣把數據開放給開發者的。
正如你所知道的數據是無價的,我們並不想任何人都能通過我們的開放平台來獲取數據。舉個栗子:你家有好多書,其實你並不看,但有好多朋友想看,你又不想任何人都能去你家拿走你心愛的《C#入門經典》,首先他要向你說明他想借你的書看看,你同意后說:你請我吃飯吧,然后我給你我家鑰匙你自己去取吧,我忙。這個過程就叫做:授權!請你吃飯可以理解為ClientIdClientSecret,你家的鑰匙就是所謂的Token
夠了夠了,你說的這些我都懂,那怎么用代碼要體現呢?

利用 Web API 來實現 OAuth 授權

為什么是 Web API ?
因為 ASP.NET Web API 是針對接口而生的阿。況且它還是REST風格的哦,更輕量級一些,其實這些都不重要,重要的它夠簡單,十分鍾即可上手。
怎么使用 OAuth 的方式實現授權?
Microsoft.Owin.Security.OAuth,就是它!你要知道這可是.Net的可愛之處,她把你需要的就放在了那里,你用不用她就在那。現在就使用它來實現 OAuth 2.0 中所說的四種授權模式之一的客戶端模式(client credentials)
Ⅰ. 打開VS2013,新建一個 Web API 項目。源碼
Ⅱ. 在Project右鍵,選擇“管理NuGet程序包”,搜索“Owin”。安裝下面的包:

  • Microsoft.Owin.Security.OAuth
  • Microsoft.Owin.Security
  • Microsoft.Owin
  • Microsoft.Owin.Host.SystemWeb(我被它坑了好久)
  • OWIN
  • Microsoft ASP.Net Web API 2.2 OWIN
  • Microsoft ASP.Net Identity OWIN

Ⅲ. 修改 Startup.cs 文件如下,如沒有,則新建。

using ...

[assembly: OwinStartup(typeof (Startup))]

namespace Mafly.OAuth2._0.Demo
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            // 有關如何配置應用程序的詳細信息,請訪問 http://go.microsoft.com/fwlink/?LinkID=316888
            var config = new HttpConfiguration();
            WebApiConfig.Register(config);

            //開啟OAuth服務
            ConfigureOAuth(app);

            app.UseWebApi(config);
        }

        public void ConfigureOAuth(IAppBuilder app)
        {
            // Token 生成配置
            var oAuthOptions = new OAuthAuthorizationServerOptions
            {
                AllowInsecureHttp = true, //允許客戶端使用Http協議請求
                AuthenticationMode = AuthenticationMode.Active,
                TokenEndpointPath = new PathString("/token"), //請求地址
                AccessTokenExpireTimeSpan = TimeSpan.FromHours(2), //token過期時間

                //提供認證策略
                Provider = new OpenAuthorizationServerProvider()
                //RefreshTokenProvider = new RefreshAuthenticationTokenProvider()
            };
            app.UseOAuthBearerTokens(oAuthOptions);
        }
    }
}

Ⅳ. 新建OpenAuthorizationServerProvider

public class OpenAuthorizationServerProvider : OAuthAuthorizationServerProvider
    {
        /// <summary>
        ///     驗證客戶端
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
        {
            string clientId;
            string clientSecret;
            context.TryGetFormCredentials(out clientId, out clientSecret);
            //context.TryGetBasicCredentials(out clientId, out clientSecret); //Basic認證

            //TODO:讀庫,驗證
            if (clientId != "malfy" && clientSecret != "111111")
            {
                context.SetError("invalid_client", "client is not valid");
                return;
            }
            context.OwinContext.Set("as:client_id", clientId);
            context.Validated(clientId);
        }

        /// <summary>
        ///     客戶端授權[生成access token]
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public override Task GrantClientCredentials(OAuthGrantClientCredentialsContext context)
        {
            var oAuthIdentity = new ClaimsIdentity(context.Options.AuthenticationType);
            oAuthIdentity.AddClaim(new Claim(ClaimTypes.Name, context.OwinContext.Get<string>("as:client_id")));
            var ticket = new AuthenticationTicket(oAuthIdentity, new AuthenticationProperties {AllowRefresh = true});
            context.Validated(ticket);
            return base.GrantClientCredentials(context);
        }
    }

Ⅴ. 沒有第五步了。是不是很簡單。源碼

測試

我聽說用postman測試API接口比較爽,然后我就用了它。

Ⅰ. 當沒有獲取Token時,請求/api/values接口。
無授權

Ⅱ. 那好,我們來獲取Token。
獲取Token

Ⅲ. 得到了access_token,我們添加Headers,Header:Authorization Value:bearer [token],token就是access_token。
有Headers

那行,總結一下

我們利用Microsoft.Owin.Security.OAuth和 Web API 實現了遵循 OAuth 2.0 協議的授權流程,這為我們開發「開發者中心」打下了堅實基礎,讓我們展望美好的未來吧。ps:說的真官方,能不能說人話。
最后一句:源碼在Github上 https://github.com/mafly/OAuth2.0


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM