Issue 1
When you hover over a menu item in the ASP.NET 2.0
Menu control,
you get the following error message:
This page contains both
secure and nonsecure items. Do you want to display the nonsecure items?
The application is supposed to be secure, you're using the SSL protocol, and you
have not added any controls that are rendering an absolute path back to an HTTP
address. What's up with this message?
Well, the problem is that the
Menu control emits some JavaScript that uses an
iFrame object to build the
fly-out menu. You have to give the frame a starting URL. To avoid making an
unnecessary round trip to the server for non-SSL scenarios, the script uses
about:blank for the URL. However, the browser considers this an unsecure
address, so you get the above error.
For more information about this problem in terms of Microsoft Windows SharePoint Services, click the following article number to view the article in the Microsoft Knowledge Base:
837850
You receive a "This page contains both secure and nonsecure items" message when you click Explorer View in a document library in Windows SharePoint Services or in SharePoint Team Services from Microsoft
I explicitly mention non-SSL scenarios because, if the Web server was receiving the HTTPS traffic instead of the SSL device, the JavaScript that the
Menu control emits would add a line of code to set the source of the
iFrame object to an HTTPS address of a page on the server. This initiates another request, but prevents the
error message. If you're deploying into this type of environment, you can force
the addition of the JavaScript to prevent the error message by adding this code
to the page that has the
Menu control.
<script runat="server">
protected override void Render(HtmlTextWriter writer)
{
Page.ClientScript.RegisterStartupScript(typeof(Page), "MenuHttpsWorkaround",
Menu1.ClientID + "_Data.iframeUrl='https://myserver/someblankpage.htm';", true);
base.Render(writer);
}
</script>
Ideally, you would have the menu in a
MasterPage class or a
UserControl class, and
could add this code just one time.
Issue 2
You may find that, when you have the
requireSSL attribute of the
<forms> element set to
true, the server responds with repeated redirects to the
FormsAuthentication login page. This is caused by a change in the way the
FormsAuthenticationModule method handles the
requireSSL attribute. If you
set the
requireSSL attribute to
true, the
FormsAuthenticationModule method creates a cookie
that has the
secure attribute set. (This behavior is the same as in the .NET Framework 1.1.) When you use the
secure
attribute, the client will only pass the cookie to the server if
the client is using SSL. This part is great, because the client is indeed using
SSL. Let's assume you have a SecurePage.aspx page that anonymous users can't access.
With the SSL protocol and the
requireSSL attribute, you end up with the
following traffic on an initial request to SecurePage.aspx:
�>Client makes a GET request for SecurePage.aspx .
<�Server responds with an HTTP 302 (Redirect) to the login page.
�>Client makes a GET request for Login.aspx.
<�Server responds with a 200 OK. The login page is rendered to client.
�>Client makes a POST request to Login.aspx.
<�Server responds with a 302 (Redirect) to SecurePage.aspx. Set Cookie header is sent with the secure attribute to the client.
�>Client makes a GET request to SecurePage.aspx. Cookie is passed because the client is using SSL.
<�Server responds with a 302 (Redirect) back to the login page.
You get the redirect in the last request because of a change in
the
FormsAuthenticationModule class. An additional check was added in ASP.NET 2.0 to determine
whether the user is passing a secure cookie over a non-SSL request. ASP.NET 2.0 returns the
FormsAuthenticationTicket class if the
FormsAuthentication.RequireSSL property is set to
false or if the
Request.IsSecure attribute is set to
true.
- The FormsAuthentication.RequireSSL property is set to false if the requireSSL attribute is set to false in the configuration file.
- The Request.IsSecure attribute is set to true if the Web server receives SSL traffic.
Since, in this scenario, the Web server is not receiving SSL traffic and
the
requireSSL attribute is set to
true, both checks return
false. As a result, the
FormsAuthenticationTicket class is not returned and the cookie is removed
from the
Request.Cookies collection.
The request that the user is making is anonymous at this point because the server has not yet validated the user's credentials. As the request passes through the ASP.NET pipeline,
the
UrlAuthorizationModule class checks whether the user has access to the
page. Since an anonymous user does not have access to a SecurePage.aspx page, the
UrlAuthorizationModule class returns a 401 error message ("Access Denied"), which results in a
redirect to the login page.
In order to avoid this behavior, you first have
to remove the
requireSSL attribute from the
<forms> tag in the configuration
file. Then you have to programmatically set the
secure attribute on the
FormsAuthentication
cookie. The following code does this for you, for both the
FormsAuthentication cookie and the
Session cookie.
void Application_EndRequest(object sender, EventArgs e)
{
if (Response.Cookies.Count > 0)
{
foreach (string s in Response.Cookies.AllKeys)
{
if (s == FormsAuthentication.FormsCookieName || s.ToLower() == "asp.net_sessionid")
{
Response.Cookies[s].Secure = true;
}
}
}
}