且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

ASP.NET通用提供程序 - Roleprovider不缓存cookie中的角色

更新时间:2022-12-04 14:55:29

以下是我写的自定义角色提供程序的详细信息,它使用正确的缓存,每个页面上的数据库加载。



=============我的代码在文件后面========== =====

 使用System; 
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
使用System.Web;
using System.Web.Caching;
using System.Web.Security;

命名空间MyProject.Providers
{
public class CustomRoleProvider:RoleProvider
{
#region属性

私有静态readonly对象LockObject = new object();
private int _cacheTimeoutInMinutes = 0;

#endregion

#region RoleProvider的覆盖

public override void Initialize(string name,NameValueCollection config)
{
//设置属性
ApplicationName = config [applicationName];
_cacheTimeoutInMinutes = Convert.ToInt32(config [cacheTimeoutInMinutes]);

//调用基本方法
base.Initialize(name,config);
}

///< summary>
///获取一个值,该值指示指定的用户是否处于配置的applicationName的指定角色中。
///< / summary>
///< returns>
///如果指定的用户在配置的applicationName的指定角色中,则为true;否则为false。
///< / returns>
///< param name =username>要搜索的用户名。< / param>< param name =roleName>要搜索的角色< / param&
public override bool IsUserInRole(string username,string roleName)
{
//获取角色
var userRoles = GetRolesForUser(username);

//返回如果存在
return userRoles.Contains(roleName);
}

///< summary>
///获取指定用户对于配置的applicationName所处的角色的列表。
///< / summary>
///< returns>
///一个字符串数组,包含指定用户对于配置的applicationName的所有角色的名称。
///< / returns>
///< param name =username>返回角色列表的用户。< / param>
public override string [] GetRolesForUser(string username)
{
//如果用户未通过身份验证则返回如果(!HttpContext.Current.User.Identity.IsAuthenticated)返回null ;

//如果存在于缓存中则返回
var cacheKey = string.format(UserRoles_ {0},username);
if(HttpRuntime.Cache [cacheKey]!= null)return(string [])HttpRuntime.Cache [cacheKey];

// Vars
var userRoles = new List< string>();
var sqlParams = new List< SqlParameter>
{
new SqlParameter(@ ApplicationName,ApplicationName),
new SqlParameter(@ UserName,username)
};

lock(LockObject)
{
// Run Stored Proc<将此块替换为您自己的数据库调用方法>>
using(IDataReader dr =
BaseDatabase.ExecuteDataReader(aspnet_UsersInRoles_GetRolesForUser,sqlParams.ToArray(),
Constants.DatabaseConnectionName)as SqlDataReader)
{
while .Read())
{
userRoles.Add(dr [RoleName]。ToString());
}
}
}

//存储在缓存中并在设置分钟后过期
HttpRuntime.Cache.Insert(cacheKey,userRoles.ToArray() ,null,
DateTime.Now.AddMinutes(_cacheTimeoutInMinutes),Cache.NoSlidingExpiration);

//返回
return userRoles.ToArray();
}

///< summary>
///获取或设置要存储和检索角色信息的应用程序的名称。
///< / summary>
///< returns>
///存储和检索角色信息的应用程序的名称。
///< / returns>
public override sealed string ApplicationName {get;组; }

//我跳过其他方法,因为它们不适用于这种情况

#endregion
}
}

=============我的代码结束文件======= ========



=============我的Web.Config文件========= ==============

 < roleManager enabled =truedefaultProvider =CustomRoleManager > 
< providers>
< clear />
< add name =SqlRoleManagertype =System.Web.Security.SqlRoleProviderconnectionStringName =AspnetDbConnectionapplicationName =MyApplication/>
< add name =CustomRoleManagertype =MyProject.Providers.CustomRoleProviderconnectionStringName =AspnetDbConnectionapplicationName =MyApplicationcacheTimeoutInMinutes =30/>
< / providers>
< / roleManager>

============= End of My Web.Config file = ===============



缓存设置为每30分钟后自动到期。您可以视需要修改此项。



干杯。


Ironically my role provider does not cache the roles in a cookie anymore. That was working earlier. Unfortunately i have noticed that only now, so i cannot say what causes the problem. But i think it has to do with the update to the new version 1.2 of the universal providers (released on 16th august).

My config for the roleprovider looks like:

 <roleManager enabled="true" cacheRolesInCookie="true" cookieName="X_Roles" 
cookiePath="/" cookieProtection="All" cookieRequireSSL="true" cookieSlidingExpiration="true" cookieTimeout="1440" 
createPersistentCookie="false" domain="" maxCachedResults="25" defaultProvider="XManager_RoleProvider">
<providers>
<clear/>
<add name="XManager_RoleProvider" type="ManagersX.XManager_RoleProvider, AssemblyX" 
connectionStringName="XEntities" applicationName="/" rolesTableName="Roles" roleMembershipsTableName="Users_Roles"/>
</providers>
</roleManager>

