88using 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: <RequiresAuthentication> (VB) | [RequiresAuthentication] (C#) .
1212/// </summary>
1313[ AttributeUsage ( AttributeTargets . Method | AttributeTargets . Class ) ]
1414public 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