Calling all developers! We invite you to provide your input on Feature Experimentation by completing this brief survey.
Calling all developers! We invite you to provide your input on Feature Experimentation by completing this brief survey.
Product version: |
EPiServer CMS 4.62 |
Document version: |
1.0 |
Document creation date: |
07-06-2006 |
Document last saved: |
09-10-2007 |
EPiServer CMS allows relocation of the edit and admin directories and configurable http ports, to make it harder for intruders to try to access sensitive resources.
This document describes how to write EPiServer CMS applications that are somehow dependent on the edit and admin directories and also, how to ensure that the applications will continue to work even if those directories are moved to unknown locations. The document also contains instructions on how to secure the edit and admin directories.
Follow the steps below to secure edit/admin and its ports on a default installation of EPiServer CMS:
1. Change the names of the edit and admin directories, e.g. c:\inetpub\episerver\admin to c:\inetpub\episerver\secretAdmin.
2. Change the EPsAdminDir, EPsEditDir, EPnEditHttpPort, and EPnAdminHttpPort using EPiServer CMS Manager. Ports can be omitted if you are only changing the directories.
3. Change the ports in the Internet Information Services (IIS) for the site where you wish to use custom ports. This step can be omitted if you are only changing the directories.
4. Change the <location path=”edit”> and <location path=”admin”> to correspond to the changed directories.
5. Edit the settings for the SysRoot and SysRecycleBin page types in Admin mode and change the path in the "File name" field so that it directs to the new edit directory.
6. Make sure that the ASP.NET account has read/execute permission for the new directories.
If a section begins with the text “No changes needed in existing applications", it means that the application does not need any modifications to work with relocated directories for that particular section in EPiServer CMS. The rest of the text in the section is merely for informational purposes.
The edit and admin directories are not hardcoded in EPiServer CMS 4.50 and later. Instead, there are two new keys in web.config that define the virtual directory locations:
EPsAdminDir |
location of admin directory, for example foo111/bar222 |
EPsEditDir |
location of edit directory, for example foo333/bar444 |
Applications can access these values by reading the new EditDir and AdminDir properties in the ApplicationConfiguration object. If the keys are not defined in web.config, EditDir and AdminDir will return default values “edit/” and “admin/” respectively.
The values returned by the EditDir/AdminDir properties have the format “path/”. To simplify their usage they are guaranteed to always have a trailing “/” and never a leading “/”, even if defined otherwise in web.config.
No changes needed in existing applications.
All language keys work as previously - they are not affected by any directory relocations. This is also true for relative language keys, i.e. keys that are prefixed with “#”.
No changes needed in existing applications.
The plugin loader in EPiServer CMS 4.50 and later knows how to handle relocated directories. Any references to “~/edit/” and “~/admin/” in the Url property in the plugin attributes are automatically mapped to the real directory locations. This is an operation that is completely transparent to the plug-ins. Therefore, plug-ins that refer to files in edit/admin in their plugin attributes can continue to do so.
Example:
[GuiPlugIn(DisplayName="",Area=PlugInArea.EditPanel, Url="~/edit/EditMultiLanguage.ascx”)]
Hardcoded paths that refer to the edit and admin directories need to be changed. To help developers with this, the following is available:
Properties in the ApplicationConfiguration object
AdminUrl |
Absolute or relative URL to the admin directory. If the admin port is the same port as in the current Http Context, the URL is relative, otherwise it is absolute. The property is especially suited for environments with proxies, where links should use relative URLs. The path is guaranteed to end with a “/”. |
EditUrl |
Absolute or relative URL to the edit directory. If the edit port is the same port as in the current Http Context, the URL is relative, otherwise it is absolute. The property is especially suited for environments with proxies, where links should use relative URLs. The path is guaranteed to end with a “/”. |
AbsoluteAdminUrl |
Absolute URL to the admin directory, including configured protocol, port and path from current configuration. The path is guaranteed to end with a “/”. |
AbsoluteEditUrl |
Absolute URL to the edit directory, including protocol, port and path from current configuration. Applications should use this property to get an URL to the edit directory when they are not running under an Http Context. The path is guaranteed to end with a “/”. |
There are also properties for Http ports – see the Configurable Http Ports section for the details.
The UrlUtility class in the EPiServer.Util namespace contains the following methods:
ResolveUrl(url) |
Resolve an expression like "~/edit" to a relative or absolute URL. The URL that is created is relative as long as the Http port obtained, when resolving the URL, is the same port as in the current Http Context. Otherwise the created URL is absolute. |
ResolveUrl(url, urlType) |
Overloaded version of ResolveUrl, where you can control whether the created URL should be relative or absolute. UrlTypes is an enumerator in EPiServer.Util that has the following values: Auto, Relative and Absolute. |
ResolveHostUrl() |
Resolve host URL using the current Http Context. |
ResolveHostUrl(context) |
Resolve host URL using the provided Http Context. |
ResolveHostUrl(context, port) |
Resolve host URL using the provided Http Context and port. |
The ControlLoader Web control:
ControlLoader |
Loads a user control using an URL expression like "~/edit/FileManagement.ascx" (the real locations of expressions like “~/edit” depend on the site’s configuration and are resolved runtime). |
From a security point of view, it is best if you avoid references to user controls in the edit and admin directories altogether. But if your application requires this anyway, follow the guidelines below to ensure that your application will work even if the directories are relocated.
Replace any user control declarations using the <%@ Register syntax with the ControlLoader Web control. Do this when:
or
Instead of: |
<% @ Register TagPrefix="edit" TagName="FileManagement" Src="~/edit/FileManagementControl.ascx"%>... < edit:FileManagement runat="server"/> |
write: |
< EPiServer:ControlLoader runat="Server" Src="~/edit/FileManagementControl.ascx"/>Add the EPiServer declaration to your aspx/ascx file, if needed: <% @ Register TagPrefix="EPiServer"Namespace="EPiServer.WebControls" Assembly="EPiServer" %> |
If you reference a user control from a file in the same directory, it is OK to use the ASPNET user control registration syntax, as long as you do not use “~/” or “../” in the URL. What happens when you use the “~/” or “../” syntax is that when the page is loaded runtime, ASPNET resolves the URL to an address that corresponds to the file’s location at design time. This is not necessarily the same as the runtime address, since the directory that the page resides in may have been relocated.
In the following example, a file in edit references the CommandActions.ascx user control, also a file in edit:
This is OK: |
<% @ Register TagPrefix="EPiServerSys" TagName="CommandActions" Src="CommandActions.ascx"%> |
These are not OK: |
<% @ Register TagPrefix="EPiServerSys" TagName="CommandActions" Src="~/edit/CommandActions.ascx"%><% @ Register TagPrefix="EPiServerSys" TagName="CommandActions" Src="../edit/CommandActions.ascx"%> |
In files both inside and outside the edit/admin directories, replace any URLs that begin with “../edit/” or “../admin/” with URLs that are based on the current site’s configuration. This applies to nested directories as well, for example “../../edit/”.
A good rule: files inside the edit and admin directories should always refer to other files using URLs that are built from EditUrl/AdminUrl in ApplicationConfiguration or the ResolveUrl method in the EPiServer.Util.UrlUtility class. As a rule, avoid references to files using the “../” syntax altogether.
For example, in files inside edit/admin:
Instead of: |
Response.Redirect( "~/Edit/Default.aspx?id=" + pageLink.ID.ToString());Response.Redirect( "~/Admin/FileManagement.aspx"); |
write: |
Response.Redirect(Configuration.EditUrl + "Default.aspx?id=" + pageLink.ID.ToString());Response.Redirect(Configuration.EditUrl + "FileManagement.aspx"); |
For example, in files outside edit/admin:
Instead of: |
Response.Redirect( "../Edit/Default.aspx?id=" + pageLink.ID.ToString());Response.Redirect( "../Admin/FileManagement.aspx"); |
write: |
Response.Redirect(Configuration.EditUrl + "Default.aspx?id=" + pageLink.ID.ToString());Response.Redirect(Configuration.AdminUrl + "FileManagement.aspx"); |
When referencing files that are outside secured directories, the URLs can be relative to the site’s root (protocol and port information not necessary). Make sure that the URLs are relative to the site’s root and do not use expressions like “../dir1/dir2/file.css”.
For example, in aspx/ascx files inside edit and admin:
Instead of: |
< link rel="stylesheet" type="text/css" href="../util/styles/system.css">< script type='text/javascript' src="../util/javascript/system.js"></ script> |
write: |
< link rel="stylesheet" type="text/css" href="<%=Configuration.RootDir%>util/styles/system.css">< script type='text/javascript' src="<%=Configuration.RootDir%>util/javascript/system.js"></ script> |
The HTTP ports used to access edit and admin directories are configurable in EPiServer 4.50 and later. Applications that rely on the default ports 80 (default HTTP port) and 443 (default HTTPS port) will probably need to be modified to handle unknown ports.
There are 2 values in web.config for HTTP ports configuration:
EPnEditHttpPort |
HTTP port required to access the edit directory, for example 80 or 887. |
EPnAdminHttpPort |
HTTP port required to access the admin directory, for example 80 or 887. |
The port values can be accessed using properties in the ApplicationConfiguration called AdminHttpPort and EditHttpPort.
To enable configurable HTTP ports, the spidersupport HTTP module must be defined in web.config. The module is defined by default in standard installations.
Since the edit and admin directories can be relocated, all references to and from files in those directories must be dynamic. This is also true for style sheet files, since they can be included by files in relocated directories and have references to images, HTCs and other files. As style sheet files are static by nature, dynamic CSS files solve this problem. Basically, it allows you to insert predefined tags into CSS files and the tags are parsed runtime.
The dynamic CSS files technology was designed with four goals in mind:
To enable dynamic CSS files, the spidersupport HTTP module must be defined in web.config. The module is defined by default in standard installations.
To make a dynamic CSS file, just create a copy of an existing style sheet file and rename it by adding the string “_template” after the file name, for example, copy of styles.css is renamed as styles_template.css. When a browser makes a request for a CSS file, EPiServer will intercept ASPNET’s CSS loading procedure and check if there is a dynamic CSS file available. If it finds one, the CSS file is read, parsed and returned. If no dynamic CSS file is found, ASPNET continues its standard CSS loading procedure.
Example:
The syntax of a tag is “$tag$”, the tag name is case-insensitive. The entire expression is replaced with the actual value runtime.
The number of predefined tags is kept to a minimum, due to security reasons. There may be more tags later, but currently only the following ones are supported:
$RootDir$ |
Virtual path to the application’s root, e.g. “/EPiServerSample/”. |
$UploadDir$ |
Virtual path to the application’s upload directory, e.g. “/upload/”. |
Examples:
.EPEdit-tabbackground
{
background-image:url($RootDir$Util/images/tabrow_background.gif);}
.EPEdit-inputNumber
{
border:solid 1px #6D8CA8; behavior:url($RootDir$Util/javascript/changedinput.htc);}