diff --git a/AuthorizationHttpModule.cs b/AuthorizationHttpModule.cs
index 29f1af0..2db763a 100644
--- a/AuthorizationHttpModule.cs
+++ b/AuthorizationHttpModule.cs
@@ -8,7 +8,7 @@
using System.Web.UI;
///
-/// Verify authorization on requests to AJAX WebServices or Pages.
+/// Verify authorization on call to WebMethods or Pages with the attribute: <RequiresAuthentication> (VB) | [RequiresAuthentication] (C#).
///
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
public class RequiresAuthenticationAttribute : Attribute { }
@@ -33,7 +33,7 @@ public void Dispose() {
}
///
- /// Authorize request.
+ /// A request has hit IIS. This events handles authorization for the given request.
///
/// Sender Parameter
/// EventArgs Parameter
@@ -43,8 +43,10 @@ private void OnPostAuthorizeRequest(object sender, EventArgs e) {
var request = context.Request;
var requestUrl = context.Request.Url.ToString();
- if (context.Handler is Page page) {
+ //The request is for a Page Class:
+ if (context.Handler is Page page) {
var pageType = page.GetType();
+ //Check if the MasterPage requires authentication:
if (!requestUrl.Contains(".axd?")) {
var masterPagePath = GetMasterPagePathFromMarkup(page.AppRelativeVirtualPath);
if (!string.IsNullOrEmpty(masterPagePath)) {
@@ -58,6 +60,7 @@ private void OnPostAuthorizeRequest(object sender, EventArgs e) {
}
}
+ //Check if the Page requires authentication:
if (pageType.GetCustomAttribute() != null) {
if (!request.IsAuthenticated || request.Cookies?[FormsAuthentication.FormsCookieName] == null) {
DenyAccess(context);
@@ -65,6 +68,7 @@ private void OnPostAuthorizeRequest(object sender, EventArgs e) {
}
}
+ //The request is for a WebMethod inside a Page Class:
if (request.HttpMethod == "POST") {
var methodName = GetWebMethodNameFromRequest(request);
if (!string.IsNullOrEmpty(methodName)) {
@@ -76,10 +80,10 @@ private void OnPostAuthorizeRequest(object sender, EventArgs e) {
}
}
}
+ };
- } else if (requestUrl.Contains(".asmx/")) {
- //Prøvd å hente Type via Handler._privateSomething
-
+ //The request is for a WebService Class:
+ if (!(context.Handler is Page) & requestUrl.Contains(".asmx/")) {
var segments = requestUrl.Split(new[] { ".asmx/" }, StringSplitOptions.RemoveEmptyEntries);
if (segments.Length > 1) {
string methodName = segments[1]; // Extract the part after .asmx/ as the method name
@@ -91,15 +95,28 @@ private void OnPostAuthorizeRequest(object sender, EventArgs e) {
dynamic _handler = context.CurrentHandler;
dynamic handlerWrapper = context.Handler;
+ // Retrieve original handler and its metadata
if (handlerWrapper != null) {
- // Retrieve original handler and its metadata
var originalHandlerField = handlerWrapper.GetType().GetField("_originalHandler", BindingFlags.NonPublic | BindingFlags.Instance);
var originalHandler = originalHandlerField?.GetValue(handlerWrapper) as dynamic;
if (originalHandler != null) {
+ //Session Disabled WebMethod is Called:
var webServiceMethodDataField = originalHandler.GetType().GetField("_webServiceMethodData", BindingFlags.NonPublic | BindingFlags.Instance);
var webServiceMethodData = webServiceMethodDataField?.GetValue(originalHandler) as dynamic;
+ //If the WebService Method has SessionEnabled=True the RestHandlerWithSession is used, instead of RestHandler class.
+ //RestHandlerWithSession is an empty class that inherits both the base RestHandler class and IRequireSessionState for session accsess
+ //Because of this we need to get the class type in a different way, through the BaseType.
+ //Since System.Web.Script.Services.RestHandlerWithSession is an internal class we also need to retive the type like so:
+ Type _RestHandlerWithSessionType = Type.GetType("System.Web.Script.Services.RestHandlerWithSession, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35");
+
+ //Session Enabled WebMethod is Called:
+ if (_RestHandlerWithSessionType == originalHandler.GetType()) {
+ webServiceMethodDataField = originalHandler.GetType().BaseType.GetField("_webServiceMethodData", BindingFlags.NonPublic | BindingFlags.Instance);
+ webServiceMethodData = webServiceMethodDataField?.GetValue(originalHandler) as dynamic;
+ };
+
if (webServiceMethodData != null) {
var ownerField = webServiceMethodData.GetType().GetField("_owner", BindingFlags.NonPublic | BindingFlags.Instance);
var owner = ownerField?.GetValue(webServiceMethodData) as dynamic;
@@ -112,10 +129,11 @@ private void OnPostAuthorizeRequest(object sender, EventArgs e) {
var actualTypeField = typeData.GetType().GetField("_actualType", BindingFlags.NonPublic | BindingFlags.Instance);
var actualType = actualTypeField?.GetValue(typeData) as dynamic;
+ //The WebMethod's Class Type is retrived, we can now check for Custom Attributes:
var attributes = actualType.GetCustomAttributes(typeof(RequiresAuthenticationAttribute), true);
bool requiresAuthentication = attributes.Length > 0;
- // Check if authentication is required for the main class
+ //Check if authentication is required for the main class
if (requiresAuthentication) {
if (!request.IsAuthenticated || request.Cookies?[FormsAuthentication.FormsCookieName] == null) {
DenyAccess(context);
@@ -123,14 +141,13 @@ private void OnPostAuthorizeRequest(object sender, EventArgs e) {
}
}
- // Check for authentication attribute on the requested method
+ //Check if authentication is required for the requested method
if (!requiresAuthentication) {
var methodInfo = actualType.GetMethod(methodName);
if (methodInfo != null) {
var methodAttributes = methodInfo.GetCustomAttributes(typeof(RequiresAuthenticationAttribute), true);
bool methodRequiresAuthentication = methodAttributes.Length > 0;
-
if (methodRequiresAuthentication) {
if (!request.IsAuthenticated || request.Cookies?[FormsAuthentication.FormsCookieName] == null) {
DenyAccess(context);
@@ -140,7 +157,6 @@ private void OnPostAuthorizeRequest(object sender, EventArgs e) {
}
}
}
-
}
}
}
@@ -175,13 +191,21 @@ private string GetRelativeVirtualPath(string absolutePath) {
}
private string GetMasterPagePathFromMarkup(string virtualPath) {
+ string currentFolder = Path.GetDirectoryName(HttpContext.Current.Server.MapPath(virtualPath));
+
string markup = File.ReadAllText(HttpContext.Current.Server.MapPath(virtualPath));
using (StringReader reader = new StringReader(markup)) {
string line;
while ((line = reader.ReadLine()) != null) {
Match match = Regex.Match(line, "MasterPageFile\\s*=\\s*\"(.+?)\"");
if (match.Success) {
- return match.Groups[1].Value;
+ string masterPagePath = match.Groups[1].Value;
+
+ if (!VirtualPathUtility.IsAppRelative(masterPagePath)) {
+ masterPagePath = VirtualPathUtility.Combine(virtualPath, masterPagePath);
+ }
+
+ return masterPagePath;
}
}
}
@@ -208,4 +232,4 @@ private static string GetWebMethodNameFromRequest(HttpRequest request) {
var slashIndex = pathInfo.IndexOf('/');
return slashIndex >= 0 ? pathInfo.Substring(0, slashIndex) : pathInfo;
}
-}
\ No newline at end of file
+}