CPOAuthentication.cs 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. using EVCB_OCPP.WEBAPI.Models.WebAPI;
  2. using EVCB_OCPP.WEBAPI.Services;
  3. using Newtonsoft.Json;
  4. using System;
  5. using System.Collections.Generic;
  6. using System.Linq;
  7. using System.Net;
  8. using System.Net.Http;
  9. using System.Security.Cryptography;
  10. using System.Text;
  11. using System.Threading;
  12. using System.Threading.Tasks;
  13. using System.Web;
  14. using System.Web.Http.Controllers;
  15. using System.Web.Http.Filters;
  16. namespace EVCB_OCPP.WEBAPI.Handlers
  17. {
  18. public class CPOAuthentication : FilterAttribute, IAuthorizationFilter
  19. {
  20. public Task<HttpResponseMessage> ExecuteAuthorizationFilterAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation)
  21. {
  22. HttpStatusCode _status = HttpStatusCode.Unauthorized;
  23. CPOOuterResponse _errorResponse = new CPOOuterResponse() { StatusMessage = CPO_StatusMessage.ERROR_MSG_INVALIDHEADER };
  24. try
  25. {
  26. string formatMsg = "";
  27. if (CheckHeaders(actionContext, out formatMsg))
  28. {
  29. string timestamp = actionContext.Request.Headers.GetValues(EVCBConfiguration.Header_Timestamp).FirstOrDefault();
  30. if (IsExpiryTime(timestamp))
  31. {
  32. _errorResponse.StatusMessage = CPO_StatusMessage.ERROR_MSG_INVALIDTIMESTAMP;
  33. }
  34. else
  35. {
  36. string partnerId = actionContext.Request.Headers.GetValues(EVCBConfiguration.Header_PartnerId).FirstOrDefault();
  37. string key = new CustomerService().GetAPIKey(new Guid(partnerId));
  38. if (IsPass(actionContext, key))
  39. {
  40. return continuation().ContinueWith<HttpResponseMessage>((tsk) =>
  41. {
  42. HttpResponseMessage response = tsk.Result;
  43. return response;
  44. }, cancellationToken);
  45. }
  46. else
  47. {
  48. _errorResponse.StatusMessage = CPO_StatusMessage.ERROR_MSG_INVALIDSIGNATURE;
  49. }
  50. }
  51. }
  52. else
  53. {
  54. _errorResponse.StatusMessage = formatMsg;
  55. }
  56. }
  57. catch (Exception ex)
  58. {
  59. _errorResponse.StatusMessage = CPO_StatusMessage.ERROR_MSG_UNEXPECTEDERROR;
  60. }
  61. return FromResult(new HttpResponseMessage(_status) { Content = new StringContent(JsonConvert.SerializeObject(_errorResponse), System.Text.Encoding.UTF8, "application/json") });
  62. }
  63. private Task<HttpResponseMessage> FromResult(HttpResponseMessage result)
  64. {
  65. var source = new TaskCompletionSource<HttpResponseMessage>();
  66. source.SetResult(result);
  67. return source.Task;
  68. }
  69. private bool IsPass(HttpActionContext actionContext, string key)
  70. {
  71. bool authenticated = false;
  72. string timestamp = actionContext.Request.Headers.GetValues(EVCBConfiguration.Header_Timestamp).FirstOrDefault();
  73. string partnerId = actionContext.Request.Headers.GetValues(EVCBConfiguration.Header_PartnerId).FirstOrDefault();
  74. string signature = actionContext.Request.Headers.GetValues(EVCBConfiguration.Header_Signature).FirstOrDefault();
  75. Task<string> content = actionContext.Request.Content.ReadAsStringAsync();
  76. string body = content.Result;
  77. string tempText = actionContext.Request.RequestUri.ToString().Substring(actionContext.Request.RequestUri.ToString().IndexOf('?') + 1).ToLower();
  78. tempText = tempText.StartsWith("http") ? string.Empty : tempText;
  79. body = tempText + body;
  80. string unencodeText = string.Format("{0}{1}{2}{3}", body, timestamp, partnerId, key).ToLower();
  81. string signVerification = GenerateSignature(unencodeText);
  82. if (signVerification == signature)
  83. {
  84. authenticated = true;
  85. }
  86. return authenticated;
  87. }
  88. private bool CheckHeaders(HttpActionContext actionContext, out string formatMessage)
  89. {
  90. formatMessage = string.Empty;
  91. if (actionContext.Request.Headers.Contains(EVCBConfiguration.Header_PartnerId)
  92. && actionContext.Request.Headers.Contains(EVCBConfiguration.Header_Signature)
  93. && actionContext.Request.Headers.Contains(EVCBConfiguration.Header_Timestamp))
  94. {
  95. string timestamp = actionContext.Request.Headers.GetValues(EVCBConfiguration.Header_Timestamp).FirstOrDefault();
  96. string PartnerId = actionContext.Request.Headers.GetValues(EVCBConfiguration.Header_PartnerId).FirstOrDefault();
  97. long _timestamp = 0;
  98. if (!long.TryParse(timestamp, out _timestamp))
  99. {
  100. formatMessage = string.Format("{0} ", "Timestamp's Format is incorrect.");
  101. return false;
  102. }
  103. Guid _PartnerId = Guid.Empty;
  104. if (!Guid.TryParse(PartnerId, out _PartnerId))
  105. {
  106. formatMessage = string.Format("{0} ", "PartnerId's Format is incorrect.it must be Guid type");
  107. return false;
  108. }
  109. return true;
  110. }
  111. else
  112. {
  113. return false;
  114. }
  115. }
  116. private static bool IsExpiryTime(string timestamp)
  117. {
  118. bool result = true;
  119. long minTime = DateTimeOffset.UtcNow.AddSeconds(-300).ToUnixTimeSeconds();
  120. long maxTime = DateTimeOffset.UtcNow.AddSeconds(300).ToUnixTimeSeconds();
  121. long requestTime = 0;
  122. if (long.TryParse(timestamp, out requestTime))
  123. {
  124. if (minTime < requestTime && maxTime > requestTime)
  125. {
  126. result = false;
  127. }
  128. }
  129. return result;
  130. }
  131. private static string GenerateSignature(string unencodeText)
  132. {
  133. if ((unencodeText == null) || (unencodeText.Length == 0))
  134. {
  135. return String.Empty;
  136. }
  137. unencodeText = unencodeText.ToLower();
  138. MD5 md5 = new MD5CryptoServiceProvider();
  139. byte[] textToHash = Encoding.UTF8.GetBytes(unencodeText);
  140. byte[] result = md5.ComputeHash(textToHash);
  141. return BitConverter.ToString(result).Replace("-", "").ToLower();
  142. }
  143. }
  144. }