プロファイルシステム:ユーザーは同じIDを共有します
-
23-09-2019 - |
質問
私は自分のサイトが重い負荷にかかっているときに私のサイトに奇妙な影響を及ぼします。
他のユーザー設定のプロパティをランダムに取得します。プロファイルシステムの独自の実装があるので、プロファイルシステム自体を責めることはできないと思います。
デバッグを開始するポイントが必要です。どこかにプロファイルエントリにマッピングする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
正しい解決策はありません
他のヒント
私はこれを深く見ていませんでしたが、一つのことが私に飛び出しました。
あなたの場所で条項が変わります
@IsAnonymous = null
に
@IsAnonymous IS NULL
@isanonymousがnullであるとき、あなたは何をしたいですか? Where句にいくつかの括弧を追加する必要があるかもしれません。
SELECT UniqueID FROM dbo.Profiles
WHERE Username = @Username
AND ApplicationName = @ApplicationName
AND (IsAnonymous = @IsAnonymous OR @IsAnonymous IS NULL)
同じプロファイルデータを受け取った2人のユーザーはいますか?もしそうなら、そこから始めてください。最初に保存されたProcを通過します。簡単で迅速に行うことができます。
これは、トラブルシューティングが非常に難しいタイプの問題です。 ASP.NETアプリ(MVCではなく)で同様の問題がありました。 ASP.NETプロファイルシステムを完全にバイパスするために、個別のCookieを設定してユーザーを識別することから始めることをお勧めします。その後、そのCookieのIDがプロファイルのIDと一致するかどうかを確認できます。そうでない場合は、1)ユーザーをログアウトして、少なくとも他の人のデータにアクセスできないため、2)診断情報を収集します - 完全なHTTPリクエストの詳細は開始です。それがいかなる種類のパターンを確立しない場合、ユーザーによるすべてのHTTP要求のログを開始して、リクエスト履歴に問題を再現するのに役立つパターンがあるかどうかを確認できます。
私たちの場合、この問題は愚かな自家製のキャッシュメカニズムになりました。アプリケーションは、ASP.NETの静的ファイル(例:画像)をキャッシュしようとし、Cookieはそれらでキャッシュされました。重い負荷の下で、ユーザーは他のユーザーのCookieで画像をロードし、他のユーザーのIDを想定する場合があります。あなたのケースは完全に異なるかもしれませんが、これはあなたに探すべきもののいくつかの手がかりを与えるかもしれません。
あなたの質問にコメントを読んだ後、ここにあなたが探しているものです
$(function(){
$('input:radio[id="<?php echo $action; ?>"]').attr('checked','checked');
});
.
href="http://jsfiddle.net/selty/" rel="nofollow"> http://jsfiddle.net/selty/
あなたが望むものをする方法はたくさんあります!
これは簡単な方法です:
あなたのASPXページでは、GridViewコントロールを追加できます。それはあなたが指定した列を指定したものを表示します! 私はそれをグリッドと呼び、私はすべての列を表示したくないがむしろ数の列だけでなくカスタムリストを構築しました:
<div style=" position:relative">
<asp:GridView ID="grid" runat="server" AutoGenerateColumns="false" Width="95%" GridLines="None" AllowPaging="true" PageSize="30" CssClass="mGrid" PagerStyle-CssClass="pgr" AlternatingRowStyle-CssClass="alt" OnRowDataBound="grid_RowDataBound" OnPageIndexChanging="grid_PageIndexChanging" >
<Columns>
<asp:BoundField DataField="ID" HeaderText="Request ref" />
<asp:BoundField DataField="Title" HeaderText="Title" />
<asp:BoundField DataField="Business_x0020_area" HeaderText="Business area" />
</Columns>
</asp:GridView>
</div>
.
だから私はユーザーに表示させたい3列のものがあります.ID、タイトル、ビジネスエリア。スペースがあるため、このBusiness_x0020_area
のようなビジネスエリアがあると名前を付けていて、フィールドの内部名を呼び出すIMとして埋め込む必要があります。
すべての列を表示するだけであれば、
<div style=" position:relative">
<asp:GridView ID="grid" runat="server" AutoGenerateColumns="true" Width="95%" GridLines="None" AllowPaging="true" PageSize="30" CssClass="mGrid" PagerStyle-CssClass="pgr" AlternatingRowStyle-CssClass="alt" OnRowDataBound="grid_RowDataBound" OnPageIndexChanging="grid_PageIndexChanging" >
</asp:GridView>
</div>
.
列を自動生成された_x0020_
の代わりに列を追加しないことから、上記のAppartと同じです。
Pageingを有効にしており、1ページあたり30行の最大30行を表示します。
appx.csおよびonload関数でGridをリストにバインドできます。
protected void Page_Load(object sender, EventArgs e)
{
using (SPSite site = new SPSite("http://yoursiteurl:2013/"))
{
using (SPWeb web = site.OpenWeb("YourSubsite"))
{
SPList list = web.Lists["USER"];
SPListItemCollection items = list.Items;
grid.DataSource = items.GetDataTable();
grid.DataBind();
}
}
}
.
ページ上のロードイベントそれは特定のURLからSPSiteオブジェクトを取得すると、SPSiteからSPWebオブジェクトを取得し、リストを保持する特定のWebを開きます。
http://yoursiteurl:2013/YourSubsite
.
移動...私たちはSite Yoursubsiteのリストを持っているので、Splistオブジェクトを使って入手します。
SPList list = web.Lists["USER"];
.
上記は、AutoGenerateColumns="true"
というリストを探すために新しく作成されたSPWebを使用しているため、スプラストオブジェクトを返し、それを操作できるようにそれを呼び出します。
SPListItemCollection items = list.Items;
grid.DataSource = items.GetDataTable();
grid.DataBind();
.
リスト内のすべての項目を取得し、それをSplistItemCollectionオブジェクト内に格納したいと思うようにします。
grid.DataSource = items.GetDataTable();
.
上記のものは、ASPXページ内で作成したグリッドのデータソースとして設定するためにリストから分解可能なものです。最後に結果をバインドする必要があります:
grid.DataBind();
.
......
最後の段階はページングイベントをバインドするため、次のページをクリックすると、再バインドして正しい結果が得られます。
protected void grid_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
grid.PageIndex = e.NewPageIndex;
grid.DataBind();
}
.