2011-01-21 11 views
1

私はWeb開発者が初めてです。私はasp.net/C#を使ってウェブサイトを構築しています。私は現在、すべてのデータベース機能を実行するために使用するDataLayerというクラスを持っており、照会された情報もいくつか保存しています。私は当初、このクラスを静的にしていました。なぜなら、それは私が振る舞いたいと思っていたからです。しかし、それは複数のユーザーにとってはまったく悪いことです。サイト全体のバックエンドデータレイヤークラスインスタンスを管理する方法

このクラスを使用するにはインスタンスを作成する必要がありますが、そのインスタンスの複数のWebページで同じインスタンスを維持する必要があります。どのようにこのアプローチについて行くべきかに関する考えやアイデア?このオブジェクトをページ間でどのように渡すか?何らかの形でグローバル変数としてセッション変数に格納しますか?私は、複数の解決策があるので、これ以上の議論があると思います。経験豊富な人からのアドバイスを参考にしたいと思っています^^ Dts:

答えて

1

静的なクラスの使用は避けてください。

ユーザー単位でオブジェクトを保持するために実装される唯一のフレームワークは、セッション変数として格納することです。

前記、私は次のベストプラクティスの推奨事項を指摘しなければならない:

  1. は、セッション変数を使用しないでください。
  2. データベース接続を開いたままにしないでください(これは計画しているものとみなします)。

セッション変数を使用すると、アプリケーションのスケーラビリティが損なわれ、使い捨てオブジェクトも保持されます。

データベースで処理できるデータベース接続の数には制限があります。したがって、サイトの使用率が高い場合は、リクエスト間で開いている接続を保持していると、エラーが発生します。

また、セッション変数は、ユーザーがWebサイトを終了した後、一定の期間にわたってメモリを占有します。これはセッション変数の避けられない副作用であり、特定の期間内に多数のユーザーがいた場合、アプリケーションは本当に必要以上に多くのRAMを使用して終了することを意味します。 メモリではなくデータベース記憶域を使用するようにセッションを設定しますが、これは別の一連の問題を作成します(データベース接続を保持する必要があります)。

セッションを使用する際のもう1つの問題は、アプリケーションを実行するサーバーが3つ以上ある場合、データベースのセッション状態を維持する必要があり、アプリケーションのパフォーマンスに影響します。

+0

ほとんど。別の方法として、認証情報を使用して、現在のユーザーに関連付けられたデータをSQLサーバーのような永続ストレージに保存することです。 –

+0

@Artur:正しいですが、 'フレームワークが実装されました 'と言いました。欠点。 –

+0

そしてそれをセッション変数として保存します。しかし、cometimesの犯罪者は、関連するすべてのデータを含めて、他の人のためにセッションを盗むのが好きであり、セッションvarablesのholv認証情報(パスワード、電子メール)を使わないでください) –

2

最近のプロジェクトでは、このパスを開始しました。私は認証CookieのカスタムUserData属性を使用して、ユーザーに関する特別な情報を保存していました。それは本当にうまくいっていて、速くて、必要なものすべてをやりました。残念ながら、 "PageSpeed"は私のクッキーが大きすぎる(2.2K)と私に言いました。私はDB呼び出しと、カスタムUserDataの代わりにキャッシュしている甘いお尻​​のキャッシングのビットに行くことにしました。

UserDataフィールドに追加情報を格納するために、私が使用しているクラス(他のStackOverflowユーザーからの借用でした)を添付しました。 @グレッグサンソムは彼のコメントの一つに言ったように

using System.Web.Security; 
using System.Web; 
namespace Utilities.Helpers 
{ 
    /// <summary> 
    /// A helper class that aids us in dealing with the Auth Cookie. 
    /// </summary> 
    /// <remarks></remarks> 
    public sealed class AuthenticationHelper 
    { 
     /// <summary> 
     /// Prevents a default instance of the <see cref="AuthenticationHelper" /> class from being created. 
     /// </summary> 
     /// <remarks></remarks> 
     private AuthenticationHelper() 
     { 
     } 
     /// <summary> 
     /// Generate an Authentication Cookie that also contains "UserData". 
     /// The UserData is a serialized "AuthUserData" Object containing "ID" 
     /// "RegionID" "Username" and "Slug" 
     /// </summary> 
     /// <param name="userName">this is the "claimedidentifier" of the user's OpenId</param> 
     /// <param name="userData">be mindful of the cookie size or you will be chasing ghosts</param> 
     /// <param name="persistent"></param> 
     public static HttpCookie CreateAuthCookie(string userName, AuthUserData userData, bool persistent) 
     { 

      DateTime issued = DateTime.UtcNow; 
      // formsAuth does not expose timeout!? have to get around the spoiled 
      // parts and keep moving.. 
      HttpCookie fooCookie = FormsAuthentication.GetAuthCookie("foo", true); 
      int formsTimeout = Convert.ToInt32((fooCookie.Expires - DateTime.UtcNow).TotalMinutes); 

      DateTime expiration = DateTime.UtcNow.AddMinutes(formsTimeout); 
      string cookiePath = FormsAuthentication.FormsCookiePath; 

      string SerializedUser = SerializeUser(userData); 

      object ticket = new FormsAuthenticationTicket(0, userName, issued, expiration, true, SerializedUser, cookiePath); 
      return CreateAuthCookie(ticket, expiration, persistent); 
     } 