Everything is working fine with the rolemanager (loginviews, menu with sitemaptrimming etc.), but it is only not caching the roles anymore. The membership provider, sessionstate etc. are also working fine and the cookies of them are set correctly.

All properties of the static Roles-class are correctly set and everything in Httpcontext (IsSecureConnection etc.) is also correct.

The roles cookie was set earlier, but not anymore. I hope anybody can help me with my problem.

Thanks in advance.

Best Regards,

HeManNew

UPDATE: Has nobody got the same problem or a tip for me, please?

Below are the details of the Custom Role Provider I wrote that uses proper caching and doesn't hit the database on each page load.

============= My Code-Behind file ===============

using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Web;
using System.Web.Caching;
using System.Web.Security;

namespace MyProject.Providers
{
    public class CustomRoleProvider : RoleProvider
    {
        #region Properties

        private static readonly object LockObject = new object();
        private int _cacheTimeoutInMinutes = 0;

        #endregion

        #region Overrides of RoleProvider

        public override void Initialize(string name, NameValueCollection config)
        {
            // Set Properties
            ApplicationName = config["applicationName"];
            _cacheTimeoutInMinutes = Convert.ToInt32(config["cacheTimeoutInMinutes"]);

            // Call base method
            base.Initialize(name, config);
        }

        /// <summary>
        /// Gets a value indicating whether the specified user is in the specified role for the configured applicationName.
        /// </summary>
        /// <returns>
        /// true if the specified user is in the specified role for the configured applicationName; otherwise, false.
        /// </returns>
        /// <param name="username">The user name to search for.</param><param name="roleName">The role to search in.</param>
        public override bool IsUserInRole(string username, string roleName)
        {
            // Get Roles
            var userRoles = GetRolesForUser(username);

            // Return if exists
            return userRoles.Contains(roleName);
        }

        /// <summary>
        /// Gets a list of the roles that a specified user is in for the configured applicationName.
        /// </summary>
        /// <returns>
        /// A string array containing the names of all the roles that the specified user is in for the configured applicationName.
        /// </returns>
        /// <param name="username">The user to return a list of roles for.</param>
        public override string[] GetRolesForUser(string username)
        {
            // Return if User is not authenticated
            if (!HttpContext.Current.User.Identity.IsAuthenticated) return null;

            // Return if present in Cache
            var cacheKey = string.format("UserRoles_{0}", username);
            if (HttpRuntime.Cache[cacheKey] != null) return (string[]) HttpRuntime.Cache[cacheKey];

            // Vars
            var userRoles = new List<string>();
            var sqlParams = new List<SqlParameter>
                                {
                                    new SqlParameter("@ApplicationName", ApplicationName),
                                    new SqlParameter("@UserName", username)
                                };

            lock (LockObject)
            {
                // Run Stored Proc << Replace this block with your own Database Call Methods >>
                using (IDataReader dr =
                    BaseDatabase.ExecuteDataReader("aspnet_UsersInRoles_GetRolesForUser", sqlParams.ToArray(),
                                                   Constants.DatabaseConnectionName) as SqlDataReader)
                {
                    while (dr.Read())
                    {
                        userRoles.Add(dr["RoleName"].ToString());
                    }
                }
            }

            // Store in Cache and expire after set minutes
            HttpRuntime.Cache.Insert(cacheKey, userRoles.ToArray(), null,
                                     DateTime.Now.AddMinutes(_cacheTimeoutInMinutes), Cache.NoSlidingExpiration);

            // Return
            return userRoles.ToArray();
        }

        /// <summary>
        /// Gets or sets the name of the application to store and retrieve role information for.
        /// </summary>
        /// <returns>
        /// The name of the application to store and retrieve role information for.
        /// </returns>
        public override sealed string ApplicationName { get; set; }

        // I skipped the other methods as they do not apply to this scenario

        #endregion
    }
}

============= End of My Code-Behind file ===============

============= My Web.Config file =======================

<roleManager enabled="true" defaultProvider="CustomRoleManager">
  <providers>
    <clear />
    <add name="SqlRoleManager" type="System.Web.Security.SqlRoleProvider" connectionStringName="AspnetDbConnection" applicationName="MyApplication"/>
    <add name="CustomRoleManager" type="MyProject.Providers.CustomRoleProvider" connectionStringName="AspnetDbConnection" applicationName="MyApplication" cacheTimeoutInMinutes="30" />
  </providers>
</roleManager>

============= End of My Web.Config file ================

The cache is set to expire automatically after every 30 minutes. You can modify this as you deem fit.

Cheers.