ASP.NET WebHook Token based authentication Web Api
▌背景
但是可以預見未來發佈後, 在開發上應該會非常方便。
但是如果在Server已有認證的服務,例如:OWIN
Authetication,只要加上”註冊通知的URL”和”Callback”服務,即可達成WebHook的效果。
▌相關文章
▌環境
l Visual Studio 2015
l WEB API 2.2
l Entity Framework 6
▌實作
▋Authentication Service
首先,我們必須實作驗證的部分,請參考上列的參考文章建立一個OWIN Identity Authentication Server。
目的是用Server提供驗證後的Token以確保使用WebHook Service的Client side都已經經過認證。
▋Data Access Layer
此例將在Http Callback要通知的客戶資訊,紀錄於資料庫。
因此先實作DAL, 採Code First的方式。 沒有太特殊的部分,直接列出POCO和DbContext。
POCO
public class WebHookCallback : BaseEntity
{
[Key]
[Column(Order = 1)]
[Display(Name = "序號")]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int WebHookCallbackId { get; set; }
[Required]
[Column(Order = 2)]
[Display(Name = "Callback URI")]
public String Uri { get; set; }
[Column(Order = 3)]
[Display(Name = "建立者")]
public String CreateBy { get; set; }
[Required]
[Column(Order = 4)]
[Display(Name = "是否啟用")]
public bool IsEnabled { get; set; }
}
public class BaseEntity
{
/// <summary>
/// 建立日期
/// </summary>
public DateTime CreateOn { get; set; }
/// <summary>
/// 更新日期
/// </summary>
public DateTime UpdateOn { get; set; }
public BaseEntity()
{
CreateOn = DateTime.Now;
UpdateOn = DateTime.Now;
}
}
|
l DbContext
public class WebHookContext : DbContext
{
public WebHookContext()
: base("name=WebHookDbContext") //指定對應的Connection String名稱
{ }
public DbSet<WebHookCallback>
WebHookCallbacks { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
//Create the relation between the
tables (POCOs)
}
}
|
▋Database service
建立一支負責處理Database CRUD的服務介面。
public class WebHookCallbackService : IDisposable
{
private WebHookContext _dbContext = null;
public WebHookCallbackService()
{
this._dbContext = new WebHookContext();
}
public void Insert(WebHookCallback entity, out int? id)
{
this._dbContext.WebHookCallbacks.Add(entity);
this._dbContext.SaveChanges();
id = entity.WebHookCallbackId;
}
public void Remove(int webhookCallbackId)
{
var entity = this._dbContext.WebHookCallbacks.Where(x
=> x.WebHookCallbackId.Equals(webhookCallbackId))
.FirstOrDefault();
entity.IsEnabled = false;
this._dbContext.SaveChanges();
}
public IQueryable<WebHookCallback> Get(Func<WebHookCallback, bool> filter)
{
var entities = this._dbContext.WebHookCallbacks.Where(filter).AsQueryable();
return entities;
}
public void Dispose()
{
this._dbContext.Dispose();
}
}
|
▋Implement the We
Api which supporting WebHook
有了DAL和介面後,接下來可專心實作中心端支援WebHook的Web Api, 至少需產生以下方法:
1.
Register : 註冊需要通知的客戶端資訊
2.
Unregister:移除不必要通知的客戶端資訊
3.
TriggerCallback : 用來測試,觸發Callback的Post
方法
[EnableCors(origins: "*", headers: "*", methods: "*")]
public class WebHookController : ApiController
{
[Authorize]
[HttpPost]
public IEnumerable<int?> Register(RegisterInfo regInfo)
{
int? registeredId = null;
if(String.IsNullOrEmpty(regInfo.WebHookUri))
{
this.Request.CreateResponse(HttpStatusCode.BadRequest);
}
else
{
using (var whService = new WebHookCallbackService())
{
whService.Insert(PocoFactory.CreateWebHookCallback(regInfo),
out registeredId);
}
}
return new int?[] { registeredId };
}
[Authorize]
[HttpPost]
public void Unregister(int id)
{
using (var whService = new WebHookCallbackService())
{
whService.Remove(id);
}
}
[HttpPost]
public void TriggerCallback(CallbackMsg callbackMsg)
{
using (var whService = new WebHookCallbackService())
{
var webhookEntities = whService.Get(
x=>!String.IsNullOrEmpty(x.Uri) &&
x.IsEnabled==true);
Parallel.ForEach(webhookEntities, entity
=>
{
String apiUrl = entity.Uri;
this.sendCallbackRequestToClient(apiUrl,
callbackMsg);
}
);
Thread.Sleep(5000);
}
}
private void sendCallbackRequestToClient(String apiUrl, CallbackMsg callbackMsg)
{
//Intial HttpClient
HttpClient httpClient = new HttpClient();
//Set the http service uri
httpClient.BaseAddress = new Uri(apiUrl);
//The http service is based on JSON
format
httpClient.DefaultRequestHeaders.Accept.Add(
new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
var msg = String.Empty;
HttpResponseMessage resp =
httpClient.PostAsJsonAsync(apiUrl, callbackMsg).Result;
Debug.WriteLine(String.Format("{0}:{1}", apiUrl,
resp.StatusCode.ToString()));
}
}
|
▋Implement the
receiver for WebHook in client sides
最後實作另外一支Web Api,加入WebHook的Callback post的Receiver Http methods.
以下面的程式碼為例:
public class ReceiveController : ApiController
{
[HttpPost]
public HttpResponseMessage Receive1()
{
return this.Request.CreateResponse(HttpStatusCode.OK);
}
[HttpPost]
public HttpResponseMessage Receive2()
{
return this.Request.CreateResponse(HttpStatusCode.OK);
}
}
|
▌測試
▋取得Token
先註冊OWIN Authentication,成功後取得Token:
▋註冊WebHook服務
測試註冊五個Callback post url的結果。
▋註銷WebHook服務
▋測試Http Callback
Server side收到Client的回覆結果。
▌Reference
沒有留言:
張貼留言