2013-12-18 2 views
6

응용 프로그램을 사용하는 회사의 각 컴퓨터에 대한 정비사가있는 곳에 응용 프로그램을 구현하고 있습니다. 사용자가 Machine1이라는 사용자 이름으로 "Mechanic"역할을하고 해당 컴퓨터에 로그인되어있는 경우 사용자의 컴퓨터 1 사용자 이름과 동시에 한 명의 사용자 만 로그온 할 수있는 사용자 정책을 구현하려고합니다. 회사. 다른 사용자가 동일한 사용자 이름으로 로그인하려고하면 이미 차단 된 사용자로 로그인 한 사용자에게 알려야합니다. 세션 시간 초과가 만료되면 로그인 한 사용자를 로그 아웃하고 로그인을 사용 가능하게해야합니다. 사용자가 혼자서 로그 아웃 할 때도 마찬가지입니다. 이 asp.net MVC 4 응용 프로그램을 만들려고 해요.MVC 4에서 단일 사용자 로그인하는 방법 applictaion

저는 데이터베이스에서 SessionId, UserId 및 IsLoggedIn 부울을 사용하려고 생각했습니다. 하지만이 경우 많은 사용자가 로그인 한 경우 과도하게 보인다 데이터베이스에 쓸 MVC 응용 프로그램에서 세션 제한 시간에 로그인 된 플래그를 변경해야합니다.

구현은 어떻게 될 것입니까? 데이터베이스에서 세션 관리를 처리하기 위해 사용해야하는 메소드 또는 속성은 무엇입니까?

참고

사용자가 로그인하면 내가 확인 난 내 자신의 방법을 만들었습니다

, 여기있다 : 세션 ID가있는 경우 여기에이 방법에

public static bool ValidateUser(string username, string password, string companyName) 
{ 
    int? companyId = myRepository.GetCompanyId(companyName); 

    int? userId = companyId == 0 ? null : myRepository.GetUserId(username, companyId); 

    if (userId.HasValue && userId.Value != 0) 
    { 
     var userKey = Security.GenerateUserKey(username, companyName); 
     return WebSecurity.Login(userKey, password); 
    } 
    else 
    { 
     return false; 
    } 
} 

내가 어떻게 든 확인하실 수 있습니다 데이터베이스와 동일합니다.

+1

두 사용자가 모두 사용자 그룹 이름 "Mechanic"및 동일한 계정 이름으로 로그인하는 사용자. 어느 쪽이 한 사람 정책을 기반으로합니까? 또한 한 사람이 동시에 사용할 수있는 웹 응용 프로그램의 이점이 무엇인지 궁금합니다. – Flater

+0

질문을 편집했습니다 – dlght

+1

_ "하지만이 경우에는 많은 사용자가 로그인 한 경우 과도한 것처럼 보이는 MVC 응용 프로그램의 세션 시간 제한에 로그인 된 플래그를 변경해야합니다."- 무엇을합니까? "과잉 공격"을 의미합니까? 잊어 버렸을 때 사용자를 로그 아웃 하시겠습니까? 그렇지 않습니다. 작동하지 않습니까? 당신은 그것이 효율적이지 않을까 두려워합니까?그런 식으로 구현해보십시오. [세션 종료 알림을받는 방법] (http://stackoverflow.com/questions/1413407/)을 참조하고 실제 문제가 발생했는지 여부를 확인하십시오. – CodeCaster

답변

3

나는 비슷한 일을 해왔으며 항상 관련되어 있습니다. 어떤 종류의 자물쇠 나 세마포가 필요합니다. 이것은 repo 조치로 db 측에서 수행하는 것이 가장 좋습니다.

나는 실제적인 대답으로 간주해야 할 지 모르겠다. 나는 접근 방식만큼 많이 구현하지 않을 것이기 때문이다.

접근법 1 : 일단 인증

단독 잠금와 사용자 열 고정 유지. 사용자가 로그 아웃하면 repo (EF) 연결이 재활용되고 독점 잠금이 해제됩니다.

로그인 시도로 인해 try-catch을 로그인 프로세스에서 사용해야하고 (아마도 타임 아웃을 사용해야 할 수도 있습니다)

방법 2 : 한 번 로그인

, 로그인 권한을 멀리 복용하여 사용자를 잠금 :

MembershipUser muUser = Membership.GetUser(strUsernameToActOn); 
muUser.IsApproved = false; 
Membership.UpdateUser(muUser); 

참고 :이 방법은 사용자의 잠금이 해제되어 있는지 보장의 유지 보수가 필요 로그 아웃 후. 이것은 까다로울 수 있습니다. destructor 작업 또는이 사용자가 실제로 활성화 된 마지막 시간을 확인하는 백그라운드 데몬을 사용하도록 선택할 수 있습니다.

방법 3 :

는 귀하의 사용자 레코드에 타임 스탬프를 기록했다.사용자가 임의의 조치에 대해 db를 조회 할 때마다이 시간 소인을 갱신하십시오.

로그인시에 허용 로깅보고 오프셋 합리적인와 타임 스탬프를 확인합니다. 로그 아웃에

, 빈 타임 스탬프.

방법 4

를 사용하여 A singleton 클래스 : 로그인 후, 로그인 할 수없는 사용자의 정적 목록에 사용자의 ID (또는 이름)를 추가 생성자와 인스턴스를 만듭니다.

사용자 제거 (또는 싱글 톤 인스턴스 존재)는 destructor 작업을 사용하십시오.

정적 - 싱글 톤 구동 목록에 사용자를위한 로그인을 허용하지 마십시오.

+0

Dave에게 감사드립니다. 필자는 초기 접근법 인 UserId 및 SessionId 필드가있는 테이블을 사용했습니다. 사용자 로그인시 사용자가 이미 로그인되어 있는지 확인하고 세션 아이디가 데이터베이스의 sessionId와 일치하는지 확인합니다. 로그 아웃/세션 만료시 데이터베이스에서 current와 일치하는 sessionId를 가진 사용자를 삭제합니다. – dlght

+0

여기() 함수 내 Session_End이다 보호 무효 Session_End (개체 송신자는 EventArgs E)를 사용 { (VAR의 새로운 데이터 컨텍스트 = MyRepository (새 ProjectEntities())) { 문자열 = Session.SessionID가 sessionID와; (세션 ID! = null) dataContext.Save(); } } } – dlght

