활성 ASP를 모두 나열합니다.NET 세션
현재 ASP를 모두 나열(반복)하려면 어떻게 해야 합니까?NET 세션?
global.asax 이벤트 Session_Start 및 Session_End에서 세션에 대한 데이터를 수집할 수 있습니다(프로 내 설정에서만).
private static readonly List<string> _sessions = new List<string>();
private static readonly object padlock = new object();
public static List<string> Sessions
{
get
{
return _sessions;
}
}
protected void Session_Start(object sender, EventArgs e)
{
lock (padlock)
{
_sessions.Add(Session.SessionID);
}
}
protected void Session_End(object sender, EventArgs e)
{
lock (padlock)
{
_sessions.Remove(Session.SessionID);
}
}
동기화 오버헤드를 낮추기 위해 일부 동시 수집을 사용하는 것을 고려해야 합니다.ConcurrentBag 또는 ConcurrentDictionary.또는 불변 목록
https://msdn.microsoft.com/en-us/library/dd997373(v=vs.110).aspx
https://msdn.microsoft.com/en-us/library/dn467185.aspx
이 정보를 제공하는 클래스나 방법이 없다는 것은 옳지 않은 것 같습니다.SessionStateStoreProvider의 기능을 사용하면 현재 활성 세션을 반환하는 방법을 사용할 수 있으므로 Jan Remunda가 언급한 session_start 및 session_end에서 세션 수명을 능동적으로 추적할 필요가 없습니다.
저는 모든 세션 목록을 얻을 수 있는 기본적인 방법을 찾을 수 없었고, Jan이 언급한 것처럼 세션 생활을 추적하고 싶지 않았기 때문에 결국 이 솔루션을 사용하게 되었고, 이것은 제 경우에 효과가 있었습니다.
public static IEnumerable<SessionStateItemCollection> GetActiveSessions()
{
object obj = typeof(HttpRuntime).GetProperty("CacheInternal", BindingFlags.NonPublic | BindingFlags.Static).GetValue(null, null);
object[] obj2 = (object[])obj.GetType().GetField("_caches", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(obj);
for (int i = 0; i < obj2.Length; i++)
{
Hashtable c2 = (Hashtable)obj2[i].GetType().GetField("_entries", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(obj2[i]);
foreach (DictionaryEntry entry in c2)
{
object o1 = entry.Value.GetType().GetProperty("Value", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(entry.Value, null);
if (o1.GetType().ToString() == "System.Web.SessionState.InProcSessionState")
{
SessionStateItemCollection sess = (SessionStateItemCollection)o1.GetType().GetField("_sessionItems", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(o1);
if (sess != null)
{
yield return sess;
}
}
}
}
}
http://weblogs.asp.net/imranbaloch/archive/2010/04/05/reading-all-users-session.aspx
작동 방식:
InProc 세션 데이터는 Icollection을 구현하는 ISessionStateItemCollection 구현에서 HttpRuntime의 내부 캐시에 저장됩니다.이 코드에서는 우선 HttpRuntime 클래스의 CacheInternalStaticProperty를 얻은 다음 이 객체의 도움으로 I 타입인 private member를 입력했습니다.그런 다음 이 사전을 열거하고 시스템 유형의 개체만 선택합니다.웹.세션 상태.ProcSessionState에서 마침내 각 사용자에 대한 SessionStateItemCollection을 가져왔습니다.
요약:.
이 글에서는 현재 사용자 세션을 모두 얻을 수 있는 방법을 보여줍니다.그러나 이 코드를 실행할 때 한 가지는 모든 페이지 이벤트 후에 세션이 저장되므로 현재 요청 컨텍스트에 설정된 현재 사용자 세션을 표시하지 않는다는 것입니다.
ASP.net 의 최신 버전에 대한 @jiitdh의 답변과 동일한 내용을 찾고 있었습니다. 아무것도 찾을 수 없어서 v4.6.2 솔루션으로 이 스레드를 업데이트하려고 했는데...최신 버전의 .net으로 테스트하지 않았지만 v4.5에서는 작동하지 않습니다.앞으로 v4.6.1과 호환이 될 것 같습니다.
Cache cache = HttpRuntime.Cache;
MethodInfo method = typeof( System.Web.Caching.Cache ).GetMethod( "GetInternalCache", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.FlattenHierarchy );
object objx = method.Invoke( cache, new object[] { false } );
FieldInfo field = objx.GetType().GetField( "_cacheInternal", BindingFlags.NonPublic | BindingFlags.FlattenHierarchy | BindingFlags.Instance );
objx = field.GetValue( objx );
field = objx.GetType().GetField( "_cachesRefs", BindingFlags.NonPublic | BindingFlags.FlattenHierarchy | BindingFlags.Instance );
objx = field.GetValue( objx );
IList cacherefs = ( (IList)objx );
foreach( object cacheref in cacherefs )
{
PropertyInfo prop = cacheref.GetType().GetProperty( "Target", BindingFlags.FlattenHierarchy | BindingFlags.Public | BindingFlags.Instance );
object y = prop.GetValue( cacheref );
field = y.GetType().GetField( "_entries", BindingFlags.NonPublic | BindingFlags.FlattenHierarchy | BindingFlags.Instance );
Hashtable c2 = (Hashtable)field.GetValue( y );
foreach( DictionaryEntry entry in c2 )
{
object o1 = entry.Value.GetType().GetProperty( "Value", BindingFlags.NonPublic | BindingFlags.Instance ).GetValue( entry.Value, null );
if( o1.GetType().ToString() == "System.Web.SessionState.InProcSessionState" )
{
SessionStateItemCollection sess = (SessionStateItemCollection)o1.GetType().GetField( "_sessionItems", BindingFlags.NonPublic | BindingFlags.Instance ).GetValue( o1 );
if( sess != null )
{
// Do your stuff with the session!
}
}
}
}
저는 ajitdh의 답변이 정말 마음에 듭니다.그에게 투표하세요.이 솔루션에 대한 또 다른 언급은 다음과 같습니다.
http://weblogs.asp.net/imranbaloch/reading-all-users-session
이것은 저를 가깝게 만들었지만, 제가 알고 있는 특정 세션 ID의 세션을 찾는 제 개인적인 목표는 달성하지 못했습니다.그래서 저는 제 목적상 세션아이디를 세션아이템으로 추가했을 뿐입니다(Session["이라고 말함).SessionId"] = 세션입니다.세션 시작 시 SessionId.)그 다음에 일치하는 값을 가진 세션을 찾았는데...저는 컬렉션 중 하나에 색인을 붙여 이 항목을 실제로 꺼내는 것을 선호했지만, 이것이 적어도 작동하게 만들었습니다.
물론, 이 모든 것은 인프로세스 세션을 위한 것으로, 저는 정말로 이 문제에서 벗어날 것을 고려하고 있습니다.
private static SessionStateItemCollection GetSession(string sessionId)
{
object obj = typeof(HttpRuntime).GetProperty("CacheInternal", BindingFlags.NonPublic | BindingFlags.Static).GetValue(null, null);
object[] obj2 = (object[])obj.GetType().GetField("_caches", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(obj);
for (int i = 0; i < obj2.Length; i++)
{
Hashtable c2 = (Hashtable)obj2[i].GetType().GetField("_entries", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(obj2[i]);
foreach (DictionaryEntry entry in c2)
{
object o0 = entry.Value.GetType().GetProperty("Value", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(entry.Key, null);
object o1 = entry.Value.GetType().GetProperty("Value", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(entry.Value, null);
if (o1.GetType().ToString() == "System.Web.SessionState.InProcSessionState")
{
SessionStateItemCollection sess = (SessionStateItemCollection)o1.GetType().GetField("_sessionItems", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(o1);
if (sess != null)
{
if (sess["SessionId"] != null && ((string)sess["SessionId"]) == sessionId)
{
return sess;
}
}
}
}
}
return null;
}
다음은 최근 30분 이내에 활성화된 로그온한 사용자의 목록을 가져오는 WebForms/Identity 예제입니다.
아래 답변은 단일 웹 서버에 적용되며, 응용프로그램이 재시작되면 캐시가 손실됩니다.데이터를 유지하고 웹 팜의 서버 간에 공유하려는 경우 이 답변이 흥미로울 수 있습니다.
Global.asa.cs 에서:
public static ActiveUsersCache ActiveUsersCache { get; } = new ActiveUsersCache();
그리고.
protected void Application_PreRequestHandlerExecute(object sender, EventArgs e)
{
if (User != null && User.Identity.IsAuthenticated)
{
// Only update when the request is for an .aspx page
if (Context.Handler is System.Web.UI.Page)
{
ActiveUsersCache.AddOrUpdate(User.Identity.Name);
}
}
}
다음 클래스를 추가합니다.
public class ActiveUsersCache
{
private readonly object padlock = new object();
private readonly Dictionary<string, DateTime> cache = new Dictionary<string, DateTime>();
private DateTime lastCleanedAt;
public int ActivePeriodInMinutes { get; } = 30;
private const int MinutesBetweenCacheClean = 30;
public List<ActiveUser> GetActiveUsers()
{
CleanCache();
var result = new List<ActiveUser>();
lock (padlock)
{
result.AddRange(cache.Select(activeUser => new ActiveUser {Name = activeUser.Key, LastActive = activeUser.Value}));
}
return result;
}
private void CleanCache()
{
lastCleanedAt = DateTime.Now;
var cutoffTime = DateTime.Now - TimeSpan.FromMinutes(ActivePeriodInMinutes);
lock (padlock)
{
var expiredNames = cache.Where(au => au.Value < cutoffTime).Select(au => au.Key).ToList();
foreach (var name in expiredNames)
{
cache.Remove(name);
}
}
}
public void AddOrUpdate(string userName)
{
lock (padlock)
{
cache[userName] = DateTime.Now;
}
if (IsTimeForCacheCleaup())
{
CleanCache();
}
}
private bool IsTimeForCacheCleaup()
{
return lastCleanedAt < DateTime.Now - TimeSpan.FromMinutes(MinutesBetweenCacheClean);
}
}
public class ActiveUser
{
public string Name { get; set; }
public DateTime LastActive { get; set; }
public string LastActiveDescription
{
get
{
var timeSpan = DateTime.Now - LastActive;
if (timeSpan.Minutes == 0 && timeSpan.Seconds == 0)
return "Just now";
if (timeSpan.Minutes == 0)
return timeSpan.Seconds + "s ago";
return $"{timeSpan.Minutes}m {timeSpan.Seconds}s ago";
}
}
}
마지막으로 활성 사용자를 표시할 페이지에서 결과를 표시합니다.
UserRepeater.DataSource = Global
.ActiveUsersCache.GetActiveUsers().OrderByDescending(u => u.LastActive);
UserRepeater.DataBind();
내가 아는 한, 표준 인메모리 세션으로는 불가능합니다.이 문제는 지난 주에 제가 고민하던 것으로 세션 상태 서버를 사용하지 않는 한 불가능하다는 결론에 도달했습니다.디자인적인 면에서 보면 다소 이상해 보입니다. :/
당신은 또한 이것을 기본적인 것으로 시도할 수 있습니다, 이것은 단지 당신이 그 개념을 이해할 수 있도록 하기 위한 것입니다.
protected void Page_Load(object sender, EventArgs e)
{
if (Convert.ToInt32(Session["islogged"]) == 0)
{
Label1.Text = "you are not logged";
}
}
protected void logged(object sender, EventArgs e)
/* 버튼을 클릭하면 로그인 버튼이 나타나도록 버튼에 추가*/ {
Label1.Text = "you are Logged in ";
}
다음 코드를 사용해 보십시오.
for (int i = 0; i < Session.Keys.Count - 1; i++)
{
Label1.Text += Session.Keys.Get(i) + " - " + Session[i].ToString()+"<br/>";
}
언급URL : https://stackoverflow.com/questions/1470334/list-all-active-asp-net-sessions
'programing' 카테고리의 다른 글
Oracle : 다른 스키마에 테이블 생성을 허용하시겠습니까? (0) | 2023.10.09 |
---|---|
PATH - Visual Studio Code 및 Node.js에서 런타임 '노드'를 찾을 수 없습니다. (0) | 2023.10.09 |
getActivity()는 Fragment 함수에서 null을 반환합니다. (0) | 2023.10.09 |
MySQL 테이블을 많은 난수로 채우려면 어떻게 해야 합니까? (0) | 2023.10.09 |
open_files_limit Centos 7 + MariaDB 10.2 - 상한 65536 (0) | 2023.10.09 |