2010-02-26 61 views
0

当我的网站负载很重时,我产生了奇怪的效果。配置文件系统:用户共享相同的ID

我随机获得其他用户的设置的属性。我有我自己的配置文件系统的实现,所以我想我不能责怪配置文件系统本身。

我只是需要一个点,从开始调试。我想有一个cookie值映射到某个配置文件条目。有没有机会看到这个映射如何工作?

这是我的个人资料提供:

using System; 
using System.Text; 
using System.Configuration; 
using System.Web; 
using System.Web.Profile; 
using System.Collections; 
using System.Collections.Specialized; 
using B2CShop.Model; 
using log4net; 
using System.Collections.Generic; 
using System.Diagnostics; 
using B2CShop.DAL; 
using B2CShop.Model.RepositoryInterfaces; 
[assembly: log4net.Config.XmlConfigurator()] 
namespace B2CShop.Profile 
{ 
    public class B2CShopProfileProvider : ProfileProvider 
    { 
     private static readonly ILog _log = LogManager.GetLogger(typeof(B2CShopProfileProvider)); 
     // Get an instance of the Profile DAL using the ProfileDALFactory 
     private static readonly B2CShop.DAL.UserRepository dal = new B2CShop.DAL.UserRepository(); 
     // Private members 
     private const string ERR_INVALID_PARAMETER = "Invalid Profile parameter:"; 

     private const string PROFILE_USER = "User"; 
     private static string applicationName = B2CShop.Model.Configuration.ApplicationConfiguration.MembershipApplicationName; 

     /// <summary> 
     /// The name of the application using the custom profile provider. 
     /// </summary> 
     public override string ApplicationName 
     { 
      get 
      { 
       return applicationName; 
      } 
      set 
      { 
       applicationName = value; 
      } 
     } 


     /// <summary> 
     /// Initializes the provider. 
     /// </summary> 
     /// <param name="name">The friendly name of the provider.</param> 
     /// <param name="config">A collection of the name/value pairs representing the provider-specific attributes specified in the configuration for this provider.</param> 
     public override void Initialize(string name, NameValueCollection config) 
     { 
      if (config == null) 
       throw new ArgumentNullException("config"); 

      if (string.IsNullOrEmpty(config["description"])) 
      { 
       config.Remove("description"); 
       config.Add("description", "B2C Shop Custom Provider"); 
      } 

      if (string.IsNullOrEmpty(name)) 
       name = "b2c_shop"; 

      if (config["applicationName"] != null && !string.IsNullOrEmpty(config["applicationName"].Trim())) 
       applicationName = config["applicationName"]; 

      base.Initialize(name, config); 

     } 

     /// <summary> 
     /// Returns the collection of settings property values for the specified application instance and settings property group. 
     /// </summary> 
     /// <param name="context">A System.Configuration.SettingsContext describing the current application use.</param> 
     /// <param name="collection">A System.Configuration.SettingsPropertyCollection containing the settings property group whose values are to be retrieved.</param> 
     /// <returns>A System.Configuration.SettingsPropertyValueCollection containing the values for the specified settings property group.</returns> 
     public override SettingsPropertyValueCollection GetPropertyValues(SettingsContext context, SettingsPropertyCollection collection) 
     { 

      string username = (string)context["UserName"]; 
      bool isAuthenticated = (bool)context["IsAuthenticated"]; 
      //if (!isAuthenticated) return null; 
      int uniqueID = dal.GetUniqueID(username, isAuthenticated, false, ApplicationName); 



      SettingsPropertyValueCollection svc = new SettingsPropertyValueCollection(); 

      foreach (SettingsProperty prop in collection) 
      { 
       SettingsPropertyValue pv = new SettingsPropertyValue(prop); 

       switch (pv.Property.Name) 
       { 
        case PROFILE_USER: 
         if (!String.IsNullOrEmpty(username)) 
         { 
          pv.PropertyValue = GetUser(uniqueID); 
         } 
         break; 
        default: 
         throw new ApplicationException(ERR_INVALID_PARAMETER + " name."); 
       } 

       svc.Add(pv); 
      } 
      return svc; 
     } 


