WebRoleが1つあるが、Cookieなしのセッションを使用するインスタンスが複数あるAzureプロジェクトに問題があります。アプリケーションはセッションストレージを必要としないため、セッションストレージプロバイダーを使用していませんが、SessionIDを追跡する必要があります。どうやら、SessionIDはWebRoleインスタンス全体で同じである必要がありますが、説明なしで突然変更されます。一部のデータを追跡するためにSessionIDを使用しているため、これは非常に重要です。
問題を再現するには:
クラウドプロジェクトを作成します。
ASP.NETWebロールを追加します。すでにその中にあるコードで十分です。
開ける
Default.aspx
SessionID
現在を表示するコントロールとポストバックを発生させるボタンを追加します<p><%= Session.SessionID %></p> <asp:Button ID="Button1" runat="server" Text="PostBack" onclick="Button1_Click" />
応答を少し遅らせるボタンのイベントハンドラーを追加します。
protected void Button1_Click(object sender, EventArgs e) { System.Threading.Thread.Sleep(150); }
開ける
Web.Config
Cookieなしのセッションを有効にします。
<system.web> <sessionState cookieless="true" /> </system.web>
プロジェクトを実行し、アドレスバーのセッションIDに注意を向けながら、しばらくの間「PostBack」ボタンをすばやく繰り返し押します。何も起こりません。セッションIDは常に同じです:)。やめろ。
開ける
ServiceConfiguration.csfg
4つのインスタンスを有効にします。
<Instances count="4" />
Web.configに、VisualStudioによって自動的に追加されたマシンキーに関連する行があることを確認します。(system.webの最後にあります)。
- プロジェクトを再実行し、すばやく繰り返し「ポストバック」ボタンをしばらく押して、アドレスバーのセッションIDに注意してください。
SessionID
しばらくすると、どのように変化するかがわかります。
なぜこうなった?私の知る限り、すべてのマシンがを共有しているmachineKey
場合、セッションはそれらの間で同じである必要があります。Cookieの場合、問題はありません。問題は、Cookieなしのセッションが使用されている場合にのみ発生するようです。
SessionID
私の推測では、複数のインスタンスがあり、あるインスタンスで生成されたものWebRole
が別のインスタンスに移動し、拒否されて再生成されたときに、何か問題が発生していると思います。WebRole
すべてのが同じであるため、これは意味がありませんmachineKey
。
問題を見つけて、それをより明確に見るために、私は自分自身を作成しましたSessionIDManager
:
public class MySessionIDManager : SessionIDManager
{
public override string CreateSessionID(HttpContext context)
{
if (context.Items.Contains("AspCookielessSession"))
{
String formerSessionID = context.Items["AspCookielessSession"].ToString();
// if (!String.IsNullOrWhiteSpace(formerSessionID) && formerSessionID != base.CreateSessionID(context))
// Debugger.Break();
return formerSessionID;
}
else
{
return base.CreateSessionID(context);
}
}
}
そしてそれを使用するには、WebConfigでこの行を変更します。
<sessionState cookieless="true" sessionIDManagerType="WebRole1.MySessionIDManager" />
これで、SessionID
どれだけ速く、どれだけ長く叩いても、が変わらないことがわかります。これらの2行のコメントを外すと、ASP.NETが新しいsessionIDを作成していることがわかります(すでに1つある場合でも)。
ASP.NETに新しいセッションを作成させるには、サイト内の絶対URLにリダイレクトするだけです。
Response.Redirect(Request.Url.AbsoluteUri.Replace(Request.Url.AbsolutePath, String.Empty));
なぜこれがCookieなしのセッションで発生するのですか?
私のソリューションはどの程度信頼できMySessionIDManager
ますか?
敬具。
更新:
私はこの回避策を試しました: サイトレベルの自動構成によって上書きされたユーザー指定のマシンキーですが、問題はまだ解決していません。
public override bool OnStart() { // For information on handling configuration changes // see the MSDN topic at http://go.microsoft.com/fwlink/?LinkId=166357. using (var server = new ServerManager()) { try { // get the site's web configuration var siteNameFromServiceModel = "Web"; // update this site name for your site. var siteName = string.Format("{0}_{1}", RoleEnvironment.CurrentRoleInstance.Id, siteNameFromServiceModel); var siteConfig = server.Sites[siteName].GetWebConfiguration(); // get the appSettings section var appSettings = siteConfig.GetSection("appSettings").GetCollection() .ToDictionary(e => (string)e["key"], e => (string)e["value"]); // reconfigure the machine key var machineKeySection = siteConfig.GetSection("system.web/machineKey"); machineKeySection.SetAttributeValue("validationKey", appSettings["validationKey"]); machineKeySection.SetAttributeValue("validation", appSettings["validation"]); machineKeySection.SetAttributeValue("decryptionKey", appSettings["decryptionKey"]); machineKeySection.SetAttributeValue("decryption", appSettings["decryption"]); server.CommitChanges(); _init = true; } catch { } } return base.OnStart(); }
また、セッション開始ハンドラーを配置してデータを追加することについても試しましたが、うまくいきませんでした。
void Session_Start(object sender, EventArgs e) { Session.Add("dummyObject", "dummy"); }
バウンティアップ!