2016-09-19 3 views
2

여러 장치 로그 아웃 기능을 구현했습니다. 누군가가 다른 장치에 로그인 한 것보다 한 장치에서 암호를 변경하는 경우 다른 페이지를 클릭하여 자동으로 로그 아웃해야합니다.로드 균형 조정 환경에서 정적 변수가 작동하지 않습니다.

다음은 내가 구현 한 접근 방식입니다. 1 단계 : 나는 이것을 달성하기 위해 아래의 정적 클래스를 만들었습니다.

enter code herepublic static class SessionStateStoreProvider 
{  
    public static List<SessionStateList> sessionStateProviderList; 
    static SessionStateStoreProvider() 
    { 
     sessionStateProviderList = new List<SessionStateList>(); 
    }   
} 


public class SessionStateList 
{ 
    public string UserName { get; set; } 
    public string GUID { get; set; } 

} 

2 단계 : 성공적으로 로그인 할 때마다 SessionStateStoreProvider 클래스에 저장합니다.

  Guid sessionIdentifier = Guid.NewGuid();     
      SessionStateList objSessionState = new SessionStateList(); 
      objSessionState.GUID = Convert.ToString(sessionIdentifier); 
      objSessionState.UserName = userName; 
      SessionStateStoreProvider.sessionStateProviderList.Add(objSessionState);     
      Session["SessionIdentifier"] = Convert.ToString(sessionIdentifier); 

3 단계 : 암호를 성공적으로 변경하면 사용자와 관련된 모든 Guid가 제거됩니다.

 SessionStateStoreProvider.sessionStateProviderList.RemoveAll(x => x.UserName == userName); 

4 단계 : 사용자 요청이 유효한지 확인하는 HTTP 모듈을 하나 생성했습니다.

string sessionIdentifier = Convert.ToString(HttpContext.Current.Session["SessionIdentifier"]); 
     string userName = HttpContext.Current.User.Identity.Name; 
     List<SessionStateList> stateList = SessionStateStoreProvider.sessionStateProviderList; 
     bool isValidSession = false; isValidSession = stateList.Any(cus => cus.GUID == sessionIdentifier); 
     if (isValidSession == false) 
     { 
    FederatedAuthentication.SessionAuthenticationModule.SignOut(); 
     } 

내 테스트에는 정상적으로 작동합니다. 모든 요청을 처리하는 서버가 하나뿐이므로 사전에 추가하십시오. 그러나 웹 요청을 처리하는 3 개의 다른 WFE가 있으므로 실제 제작 환경에서는 작동하지 않습니다. 내 로그에서 각 로그인 요청이 다른 WFE에 의해 처리되고 있음을 발견했습니다. 동시에 4 개의 다른 브라우저로 로그인했지만 SessionStateProviderList는 하나의 활성 세션 만 기록했습니다.

int numberOfActiveSession = 0; 
numberOfActiveSession = Convert.ToInt32(SessionStateStoreProvider.sessionStateProviderList.FindAll(x => x.UserName == userName).Count); 

이 시나리오는 어떻게 처리합니까? 어떤 접근 방식을 따라야합니까? 캐싱이이 문제의 해결책입니까? 도움을 주시면 감사하겠습니다.

답변

1

정적 변수는 하나의 풀과 풀의 한 프로세스 내에서 과 동일합니다.

프로세스간에 데이터를 공유하려면 공통 데이터베이스 파일 또는 공용 공유 메모리이 필요합니다. 둘 다 모든 풀/컴퓨터/프로세스에서 액세스하는 중앙 컴퓨터에 있어야합니다.

redis은이를 위해 사용되는 오픈 소스 인 메모리 데이터 구조 저장소입니다. 또한 MS SQL 2016은 빠른 액세스를 위해 메모리 내 데이터를 사용한다는 것을 광고합니다.

좀 더

는 정적 변수에 대한 읽기 : Lifetime of ASP.NET Static Variable

+1

내 관심사는 내가 모든 요청에 ​​데이터베이스에 충돌하지 않으려는 것입니다. –

+0

@SavanPatel 당신과 다른 많은 사람들 - 그러나 이것이 유일한 방법입니다. Redis는 빠른 메모리 내 데이터 구조를위한 방법이며, MS SQL 2016은 비슷한 기능을 가지고 있습니다. 메모리에 데이터를 저장하고 너무 많은 IO 디스크를 사용하지 마십시오. 모든 경우에 하나의 중앙 컴퓨터를 사용하여 해당 데이터베이스를 처리하고 호출해야합니다 그들. – Aristos

+0

Aristos에 대한 제안에 감사드립니다. 나는 redis를 조사 할 것이다. –