     /// <summary> 
     /// Sets the values of the specified group of property settings. 
     /// </summary> 
     /// <param name="context">A System.Configuration.SettingsContext describing the current application usage.</param> 
     /// <param name="collection">A System.Configuration.SettingsPropertyValueCollection representing the group of property settings to set.</param> 
     public override void SetPropertyValues(SettingsContext context, SettingsPropertyValueCollection collection) 
     { 

      string username = (string)context["UserName"]; 
      CheckUserName(username); 
      bool isAuthenticated = (bool)context["IsAuthenticated"]; 

      int uniqueID = dal.GetUniqueID(username, isAuthenticated, false, ApplicationName); 
      if (uniqueID == 0) 
      { 
       uniqueID = dal.CreateProfileForUser(username, isAuthenticated, ApplicationName); 
      } 

      foreach (SettingsPropertyValue pv in collection) 
      { 

       if (pv.PropertyValue != null) 
       { 
        switch (pv.Property.Name) 
        { 
         case PROFILE_USER: 
          SetUser(uniqueID, (UserInfo)pv.PropertyValue); 
          break; 
         default: 
          throw new ApplicationException(ERR_INVALID_PARAMETER + " name."); 
        } 
       } 
      } 

      UpdateActivityDates(username, false); 
     } 


     // Profile gettters 
     // Retrieve UserInfo 
     private static UserInfo GetUser(int userID) 
     { 
      return dal.GetUser(userID); 
     } 




     // Update account info 
     private static void SetUser(int uniqueID, UserInfo user) 
     { 
      user.UserID = uniqueID; 
      dal.SetUser(user); 
     } 


     // UpdateActivityDates 
     // Updates the LastActivityDate and LastUpdatedDate values 
     // when profile properties are accessed by the 
     // GetPropertyValues and SetPropertyValues methods. 
     // Passing true as the activityOnly parameter will update 
     // only the LastActivityDate. 
     private static void UpdateActivityDates(string username, bool activityOnly) 
     { 
      dal.UpdateActivityDates(username, activityOnly, applicationName); 
     } 

     /// <summary> 
     /// Deletes profile properties and information for the supplied list of profiles. 
     /// </summary> 
     /// <param name="profiles">A System.Web.Profile.ProfileInfoCollection of information about profiles that are to be deleted.</param> 
     /// <returns>The number of profiles deleted from the data source.</returns> 
     public override int DeleteProfiles(ProfileInfoCollection profiles) 
     { 

      int deleteCount = 0; 

      foreach (ProfileInfo p in profiles) 
       if (DeleteProfile(p.UserName)) 
        deleteCount++; 

      return deleteCount; 
     } 

     /// <summary> 
     /// Deletes profile properties and information for profiles that match the supplied list of user names. 
     /// </summary> 
     /// <param name="usernames">A string array of user names for profiles to be deleted.</param> 
     /// <returns>The number of profiles deleted from the data source.</returns> 
     public override int DeleteProfiles(string[] usernames) 
     { 

      int deleteCount = 0; 

      foreach (string user in usernames) 
       if (DeleteProfile(user)) 
        deleteCount++; 

      return deleteCount; 
     } 

     // DeleteProfile 
     // Deletes profile data from the database for the specified user name. 
     private static bool DeleteProfile(string username) 
     { 
      CheckUserName(username); 
      return dal.DeleteAnonymousProfile(username, applicationName); 
     } 

     // Verifies user name for sise and comma 
     private static void CheckUserName(string userName) 
     { 
      if (string.IsNullOrEmpty(userName) || userName.Length > 256 || userName.IndexOf(",") > 0) 
       throw new ApplicationException(ERR_INVALID_PARAMETER + " user name."); 
     } 

     /// <summary> 
     /// Deletes all user-profile data for profiles in which the last activity date occurred before the specified date. 
     /// </summary> 
     /// <param name="authenticationOption">One of the System.Web.Profile.ProfileAuthenticationOption values, specifying whether anonymous, authenticated, or both types of profiles are deleted.</param> 
     /// <param name="userInactiveSinceDate">A System.DateTime that identifies which user profiles are considered inactive. If the System.Web.Profile.ProfileInfo.LastActivityDate value of a user profile occurs on or before this date and time, the profile is considered inactive.</param> 
     /// <returns>The number of profiles deleted from the data source.</returns> 
     public override int DeleteInactiveProfiles(ProfileAuthenticationOption authenticationOption, DateTime userInactiveSinceDate) 
     { 

      string[] userArray = new string[0]; 
      dal.GetInactiveProfiles((int)authenticationOption, userInactiveSinceDate, ApplicationName).CopyTo(userArray, 0); 

      return DeleteProfiles(userArray); 
     } 