3

이 문제의 핵심은 사용자가 같은 이름의 다음 사용자를 허용하기 위해 로그 아웃 한 시점을 파악하는 것입니다. 웹 응용 프로그램에서이 작업을 수행하는 정확한 방법을 모르지만 사용자 로그인 시간을 제어하여 사용자가 로그 아웃 한 시점을 대략적으로 알 수있는 방법이 있습니다. 이 테스트를 위해 타임 아웃을 1 분으로 설정 했으므로 동일한 사용자 이름으로 여러 사용자간에 빠르게 테스트 할 수있었습니다. web.config를 통해이를 제어합니다.

<forms loginUrl="~/Account/Login" timeout="1" slidingExpiration="false" /> 

언제 slidingExpiration을 false로 설정하여 로그 아웃 될지 정확히 알 수 있습니다. 슬라이딩 만료를 사용하면 물리적으로 로그 아웃 한 사용자 수를 계산할 수 없기 때문에 로그 아웃이 실제로 발생했는지 예측할 수 없습니다.

현재 로그인 한 사용자를 추적하려면 MemoryCache를 사용하고 만료 정책을 사용하여 자동으로 시간을 추적합니다. 다음은 이것을 관리하기 위해 작성한 간단한 도우미 클래스입니다.

public class UserManager 
{ 
    public static bool IsLoggedIn(string username) 
    { 
     ObjectCache cache = MemoryCache.Default; 
     return !string.IsNullOrEmpty(cache[username] as string); 

    } 

    public static void SetToLoggedIn(string username) 
    { 
     ObjectCache cache = MemoryCache.Default; 
     CacheItemPolicy policy = new CacheItemPolicy(); 
     //Expires after 1 minute. 
     policy.AbsoluteExpiration = new DateTimeOffset(DateTime.Now.AddMinutes(1)); 
     cache.Set(username, username, policy); 

    } 
} 

내가 AbsoluteExpiration을 사용하고 양식 인증을 위해 설정 한 길이로 시간 제한을 설정했음을 주목하십시오. 이것은 쓰여진 1 분 후에 캐시에서 객체를 지 웁니다. 그렇게하면 캐시에있는 개체의 존재 여부를 확인하여 사용자 로그인에 할당 된 시간이 경과했는지 여부를 확인할 수 있습니다. 캐시 된 객체의 키로 사용자 이름을 사용합니다. 왜냐하면 우리는 한 번에 그 사용자 이름을 가진 한 사용자가 시스템에 있는지 확인하고 있기 때문입니다.

이제 로그인 동작을 다음과 같이 변경합니다.

[HttpPost] 
    [AllowAnonymous] 
    [ValidateAntiForgeryToken] 
    public ActionResult Login(LoginModel model, string returnUrl) 
    { 
     if (ModelState.IsValid) 
     { 
      if (UserManager.IsLoggedIn(model.UserName)) 
      { 
       ModelState.AddModelError("", "A user with that user name is already logged in."); 
       return View(model); 
      } 
      if (WebSecurity.Login(model.UserName, model.Password, persistCookie: model.RememberMe)) 
      { 
       UserManager.SetToLoggedIn(model.UserName); 
       return RedirectToLocal(returnUrl); 
      } 
     } 

     // If we got this far, something failed, redisplay form 
     ModelState.AddModelError("", "The user name or password provided is incorrect."); 
     return View(model); 
    } 

SimpleMembership을 사용하여 MVC 4 응용 프로그램에서이를 테스트했으며 작동합니다. 이 방법으로 볼 수있는 유일한 단점은 슬라이딩 대신 절대 시간 제한이 필요하다는 것입니다. 시간 초과에 대한 올바른 설정을 얻는 것은 특정 간격으로 로그 아웃되는 사용자의 불만을 줄이고 다른 사용자가 로그인하기 위해 기다려야하는 시간을 최소화하는 데 중요합니다.

+0

사용자가 1 분 후에도 계속 로그인하면 캐시 항목이 삭제되고 로그인하면 null이 반환됩니까? 내가 뭘 놓치고 있니? –

+0

IsLoggedIn은 부울을 반환합니다. 캐시에 저장된 객체가 문자열이기 때문에 cache 객체가 있는지 여부를 string.IsNullOrEmpty를 사용하여 확인합니다. 캐시 된 오브젝트가없는 경우 캐시 정책에 설정된 해당 사용자에 대해 할당 된 시간이 만기되고 다른 시간은 만료되지 않습니다. 캐시에 할당 된 시간은 폼 인증을 위해 web.config에서 설정 한 것과 같이 사용자가 로그인 할 수있는 시간과 같습니다. –

+0

내 경우에는 메모리 캐시를 사용할 수 없습니다. 나는 기록 된 모든 사용자와 함께 SQL 테이블을 사용하여 로그인 및 Session_End()에 삭제를 추가했습니다. – dlght