11using System ;
2+ using System . IO ;
23using System . Reflection ;
4+ using System . Text . RegularExpressions ;
35using System . Web ;
46using System . Web . Compilation ;
57using System . Web . Security ;
68using System . Web . UI ;
9+
710/// <summary>
8- /// Verify authorization on call to WebMethods or Pages with the attribute: <RequiresAuthentication> (VB) | [RequiresAuthentication] (C#) .
11+ /// Verify authorization on requests to AJAX WebServices or Pages.
912/// </summary>
1013[ AttributeUsage ( AttributeTargets . Method | AttributeTargets . Class ) ]
1114public class RequiresAuthenticationAttribute : Attribute { }
@@ -38,26 +41,151 @@ private void OnPostAuthorizeRequest(object sender, EventArgs e) {
3841 var app = ( HttpApplication ) sender ;
3942 var context = app . Context ;
4043 var request = context . Request ;
44+ var requestUrl = context . Request . Url . ToString ( ) ;
4145
42- if ( context . Handler is Page page ) {
43- if ( page ? . GetType ( ) . GetCustomAttribute < RequiresAuthenticationAttribute > ( ) != null ) {
44- if ( ! request . IsAuthenticated || request . Cookies [ FormsAuthentication . FormsCookieName ] == null ) {
46+ if ( context . Handler is Page page ) {
47+ var pageType = page . GetType ( ) ;
48+ if ( ! requestUrl . Contains ( ".axd?" ) ) {
49+ var masterPagePath = GetMasterPagePathFromMarkup ( page . AppRelativeVirtualPath ) ;
50+ if ( ! string . IsNullOrEmpty ( masterPagePath ) ) {
51+ var masterPageType = BuildManager . GetCompiledType ( masterPagePath ) ;
52+ if ( masterPageType != null && masterPageType . GetCustomAttribute < RequiresAuthenticationAttribute > ( ) != null ) {
53+ if ( ! request . IsAuthenticated || request . Cookies ? [ FormsAuthentication . FormsCookieName ] == null ) {
54+ DenyAccess ( context ) ;
55+ return ;
56+ }
57+ }
58+ }
59+ }
60+
61+ if ( pageType . GetCustomAttribute < RequiresAuthenticationAttribute > ( ) != null ) {
62+ if ( ! request . IsAuthenticated || request . Cookies ? [ FormsAuthentication . FormsCookieName ] == null ) {
4563 DenyAccess ( context ) ;
64+ return ;
4665 }
4766 }
67+
4868 if ( request . HttpMethod == "POST" ) {
4969 var methodName = GetWebMethodNameFromRequest ( request ) ;
5070 if ( ! string . IsNullOrEmpty ( methodName ) ) {
51- var pageType = page ? . GetType ( ) ;
52- var methodInfo = pageType ? . GetMethod ( methodName , BindingFlags . Public | BindingFlags . Static | BindingFlags . FlattenHierarchy ) ;
71+ var methodInfo = pageType . GetMethod ( methodName , BindingFlags . Public | BindingFlags . Static | BindingFlags . FlattenHierarchy ) ;
5372 if ( methodInfo ? . GetCustomAttribute < RequiresAuthenticationAttribute > ( ) != null ) {
54- if ( ! request . IsAuthenticated || request . Cookies [ FormsAuthentication . FormsCookieName ] == null ) {
73+ if ( ! request . IsAuthenticated || request . Cookies ? [ FormsAuthentication . FormsCookieName ] == null ) {
5574 DenyAccess ( context ) ;
5675 }
5776 }
5877 }
5978 }
79+
80+ } else if ( requestUrl . Contains ( ".asmx/" ) ) {
81+ //Prøvd å hente Type via Handler._privateSomething
82+
83+ var segments = requestUrl . Split ( new [ ] { ".asmx/" } , StringSplitOptions . RemoveEmptyEntries ) ;
84+ if ( segments . Length > 1 ) {
85+ string methodName = segments [ 1 ] ; // Extract the part after .asmx/ as the method name
86+ string asmxUrlWithoutMethod = requestUrl . Replace ( "/" + methodName , "" ) ; // Remove the method name from the URL
87+
88+ var codeBehindPath = GetCodeBehindPathFromASMXUrl ( asmxUrlWithoutMethod ) ;
89+
90+ if ( ! string . IsNullOrEmpty ( codeBehindPath ) ) {
91+ dynamic _handler = context . CurrentHandler ;
92+ dynamic handlerWrapper = context . Handler ;
93+
94+ if ( handlerWrapper != null ) {
95+ // Retrieve original handler and its metadata
96+ var originalHandlerField = handlerWrapper . GetType ( ) . GetField ( "_originalHandler" , BindingFlags . NonPublic | BindingFlags . Instance ) ;
97+ var originalHandler = originalHandlerField ? . GetValue ( handlerWrapper ) as dynamic ;
98+
99+ if ( originalHandler != null ) {
100+ var webServiceMethodDataField = originalHandler . GetType ( ) . GetField ( "_webServiceMethodData" , BindingFlags . NonPublic | BindingFlags . Instance ) ;
101+ var webServiceMethodData = webServiceMethodDataField ? . GetValue ( originalHandler ) as dynamic ;
102+
103+ if ( webServiceMethodData != null ) {
104+ var ownerField = webServiceMethodData . GetType ( ) . GetField ( "_owner" , BindingFlags . NonPublic | BindingFlags . Instance ) ;
105+ var owner = ownerField ? . GetValue ( webServiceMethodData ) as dynamic ;
106+
107+ if ( owner != null ) {
108+ var typeDataField = owner . GetType ( ) . GetField ( "_typeData" , BindingFlags . NonPublic | BindingFlags . Instance ) ;
109+ var typeData = typeDataField ? . GetValue ( owner ) as dynamic ;
110+
111+ if ( typeData != null ) {
112+ var actualTypeField = typeData . GetType ( ) . GetField ( "_actualType" , BindingFlags . NonPublic | BindingFlags . Instance ) ;
113+ var actualType = actualTypeField ? . GetValue ( typeData ) as dynamic ;
114+
115+ var attributes = actualType . GetCustomAttributes ( typeof ( RequiresAuthenticationAttribute ) , true ) ;
116+ bool requiresAuthentication = attributes . Length > 0 ;
117+
118+ // Check if authentication is required for the main class
119+ if ( requiresAuthentication ) {
120+ if ( ! request . IsAuthenticated || request . Cookies ? [ FormsAuthentication . FormsCookieName ] == null ) {
121+ DenyAccess ( context ) ;
122+ return ;
123+ }
124+ }
125+
126+ // Check for authentication attribute on the requested method
127+ if ( ! requiresAuthentication ) {
128+ var methodInfo = actualType . GetMethod ( methodName ) ;
129+ if ( methodInfo != null ) {
130+ var methodAttributes = methodInfo . GetCustomAttributes ( typeof ( RequiresAuthenticationAttribute ) , true ) ;
131+ bool methodRequiresAuthentication = methodAttributes . Length > 0 ;
132+
133+
134+ if ( methodRequiresAuthentication ) {
135+ if ( ! request . IsAuthenticated || request . Cookies ? [ FormsAuthentication . FormsCookieName ] == null ) {
136+ DenyAccess ( context ) ;
137+ return ;
138+ }
139+ }
140+ }
141+ }
142+ }
143+
144+ }
145+ }
146+ }
147+ }
148+ }
149+ }
150+ }
151+ }
152+
153+ private string GetCodeBehindPathFromASMXUrl ( string asmxUrl ) {
154+ string relativePath = GetRelativeVirtualPath ( asmxUrl ) ;
155+ if ( ! string . IsNullOrEmpty ( relativePath ) ) {
156+ string asmxMarkup = File . ReadAllText ( HttpContext . Current . Server . MapPath ( relativePath ) ) ;
157+
158+ Match match = Regex . Match ( asmxMarkup , @"<%@ WebService Language=""VB"" CodeBehind=""(.*?)"" Class=""(.*?)"" %>" ) ;
159+ if ( match . Success && match . Groups . Count > 1 ) {
160+ string codeBehindPath = match . Groups [ 1 ] . Value ;
161+ return codeBehindPath ;
162+ }
163+ }
164+
165+ return string . Empty ;
166+ }
167+
168+ private string GetRelativeVirtualPath ( string absolutePath ) {
169+ Uri uri = new Uri ( absolutePath ) ;
170+ string rootPath = HttpContext . Current . Request . Url . GetLeftPart ( UriPartial . Authority ) ;
171+ if ( uri . AbsoluteUri . StartsWith ( rootPath , StringComparison . OrdinalIgnoreCase ) ) {
172+ return "~" + uri . AbsolutePath . Replace ( "\\ " , "/" ) ;
173+ }
174+ return string . Empty ;
175+ }
176+
177+ private string GetMasterPagePathFromMarkup ( string virtualPath ) {
178+ string markup = File . ReadAllText ( HttpContext . Current . Server . MapPath ( virtualPath ) ) ;
179+ using ( StringReader reader = new StringReader ( markup ) ) {
180+ string line ;
181+ while ( ( line = reader . ReadLine ( ) ) != null ) {
182+ Match match = Regex . Match ( line , "MasterPageFile\\ s*=\\ s*\" (.+?)\" " ) ;
183+ if ( match . Success ) {
184+ return match . Groups [ 1 ] . Value ;
185+ }
186+ }
60187 }
188+ return null ;
61189 }
62190
63191 /// <summary>
@@ -80,4 +208,4 @@ private static string GetWebMethodNameFromRequest(HttpRequest request) {
80208 var slashIndex = pathInfo . IndexOf ( '/' ) ;
81209 return slashIndex >= 0 ? pathInfo . Substring ( 0 , slashIndex ) : pathInfo ;
82210 }
83- }
211+ }
0 commit comments