     /// <summary> 
     /// Retrieves profile information for profiles in which the user name matches the specified user names. 
     /// </summary> 
     /// <param name="authenticationOption">One of the System.Web.Profile.ProfileAuthenticationOption values, specifying whether anonymous, authenticated, or both types of profiles are returned.</param> 
     /// <param name="usernameToMatch">The user name to search for.</param> 
     /// <param name="pageIndex">The index of the page of results to return.</param> 
     /// <param name="pageSize">The size of the page of results to return.</param> 
     /// <param name="totalRecords">When this method returns, contains the total number of profiles.</param> 
     /// <returns>A System.Web.Profile.ProfileInfoCollection containing user-profile information 
     //  for profiles where the user name matches the supplied usernameToMatch parameter.</returns> 
     public override ProfileInfoCollection FindProfilesByUserName(ProfileAuthenticationOption authenticationOption, string usernameToMatch, int pageIndex, int pageSize, out int totalRecords) 
     { 

      CheckParameters(pageIndex, pageSize); 

      return GetProfileInfo(authenticationOption, usernameToMatch, null, pageIndex, pageSize, out totalRecords); 
     } 

     /// <summary> 
     /// Retrieves profile information for profiles in which the last activity date occurred on or before the specified date and the user name matches the specified user name. 
     /// </summary> 
     /// <param name="authenticationOption">One of the System.Web.Profile.ProfileAuthenticationOption values, specifying whether anonymous, authenticated, or both types of profiles are returned.</param> 
     /// <param name="usernameToMatch">The user name to search for.</param> 
     /// <param name="userInactiveSinceDate">A System.DateTime that identifies which user profiles are considered inactive. If the System.Web.Profile.ProfileInfo.LastActivityDate value of a user profile occurs on or before this date and time, the profile is considered inactive.</param> 
     /// <param name="pageIndex">The index of the page of results to return.</param> 
     /// <param name="pageSize">The size of the page of results to return.</param> 
     /// <param name="totalRecords">When this method returns, contains the total number of profiles.</param> 
     /// <returns>A System.Web.Profile.ProfileInfoCollection containing user profile information for inactive profiles where the user name matches the supplied usernameToMatch parameter.</returns> 
     public override ProfileInfoCollection FindInactiveProfilesByUserName(ProfileAuthenticationOption authenticationOption, string usernameToMatch, DateTime userInactiveSinceDate, int pageIndex, int pageSize, out int totalRecords) 
     { 

      CheckParameters(pageIndex, pageSize); 

      return GetProfileInfo(authenticationOption, usernameToMatch, userInactiveSinceDate, pageIndex, pageSize, out totalRecords); 
     } 

     /// <summary> 
     /// Retrieves user profile data for all profiles in the data source. 
     /// </summary> 
     /// <param name="authenticationOption">One of the System.Web.Profile.ProfileAuthenticationOption values, specifying whether anonymous, authenticated, or both types of profiles are returned.</param> 
     /// <param name="pageIndex">The index of the page of results to return.</param> 
     /// <param name="pageSize">The size of the page of results to return.</param> 
     /// <param name="totalRecords">When this method returns, contains the total number of profiles.</param> 
     /// <returns>A System.Web.Profile.ProfileInfoCollection containing user-profile information for all profiles in the data source.</returns>  
     public override ProfileInfoCollection GetAllProfiles(ProfileAuthenticationOption authenticationOption, int pageIndex, int pageSize, out int totalRecords) 
     { 
      CheckParameters(pageIndex, pageSize); 

      return GetProfileInfo(authenticationOption, null, null, pageIndex, pageSize, out totalRecords); 
     } 

