8
8
using System . Web . UI ;
9
9
10
10
/// <summary>
11
- /// Verify authorization on requests to AJAX WebServices or Pages.
11
+ /// Verify authorization on call to WebMethods or Pages with the attribute: <RequiresAuthentication> (VB) | [RequiresAuthentication] (C#) .
12
12
/// </summary>
13
13
[ AttributeUsage ( AttributeTargets . Method | AttributeTargets . Class ) ]
14
14
public class RequiresAuthenticationAttribute : Attribute { }
@@ -33,7 +33,7 @@ public void Dispose() {
33
33
}
34
34
35
35
/// <summary>
36
- /// Authorize request.
36
+ /// A request has hit IIS. This events handles authorization for the given request.
37
37
/// </summary>
38
38
/// <param name="sender">Sender Parameter</param>
39
39
/// <param name="e">EventArgs Parameter</param>
@@ -43,8 +43,10 @@ private void OnPostAuthorizeRequest(object sender, EventArgs e) {
43
43
var request = context . Request ;
44
44
var requestUrl = context . Request . Url . ToString ( ) ;
45
45
46
- if ( context . Handler is Page page ) {
46
+ //The request is for a Page Class:
47
+ if ( context . Handler is Page page ) {
47
48
var pageType = page . GetType ( ) ;
49
+ //Check if the MasterPage requires authentication:
48
50
if ( ! requestUrl . Contains ( ".axd?" ) ) {
49
51
var masterPagePath = GetMasterPagePathFromMarkup ( page . AppRelativeVirtualPath ) ;
50
52
if ( ! string . IsNullOrEmpty ( masterPagePath ) ) {
@@ -58,13 +60,15 @@ private void OnPostAuthorizeRequest(object sender, EventArgs e) {
58
60
}
59
61
}
60
62
63
+ //Check if the Page requires authentication:
61
64
if ( pageType . GetCustomAttribute < RequiresAuthenticationAttribute > ( ) != null ) {
62
65
if ( ! request . IsAuthenticated || request . Cookies ? [ FormsAuthentication . FormsCookieName ] == null ) {
63
66
DenyAccess ( context ) ;
64
67
return ;
65
68
}
66
69
}
67
70
71
+ //The request is for a WebMethod inside a Page Class:
68
72
if ( request . HttpMethod == "POST" ) {
69
73
var methodName = GetWebMethodNameFromRequest ( request ) ;
70
74
if ( ! string . IsNullOrEmpty ( methodName ) ) {
@@ -76,10 +80,10 @@ private void OnPostAuthorizeRequest(object sender, EventArgs e) {
76
80
}
77
81
}
78
82
}
83
+ } ;
79
84
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/" ) ) {
83
87
var segments = requestUrl . Split ( new [ ] { ".asmx/" } , StringSplitOptions . RemoveEmptyEntries ) ;
84
88
if ( segments . Length > 1 ) {
85
89
string methodName = segments [ 1 ] ; // Extract the part after .asmx/ as the method name
@@ -91,15 +95,28 @@ private void OnPostAuthorizeRequest(object sender, EventArgs e) {
91
95
dynamic _handler = context . CurrentHandler ;
92
96
dynamic handlerWrapper = context . Handler ;
93
97
98
+ // Retrieve original handler and its metadata
94
99
if ( handlerWrapper != null ) {
95
- // Retrieve original handler and its metadata
96
100
var originalHandlerField = handlerWrapper . GetType ( ) . GetField ( "_originalHandler" , BindingFlags . NonPublic | BindingFlags . Instance ) ;
97
101
var originalHandler = originalHandlerField ? . GetValue ( handlerWrapper ) as dynamic ;
98
102
99
103
if ( originalHandler != null ) {
104
+ //Session Disabled WebMethod is Called:
100
105
var webServiceMethodDataField = originalHandler . GetType ( ) . GetField ( "_webServiceMethodData" , BindingFlags . NonPublic | BindingFlags . Instance ) ;
101
106
var webServiceMethodData = webServiceMethodDataField ? . GetValue ( originalHandler ) as dynamic ;
102
107
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
+
103
120
if ( webServiceMethodData != null ) {
104
121
var ownerField = webServiceMethodData . GetType ( ) . GetField ( "_owner" , BindingFlags . NonPublic | BindingFlags . Instance ) ;
105
122
var owner = ownerField ? . GetValue ( webServiceMethodData ) as dynamic ;
@@ -112,25 +129,25 @@ private void OnPostAuthorizeRequest(object sender, EventArgs e) {
112
129
var actualTypeField = typeData . GetType ( ) . GetField ( "_actualType" , BindingFlags . NonPublic | BindingFlags . Instance ) ;
113
130
var actualType = actualTypeField ? . GetValue ( typeData ) as dynamic ;
114
131
132
+ //The WebMethod's Class Type is retrived, we can now check for Custom Attributes:
115
133
var attributes = actualType . GetCustomAttributes ( typeof ( RequiresAuthenticationAttribute ) , true ) ;
116
134
bool requiresAuthentication = attributes . Length > 0 ;
117
135
118
- // Check if authentication is required for the main class
136
+ //Check if authentication is required for the main class
119
137
if ( requiresAuthentication ) {
120
138
if ( ! request . IsAuthenticated || request . Cookies ? [ FormsAuthentication . FormsCookieName ] == null ) {
121
139
DenyAccess ( context ) ;
122
140
return ;
123
141
}
124
142
}
125
143
126
- // Check for authentication attribute on the requested method
144
+ //Check if authentication is required for the requested method
127
145
if ( ! requiresAuthentication ) {
128
146
var methodInfo = actualType . GetMethod ( methodName ) ;
129
147
if ( methodInfo != null ) {
130
148
var methodAttributes = methodInfo . GetCustomAttributes ( typeof ( RequiresAuthenticationAttribute ) , true ) ;
131
149
bool methodRequiresAuthentication = methodAttributes . Length > 0 ;
132
150
133
-
134
151
if ( methodRequiresAuthentication ) {
135
152
if ( ! request . IsAuthenticated || request . Cookies ? [ FormsAuthentication . FormsCookieName ] == null ) {
136
153
DenyAccess ( context ) ;
@@ -140,7 +157,6 @@ private void OnPostAuthorizeRequest(object sender, EventArgs e) {
140
157
}
141
158
}
142
159
}
143
-
144
160
}
145
161
}
146
162
}
@@ -175,13 +191,21 @@ private string GetRelativeVirtualPath(string absolutePath) {
175
191
}
176
192
177
193
private string GetMasterPagePathFromMarkup ( string virtualPath ) {
194
+ string currentFolder = Path . GetDirectoryName ( HttpContext . Current . Server . MapPath ( virtualPath ) ) ;
195
+
178
196
string markup = File . ReadAllText ( HttpContext . Current . Server . MapPath ( virtualPath ) ) ;
179
197
using ( StringReader reader = new StringReader ( markup ) ) {
180
198
string line ;
181
199
while ( ( line = reader . ReadLine ( ) ) != null ) {
182
200
Match match = Regex . Match ( line , "MasterPageFile\\ s*=\\ s*\" (.+?)\" " ) ;
183
201
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 ;
185
209
}
186
210
}
187
211
}
@@ -208,4 +232,4 @@ private static string GetWebMethodNameFromRequest(HttpRequest request) {
208
232
var slashIndex = pathInfo . IndexOf ( '/' ) ;
209
233
return slashIndex >= 0 ? pathInfo . Substring ( 0 , slashIndex ) : pathInfo ;
210
234
}
211
- }
235
+ }
0 commit comments