History

Renamed folders and separated GSF.Media and GSF.Net into separate projects.

StephenCWills committed 14 years ago

Commit ac1ef661 parent 45bce55628 files · +733 −461Browse files

Showing the changes to Source/Libraries/GSF.Web/SecurityModule.cs (1 of 628 files). Show all

Unified · Split

Source/Libraries/GSF.Web/SecurityModule.cs+305−0
@@ -0,0 +1,305 @@
1//******************************************************************************************************
2// SecurityModule.cs - Gbtc
3//
4// Copyright © 2010, Grid Protection Alliance. All Rights Reserved.
5//
6// Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See
7// the NOTICE file distributed with this work for additional information regarding copyright ownership.
8// The GPA licenses this file to you under the Eclipse Public License -v 1.0 (the "License"); you may
9// not use this file except in compliance with the License. You may obtain a copy of the License at:
10//
11// http://www.opensource.org/licenses/eclipse-1.0.php
12//
13// Unless agreed to in writing, the subject software distributed under the License is distributed on an
14// "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the
15// License for the specific language governing permissions and limitations.
16//
17// Code Modification History:
18// ----------------------------------------------------------------------------------------------------
19// 03/31/2010 - Pinal C. Patel
20// Generated original version of source code.
21// 05/27/2010 - Pinal C. Patel
22// Added usage example to code comments.
23// 06/30/2010 - Pinal C. Patel
24// Modified redirection logic to support security of static resources (*.txt, *.pdf, *.exe).
25// 07/01/2010 - Pinal C. Patel
26// Modified redirection logic to allow for custom redirection using customErrors settings.
27// 08/11/2010 - Pinal C. Patel
28// Made key methods virtual for extensibility.
29// 10/14/2010 - Pinal C. Patel
30// Modified GetResourceName() to return path and query for consistency with SecurityPolicy.
31// 01/06/2011 - Pinal C. Patel
32// Implemented logic to use RestrictAccessAttribute for access control on the requested resource.
33// 06/09/2011 - Pinal C. Patel
34// Added null reference check in IsAccessRestricted() method.
35// 07/29/2011 - Pinal C. Patel
36// Made the referral URL passed to SecurityPortal.aspx page relative so redirection work correctly
37// when reverse proxy is involved where requested URL that the web server sees is different than
38// what the user requested.
39// 08/18/2011 - Pinal C. Patel
40// Made Redirect() overridable by deriving classes to control the redirection behavior.
41// 08/19/2011 - Pinal C. Patel
42// Changed the type input parameter for Redirect() from int to HttpStatusCode.
43// 10/8/2012 - Danyelle Gilliam
44// Modified Header
45//
46//******************************************************************************************************
47
48using GSF.Configuration;
49using GSF.Security;
50using GSF.Web.Hosting;
51using System;
52using System.Net;
53using System.Web;
54using System.Web.Configuration;
55using System.Web.Hosting;
56using System.Web.SessionState;
57
58namespace GSF.Web
59{
60 #region [ Enumerations ]
61
62 #endregion
63
64 /// <summary>
65 /// Represents an <see cref="IHttpModule">HTTP module</see> that can be used to enable site-wide role-based security.
66 /// </summary>
67 /// <example>
68 /// Required config file entries:
69 /// <code>
70 /// <![CDATA[
71 /// <?xml version="1.0"?>
72 /// <configuration>
73 /// <configSections>
74 /// <section name="categorizedSettings" type="GSF.Configuration.CategorizedSettingsSection, GSF.Core" />
75 /// </configSections>
76 /// <categorizedSettings>
77 /// <securityProvider>
78 /// <add name="ApplicationName" value="" description="Name of the application being secured as defined in the backend security datastore."
79 /// encrypted="false" />
80 /// <add name="ConnectionString" value="" description="Connection string to be used for connection to the backend security datastore."
81 /// encrypted="false" />
82 /// <add name="ProviderType" value="GSF.Security.LdapSecurityProvider, GSF.Security"
83 /// description="The type to be used for enforcing security." encrypted="false" />
84 /// <add name="IncludedResources" value="*/*.*=*" description="Semicolon delimited list of resources to be secured along with role names."
85 /// encrypted="false" />
86 /// <add name="ExcludedResources" value="*/WebResource.axd*;*/SecurityPortal.aspx*"
87 /// description="Semicolon delimited list of resources to be excluded from being secured."
88 /// encrypted="false" />
89 /// <add name="NotificationSmtpServer" value="localhost" description="SMTP server to be used for sending out email notification messages."
90 /// encrypted="false" />
91 /// <add name="NotificationSenderEmail" value="sender@company.com" description="Email address of the sender of email notification messages."
92 /// encrypted="false" />
93 /// </securityProvider>
94 /// <activeDirectory>
95 /// <add name="PrivilegedDomain" value="" description="Domain of privileged domain user account."
96 /// encrypted="false" />
97 /// <add name="PrivilegedUserName" value="" description="Username of privileged domain user account."
98 /// encrypted="false" />
99 /// <add name="PrivilegedPassword" value="" description="Password of privileged domain user account."
100 /// encrypted="true" />
101 /// </activeDirectory>
102 /// </categorizedSettings>
103 /// <system.web>
104 /// <authentication mode="Windows"/>
105 /// <httpModules>
106 /// <add name="SecurityModule" type="GSF.Web.SecurityModule, GSF.Web" />
107 /// </httpModules>
108 /// </system.web>
109 /// </configuration>
110 /// ]]>
111 /// </code>
112 /// </example>
113 /// <seealso cref="ISecurityProvider"/>
114 public class SecurityModule : IHttpModule
115 {
116 #region [ Members ]
117
118 // Nested Types
119
120 /// <summary>
121 /// A handler used to force the SessionStateModule to load session state.
122 /// </summary>
123 private class SessionEnabledHandler : IHttpHandler, IRequiresSessionState
124 {
125 public IHttpHandler OriginalHandler;
126
127 /// <summary>
128 /// Initializes a new instance of the <see cref="SessionEnabledHandler"/> class.
129 /// </summary>
130 /// <param name="originalHandler">The original handler object.</param>
131 public SessionEnabledHandler(IHttpHandler originalHandler)
132 {
133 OriginalHandler = originalHandler;
134 }
135
136 /// <summary>
137 /// This method will never get called.
138 /// </summary>
139 public void ProcessRequest(HttpContext context)
140 {
141 throw new NotSupportedException();
142 }
143
144 /// <summary>
145 /// Returns false since class has a member.
146 /// </summary>
147 public bool IsReusable
148 {
149 get { return false; }
150 }
151 }
152
153 // Fields
154 private HttpApplication m_application;
155
156 #endregion
157
158 #region [ Properties ]
159
160 /// <summary>
161 /// Gets the current <see cref="HttpApplication"/> instance.
162 /// </summary>
163 protected HttpApplication Application
164 {
165 get
166 {
167 return m_application;
168 }
169 }
170
171 #endregion
172
173 #region [ Methods ]
174
175 /// <summary>
176 /// Initializes the <see cref="SecurityModule"/>.
177 /// </summary>
178 /// <param name="context">An <see cref="HttpApplication"/> object.</param>
179 public void Init(HttpApplication context)
180 {
181 m_application = context;
182 m_application.PostMapRequestHandler += Application_PostMapRequestHandler;
183 m_application.PostAcquireRequestState += Application_PostAcquireRequestState;
184 m_application.PreRequestHandlerExecute += Application_PreRequestHandlerExecute;
185
186 if (!(HostingEnvironment.VirtualPathProvider is EmbeddedResourcePathProvider))
187 HostingEnvironment.RegisterVirtualPathProvider(new EmbeddedResourcePathProvider());
188 }
189
190 /// <summary>
191 /// Releases the resources used by <see cref="SecurityModule"/>.
192 /// </summary>
193 public void Dispose()
194 {
195 m_application.PostMapRequestHandler -= Application_PostMapRequestHandler;
196 m_application.PostAcquireRequestState -= Application_PostAcquireRequestState;
197 m_application.PreRequestHandlerExecute -= Application_PreRequestHandlerExecute;
198 }
199
200 /// <summary>
201 /// Redirects the client browser based on the specified <paramref name="httpStatusCode"/>
202 /// </summary>
203 /// <param name="httpStatusCode"><see cref="HttpStatusCode"/> to be used for the redirect.</param>
204 protected virtual void Redirect(HttpStatusCode httpStatusCode)
205 {
206 int statusCode = (int)httpStatusCode;
207 if (m_application.Context.IsCustomErrorEnabled)
208 {
209 // Defer redirect to customErrors settings in the config file to allow for custom error pages.
210 ConfigurationFile configFile = ConfigurationFile.Current;
211 CustomErrorsSection customErrors = configFile.Configuration.GetSection("system.web/customErrors") as CustomErrorsSection;
212 if (customErrors != null && customErrors.Errors[statusCode.ToString()] != null)
213 {
214 // Set status code for the response.
215 m_application.Context.Response.StatusCode = statusCode;
216 // Throw exception for ASP.NET pipeline to takeover processing.
217 throw new HttpException(statusCode, string.Format("Security exception (HTTP status code: {0})", statusCode));
218 }
219 }
220
221 // Abruptly ending the processing caused by a redirect does not work well when processing static content.
222 string redirectUrl = string.Format("~/SecurityPortal.aspx?s={0}&r={1}", statusCode, HttpUtility.UrlEncode(VirtualPathUtility.ToAppRelative(m_application.Request.Url.PathAndQuery)));
223 if (m_application.Context.Handler is DefaultHttpHandler)
224 // Accessed resource is static.
225 m_application.Context.Response.Redirect(redirectUrl, false);
226 else
227 // Accessed resource is dynamic.
228 m_application.Context.Response.Redirect(redirectUrl, true);
229 }
230
231 /// <summary>
232 /// Gets the name of resource being accessed.
233 /// </summary>
234 /// <returns><see cref="HttpApplication.Request"/>.<see cref="HttpRequest.Url"/>.<see cref="Uri.PathAndQuery"/> property value.</returns>
235 protected virtual string GetResourceName()
236 {
237 return m_application.Request.Url.PathAndQuery;
238 }
239
240 /// <summary>
241 /// Determines if access to the requested resource is restricted by <see cref="RestrictAccessAttribute"/>.
242 /// </summary>
243 /// <returns>true if access to the requested resource is restricted, otherwise false.</returns>
244 protected virtual bool IsAccessRestricted()
245 {
246 // Check for the request handler.
247 IHttpHandler handler = m_application.Context.Handler;
248 if (handler == null)
249 return false;
250
251 // Evaluate access restriction if defined.
252 object[] attributes = handler.GetType().GetCustomAttributes(typeof(RestrictAccessAttribute), true);
253 if (attributes.Length > 0)
254 return !((RestrictAccessAttribute)attributes[0]).CheckAccess();
255 else
256 return false;
257 }
258
259 private void Application_PostMapRequestHandler(object sender, EventArgs e)
260 {
261 if (!SecurityProviderUtility.IsResourceSecurable(GetResourceName()))
262 return;
263
264 if (m_application.Context.Handler is IReadOnlySessionState ||
265 m_application.Context.Handler is IRequiresSessionState)
266 // no need to replace the current handler
267 return;
268
269 // swap the current handler
270 m_application.Context.Handler = new SessionEnabledHandler(m_application.Context.Handler);
271 }
272
273 private void Application_PostAcquireRequestState(object sender, EventArgs e)
274 {
275 if (!SecurityProviderUtility.IsResourceSecurable(GetResourceName()))
276 return;
277
278 SessionEnabledHandler handler = HttpContext.Current.Handler as SessionEnabledHandler;
279 if (handler != null)
280 // set the original handler back
281 HttpContext.Current.Handler = handler.OriginalHandler;
282 }
283
284 private void Application_PreRequestHandlerExecute(object sender, EventArgs e)
285 {
286 string resource = GetResourceName();
287 if (!SecurityProviderUtility.IsResourceSecurable(resource))
288 return;
289
290 if (SecurityProviderCache.CurrentProvider == null)
291 SecurityProviderCache.CurrentProvider = SecurityProviderUtility.CreateProvider(string.Empty);
292
293 if (!m_application.User.Identity.IsAuthenticated)
294 // Failed to authenticate user.
295 Redirect(HttpStatusCode.Unauthorized);
296
297 if (IsAccessRestricted() ||
298 !SecurityProviderUtility.IsResourceAccessible(resource))
299 // User does not have access to the resource.
300 Redirect(HttpStatusCode.Forbidden);
301 }
302
303 #endregion
304 }
305}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t