     /// <summary> 
     /// Retrieves user-profile data from the data source for profiles in which the last activity date occurred on or before the specified date. 
     /// </summary> 
     /// <param name="authenticationOption">One of the System.Web.Profile.ProfileAuthenticationOption values, specifying whether anonymous, authenticated, or both types of profiles are returned.</param> 
     /// <param name="userInactiveSinceDate">A System.DateTime that identifies which user profiles are considered inactive. If the System.Web.Profile.ProfileInfo.LastActivityDate of a user profile occurs on or before this date and time, the profile is considered inactive.</param> 
     /// <param name="pageIndex">The index of the page of results to return.</param> 
     /// <param name="pageSize">The size of the page of results to return.</param> 
     /// <param name="totalRecords">When this method returns, contains the total number of profiles.</param> 
     /// <returns>A System.Web.Profile.ProfileInfoCollection containing user-profile information about the inactive profiles.</returns> 
     public override ProfileInfoCollection GetAllInactiveProfiles(ProfileAuthenticationOption authenticationOption, DateTime userInactiveSinceDate, int pageIndex, int pageSize, out int totalRecords) 
     { 
      CheckParameters(pageIndex, pageSize); 

      return GetProfileInfo(authenticationOption, null, userInactiveSinceDate, pageIndex, pageSize, out totalRecords); 
     } 

     /// <summary> 
     /// Returns the number of profiles in which the last activity date occurred on or before the specified date. 
     /// </summary> 
     /// <param name="authenticationOption">One of the System.Web.Profile.ProfileAuthenticationOption values, specifying whether anonymous, authenticated, or both types of profiles are returned.</param> 
     /// <param name="userInactiveSinceDate">A System.DateTime that identifies which user profiles are considered inactive. If the System.Web.Profile.ProfileInfo.LastActivityDate of a user profile occurs on or before this date and time, the profile is considered inactive.</param> 
     /// <returns>The number of profiles in which the last activity date occurred on or before the specified date.</returns> 
     public override int GetNumberOfInactiveProfiles(ProfileAuthenticationOption authenticationOption, DateTime userInactiveSinceDate) 
     { 

      int inactiveProfiles = 0; 

      ProfileInfoCollection profiles = GetProfileInfo(authenticationOption, null, userInactiveSinceDate, 0, 0, out inactiveProfiles); 

      return inactiveProfiles; 
     } 

     //Verifies input parameters for page size and page index. 
     private static void CheckParameters(int pageIndex, int pageSize) 
     { 
      if (pageIndex < 1 || pageSize < 1) 
       throw new ApplicationException(ERR_INVALID_PARAMETER + " page index."); 
     } 

     //GetProfileInfo 
     //Retrieves a count of profiles and creates a 
     //ProfileInfoCollection from the profile data in the 
     //database. Called by GetAllProfiles, GetAllInactiveProfiles, 
     //FindProfilesByUserName, FindInactiveProfilesByUserName, 
     //and GetNumberOfInactiveProfiles. 
     //Specifying a pageIndex of 0 retrieves a count of the results only. 
     private static ProfileInfoCollection GetProfileInfo(ProfileAuthenticationOption authenticationOption, string usernameToMatch, object userInactiveSinceDate, int pageIndex, int pageSize, out int totalRecords) 
     { 

      ProfileInfoCollection profiles = new ProfileInfoCollection(); 

      totalRecords = 0; 

      // Count profiles only. 
      if (pageSize == 0) 
       return profiles; 

      int counter = 0; 
      int startIndex = pageSize * (pageIndex - 1); 
      int endIndex = startIndex + pageSize - 1; 

      DateTime dt = new DateTime(1900, 1, 1); 
      if (userInactiveSinceDate != null) 
       dt = (DateTime)userInactiveSinceDate; 

      /* 
      foreach(CustomProfileInfo profile in dal.GetProfileInfo((int)authenticationOption, usernameToMatch, dt, applicationName, out totalRecords)) { 
       if(counter >= startIndex) { 
        ProfileInfo p = new ProfileInfo(profile.UserName, profile.IsAnonymous, profile.LastActivityDate, profile.LastUpdatedDate, 0); 
        profiles.Add(p); 
       } 

       if(counter >= endIndex) { 
        break; 
       } 

       counter++; 
      } 
      */ 
      return profiles; 
     } 
    } 
} 

这是我如何使用它的控制器:

public ActionResult AddTyreToCart(CartViewModel model) 
    { 

     string profile = Request.IsAuthenticated ? Request.AnonymousID : User.Identity.Name; 

    } 

我想调试:谁提供不同的Cookie 2个用户如何获得相同的配置文件?

编辑

这里是getuniqueid

