程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> 自己開發實現OAuth做webapi認證,oauthwebapi

自己開發實現OAuth做webapi認證,oauthwebapi

編輯:C#入門知識

自己開發實現OAuth做webapi認證,oauthwebapi


看到園子裡面有人寫的OAuth,就想把自己實現的OAuth也分享一下,關於OAuth協議這裡就不再贅述。

一、作為認證服務器,首先需要提供一個可以通過appid/appsecret來獲取token這樣的一個接口,於是便有了以下代碼。

public class AuthController : ApiController { [HttpGet] public HttpResponseMessage Token(string appid = "", string appsecret = "") { ApiResponseEntity rep; var isv = AppManage.Instance.GetAppISV(appid, appsecret); if (isv != null) { string token = TokenManage.Instance.CreateToken(appid); rep = new ApiResponseEntity { Status = InterfaceStatus.Success, BizData = new { AccessToken = token } }; } else { rep = new ApiResponseEntity() { Status = InterfaceStatus.Parm_Missing, Message = "param error" }; } return rep.ToHttpResponseMessage(); } } View Code

創建token的算法可以自行實現,我是將新生成的Guid做了一下md5處理,代碼如下:

public string CreateToken(string appid) { string token = Guid.NewGuid().ToString().ToMd5(); Set(token, appid); return token; } View Code

上文可以看到,在生成token了以後,就一個SetToken,就是將token存儲在緩存裡面,並設置了一定時間的生存周期,代碼如下:

public void Set(string token, string appid) { var config = ServerConfigManage.Instance.GetServerConfig(); string key = string.Format(RedisCacheKey.App_Token, token); RedisNetHelper.Set<string>(key, appid, DateTime.Now.AddSeconds(config.TokenSurvivalTime)); } View Code

為什麼要用token做key,是因為token的變更會導致isv token驗證失效,但是用token做key就可以在存活周期內,這個key都可以使用,避免了多線程獲取token,或是其他原因導致的token失效。作為認證服務器,還需要提供一個RefreshToken這樣的接口,用來給刷新token的存活周期,代碼相似這裡就不再贅述。

 

二、在Api做驗證的時候,就需要開始對Token進行驗證了,代碼如下:

public class OAuthHandler : DelegatingHandler { protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) { ApiResponseEntity repEntity = null; string appid = ""; string ip = RequestHelper.GetWebClientIp(); if (!OAuthValidate.IpValidate(ip)) { repEntity = new ApiResponseEntity { Status = InterfaceStatus.IllegalIp, Message = "ip access limit" }; } else { string token = ""; string url = request.RequestUri.AbsoluteUri; var routeData = request.GetRouteData(); string controller = routeData.Values["controller"].ToString().ToLower(); string action = routeData.Values["action"].ToString().ToLower(); if (controller.Equals("auth") && action.Equals("token")) { return base.SendAsync(request, cancellationToken); } if (request.Method == HttpMethod.Get) { var query = request.RequestUri.ParseQueryString(); token = query["token"]; } if (token == null || token.Length == 0) { repEntity = new ApiResponseEntity { Status = InterfaceStatus.Token_Faild, Message = "token invalid" }; } else { appid = TokenManage.Instance.Get(token); if (appid == null || appid.Length == 0) { repEntity = new ApiResponseEntity { Status = InterfaceStatus.Token_Faild, Message = "token invalid" }; } else { if (!OAuthValidate.ApiValidate ( string.Format("{0}/{1}", controller, action), appid )) { repEntity = new ApiResponseEntity { Status = InterfaceStatus.No_Access, Message = "api access limit" }; } } } } if (repEntity != null) { var tsc = new TaskCompletionSource<HttpResponseMessage>(); tsc.SetResult(repEntity.ToHttpResponseMessage()); return tsc.Task; } else { return base.SendAsync(request, cancellationToken); } } } View Code

使用比較傳統的方式,繼承於DelegatingHandler,然後進行處理,首先是做的IP驗證,然後再進行token有效期驗證,最後再進行Api的權限調用驗證。驗證的代碼如下:

public static bool IpValidate(string ip) { var config = ServerConfigManage.Instance.GetServerConfig(); bool isPass = true; if (isPass && config.IsStartIpWhiteList) { isPass = config.IpWhiteList.Contains(ip); } if (isPass && config.IsStartIpBlackList) { isPass = !config.IpBlackList.Contains(ip); } return isPass; } public static bool ApiValidate(string api, string appid) { var config = ServerConfigManage.Instance.GetServerConfig(); if (config.IsStartApiControl) { var apis = AppManage.Instance.GetAppApiResource(appid); return apis != null && apis.Contains(api); } return true; } View Code

GetServerConfig()是從DB/Cache裡面獲取服務器的自定義配置,然後看是否開啟ip白名單/黑名單,下面的代碼同理,是否開啟權限驗證。

那認證服務器到這裡實際上就結束了,關於isv申請appid/appsecret。然後用戶同意授權以後,存儲appid和user之間的關聯關系,就需要看客自行實現了。

 

另外有一個擴展代碼這裡也提一下,就是關於ApiResponseEntity的返回值處理,代碼如下:

public static HttpResponseMessage ToHttpResponseMessage(this ResponseEntity rep, bool isEncrypt = false) { return new HttpResponseMessage(HttpStatusCode.OK) { Content = new StringContent ( isEncrypt ? EncryptHelper.Base64Replace(EncryptHelper.AESEncryptBase64(JsonHelper.ToJson(rep), Config.ApiEncryptKey)) : JsonHelper.ToJson(rep), System.Text.Encoding.UTF8, "application/json" ) }; } View Code

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved