Advertisement
Guest User

Untitled

a guest
Jul 18th, 2016
88
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.05 KB | None | 0 0
  1. using System;
  2. using System.Security.Authentication;
  3. using System.Text;
  4. using System.Web.Mvc;
  5. using TenForce.Execution.Framework;
  6. using TenForce.Execution.Api2.Implementation;
  7.  
  8. namespace TenForce.Execution.Web.Filters
  9. {
  10. /// <summary>
  11. /// This class defines a custom Authentication attribute that can be applied on controllers.
  12. /// This results in authentication occurring on all actions that are beeing defined in the controller
  13. /// who implements this filter.
  14. /// </summary>
  15. [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
  16. public class AuthenticationFilter : ActionFilterAttribute
  17. {
  18. #region IAuthorizationFilter Members
  19.  
  20. /// <summary>
  21. /// This function get's called by the Mvc framework prior to performing any actions on
  22. /// the controller. The function will check if a call is authorized by the caller.
  23. /// The function will extract the username and password from the HTTP headers send by
  24. /// the caller and will validate these against the database to see if there is a valid
  25. /// account for the user.
  26. /// If the user can be found in the database, operations will resume, otherwise the action
  27. /// is canceled.
  28. /// </summary>
  29. /// <param name="filterContext">The context for the filter.</param>
  30. public override void OnActionExecuting(ActionExecutingContext filterContext)
  31. {
  32. // Call the base operations first.
  33. base.OnActionExecuting(filterContext);
  34.  
  35. // Surround the entire authentication process with a try-catch to prevent errors from
  36. // breaking the code.
  37. try
  38. {
  39. // Extract the custom authorization header from the HTTP headers.
  40. string customAuthHeader = Encoding.UTF8.GetString(Convert.FromBase64String(filterContext.RequestContext.HttpContext.Request.Headers["TenForce-Auth"]));
  41.  
  42. // Split the header in the subcomponents.
  43. string[] components = customAuthHeader.Split('|');
  44.  
  45. // Check if both components are present.
  46. if (components.Length >= 2)
  47. {
  48. // This header consists of 2 parts, the username and password, seperate by a vertical pipe.
  49. string username = components[0] ?? string.Empty;
  50. string password = components[1] ?? string.Empty;
  51. string databaseId = Authenticator.ConstructDatabaseId(filterContext.HttpContext.Request.RawUrl);
  52.  
  53. // Validate the user against the database.
  54. if (Authenticator.Authenticate(username, password, databaseId))
  55. {
  56. // The request is valid, so add the custom header to inform the request was
  57. // authorized.
  58. AllowRequest(filterContext);
  59. return;
  60. }
  61.  
  62. throw new InvalidCredentialException(@"The provided username & password combination is invalid. Username : " + username);
  63. }
  64.  
  65. // If we reach this point, the authorization request is no longer valid.
  66. throw new InvalidCredentialException(@"Insufficient parameters supplied for a valid authentication.");
  67. }
  68. catch (Exception ex)
  69. {
  70. // Log the exception that has occurred.
  71. Logger.Log(GetType(), ex);
  72.  
  73. // Cancel the request, as we could not properly process it.
  74. CancelRequest(filterContext);
  75. }
  76. }
  77.  
  78. #endregion
  79.  
  80. #region Private Methods
  81.  
  82. /// <summary>
  83. /// Cancels the Athorization and adds the custom tenforce header to the response to
  84. /// inform the caller that his call has been denied.
  85. /// </summary>
  86. /// <param name="authContext">The authorizationContxt that needs to be canceled.</param>
  87. private static void CancelRequest(ActionExecutingContext authContext)
  88. {
  89. authContext.Result = new HttpUnauthorizedResult();
  90. if (!authContext.RequestContext.HttpContext.Request.ServerVariables[@"SERVER_SOFTWARE"].Contains(@"Microsoft-IIS/7."))
  91. authContext.HttpContext.Response.AddHeader(@"Tenforce-RAuth", @"DENIED");
  92. else
  93. authContext.HttpContext.Response.Headers.Add(@"Tenforce-RAuth", @"DENIED");
  94. }
  95.  
  96. /// <summary>
  97. /// Allows the Authorization and adds the custom tenforce header to the response to
  98. /// inform the claler that his call has been allowed.
  99. /// </summary>
  100. /// <param name="authContext">The authorizationContext that needs to be allowed.</param>
  101. private static void AllowRequest(ActionExecutingContext authContext)
  102. {
  103. authContext.Result = null;
  104. if (!authContext.RequestContext.HttpContext.Request.ServerVariables[@"SERVER_SOFTWARE"].Contains(@"Microsoft-IIS/7."))
  105. authContext.HttpContext.Response.AddHeader(@"Tenforce-RAuth", @"OK");
  106. else
  107. authContext.HttpContext.Response.Headers.Add(@"Tenforce-RAuth", @"OK");
  108. }
  109.  
  110. #endregion
  111. }
  112. }
  113.  
  114. /// <summary>
  115. /// This function is called before running each test and configures the various properties
  116. /// of the test class so that each test will run with the same settings initialy.
  117. /// The function will configure the Mock Framework object so that they simulate a proper
  118. /// web request on the ActionFilter of a Controller.
  119. /// </summary>
  120. [SetUp]
  121. protected void TestSetup()
  122. {
  123. // Construct the Mock object required for the test.
  124. HttpRequest = new Mock<HttpRequestBase>();
  125. HttpResponse = new Mock<HttpResponseBase>();
  126. HttpContext = new Mock<HttpContextBase>();
  127. ActionContext = new Mock<ActionExecutingContext>();
  128. Filter = new Web.Filters.AuthenticationFilter();
  129.  
  130. // Configure the properties to modify the headers, request and response
  131. // objects starting from the HttpContext base object.
  132. // Also create the custom header collection and set the test URI.
  133. ActionContext.SetupGet(c => c.HttpContext).Returns(HttpContext.Object);
  134. HttpContext.SetupGet(r => r.Request).Returns(HttpRequest.Object);
  135. HttpContext.SetupGet(r => r.Response).Returns(HttpResponse.Object);
  136. HttpResponse.SetupGet(x => x.Headers).Returns(new System.Net.WebHeaderCollection());
  137. HttpRequest.SetupGet(r => r.RawUrl).Returns(@"http://test.tenforce.tst");
  138. }
  139.  
  140. /// <summary>
  141. /// <para>This test will call the ActionFilter and perform a standard authorization request against the
  142. /// database using the credentials of the system administrator account. The test relies on the MoQ
  143. /// framework to mock several of the key components in the MVC Framework such as the HttpRequest,
  144. /// HttpResponse and HttpContext objects.</para>
  145. /// <para>The test expects the authentication to succeed, and relies on the IIS6 implementation.</para>
  146. /// </summary>
  147. [Test, MaxDuration]
  148. public void SuccessfullAuthenticationOnIis6()
  149. {
  150. // Configure the Authentication header of the request, so that a valid authentication
  151. // can take place. We want valid login credentials when the filter requests the header.
  152. HttpRequest.SetupGet(r => r.Headers).Returns(new System.Net.WebHeaderCollection { { @"TenForce-Auth", CorrectAuthToken } });
  153. HttpRequest.SetupGet(r => r.ServerVariables).Returns(
  154. new System.Collections.Specialized.NameValueCollection { { @"SERVER_SOFTWARE", @"Microsoft-IIS/6.0" } });
  155. HttpResponse.SetupGet(r => r.Headers).Returns(new System.Collections.Specialized.NameValueCollection());
  156. HttpResponse.Setup(r => r.AddHeader(@"TenForce-RAuth", @"OK"));
  157.  
  158. // Call the action on the filter and check the response.
  159. Filter.OnActionExecuting(ActionContext.Object);
  160.  
  161. // Check the ActionResult to null and that the response header contains the correct value.
  162. Assert.IsTrue(ActionContext.Object.Result == null);
  163. Assert.IsTrue(ActionContext.Object.HttpContext.Response.Headers["TenForce-RAuth"].Equals(@"OK"));
  164. }
  165.  
  166. HttpResponse.Setup(r => r.AddHeader(It.IsAny<string>(), It.IsAny<string>())).Callback<string, string>((x,y) => HttpResponse.Object.Headers.Add(x, y));
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement