Skip to content

Commit 6ddd5bf

Browse files
authored
Update AuthorizationHttpModule.cs
Signed-off-by: Joachim Fosse <56757601+joaf123@users.noreply.github.com>
1 parent 4dd31c5 commit 6ddd5bf

File tree

1 file changed

+37
-13
lines changed

1 file changed

+37
-13
lines changed

AuthorizationHttpModule.cs

Lines changed: 37 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
using System.Web.UI;
99

1010
/// <summary>
11-
/// Verify authorization on requests to AJAX WebServices or Pages.
11+
/// Verify authorization on call to WebMethods or Pages with the attribute: &lt;RequiresAuthentication&gt; (VB) | [RequiresAuthentication] (C#).
1212
/// </summary>
1313
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
1414
public class RequiresAuthenticationAttribute : Attribute { }
@@ -33,7 +33,7 @@ public void Dispose() {
3333
}
3434

3535
/// <summary>
36-
/// Authorize request.
36+
/// A request has hit IIS. This events handles authorization for the given request.
3737
/// </summary>
3838
/// <param name="sender">Sender Parameter</param>
3939
/// <param name="e">EventArgs Parameter</param>
@@ -43,8 +43,10 @@ private void OnPostAuthorizeRequest(object sender, EventArgs e) {
4343
var request = context.Request;
4444
var requestUrl = context.Request.Url.ToString();
4545

46-
if (context.Handler is Page page) {
46+
//The request is for a Page Class:
47+
if (context.Handler is Page page) {
4748
var pageType = page.GetType();
49+
//Check if the MasterPage requires authentication:
4850
if (!requestUrl.Contains(".axd?")) {
4951
var masterPagePath = GetMasterPagePathFromMarkup(page.AppRelativeVirtualPath);
5052
if (!string.IsNullOrEmpty(masterPagePath)) {
@@ -58,13 +60,15 @@ private void OnPostAuthorizeRequest(object sender, EventArgs e) {
5860
}
5961
}
6062

63+
//Check if the Page requires authentication:
6164
if (pageType.GetCustomAttribute<RequiresAuthenticationAttribute>() != null) {
6265
if (!request.IsAuthenticated || request.Cookies?[FormsAuthentication.FormsCookieName] == null) {
6366
DenyAccess(context);
6467
return;
6568
}
6669
}
6770

71+
//The request is for a WebMethod inside a Page Class:
6872
if (request.HttpMethod == "POST") {
6973
var methodName = GetWebMethodNameFromRequest(request);
7074
if (!string.IsNullOrEmpty(methodName)) {
@@ -76,10 +80,10 @@ private void OnPostAuthorizeRequest(object sender, EventArgs e) {
7680
}
7781
}
7882
}
83+
};
7984

80-
} else if (requestUrl.Contains(".asmx/")) {
81-
//Prøvd å hente Type via Handler._privateSomething
82-
85+
//The request is for a WebService Class:
86+
if (!(context.Handler is Page) & requestUrl.Contains(".asmx/")) {
8387
var segments = requestUrl.Split(new[] { ".asmx/" }, StringSplitOptions.RemoveEmptyEntries);
8488
if (segments.Length > 1) {
8589
string methodName = segments[1]; // Extract the part after .asmx/ as the method name
@@ -91,15 +95,28 @@ private void OnPostAuthorizeRequest(object sender, EventArgs e) {
9195
dynamic _handler = context.CurrentHandler;
9296
dynamic handlerWrapper = context.Handler;
9397

98+
// Retrieve original handler and its metadata
9499
if (handlerWrapper != null) {
95-
// Retrieve original handler and its metadata
96100
var originalHandlerField = handlerWrapper.GetType().GetField("_originalHandler", BindingFlags.NonPublic | BindingFlags.Instance);
97101
var originalHandler = originalHandlerField?.GetValue(handlerWrapper) as dynamic;
98102

99103
if (originalHandler != null) {
104+
//Session Disabled WebMethod is Called:
100105
var webServiceMethodDataField = originalHandler.GetType().GetField("_webServiceMethodData", BindingFlags.NonPublic | BindingFlags.Instance);
101106
var webServiceMethodData = webServiceMethodDataField?.GetValue(originalHandler) as dynamic;
102107

108+
//If the WebService Method has SessionEnabled=True the RestHandlerWithSession is used, instead of RestHandler class.
109+
//RestHandlerWithSession is an empty class that inherits both the base RestHandler class and IRequireSessionState for session accsess
110+
//Because of this we need to get the class type in a different way, through the BaseType.
111+
//Since System.Web.Script.Services.RestHandlerWithSession is an internal class we also need to retive the type like so:
112+
Type _RestHandlerWithSessionType = Type.GetType("System.Web.Script.Services.RestHandlerWithSession, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35");
113+
114+
//Session Enabled WebMethod is Called:
115+
if (_RestHandlerWithSessionType == originalHandler.GetType()) {
116+
webServiceMethodDataField = originalHandler.GetType().BaseType.GetField("_webServiceMethodData", BindingFlags.NonPublic | BindingFlags.Instance);
117+
webServiceMethodData = webServiceMethodDataField?.GetValue(originalHandler) as dynamic;
118+
};
119+
103120
if (webServiceMethodData != null) {
104121
var ownerField = webServiceMethodData.GetType().GetField("_owner", BindingFlags.NonPublic | BindingFlags.Instance);
105122
var owner = ownerField?.GetValue(webServiceMethodData) as dynamic;
@@ -112,25 +129,25 @@ private void OnPostAuthorizeRequest(object sender, EventArgs e) {
112129
var actualTypeField = typeData.GetType().GetField("_actualType", BindingFlags.NonPublic | BindingFlags.Instance);
113130
var actualType = actualTypeField?.GetValue(typeData) as dynamic;
114131

132+
//The WebMethod's Class Type is retrived, we can now check for Custom Attributes:
115133
var attributes = actualType.GetCustomAttributes(typeof(RequiresAuthenticationAttribute), true);
116134
bool requiresAuthentication = attributes.Length > 0;
117135

118-
// Check if authentication is required for the main class
136+
//Check if authentication is required for the main class
119137
if (requiresAuthentication) {
120138
if (!request.IsAuthenticated || request.Cookies?[FormsAuthentication.FormsCookieName] == null) {
121139
DenyAccess(context);
122140
return;
123141
}
124142
}
125143

126-
// Check for authentication attribute on the requested method
144+
//Check if authentication is required for the requested method
127145
if (!requiresAuthentication) {
128146
var methodInfo = actualType.GetMethod(methodName);
129147
if (methodInfo != null) {
130148
var methodAttributes = methodInfo.GetCustomAttributes(typeof(RequiresAuthenticationAttribute), true);
131149
bool methodRequiresAuthentication = methodAttributes.Length > 0;
132150

133-
134151
if (methodRequiresAuthentication) {
135152
if (!request.IsAuthenticated || request.Cookies?[FormsAuthentication.FormsCookieName] == null) {
136153
DenyAccess(context);
@@ -140,7 +157,6 @@ private void OnPostAuthorizeRequest(object sender, EventArgs e) {
140157
}
141158
}
142159
}
143-
144160
}
145161
}
146162
}
@@ -175,13 +191,21 @@ private string GetRelativeVirtualPath(string absolutePath) {
175191
}
176192

177193
private string GetMasterPagePathFromMarkup(string virtualPath) {
194+
string currentFolder = Path.GetDirectoryName(HttpContext.Current.Server.MapPath(virtualPath));
195+
178196
string markup = File.ReadAllText(HttpContext.Current.Server.MapPath(virtualPath));
179197
using (StringReader reader = new StringReader(markup)) {
180198
string line;
181199
while ((line = reader.ReadLine()) != null) {
182200
Match match = Regex.Match(line, "MasterPageFile\\s*=\\s*\"(.+?)\"");
183201
if (match.Success) {
184-
return match.Groups[1].Value;
202+
string masterPagePath = match.Groups[1].Value;
203+
204+
if (!VirtualPathUtility.IsAppRelative(masterPagePath)) {
205+
masterPagePath = VirtualPathUtility.Combine(virtualPath, masterPagePath);
206+
}
207+
208+
return masterPagePath;
185209
}
186210
}
187211
}
@@ -208,4 +232,4 @@ private static string GetWebMethodNameFromRequest(HttpRequest request) {
208232
var slashIndex = pathInfo.IndexOf('/');
209233
return slashIndex >= 0 ? pathInfo.Substring(0, slashIndex) : pathInfo;
210234
}
211-
}
235+
}

0 commit comments

Comments
 (0)