Domanda

Ho uno strano effetto sul mio sito, quando si è sotto carico pesante.

Ho casualmente ottenere la proprietà di altri utenti impostazioni.Io ho la mia implementazione del sistema di profilo quindi credo che non posso dare la colpa al profilo del sistema stesso.

Ho solo bisogno di un punto di partenza per il debugging.Credo che c'è un cookie di valore che è associato a un Profilo di voce da qualche parte.C'è qualche possibilità di vedere come questo mapping funziona?

Ecco il mio profilo fornitore di:

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;
        }
    }
}

Questo è come io la uso nel controller:

    public ActionResult AddTyreToCart(CartViewModel model)
    {

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

    }

Vorrei eseguire il debug:Come possono i 2 utenti che forniscono diversi cookies ottenere lo stesso profileid?

MODIFICA

Ecco il codice per 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;
}

E questo è l'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

Nessuna soluzione corretta

Altri suggerimenti

Non ho guardato questo in profondità, ma una cosa ha fatto saltare fuori di me.

Nel vostro in cui il cambiamento clausola

@IsAnonymous = null

a

@IsAnonymous IS NULL

Che cosa vuoi che accada quando @IsAnonymous è nullo? Potrebbe essere necessario aggiungere un paio di parentesi alla clausola dove.

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

Sei due utenti che hanno ricevuto gli stessi dati del profilo? Se è così cominciare da lì. Io li correre attraverso il proc memorizzato prima. Sarebbe facile e veloce da fare.

Questo è un tipo molto difficile di problema da risolvere. Abbiamo avuto un problema simile in un app ASP.NET (non MVC). Io suggerirei che si può iniziare impostando un cookie separato per identificare l'utente, bypassando completamente il sistema di profilo ASP.NET. È quindi possibile verificare se l'identità di quel cookie corrisponde l'identità nel profilo. Se non è possibile, allora 1) scollegare l'utente così almeno non ottengono l'accesso ai dati di qualcun altro e 2) raccogliere alcune informazioni di diagnostica - i dettagli completi di richiesta HTTP sarebbe un inizio. Se questo non stabilire alcun tipo di modello si potrebbe iniziare a registrare tutte le richieste HTTP per utente per vedere se c'è un modello in loro storia richiesta, che ti aiuta a riprodurre il problema.

Nel nostro caso la questione ha finito per essere un meccanismo di caching sciocca home-grown. L'applicazione avrebbe cercato di memorizzare nella cache i file statici (ad es. Immagini) in ASP.NET e biscotti ma ho cache con loro. Sotto carico pesante di un utente a volte caricare un'immagine con i cookie di un altro utente e assumere l'identità di un altro utente. Il tuo caso potrebbe essere completamente diverso, ma questo potrebbe dare qualche indizio sul tipo di cosa da cercare.

Il dato origini sembrano essere a posto, ma non riesco a fare una dichiarazione profonda senza avere tutti il corrispondente codice sorgente (es.tutti i metodi della classe B2CShop.DAL.UserRepository), forse anche lo schema della base di dati.

Il primo sarebbe quello di controllare se forse i dati nel database è corrotto, così per dire che qualche utente possa letteralmente proprio lo stesso id univoco o lo stesso nome utente/applicazione/isanonymous combinazione.Questo può essere escluso se uniqueid è una chiave primaria.

Ogni volta che questi tipi di problema accadere ... Ho visto le seguenti circostanze come le cause ...

  1. Cache
  2. Le variabili statiche

Puoi provare a scrivere questo codice senza variabili statiche e verificare se il problema si risolve?

Saluti, Rahul

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top