1
1
using System ;
2
+ using System . IO ;
2
3
using System . Reflection ;
4
+ using System . Text . RegularExpressions ;
3
5
using System . Web ;
4
6
using System . Web . Compilation ;
5
7
using System . Web . Security ;
6
8
using System . Web . UI ;
9
+
7
10
/// <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.
9
12
/// </summary>
10
13
[ AttributeUsage ( AttributeTargets . Method | AttributeTargets . Class ) ]
11
14
public class RequiresAuthenticationAttribute : Attribute { }
@@ -38,26 +41,151 @@ private void OnPostAuthorizeRequest(object sender, EventArgs e) {
38
41
var app = ( HttpApplication ) sender ;
39
42
var context = app . Context ;
40
43
var request = context . Request ;
44
+ var requestUrl = context . Request . Url . ToString ( ) ;
41
45
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 ) {
45
63
DenyAccess ( context ) ;
64
+ return ;
46
65
}
47
66
}
67
+
48
68
if ( request . HttpMethod == "POST" ) {
49
69
var methodName = GetWebMethodNameFromRequest ( request ) ;
50
70
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 ) ;
53
72
if ( methodInfo ? . GetCustomAttribute < RequiresAuthenticationAttribute > ( ) != null ) {
54
- if ( ! request . IsAuthenticated || request . Cookies [ FormsAuthentication . FormsCookieName ] == null ) {
73
+ if ( ! request . IsAuthenticated || request . Cookies ? [ FormsAuthentication . FormsCookieName ] == null ) {
55
74
DenyAccess ( context ) ;
56
75
}
57
76
}
58
77
}
59
78
}
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
+ }
60
187
}
188
+ return null ;
61
189
}
62
190
63
191
/// <summary>
@@ -80,4 +208,4 @@ private static string GetWebMethodNameFromRequest(HttpRequest request) {
80
208
var slashIndex = pathInfo . IndexOf ( '/' ) ;
81
209
return slashIndex >= 0 ? pathInfo . Substring ( 0 , slashIndex ) : pathInfo ;
82
210
}
83
- }
211
+ }
0 commit comments