- PR -

ASP.NET セッション変数

投稿者投稿内容
どっとねっとふぁん
ぬし
会議室デビュー日: 2005/02/23
投稿数: 935
投稿日時: 2005-09-07 10:48
引用:

ts12_さんの書き込み (2005-09-06 21:59) より:

Module内でセッション変数を使用すると入れ替わってしまうような
事があるのでしょうか…?



NALさんや一郎さんが書かれているように、Module内で変数を定義すると
それは静的変数になります。
ASP.NETで静的変数を使っている場合、複数のクライアントが同じ一つの
変数を利用することになります。

> SQL文 = "SELECT * FROM <テーブル名>"
> SQL文 &= " WHERE ログインユーザ = " & HttpContext.Current.Session("<セッション変数名>").ToString

この「SQL文」がModule内で定義された変数であった場合、上記の理由から
同時にAさんとBさんがアクセスすると、常に後からアクセスした人の
値が利用されることになります。

問題点は
・Moduleの特性をよく知らずにASP.NETで利用した。
・同時に利用するということに対してテストが不十分だった。
ということになるかと思います。
で、対処法としては、Moduleを使わない、すくなくともModule内で
変数を使わない形にプログラムを修正しましょう、ということになるかと。



ts12_
会議室デビュー日: 2005/09/05
投稿数: 10
投稿日時: 2005-09-07 23:35
多々ご指摘、アドバイスありがとうございます。

「SQL文」はModule内で定義された変数です。
よって、後からアクセスした人の結果が返ってくる
という部分は納得できました。

私の理解不足かもしれませんが、一点確認させて下さい。
Module内で他人の結果が返ってきた後に、Module内では
なくフォームのコードビハインド部分で
<テキストボックス名>.Text = Session("<セッション変数名>").ToString
としているのですが、そこでテキストボックスに「B」と入るのは
なぜでしょうか?

自分自身で整理する意味を含めてまとめると、
@「A」でログイン
  ↓
Aしばらくは「A」のまま実行している
  ↓
Bある時Module内の関数を呼び出す
  ↓
Cその際に「B」と実行が重なる
 (「B」の方が微妙にタイミングが遅い)
  ↓
D「B」として関数を実行した結果が返ってくる
  ↓
Eテキストボックスにセッション変数の値をセットする
 (Module内ではない場所)
  ↓
Fテキストボックスに「B」と表示される

B〜Eの部分を簡単にコードで書くと、
・Webフォーム
Public Class WebForm1
Inherits System.Web.UI.Page

  ・
  ・

Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'B関数呼び出し
Dim X As Integer = Y()

'Eテキストボックスにセッション変数をセット
TextBox1.Text = Session("<セッション変数名>").ToString
End Sub
End Class

・Module
Module Module1
Function Y() As Integer
'CD静的変数により「B」の結果が返る
Dim SQL文 As String
SQL文 = "SELECT * FROM <テーブル名>"
SQL文 &= " WHERE ログインユーザ = " & HttpContext.Current.Session("<セッション変数名>").ToString

     ・
     ・

End Function
End Module

このFで「B」と表示される結果が分からないのです。
Module内でセッション変数を使用した際に、
同時に中身まで変わってしまうということなのでしょうか…?


(余談1)
SQLインジェクションの問題とか、StringBuilderを使用した方が
速いとかいう点は承知しております。
このプログラムは私の消し去りたい過去の一部でして、
直したいとは思っているのですがなかなか時間がとれず…。

(余談2)
毎回返答が遅くなりまして申し訳ありません。
私の会社では、インターネット掲示板と名のつくモノには
一律書き込み禁止のブロックがかかっておりまして、
会社にいるうちは返答ができません。
ご容赦ください…。
囚人
ぬし
会議室デビュー日: 2005/08/13
投稿数: 1019
投稿日時: 2005-09-08 00:07
確認したいのですが、Module 内で Shared(static) なのはメンバ変数だけですよね?(すみません。VB にかなり疎いです)
どうも特に static な変数がないような…。コード上問題ないように見えますが…。
それとも他の所でやっちゃってますか?

