문제

사용자가 일련의 다양한 ASP.Net 웹 양식에서 수행하는 일부 작업의 "상태"를 저장하고 싶습니다.상태 유지에 대한 선택은 무엇이며 각 솔루션의 장단점은 무엇입니까?

저는 Session 개체를 사용하고 있으며 몇 가지 도우미 메서드를 사용하여 개체를 강력하게 입력했습니다.

    public static Account GetCurrentAccount(HttpSessionState session)
    {
        return (Account)session[ACCOUNT];
    }

    public static void SetCurrentAccount(Account obj, HttpSessionState session)
    {
        session[ACCOUNT] = obj;
    }

나는 수많은 소스로부터 "세션이 나쁘다"는 말을 들었고 이것이 바로 이 질문의 근본 원인입니다.나는 당신이 "모범 사례"라고 생각하는 것과 그 이유를 알고 싶습니다.

도움이 되었습니까?

해결책

세션 상태에는 본질적으로 악이 없습니다.

그래도 당신을 물릴 수있는 몇 가지 사항이 있습니다.

  1. 사용자가 브라우저 뒤로 버튼을 누르면 이전 페이지로 돌아가지 만 세션 상태가 되돌아 가지 않습니다. 따라서 CurrentAccount는 원래 페이지에 있지 않을 수 있습니다.
  2. ASP.NET 프로세스는 IIS에 의해 재활용 될 수 있습니다. 이런 일이 발생하면 다음 요청은 새로운 프로세스를 시작합니다. 프로세스 세션 상태에서 기본값을 사용하는 경우 다음과 같이 사라집니다 .-(
  3. 사용자가 한동안 활성화되지 않은 경우 세션은 동일한 결과로 시간을 초과 할 수 있습니다. 이것은 불이행이 20 분으로 20 분으로 멋진 점심이 할 것입니다.
  4. 프로세스 세션 상태를 사용하려면 세션 상태에 저장된 모든 객체가 직렬화 할 수 있어야합니다.
  5. 사용자가 두 번째 브라우저 창을 엽니다면 두 번째 및 별개의 응용 프로그램이있을 것으로 예상되지만 세션 상태는 2에서 2 사이에 공유 될 가능성이 높습니다. 따라서 한 브라우저 창에서 CurrentAccount를 변경하면 다른 브라우저 창에서 동일하게됩니다.

다른 팁

양식 데이터를 임시로 저장하기위한 두 가지 선택은 먼저 각 양식의 정보를 세션 상태 변수에 저장하고 둘째는 URL 매개 변수를 사용하여 양식 정보를 전달하는 것입니다. 쿠키를 잠재적 인 세 번째 옵션으로 사용하는 것은 단순한 방문자가 쿠키를 꺼질 가능성이 높은 간단한 이유 때문에 단순히 작동하지 않습니다 (그러나 세션 쿠키에는 영향을 미치지 않습니다). 또한, 귀하의 질문의 특성에 따르면이 정보가 데이터베이스 테이블에 완전히 커밋 될 때 까지이 정보를 저장하고 싶지 않다고 가정합니다.

세션 변수를 사용하는 것은이 문제에 대한 고전적인 솔루션이지만 몇 가지 단점으로 어려움을 겪습니다. 그중에는 (1) Inproc 세션 관리를 사용하는 경우 (2) 서버 팜의 여러 서버에서 세션 변수를 공유하는 경우 많은 양의 데이터가 서버 RAM을 사용할 수 있습니다. 세션 만료에 대한 경비 (세션 변수 만 캐스트하지 말고 사용하지 마십시오. 세션이 만료 된 경우 캐스트가 오류가 발생합니다). 그러나 대부분의 응용 프로그램의 경우 세션 변수는 의심 할 여지없이가는 길입니다.

대안은 각 양식의 정보를 URL에서 전달하는 것입니다. 이 접근법의 주요 문제는 정보를 전달하는 데 매우주의해야한다는 것입니다. 예를 들어, 4 페이지로 정보를 수집하는 경우 첫 번째로 정보를 수집하고 URL에 정보를 두 번째 페이지로 전달 해야하는 페이지의 ViewState에 저장해야합니다. 그런 다음 세 번째 페이지를 호출 할 때는 두 번째 페이지와 ViewState 변수에서 양식 데이터를 수집하고 URL 등을 모두 인코딩합니다. '당신의 손에 정말 엉망이 있습니다. 또한 모든 정보는 a) URL 안전 문자열로 직렬화되고 b) 간단한 URL 기반 해킹을 방지하는 방식으로 인코딩해야한다는 점을 명심하십시오 (예 : 가격을 클리어 텍스트에 넣고 전달하는 경우 누군가가 가격을 바꿀 수 있습니다). 일종의 "세션 관리자"를 만들어 이러한 문제 중 일부를 줄이고 URL 문자열을 관리하도록 할 수 있지만 주어진 링크가 누군가의 전체 세션을 날려 버릴 가능성에 여전히 매우 민감해야합니다. 제대로 관리되지 않습니다.

결국, 나는 한 페이지에서 다음 페이지로 매우 제한된 데이터를 전달하기 위해 URL 변수 만 사용합니다 (예 : 해당 항목에 대한 링크에 인코딩 된 항목의 ID).

그렇다면 내장 세션 기능을 사용하여 사용자의 데이터를 실제로 관리한다고 가정합시다. 왜 누군가가 "세션이 악"이라고 말합니까? 음, 위에서 제시된 메모리 부하, 서버-농장 및 만료 고려 사항 외에도 효과적으로 변수 인 세션 변수에 대한 주요 비판.

다행히도 세션 변수를 신중하게 사용하면 메모리 문제를 피할 수 있습니다 (큰 항목은 데이터베이스에 큰 항목을 유지해야합니다). 서버 팜이 필요한 충분한 사이트를 실행하는 경우 ASP에 내장 된 상태를 공유 할 수있는 메커니즘이 많이 있습니다. .NET (힌트 : InProc 스토리지를 사용하지 않음).

본질적으로 나머지 세션의 단점을 피하려면 세션 데이터를 보유 할 객체와 간단한 세션 객체 관리 기능을 구현하는 것이 좋습니다. 그런 다음 페이지 클래스의 후손으로 빌드하고 모든 페이지 에이 자손 페이지 클래스를 사용하십시오. 그런 다음 페이지 클래스를 통해 세션 데이터에 강력하게 유형 된 값 세트로 액세스하는 것이 간단한 문제입니다. 객체의 필드는 강력하게 입력 된 방식으로 각 "세션 변수"에 액세스 할 수있는 방법을 제공합니다 (예 : 변수 당 하나의 필드).

이것이 당신에게 간단한 작업인지 또는 샘플 코드를 원하면 알려주십시오!

내가 아는 한, Session 이 정보를 저장하는 의도 된 방법입니다. 세션 상태는 일반적으로 기본적으로 프로세스에 저장됩니다. 여러 웹 서버가 있거나 IIS 재부팅이있는 경우 세션 상태가 손실됩니다. 이는 ASP.NET State Service 또는 SQL 데이터베이스를 사용하여 세션을 저장하여 수정할 수 있습니다. 이를 통해 사람들은 다른 웹 서버 또는 작업자 프로세스의 재활용이 발생하는 경우에도 세션을 되 찾을 수 있습니다.

불길한 명성의 이유 중 하나는 서둘러 개발자가 항목 키로 UI 코드 (도우미 클래스가 아닌)의 문자열 리터럴로 과도하게 사용했기 때문입니다. 어떤 종류의 래퍼는 비 이사 세션 사용에 대한 엔트리 레벨 요구 사항입니다.

"세션이 악한 세션"에 관해서는 ... 고전 ASP에서 발전하고 있다면 동의해야하지만 ASP.NET/IIS는 훨씬 더 나은 일을합니다.

실제 질문은 상태를 유지하는 가장 좋은 방법입니다. 우리의 경우 현재 로그인 한 사용자와 관련하여 해당 객체를 세션에 저장합니다. 지속적으로 그들의 이름, 이메일 주소, 승인 등에 대해 참조.

다른 작은 tidbits 장기적인 지속성이 필요없는 정보의 쿠키와 뷰 스테이트의 조합을 사용합니다.

웹 애플리케이션에서 전역적으로 액세스할 수 있는 정보를 저장하려는 경우 이를 수행하는 방법은 다음과 같습니다. ThreadStatic 기인하다.이것은 static 회원 Class 현재 스레드가 공유하지만 다른 스레드는 공유하지 않는 멤버로 변경됩니다.장점 ThreadStatic 웹 컨텍스트를 사용할 필요가 없다는 것입니다.예를 들어, 참조하지 않는 백엔드가 있는 경우 System.Web, 하지만 거기에서도 정보를 공유하고 싶다면 사용자의 id 모든 요청의 시작 부분에 ThreadStatic 속성에 액세스할 필요 없이 종속성에서 이를 참조합니다. Session 물체.

이 때문에 static 그러나 단일 스레드에 대해서만 다른 동시 방문자가 우리 세션을 얻지 못하도록 보장합니다.모든 요청에 ​​대해 속성이 재설정되는지 확인하는 한 이는 작동합니다.이는 쿠키와 이상적인 동반자가 됩니다.

이 경우 세션 객체를 사용하는 것이 괜찮다고 생각하지만 오랫동안 브라우저 활동이 없으면 세션이 만료 될 수 있다는 것을 기억해야합니다 (httpsessionstate.timeout 속성은 몇 분 동안 세션-국가 제공 업체가 세션을 종료하는지 결정하므로 반품 전에 가치 존재를 확인하는 것이 좋습니다.

public static Account GetCurrentAccount(HttpSessionState session)
{
    if (Session[ACCOUNT]!=null)
        return (Account)Session[ACCOUNT];
    else
        throw new Exception("Can't get current account. Session expired.");
}

다음 요청까지만 살아야하는 단기 정보는 또한 ViewState. 즉, 객체가 직렬화되어 브라우저로 전송 된 페이지에 저장된 후 클릭 이벤트 또는 이와 유사한 클릭 이벤트에서 서버에 다시 게시됩니다. 그럼 ViewState 디코딩되어 다시 물체로 바뀌어 검색 할 준비가되었습니다.

세션은 사악하지 않으며 ASP.NET 응용 프로그램에서 중요한 기능을 제공하며 사용자의 "세션"중에 여러 페이지간에 공유 해야하는 데이터를 제공합니다. 몇 가지 제안이 있습니다. 가능한 경우 SQL 세션 관리를 사용하고 세션 컬렉션에서 사용중인 객체가 "직렬화 가능"하는지 확인합니다. 모범 사례는 페이지에서 상태 정보를 절대적으로 공유해야 할 때 세션 객체를 사용하고 필요하지 않을 때는 사용하지 않는 것입니다. 정보는 사용 가능한 클라이언트 측면이되지 않으며, 세션 키는 쿠키 또는 쿼리 문자열을 통해 또는 구성 방법에 따라 다른 방법을 사용한 다음 세션 객체를 데이터베이스 테이블에서 사용할 수 있습니다 ( Inproc을 사용하지 않는 한,이 경우 세션은 사이트 재 장전 중에 날아갈 가능성이 있거나 대부분의 군집 환경에서 거의 쓸모가 없습니다).

나는 "악"이 세션을 과도하게 사용하는 것에서 나온다고 생각합니다. 당신이 그냥 모든 것을 붙잡고 있다면 (모든 것을 위해 글로벌 변수를 사용하는 것과 같이) 성능이 좋지 않고 엉망이 될 것입니다.

세션 객체에 넣은 것은 세션이 정리되지 않는 한 세션 기간 동안 유지됩니다. InProc 및 StatesErver를 사용하여 저장된 메모리 관리가 필요하면 필요한 것보다 일찍 확장해야합니다. 세션에서 세션/사용자에 대한 ID 만 저장하고 헬퍼 클래스를 사용하여 필요한 캐시 객체에 필요한 것을로드하십시오. 그렇게하면 우리가 사용한 데이터가 얼마나 자주 사용되었는지에 따라 수명을 미세 조정할 수 있습니다. ASP.NET의 다음 버전에는 분산 캐시 (소문)가있을 수 있습니다.

악으로서의 세션 : ASP.net이 아닌 제대로 구성되었습니다. 그렇습니다. 가능한 한 무국적이지 않은 것이 이상적이지만 현실은 여기서 갈 수 없다는 것입니다. 그러나 세션이 영향을 줄이는 방식 (특히 Stateserver 또는 Database 세션)을 적용 할 수 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top