C# 如何持久化应用程序_AuthenticateRequest中所需的特定于会话的值?

C# 如何持久化应用程序_AuthenticateRequest中所需的特定于会话的值?,c#,asp.net,C#,Asp.net,我们有一个非常大的web应用程序,有很多页面。这些页面要求我们了解用户的角色,以便正确显示内容。因此,在Application_AuthenticationRequest中,我们有以下代码: var id = new GenericIdentity(Request.Headers["ceid"]); var rp = new MyRoleProvider(); var principal = new GenericPrincipal(id, rp.GetRolesForUser(id.Na

我们有一个非常大的web应用程序,有很多页面。这些页面要求我们了解用户的角色,以便正确显示内容。因此,在Application_AuthenticationRequest中,我们有以下代码:

 var id = new GenericIdentity(Request.Headers["ceid"]);
 var rp = new MyRoleProvider();
 var principal = new GenericPrincipal(id, rp.GetRolesForUser(id.Name));
 Context.User = principal;
问题是我们需要使用web服务来获取角色,而且由于每次用户访问页面时都会调用该服务,因此web服务被点击的次数太多

理想的解决方案是,我们可以将角色存储在会话变量中,但是,会话在应用程序_AuthenticateRequest中不可用。我们考虑在应用程序变量中存储一个包含所有用户条目的字典,但我希望我们能找到更好的解决方案


是否有任何方法可以存储当前用户的角色,使其在Application_AuthenticationRequest中可用?我们很有安全意识;cookie是一个有效的选项吗?

我将创建一个静态类来保存所有当前用户的角色列表(基本上扩展了字典的概念):如果给定ID的角色不在列表中,我们将从web服务检索它们。否则,我们将返回存储的角色。

我们需要在一定程度的用户不活动后使数据过期的方法(我们不想让所有用户的所有角色始终保留在内存中),因此我们将实现自己的过期机制(在我的示例中为20分钟)。

下面是我将如何编写这个类,以及如何使用它:

    /// <summary>
    /// This is the static class that will hold the roles for all active users (active users 
    /// are those that have been using the website within the last 20 minutes).
    /// </summary>
    public static class MyRoles
    {
        /// <summary>
        /// This class holds your roles
        /// </summary>
        private class Principal
        {
            private DateTime lastAccess; // Our expiration timer
            private System.Security.Principal.GenericPrincipal principal; // Our roles

            public Principal(System.Security.Principal.GenericPrincipal principal)
            {
                this.principal = principal;
                this.lastAccess = DateTime.Now;
            }

            public System.Security.Principal.GenericPrincipal GenericPrincipal
            {
                get
                { 
                    // We reset our timer. It will expire 20 minutes from now. 
                    this.lastAccess = DateTime.Now;

                    return principal;
                }
            }                                

            /// <summary>
            /// This tells us if a user has been active in the last 20 minutes
            /// </summary>
            public bool IsValid
            {
                get
                {
                    // Valid within 20 minutes from last call
                    return DateTime.Now <= this.lastAccess.AddMinutes(20);                        
                }
            }
        }

        /// <summary>
        /// This will hold IDs and related roles
        /// </summary>
        private static Dictionary<string, Principal> ids = new Dictionary<string, Principal>();

        /// <summary>
        /// Method to retrieve roles for a given ID
        /// </summary>
        /// <param name="header">Our ID</param>
        /// <returns></returns>
        public static System.Security.Principal.GenericPrincipal GetRoles(string header)
        {
            if (ids.ContainsKey(header) && ids[header].IsValid)
            {
                // We have roles for this ID
                return ids[header].GenericPrincipal;
            }
            else
            {
                // We don't have this ID (or it's expired) so get it from the web service
                var id = new System.Security.Principal.GenericIdentity(header);
                var principal = new System.Security.Principal.GenericPrincipal(id, new MyRoleProvider().GetRolesForUser(id.Name));

                // Store roles
                ids.Add(header, new Principal(principal));

                return principal;
            }
        }            
    }

    protected void Application_AuthenticateRequest(object sender, EventArgs e)
    {
        // This is how we use our class
        var principal = MyRoles.GetRoles(Request.Headers["ceid"]);
    }
//
///这是将为所有活动用户(活动用户)保留角色的静态类
///是指在过去20分钟内使用该网站的用户)。
/// 
公共静态类MyRoles
{
/// 
///这个类负责你的角色
/// 
私班校长
{
private DateTime lastAccess;//我们的过期计时器
private System.Security.Principal.GenericPrincipal;//我们的角色
公共主体(System.Security.Principal.GenericPrincipal)
{
this.principal=principal;
this.lastAccess=DateTime.Now;
}
公共系统.Security.Principal.GenericPrincipal GenericPrincipal
{
得到
{ 
//我们重置了计时器。它将在20分钟后过期。
this.lastAccess=DateTime.Now;
返还本金;
}
}                                
/// 
///这告诉我们用户在过去20分钟内是否处于活动状态
/// 
公共布尔是有效的
{
得到
{
//上次通话后20分钟内有效

return DateTime。现在您知道有现成的功能可以在cookie中“缓存”用户的角色吗?如果您想使用角色API,这一功能可以正常工作;许多人都会使用自己的角色,因此存储在只有HttpOnly(仅在服务器上可用)的cookie中设置为true是一个很好的解决方案。如果你不喜欢使用cookie,可能是一个可能的解决方案?谢谢,@Alex…我会尽快尝试。很抱歉延迟,但我的VS2013试用版刚刚过期,我为一家大公司工作,因此让他们给我一个实际的MSDN许可证所花的时间比预期的要长:(没问题,@FrancineDeGroodTaylor。只要记住注意静态类的内存占用(就像使用会话对象时一样)。如果需要我,你知道在哪里可以找到我:)