確認方法としては、ユーザAの場合は、Eの直前に無限ループでとめてみて、そしてユーザBでログインしてみて下さい。
そして、Eでブレークポイントを張ってみて、デバッガで値を確認する、とかはどうでしょうか?
Moo
大ベテラン
会議室デビュー日: 2004/04/12
投稿数: 118
お住まい・勤務地: 地球・港
投稿日時: 2005-09-08 10:29
引用:

ts12_さんの書き込み (2005-09-07 23:35) より:
・Module
Module Module1
Function Y() As Integer
'CD静的変数により「B」の結果が返る
Dim SQL文 As String
SQL文 = "SELECT * FROM <テーブル名>"
SQL文 &= " WHERE ログインユーザ = " & HttpContext.Current.Session("<セッション変数名>").ToString
End Function
End Module



ですか...

憶測(&未検証)ですが...
Module内でHttpContext.Currentしているところが怪しいですね。
Class化することはできないのですか?

若しくはApplication.Lockを使って同時に処理されないようにするとか
#これははずしているかも
_________________
ASP/ASP.NETだいすき。 ASP++ by Moo http://moo-asp.net/
日記は ほぼ毎日更新中 http://d.hatena.ne.jp/aspx/
どっとねっとふぁん
ぬし
会議室デビュー日: 2005/02/23
投稿数: 935
投稿日時: 2005-09-08 10:33
引用:

ts12_さんの書き込み (2005-09-07 23:35) より:

Module内で他人の結果が返ってきた後に、Module内では
なくフォームのコードビハインド部分で
<テキストボックス名>.Text = Session("<セッション変数名>").ToString
としているのですが、そこでテキストボックスに「B」と入るのは
なぜでしょうか?



これもしかして、1台のマシンからIEを2つ立ち上げてテストしてるって
ことはないですか?
この場合、IEの設定によっては同じセッションを利用してしまいます。
どっとねっとふぁん
ぬし
会議室デビュー日: 2005/02/23
投稿数: 935
投稿日時: 2005-09-08 10:37
引用:

Mooさんの書き込み (2005-09-08 10:29) より:

憶測(&未検証)ですが...
Module内でHttpContext.Currentしているところが怪しいですね。



提示されたプログラムをみる限りではSessionの中身を見てるだけですから
書き換わるはずはありませんよね。
この後にSessionの値を書き換えるような処理があるなら別ですが。
Moo
大ベテラン
会議室デビュー日: 2004/04/12
投稿数: 118
お住まい・勤務地: 地球・港
投稿日時: 2005-09-08 10:59
実験してみました。

Module Module1
Function x() As String
Return (HttpContext.Current.Session.SessionID.ToString)
End Function
End Module

コード:
        Dim sessionX As String = x()
        Dim sessionY As String = Session.SessionID.ToString
        If sessionX = sessionY Then
            Response.Write(sessionX)
            Response.Write("<br>")
            Response.Write(sessionY)
        Else
            Throw New System.Web.HttpException("セッションの相違が発生しました")
        End If



として1秒間に500リクエスト(セッションIDはすべて別)の
負荷試験してみましたが、問題なかったですね。

原因はほかのところにあるのでしょうか...
_________________
ASP/ASP.NETだいすき。 ASP++ by Moo http://moo-asp.net/
日記は ほぼ毎日更新中 http://d.hatena.ne.jp/aspx/
ts12_
会議室デビュー日: 2005/09/05
投稿数: 10
投稿日時: 2005-09-08 23:23
さまざまご意見ありがとうございます。

セッション変数に値をセットするのはログイン直後の1回のみで、
以後はその部分を通りません。
これについては何度も確認しましたし、その部分にブレークポイントを
つけていろいろ動かしたりもしたので、やはり意図的に上書きしている
ような事はないはずです。
(静的変数により上書きされているなら、それは意図的ではないという事で…)

また、この件はお客様からの報告により発覚したのですが、
私自身は現象を目の当たりにした事はありません。
再現しようと、アドバイス頂いたようにブレークポイントをつけたり、
複数台のPCで同時に動かしたりしたのですが、今までのところ再現できて
おりません。
容易に再現できるならば、話はもっと簡単だと思うのですが…。
ちなみに、そのお客様が遭遇した際は、遠く離れた営業所のユーザIDに
突然変わってしまったそうです。

Module内で宣言した変数を使用しないように修正して、
様子を見てみるしかないでしょうか…。

スキルアップ/キャリアアップ(JOB@IT)