2

ASP.NET アプリケーションに役割があります。私は問題を理解しました(私は思う)。アプリケーション内のすべてのページがロールとパーミッションを使用する問題。したがって、ページの読み込みで次の関数を使用します

if (Roles.IsUserInRole("Admin")) { // ページを表示する } else { // いいえ }

この質問から私の問題の解決策を見つけましたWindowsTokenRoleProviderでパフォーマンスが悪い

しかし、いくつかの違いがあります 1.上記の質問ではWindowsTokenRoleProviderを使用しています。私は SqlRoleProvider を使用しています

上記の問題のため、上記の解決策は私にはうまくいきません。

私がこれまでに行ったこと、そして部分的に成功したことは、SqlRoleProvider からクラスを派生させ、上記の質問と同じであるが変更されたこの関数を含めたことです。このようになるようにweb.configを変更しました

<roleManager enabled="true" cacheRolesInCookie="true" cookieName=".ASPR0L3S" cookieTimeout="117" cookieSlidingExpiration="true" cookieProtection="All" createPersistentCookie="false" defaultProvider="CustomSqlRoleProvider">
            <providers>
                <add name="CustomizedRoleProvider" type="CustomSqlRoleProvider" connectionStringName="PEGConn" applicationName="/CRM"/>
            </providers>
        </roleManager>

これは私のクラス内の関数であり、取得します(ユーザーがログインしたときにのみ実行されます)

public override string[] GetRolesForUser(string username)
    {
        // Will contain the list of roles that the user is a member of
        List<string> roles = null;

        // Create unique cache key for the user
        string key = String.Concat(username, ":", base.ApplicationName);

        // Get cache for current session
        Cache cache = HttpContext.Current.Cache;

        // Obtain cached roles for the user
        if (cache[key] != null)
        {
            roles = new List<string>(cache[key] as string[]);
        }

        // Was the list of roles for the user in the cache?



        if (roles == null)
        {
            string[] AllRoles = GetAllRoles();
            roles = new List<string>();

            // For each system role, determine if the user is a member of that role
            foreach (String role in AllRoles)
            {
                if (base.IsUserInRole(username, role))
                {
                    roles.Add(role);
                }
            }

            // Cache the roles for 1 hour
            cache.Insert(key, roles.ToArray(), null, DateTime.Now.AddHours(1), Cache.NoSlidingExpiration);
        }

        // Return list of roles for the user
        return roles.ToArray();
    }

問題は、 Roles.IsUserInRole 関数が同じ古いものを呼び出すときです

System.Web.Security.Roles.IsUserInRole

関数。新しいクラスでこの関数をオーバーロードしましたが、実行されません。私は基本的にすべてのロールをキャッシュしているので、ページが更新されるたびに、アプリケーションは最初からすべてのロールを検索しません。

から別のクラスを派生させる必要がありSystem.Web.Security.Roles.IsUserInRoleますか? やった人いる?

各ページは、フレッシュで長すぎる約4〜8秒かかります. コードは VS 2008、C# 3.5 にあります

4

5 に答える 5

1

これは、アプリケーション設計の根本的な問題を隠している可能性もあると思います。DRY 原則に同意する必要があります。同じことを繰り返さないでください。つまり、すべてのページで同じルックアップ/コードを繰り返さないでください。これらの高価な Role ルックアップを「キャッシュ」できるように、セッション変数を使用することをお勧めします。セッション変数を使用するためのクイック ガイドを次に示します。

http://msdn.microsoft.com/en-us/library/ms178581.aspx

余談ですが。これらの「役割」を保存するために Cookie を使用しているようです。これはあまり安全とは言えません。したがって、セキュリティはこの演習の主な目標ではないと仮定します。

于 2012-07-09T22:04:26.620 に答える
1
  1. 呼び出しのたびにデータベースにアクセスする IsUserInRole を繰り返し呼び出すのではなく、GetRolesForUser の基本クラスの実装を活用することをお勧めします。

    public override string[] GetRolesForUser(string username)
    {
        // Create unique cache key for the user
        string key = String.Concat(username, ":", base.ApplicationName);
    
        string[] roles = HttpRuntime.Cache[key] as string[];
    
        if (roles != null)
        {
            roles = base.GetRolesForUser(username);
    
            HttpRuntine.Cache.Insert(key, roles.ToArray(), ...);
        }
    
    }
    
  2. また、スライド有効期限を使用することも検討します。その値は構成可能で、デフォルトで約 30 分に設定できます (デフォルトの RoleManagerSection.CookieTimeout と同様)。これは、1 時間の絶対有効期限に追加される可能性があります。

  3. 最後に、IsUserInRole をオーバーライドしてキャッシュを使用する必要があります。次のように実装できます。

    public override bool IsUserInRole(string username, string roleName)
    {
        // Case-insensitive comparison for compatibility with RolePrincipal class
        return thisGetRolesForUser(username).Contains(roleName, 
                            StringComparer.OrdinalIgnoreCase);
    }
    
于 2014-10-15T13:51:43.907 に答える
1

Roles.IsUserInRole("Admin") に時間がかかる場合は、(ログイン時に) ユーザーのロールを一度確認し、値をセッション オブジェクトに保存できます。

const string IS_ADMIN_KEY; //this can be on a base class of page / master page

Session[IS_ADMIN_KEY] = Roles.IsUserInRole("Admin"); // do this when logging in

//Add this to page load
bool isAdmin = Session[IS_ADMIN_KEY]; 
if(isAdmin)) 
{ 
   // display the page 
} else 
{ 
   // don't display the page 
}
于 2012-07-10T04:10:23.810 に答える
0

