1 //------------------------------------------------------------------------------ 2 // <copyright file="WebFormRouteHandler.cs" company="Microsoft"> 3 // Copyright (c) Microsoft Corporation. All rights reserved. 4 // </copyright> 5 //------------------------------------------------------------------------------ 6 7 namespace System.Web.Routing { 8 9 using System; 10 using System.Web.UI; 11 using System.Web.Compilation; 12 using System.Web.Security; 13 using System.Security; 14 using System.Security.Permissions; 15 using System.Security.Principal; 16 17 public class PageRouteHandler : IRouteHandler { PageRouteHandler(string virtualPath)18 public PageRouteHandler(string virtualPath) 19 : this(virtualPath, true) { 20 } 21 PageRouteHandler(string virtualPath, bool checkPhysicalUrlAccess)22 public PageRouteHandler(string virtualPath, bool checkPhysicalUrlAccess) { 23 if (string.IsNullOrEmpty(virtualPath) || !virtualPath.StartsWith("~/", StringComparison.OrdinalIgnoreCase)) { 24 throw new ArgumentException(SR.GetString(SR.PageRouteHandler_InvalidVirtualPath), "virtualPath"); 25 } 26 27 this.VirtualPath = virtualPath; 28 this.CheckPhysicalUrlAccess = checkPhysicalUrlAccess; 29 _useRouteVirtualPath = VirtualPath.Contains("{"); 30 } 31 32 /// <summary> 33 /// This is the full virtual path (using tilde syntax) to the WebForm page. 34 /// </summary> 35 /// <remarks> 36 /// Needs to be thread safe so this is only settable via ctor. 37 /// </remarks> 38 public string VirtualPath { get; private set; } 39 40 /// <summary> 41 /// Because we're not actually rewriting the URL, ASP.NET's URL Auth will apply 42 /// to the incoming request URL and not the URL of the physical WebForm page. 43 /// Setting this to true (default) will apply URL access rules against the 44 /// physical file. 45 /// </summary> 46 /// <value>True by default</value> 47 public bool CheckPhysicalUrlAccess { get; private set; } 48 49 private bool _useRouteVirtualPath; 50 private Route _routeVirtualPath; 51 private Route RouteVirtualPath { 52 get { 53 if (_routeVirtualPath == null) { 54 //Trim off ~/ 55 _routeVirtualPath = new Route(VirtualPath.Substring(2), this); 56 } 57 return _routeVirtualPath; 58 } 59 } 60 CheckUrlAccess(string virtualPath, RequestContext requestContext)61 private bool CheckUrlAccess(string virtualPath, RequestContext requestContext) { 62 IPrincipal user = requestContext.HttpContext.User; 63 // If there's no authenticated user, use the default identity 64 if (user == null) { 65 user = new GenericPrincipal(new GenericIdentity(String.Empty, String.Empty), new string[0]); 66 } 67 return CheckUrlAccessWithAssert(virtualPath, requestContext, user); 68 } 69 70 [SecurityPermission(SecurityAction.Assert, Unrestricted = true)] CheckUrlAccessWithAssert(string virtualPath, RequestContext requestContext, IPrincipal user)71 private bool CheckUrlAccessWithAssert(string virtualPath, RequestContext requestContext, IPrincipal user) { 72 return UrlAuthorizationModule.CheckUrlAccessForPrincipal(virtualPath, user, requestContext.HttpContext.Request.HttpMethod); 73 } 74 GetHttpHandler(RequestContext requestContext)75 public virtual IHttpHandler GetHttpHandler(RequestContext requestContext) { 76 if (requestContext == null) { 77 throw new ArgumentNullException("requestContext"); 78 } 79 80 string virtualPath = GetSubstitutedVirtualPath(requestContext); 81 // Virtual Path ----s up with query strings, so we need to strip them off 82 int qmark = virtualPath.IndexOf('?'); 83 if (qmark != -1) { 84 virtualPath = virtualPath.Substring(0, qmark); 85 } 86 if (this.CheckPhysicalUrlAccess && !CheckUrlAccess(virtualPath, requestContext)) { 87 return new UrlAuthFailureHandler(); 88 } 89 90 Page page = BuildManager.CreateInstanceFromVirtualPath(virtualPath, typeof(Page)) as Page; 91 return page; 92 } 93 94 /// <summary> 95 /// Gets the virtual path to the resource after applying substitutions based on route data. 96 /// </summary> 97 /// <param name="requestContext"></param> 98 /// <returns></returns> GetSubstitutedVirtualPath(RequestContext requestContext)99 public string GetSubstitutedVirtualPath(RequestContext requestContext) { 100 if (requestContext == null) { 101 throw new ArgumentNullException("requestContext"); 102 } 103 104 if (!_useRouteVirtualPath) 105 return VirtualPath; 106 107 VirtualPathData vpd = RouteVirtualPath.GetVirtualPath(requestContext, requestContext.RouteData.Values); 108 // 109 if (vpd == null) 110 return VirtualPath; 111 return "~/" + vpd.VirtualPath; 112 } 113 } 114 } 115