public int GetUniqueID(string userName, bool isAuthenticated, bool ignoreAuthenticationType, string appName) 
{ 

    SqlParameter[] parms = { 
      new SqlParameter("@Username", SqlDbType.VarChar, 256), 
      new SqlParameter("@ApplicationName", SqlDbType.VarChar, 256)}; 
    parms[0].Value = userName; 
    parms[1].Value = appName; 

    if (!ignoreAuthenticationType) 
    { 
    Array.Resize(ref parms, parms.Length + 1); 
    parms[2] = new SqlParameter("@IsAnonymous", SqlDbType.Bit) { Value = !isAuthenticated }; 
    } 

    int userID; 

    object retVal = null; 
    retVal = SqlHelper.ExecuteScalar(ConfigurationManager.ConnectionStrings["SQLOrderB2CConnString"].ConnectionString, CommandType.StoredProcedure, "getProfileUniqueID", parms); 

    if (retVal == null) 
    userID = CreateProfileForUser(userName, isAuthenticated, appName); 
    else 
    userID = Convert.ToInt32(retVal); 
    return userID; 
} 

代码这是SP:

CREATE PROCEDURE [dbo].[getProfileUniqueID] 

@Username VarChar(256), 
@ApplicationName VarChar(256), 
@IsAnonymous bit = null 
AS 
BEGIN 

    SET NOCOUNT ON; 
/* 
[getProfileUniqueID] 

created 
08.07.2009 mf 

Retrive unique id for current user 

*/ 
SELECT UniqueID FROM dbo.Profiles WHERE Username = @Username 
AND ApplicationName = @ApplicationName 
AND IsAnonymous = @IsAnonymous or @IsAnonymous = null 

END 
+0

你能张贴'dal.GetUniqueID(用户名,isAuthenticated,假的,应用程序名称)来源;'? – 2010-02-26 18:16:58

+0

@nick我更新了这个帖子 – 2010-02-27 10:23:38

回答

1

这是一个非常困难的问题类型进行故障排除。我们在ASP.NET应用程序(而不是MVC)中遇到过类似的问题。我建议你可以先设置一个单独的cookie来识别用户,完全绕过ASP.NET配置文件系统。然后,您可以检查该cookie中的身份是否与配置文件中的身份相匹配。如果没有,那么你可以1)注销用户,至少他们不能访问别人的数据,2)收集一些诊断信息 - 完整的HTTP请求细节将是一个开始。如果没有建立任何类型的模式,您可以开始记录用户的所有HTTP请求,以查看其请求历史记录中是否存在可帮助您重现问题的模式。

在我们的情况下,问题最终是一个愚蠢的土生土长的缓存机制。该应用程序会尝试缓存ASP.NET中的静态文件(例如图像),并将cookie与它们缓存起来。在重负载下,用户有时会用另一个用户的cookies加载图像并假定其他用户的身份。你的情况可能完全不同,但这可能会给你一些线索寻找的东西类型。

+0

你的故事看起来有点像我在这里发生的事情。我现在看到,不同的用户(不同的IP)获得相同的cookie值.ASPXANONYMOUS。我想我会打开一个新的问题,询问“FormsAuthentication”。 – 2010-03-15 16:11:41

0

给定的来源似乎没问题,但是如果不具备所有相应的源代码(例如,类B2CShop.DAL.UserRepository的所有使用方法),甚至可能是数据库方案,我都无法做出深刻的陈述。

首先会检查是否也许是在数据库中的数据被损坏,所以说,有些用户可能从字面上拥有相同的唯一ID或者相同的用户名/应用/ isanonymous组合。如果uniqueid是主键,这可以被排除。

1

我还没有深入地看着这一点,但有一件事做我跳出。

在您的where子句变化

@IsAnonymous = null 

@IsAnonymous IS NULL 

你希望发生时@IsAnonymous为空怎么办?您可能需要在where子句中添加一些括号。

SELECT UniqueID FROM dbo.Profiles 
WHERE Username = @Username 
    AND ApplicationName = @ApplicationName 
    AND (IsAnonymous = @IsAnonymous OR @IsAnonymous IS NULL) 

您是否收到相同配置文件数据的两位用户?如果是这样的话。我会首先通过存储的proc来运行它们。这将是容易和快速的事情。

0

每当这类问题的发生......我看过以下是原因......

  1. 缓存
  2. 静态变量

你可以尝试写这样的代码没有静态变量,并检查问题是否解决?

问候, 拉胡尔

相关问题