     /// <summary> 
     /// Creates the auth cookie. 
     /// </summary> 
     /// <param name="ticket">The ticket.</param> 
     /// <param name="expiration">The expiration.</param> 
     /// <param name="persistent">if set to <c>true</c> [persistent].</param> 
     /// <returns></returns> 
     /// <remarks></remarks> 
     public static HttpCookie CreateAuthCookie(FormsAuthenticationTicket ticket, DateTime expiration, bool persistent) 
     { 
      string creamyFilling = FormsAuthentication.Encrypt(ticket); 
      object cookie = new HttpCookie(FormsAuthentication.FormsCookieName, creamyFilling) { 
       Domain = FormsAuthentication.CookieDomain, 
       Path = FormsAuthentication.FormsCookiePath 
      }; 
      if (persistent) { 
       cookie.Expires = expiration; 
      } 

      return cookie; 
     } 


     /// <summary> 
     /// Retrieves the auth user. 
     /// </summary> 
     /// <returns></returns> 
     /// <remarks></remarks> 
     public static AuthUserData RetrieveAuthUser() 
     { 
      string cookieName = FormsAuthentication.FormsCookieName; 
      HttpCookie authCookie = HttpContext.Current.Request.Cookies(cookieName); 
      FormsAuthenticationTicket authTicket = default(FormsAuthenticationTicket); 
      string userdata = string.Empty; 
      AuthUserData aum = new AuthUserData(); //AuthUserData is a custom serializable Poco that holds all the required user data for my cookie (userID, email address, whatever. 

      if ((authCookie != null)) { 
       authTicket = FormsAuthentication.Decrypt(authCookie.Value); 
       userdata = authTicket.UserData; 
      } 


      if ((!object.ReferenceEquals(userdata, string.Empty))) { 
       aum = DeserializeUser(userdata); 
       if (string.IsNullOrEmpty(aum.Username)) { 
        aum.Username = "User" + aum.ID; 
       } 
      } else { 
       aum.ID = null; 
       aum.Region = null; 
       aum.Username = string.Empty; 
       aum.Reputation = 0; 
      } 

      return aum; 
     } 


     /// <summary> 
     /// Serializes the user. 
     /// </summary> 
     /// <param name="aum">The AuthUserData.</param> 
     /// <returns></returns> 
     /// <remarks>The AuthUserData is a custom serializable poco that holds the data</remarks> 
     private static string SerializeUser(AuthUserData aud) 
     { 
      Runtime.Serialization.Formatters.Binary.BinaryFormatter bf = new Runtime.Serialization.Formatters.Binary.BinaryFormatter(); 
      IO.MemoryStream mem = new IO.MemoryStream(); 
      bf.Serialize(mem, aud); 
      return Convert.ToBase64String(mem.ToArray()); 
     } 

     /// <summary> 
     /// Deserializes the user. 
     /// </summary> 
     /// <param name="serializedaum">The serialized AuthUserData.</param> 
     /// <returns></returns> 
     /// <remarks></remarks> 
     private static AuthUserData DeserializeUser(string serializedaud) 
     { 
      Runtime.Serialization.Formatters.Binary.BinaryFormatter bf = new Runtime.Serialization.Formatters.Binary.BinaryFormatter(); 
      IO.MemoryStream mem = new IO.MemoryStream(Convert.FromBase64String(serializedaud)); 
      return (AuthUserData)bf.Deserialize(mem); 
     } 
    } 
} 

ただし、アプリのステートレスを維持することは、将来の拡張性には本当に良いボーナスです。データベースコールを作成し、データをキャッシュすることでこれを行うことができれば(これが私が選んだものです)、スピードと結果に満足していると思います。

ただし、私はASP.NET MVCを使用しており、人間的に可能な限りあらゆる種類の状態を回避しています。

+0

+1ロックソリッド! ;)私は意味します - 目に見える脆弱性はありませんが、テストが必要です;) –

+0

さらに、シリアル化レイヤーでいくつかの暗号化(RSA、DES)を使用して、 /stackoverflow.com/questions/4723322/des-encoding-with-security-key-c/4723746#4723746]誰かがあなたの保護されていないAuthUsedDataであなたのCookieを盗むことができるからです! –

+0

@Arturチケット全体が暗号化されているために暗号化されていませんか( 'FormsAuthentication.Encrypt')? – Chris