【7】.net WebAPI Owin OAuth 2.0 密碼模式驗證實例


1.OAuth密碼模式

 

2.在VS中創建WebAPI項目

在nuget中安裝:

Microsoft.AspNet.WebApi.Owin

Microsoft.Owin.Host.SystemWeb

這兩個類庫並添加Owin啟動類Startup

 

using System;
using System.Threading.Tasks;
using Microsoft.Owin;
using Owin;
using Microsoft.Owin.Security.OAuth;

[assembly: OwinStartup(typeof(WebAPIOAuth.Startup))]

namespace WebAPIOAuth
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            var OAuthOptions = new OAuthAuthorizationServerOptions
            {
                AllowInsecureHttp = true,
                TokenEndpointPath = new PathString("/token"), //獲取 access_token 授權服務請求地址
                AuthorizeEndpointPath = new PathString("/authorize"), //獲取 authorization_code 授權服務請求地址
                AccessTokenExpireTimeSpan = TimeSpan.FromSeconds(10), //access_token 過期時間

                Provider = new OpenAuthorizationServerProvider(), //access_token 相關授權服務
            };

            app.UseOAuthBearerTokens(OAuthOptions); //表示 token_type 使用 bearer 方式 不記名令牌驗證
        }
    }
}

 

ConfigureOAuth(IAppBuilder app)方法開啟了OAuth服務。簡單說一下OAuthAuthorizationServerOptions中各參數的含義:

AllowInsecureHttp:允許客戶端一http協議請求;

TokenEndpointPath:token請求的地址,即http://localhost:端口號/token;

AccessTokenExpireTimeSpan :token過期時間;

Provider :提供具體的認證策略;

3.繼承授權服務OAuthAuthorizationServerProvider類

 

重載ValidateClientAuthentication方法驗證客戶端的正確性

重載GrantResourceOwnerCredentials方法實現用戶名密碼的驗證,驗證通過后會頒發token。

 

public class OpenAuthorizationServerProvider : OAuthAuthorizationServerProvider
    {
        /// <summary>
        /// 驗證調用端的clientid與clientSecret已驗證調用端的合法性(clientid、clientSecret為約定好的字符串)。
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
        {
            string clientId;
            string clientSecret;
            context.TryGetBasicCredentials(out clientId, out clientSecret);
            if (clientId == "1234" && clientSecret == "5678")
            {
                context.Validated(clientId);
            }
            await base.ValidateClientAuthentication(context);
        }

        /// <summary>
        /// 通過重載GrantResourceOwnerCredentials獲取用戶名和密碼進行認證
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
        {
            //調用后台的登錄服務驗證用戶名與密碼
            if (context.UserName != "Admin" || context.Password != "123456")
            {
                context.SetError("invalid_grant", "用戶名或密碼不正確。");
                return;
            }
            
            var oAuthIdentity = new ClaimsIdentity(context.Options.AuthenticationType);
            oAuthIdentity.AddClaim(new Claim(ClaimTypes.Name, context.UserName));
            var ticket = new AuthenticationTicket(oAuthIdentity, new AuthenticationProperties());
            context.Validated(ticket);

            await base.GrantResourceOwnerCredentials(context);
        }
    }

 

在需要驗證的方法處添加[Authorize]標簽,當訪問此接口時必須通過授權驗證才可訪問。

以上服務器端代碼全部完成。

4.創建新的客戶端項目進行測試

添加測試類

 

class OAuthClientTest
    {
        private HttpClient _httpClient;
        private string token;
        
        public OAuthClientTest()
        {
            _httpClient = new HttpClient();
            _httpClient.BaseAddress = new Uri("http://localhost");
        }

        public async Task<string> GetAccessToken()
        {
            var clientId = "1234";
            var clientSecret = "5678";

            var parameters = new Dictionary<string, string>();
            parameters.Add("grant_type", "password");
            parameters.Add("username", "Admin");
            parameters.Add("password", "123456");

            _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(
                "Basic",
                Convert.ToBase64String(Encoding.ASCII.GetBytes(clientId + ":" + clientSecret))
                );

            var response = await _httpClient.PostAsync("OAuthTest/token", new FormUrlEncodedContent(parameters));
            var responseValue = await response.Content.ReadAsStringAsync();
            if (response.StatusCode == System.Net.HttpStatusCode.OK)
            {
                return JObject.Parse(responseValue)["access_token"].Value<string>();
            }
            else
            {
                Console.WriteLine(responseValue);
                return string.Empty;
            }
        }

        public async Task Call_WebAPI_By_Resource_Owner_Password_Credentials_Grant()
        {
            if(string.IsNullOrEmpty(token))
                token = await GetAccessToken();
            Console.WriteLine(token);
            _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
            Console.WriteLine(await (await _httpClient.GetAsync("OAuthTest/api/Values")).Content.ReadAsStringAsync());
        }
    }

 

main方法中調用進行測試:
static void Main(string[] args)
        {
            var clientTest = new OAuthClientTest();
            var task = clientTest.Call_WebAPI_By_Resource_Owner_Password_Credentials_Grant();
            task.Wait();
            //var token = clientTest.GetAccessToken();
            //var strToken = token.Result;
            //Console.WriteLine(strToken);
            Console.ReadLine();
        }

結果如下:

 



其中長串字符為token,"value1, value2"為訪問webapi返回的結果,表明訪問成功。

參考1:http://www.cnblogs.com/xishuai/p/aspnet-webapi-owin-oauth2.html

參考2:http://www.cnblogs.com/Leo_wl/p/4919783.html

 


免責聲明!

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



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