我可以将 ASP.Net 会话 ID 放在隐藏的表单字段中吗? [英] Can I put an ASP.Net session ID in a hidden form field?

查看:18
本文介绍了我可以将 ASP.Net 会话 ID 放在隐藏的表单字段中吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在我的 ASP.Net 网站上使用 Yahoo Uploader,它是 Yahoo UI 库的一部分,以允许用户上传文件.对于那些不熟悉的人,上传程序通过使用 Flash 小程序来让我更好地控制 FileOpen 对话框.我可以为文件类型指定过滤器,允许选择多个文件等.这很好,但它有以下记录限制:

<块引用>

由于已知的 Flash 错误,在 Windows 的 Firefox 中运行的上传器不会在上传时发送正确的 cookie;它不会发送 Firefox cookie,而是发送 Internet Explorer 的相应域的 cookie.作为一种解决方法,我们建议使用无 cookie 上传方法或将 document.cookie 附加到上传请求中.

因此,如果用户使用 Firefox,当他们上传文件时,我不能依靠 cookie 来保持他们的会话.我需要他们的会议,因为我需要知道他们是谁!作为一种解决方法,我正在使用 Application 对象:

Guid UploadID = Guid.NewGuid();Application.Add(Guid.ToString(), User);

因此,我创建了一个唯一的 ID,并将其用作在应用程序范围内存储 Page.User 对象的键.上传文件时,我将该 ID 作为变量包含在 POST 中.然后,在接受文件上传的处理程序中,我这样抓取 User 对象:

IPrincipal User = (IPrincipal)Application[Request.Form["uploadid"]];

这确实有效,但它有两个明显的缺点:

  • 如果在用户访问上传页面和实际上传文件之间重新启动了 IIS、应用程序池,甚至只是应用程序,则它们的uploadid"将从应用程序范围中删除并且上传失败,因为我无法验证它们.

  • 如果我扩展到网络农场(甚至可能是网络花园)场景,这将完全中断.我可能并不担心,除非我计划在未来扩展此应用.

有没有更好的办法?有没有办法让我在 POST 变量中传递实际的 ASP.Net 会话 ID,然后在另一端使用该 ID 来检索会话?

我知道我可以通过Session.SessionID获取会话ID,并且我知道如何使用YUI将其发布到下一页.我不知道如何使用 SessionID 从状态服务器获取会话.

是的,我使用状态服务器来存储会话,因此它们会持续应用程序/IIS 重新启动,并且可以在网络场场景中工作.

解决方案

这里来自 SWFUpload 维护者的帖子,解释了如何从存储在 Request.Form 中的 ID 加载会话.我想同样的事情也适用于雅虎组件.

注意帖子底部的安全免责声明.

<小时><块引用>

通过包含 Global.asax 文件和以下代码,您可以覆盖缺少的会话 ID cookie:

使用系统;使用 System.Web;公共类 Global_asax : System.Web.HttpApplication{private void Application_BeginRequest(对象发送者,EventArgs e){/*修复了非 IE 浏览器中的 Flash Player Cookie 错误.由于 Flash Player 即使在 FireFox 中也总是发送 IE cookie我们必须通过将值作为 POST 或 GET 的一部分发送来绕过 cookie并用传入的值覆盖 cookie.理论是此时 (BeginRequest) cookie 还没有准备好会话和身份验证逻辑,如果我们在这里更新 cookie,我们将得到我们的会话和身份验证正确恢复*/HttpRequest 请求 = HttpContext.Current.Request;尝试{string sessionParamName = "ASPSESSID";string sessionCookieName = "ASP.NET_SESSIONID";字符串 sessionValue = request.Form[sessionParamName] ??request.QueryString[sessionParamName];如果(会话值!= null){UpdateCookie(sessionCookieName, sessionValue);}}捕获(异常前){//TODO: 在此处添加日志记录.}尝试{string authParamName = "AUTHID";字符串 authCookieName = FormsAuthentication.FormsCookieName;字符串 authValue = request.Form[authParamName] ??request.QueryString[authParamName];如果 (authValue != null){UpdateCookie(authCookieName, authValue);}}捕获(异常前){//TODO: 在此处添加日志记录.}}私有无效UpdateCookie(字符串cookieName,字符串cookieValue){HttpCookie cookie = HttpContext.Current.Request.Cookies.Get(cookieName);如果(cookie == null){HttpCookie newCookie = new HttpCookie(cookieName, cookieValue);Response.Cookies.Add(newCookie);}别的{cookie.Value = cookieValue;HttpContext.Current.Request.Cookies.Set(cookie);}}}

<块引用>

安全警告:不要在不知道您在做什么的情况下复制并粘贴此代码到您的 ASP.Net 应用程序中.它介绍了跨站点脚本的安全问题和可能性.

I'm using the Yahoo Uploader, part of the Yahoo UI Library, on my ASP.Net website to allow users to upload files. For those unfamiliar, the uploader works by using a Flash applet to give me more control over the FileOpen dialog. I can specify a filter for file types, allow multiple files to be selected, etc. It's great, but it has the following documented limitation:

Because of a known Flash bug, the Uploader running in Firefox in Windows does not send the correct cookies with the upload; instead of sending Firefox cookies, it sends Internet Explorer’s cookies for the respective domain. As a workaround, we suggest either using a cookieless upload method or appending document.cookie to the upload request.

So, if a user is using Firefox, I can't rely on cookies to persist their session when they upload a file. I need their session because I need to know who they are! As a workaround, I'm using the Application object thusly:

Guid UploadID = Guid.NewGuid();
Application.Add(Guid.ToString(), User);

So, I'm creating a unique ID and using it as a key to store the Page.User object in the Application scope. I include that ID as a variable in the POST when the file is uploaded. Then, in the handler that accepts the file upload, I grab the User object thusly:

IPrincipal User = (IPrincipal)Application[Request.Form["uploadid"]];

This actually works, but it has two glaring drawbacks:

  • If IIS, the app pool, or even just the application is restarted between the time the user visits the upload page, and actually uploads a file, their "uploadid" is deleted from application scope and the upload fails because I can't authenticate them.

  • If I ever scale to a web farm (possibly even a web garden) scenario, this will completely break. I might not be worried, except I do plan on scaling this app in the future.

Does anyone have a better way? Is there a way for me to pass the actual ASP.Net session ID in a POST variable, then use that ID at the other end to retrieve the session?

I know I can get the session ID through Session.SessionID, and I know how to use YUI to post it to the next page. What I don't know is how to use that SessionID to grab the session from the state server.

Yes, I'm using a state server to store the sessions, so they persist application/IIS restarts, and will work in a web farm scenario.

解决方案

Here is a post from the maintainer of SWFUpload which explains how to load the session from an ID stored in Request.Form. I imagine the same thing would work for the Yahoo component.

Note the security disclaimers at the bottom of the post.


By including a Global.asax file and the following code you can override the missing Session ID cookie:

using System;
using System.Web;

public class Global_asax : System.Web.HttpApplication
{
    private void Application_BeginRequest(object sender, EventArgs e)
    {
        /* 
        Fix for the Flash Player Cookie bug in Non-IE browsers.
        Since Flash Player always sends the IE cookies even in FireFox
        we have to bypass the cookies by sending the values as part of the POST or GET
        and overwrite the cookies with the passed in values.

        The theory is that at this point (BeginRequest) the cookies have not been ready by
        the Session and Authentication logic and if we update the cookies here we'll get our
        Session and Authentication restored correctly
        */

        HttpRequest request = HttpContext.Current.Request;

        try
        {
            string sessionParamName = "ASPSESSID";
            string sessionCookieName = "ASP.NET_SESSIONID";

            string sessionValue = request.Form[sessionParamName] ?? request.QueryString[sessionParamName];
            if (sessionValue != null)
            {
                UpdateCookie(sessionCookieName, sessionValue);
            }
        }
        catch (Exception ex)
        {
            // TODO: Add logging here.
        }

        try
        {
            string authParamName = "AUTHID";
            string authCookieName = FormsAuthentication.FormsCookieName;

            string authValue = request.Form[authParamName] ?? request.QueryString[authParamName];
            if (authValue != null)
            {
                UpdateCookie(authCookieName, authValue);
            }
        }
        catch (Exception ex)
        {
            // TODO: Add logging here.
        }
    }

    private void UpdateCookie(string cookieName, string cookieValue)
    {
        HttpCookie cookie = HttpContext.Current.Request.Cookies.Get(cookieName);
        if (cookie == null)
        {
            HttpCookie newCookie = new HttpCookie(cookieName, cookieValue);
            Response.Cookies.Add(newCookie);
        }
        else
        {
            cookie.Value = cookieValue;
            HttpContext.Current.Request.Cookies.Set(cookie);
        }
    }
}

Security Warning: Don't just copy and paste this code in to your ASP.Net application without knowing what you are doing. It introduces security issues and possibilities of Cross-site Scripting.

这篇关于我可以将 ASP.Net 会话 ID 放在隐藏的表单字段中吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