デフォルトでは、指定したもの以外に、いくつかのプロバイダーがアプリケーションに追加されます。プロバイダーのリストからそれらを削除すると、必要なプロバイダーのみを使用することになるため、パフォーマンスが確実に向上する可能性があります。

<system.web>
  <membership defaultProvider="MyMembershipProvider">
    <providers>
      <clear />
      <add name="MyMembershipProvider" type="MyMembershipProvider" applicationName="My App" />
    </providers>
  </membership>
  <roleManager defaultProvider="MyRoleProvider" enabled="true" cacheRolesInCookie="true" cookieTimeout="60">
    <providers>
      <clear />
      <add name="MyRoleProvider" type="MyRoleProvider" applicationName="My App" />
    </providers>
  </roleManager>
</system.web>

また、結果を Cookie にキャッシュする場合、プロバイダーに余分なものを実装する必要がないことも理解しています。cacheRolesInCookie 属性を True に設定すると、.NET がキャッシュを処理するように指示されます。System.Web.Security.Roles を使用してロール プロバイダーを呼び出している限り、.NET はロールのキャッシュと Cookie への配置を処理します。

私は試してみます:

<system.web>
  <roleManager enabled="true" cacheRolesInCookie="true" cookieName=".ASPR0L3S" cookieTimeout="117" cookieSlidingExpiration="true" cookieProtection="All" createPersistentCookie="false" defaultProvider="SqlRoleProvider">
    <providers>
      <clear />
      <add name="SqlRoleProvider" type="System.Web.Security.SqlRoleProvider" connectionStringName="PEGConn" applicationName="/CRM"/>
    </providers>
  </roleManager>
</system.web>
于 2012-07-09T21:53:01.393 に答える
0

まず、やり方が間違っています。これを行うために Page_Load に何も配置しないでください。ロールが静的な場合は代わりに認証キー web.config を使用する必要があります。ロールが動的な場合は、global.asax Application_AuthorizeRequest イベントでこれを行う必要があります。

これにより、ページのライフサイクルがさらに進み、より安全になり、リソースの浪費が少なくなります。

次に、これが遅い理由を調査する必要があります。ロールを Cookie にキャッシュすることで回避できますが (JG はその方法について言及しています)、実際には、データベース自体を調べてください。ロールの検索に時間がかからないようにする必要があります。ロール ルックアップをサポートするストアド プロシージャ (データベース内にあります) を実行し、その実行が遅いかどうかを確認します。

于 2012-07-09T22:37:13.450 に答える