2008-09-04 7 views
9

私はYahooのUIライブラリの一部であるYahoo UploaderをASP.NetのWebサイトで使用して、ユーザーがファイルをアップロードできるようにしています。よく知られていない人には、アップローダはFlashアプレットを使ってFileOpenダイアログをより詳細に制御できます。私は、ファイルタイプのフィルタを指定する複数のファイルを選択できるようにする、などそれは素晴らしいことだが、それは次のように文書の制限があることができますので、既知のフラッシュのバグの隠しフォームフィールドにASP.NetセッションIDを入力できますか?

を、WindowsでFirefoxで実行されているアップローダはありませんアップロード時に正しいCookieを送信しないでください。 FirefoxのCookieを送信する代わりに、Internet ExplorerのCookieをそれぞれのドメインに送信します。回避策として、cookielessアップロードメソッドを使用するか、document.cookieをアップロードリクエストに追加することをお勧めします。

ユーザーがFirefoxを使用している場合、ファイルをアップロードするときにセッションを維持するためにCookieを使用することはできません。私は彼らが誰であるかを知る必要があるので、セッションが必要です!回避策として、私はthusly Applicationオブジェクトを使用しています:

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

だから、私は一意のIDを作成し、ApplicationスコープでPage.Userオブジェクトを格納するためのキーとしてそれを使用しています。ファイルをアップロードするときに、そのIDを変数にPOSTに含めます。次に、ファイルのアップロードを受け入れるハンドラで、私は以下のようなものをユーザーオブジェクトつかむ:

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

をこの実際に動作しますが、それは2つの明白な欠点があります:IIS、アプリケーションプール場合

  • を、ユーザーがアップロードページにアクセスして実際にファイルをアップロードするまでにアプリケーションが再起動されても、アプリケーションスコープから「uploadid」が削除され、認証できないためアップロードが失敗します。

  • 私はこれまでにウェブファーム(場合によってはウェブガーデン)のシナリオに拡大すると、これは完全に壊れます。私は、今後このアプリケーションのスケーリングを計画することを除いて、心配しないかもしれない。

もっと良い方法がありますか? POST変数に実際のASP.NetセッションIDを渡し、セッションを取得するためにそのIDを他端で使用する方法はありますか?

私はSession.SessionIDでセッションIDを取得できますが、私はYUIを使用して次のページに投稿する方法を知っています。私が知らないのは、それを使って状態サーバーからセッションを取得する方法です。

はい、セッションを保存するために状態サーバーを使用しているため、アプリケーション/ IISが再起動され、Webファームのシナリオで動作します。

答えて

3

Hereは、Request.Formに格納されたIDからセッションをロードする方法を説明するSWFUploadの管理者の投稿です。同じことがYahooコンポーネントではうまくいくと思います。

ポストの下部にあるセキュリティの免責事項に注意してください。 Global.asaxファイルと、あなたが不足しているセッションIDクッキーを無効にすることができ、次のコードを含むことで


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); 
     } 
    } 
} 

セキュリティ警告:だけでコピーしないでくださいあなたが何をしているのかを知らずにASP.Netアプリケーションにこのコードを貼り付けます。クロスサイトスクリプティングのセキュリティ上の問題と可能性を紹介します。

+0

これは私が探していたまさにです。ありがとう! –

+7

ねえ...リンクが壊れているようです。 – Mulki

+2

はい、これが必要です!新しいリンクを提供してください! – pilavdzice

0

ASP.NetセッションIDはSession.SessionIDに格納されているため、非表示のフィールドに設定して次のページに投稿できます。

ただし、アプリケーションが再起動した場合は、store your sessions in sql serverがないとセッションIDが期限切れになると思います。

1

次のコードから、あなたの現在のセッションIDを取得することができます。そして、あなたは多分、隠しフィールドにそれを送り、その後、YUIを通じて、その値にアクセスすることができ

string sessionId = HttpContext.Current.Session.SessionID; 

これはちょっとしたことだから、スケーリングに問題はないと思います。しかし、セキュリティの問題は、私は知らない。

1

this blog postに頼って、ここではそれはかなりありませんが、あなたのセッションIDに基づいて、任意のユーザーのセッションを取得する必要がある関数です:

public SessionStateStoreData GetSessionById(string sessionId) 
{ 
    HttpApplication httpApplication = HttpContext.ApplicationInstance; 

    // Black magiC#1: getting to SessionStateModule 
    HttpModuleCollection httpModuleCollection = httpApplication.Modules; 
    SessionStateModule sessionHttpModule = httpModuleCollection["Session"] as SessionStateModule; 
    if (sessionHttpModule == null) 
    { 
     // Couldn't find Session module 
     return null; 
    } 

    // Black magiC#2: getting to SessionStateStoreProviderBase through reflection 
    FieldInfo fieldInfo = typeof(SessionStateModule).GetField("_store", BindingFlags.NonPublic | BindingFlags.Instance); 
    SessionStateStoreProviderBase sessionStateStoreProviderBase = fieldInfo.GetValue(sessionHttpModule) as SessionStateStoreProviderBase; 
    if (sessionStateStoreProviderBase == null) 
    { 
     // Couldn't find sessionStateStoreProviderBase 
     return null; 
    } 

    // Black magiC#3: generating dummy HttpContext out of the thin air. sessionStateStoreProviderBase.GetItem in #4 needs it. 
    SimpleWorkerRequest request = new SimpleWorkerRequest("dummy.html", null, new StringWriter()); 
    HttpContext context = new HttpContext(request); 

    // Black magiC#4: using sessionStateStoreProviderBase.GetItem to fetch the data from session with given Id. 
    bool locked; 
    TimeSpan lockAge; 
    object lockId; 
    SessionStateActions actions; 
    SessionStateStoreData sessionStateStoreData = sessionStateStoreProviderBase.GetItem(
     context, sessionId, out locked, out lockAge, out lockId, out actions); 
    return sessionStateStoreData; 
} 
+0

完璧!ありがとうございました! – defines