[c#] ASP.NET 세션을 개방 / 활성 유지

사용자가 브라우저 창을 열어 두는 한 ASP.NET 세션을 유지하는 가장 쉽고 눈에 띄지 않는 방법은 무엇입니까? 정기 AJAX 호출입니까? 다음을 방지하고 싶습니다. 때때로 사용자는 창을 오랫동안 열어 둔 다음 항목을 입력하고 제출할 때 서버 측 세션이 만료 되었기 때문에 더 이상 작동하지 않습니다. 닫힌 세션 (브라우저 창을 닫음)이 빠르게 시간 초과되기를 원하므로 서버에서 10 분 이상 시간 초과 값을 늘리고 싶지 않습니다.

제안, 코드 샘플?



답변

JQuery를 사용하여 세션을 유지하는 것 외에는 아무것도하지 않는 더미 HTTP 핸들러에 대한 간단한 AJAX 호출을 수행합니다.

function setHeartbeat() {
    setTimeout("heartbeat()", 5*60*1000); // every 5 min
}

function heartbeat() {
    $.get(
        "/SessionHeartbeat.ashx",
        null,
        function(data) {
            //$("#heartbeat").show().fadeOut(1000); // just a little "red flash" in the corner :)
            setHeartbeat();
        },
        "json"
    );
}

세션 핸들러는 다음과 같이 간단 할 수 있습니다.

public class SessionHeartbeatHttpHandler : IHttpHandler, IRequiresSessionState
{
    public bool IsReusable { get { return false; } }

    public void ProcessRequest(HttpContext context)
    {
        context.Session["Heartbeat"] = DateTime.Now;
    }
}

핵심은 IRequiresSessionState를 추가하는 것입니다. 그렇지 않으면 세션을 사용할 수 없습니다 (= null). 물론 일부 데이터를 호출하는 JavaScript로 반환해야하는 경우 핸들러는 JSON 직렬화 된 객체를 반환 할 수도 있습니다.

web.config를 통해 제공 :

<httpHandlers>
    <add verb="GET,HEAD" path="SessionHeartbeat.ashx" validate="false" type="SessionHeartbeatHttpHandler"/>
</httpHandlers>

추가balexandre 2012 년 8 월 14 일에

이 예제를 너무 좋아해서 HTML / CSS와 비트 부분을 개선하고 싶습니다.

이것을 변경

//$("#heartbeat").show().fadeOut(1000); // just a little "red flash" in the corner :)

으로

beatHeart(2); // just a little "red flash" in the corner :)

추가

// beat the heart 
// 'times' (int): nr of times to beat
function beatHeart(times) {
    var interval = setInterval(function () {
        $(".heartbeat").fadeIn(500, function () {
            $(".heartbeat").fadeOut(500);
        });
    }, 1000); // beat every second

    // after n times, let's clear the interval (adding 100ms of safe gap)
    setTimeout(function () { clearInterval(interval); }, (1000 * times) + 100);
}

HTML 및 CSS

<div class="heartbeat">&hearts;</div>

/* HEARBEAT */
.heartbeat {
    position: absolute;
    display: none;
    margin: 5px;
    color: red;
    right: 0;
    top: 0;
}

다음은 구타 부분에 대한 실제 예 입니다. http://jsbin.com/ibagob/1/


답변

ASP.NET MVC를 사용하는 경우 추가 HTTP 처리기 및 web.config 파일의 일부 수정이 필요하지 않습니다. 필요한 모든 것 – 홈 / 공통 컨트롤러에 몇 가지 간단한 동작을 추가하기 만하면됩니다.

[HttpPost]
public JsonResult KeepSessionAlive() {
    return new JsonResult {Data = "Success"};
}

, 다음과 같은 JavaScript 코드를 작성하십시오 (사이트의 JavaScript 파일 중 하나에 넣었습니다).

var keepSessionAlive = false;
var keepSessionAliveUrl = null;

function SetupSessionUpdater(actionUrl) {
    keepSessionAliveUrl = actionUrl;
    var container = $("#body");
    container.mousemove(function () { keepSessionAlive = true; });
    container.keydown(function () { keepSessionAlive = true; });
    CheckToKeepSessionAlive();
}

function CheckToKeepSessionAlive() {
    setTimeout("KeepSessionAlive()", 5*60*1000);
}

function KeepSessionAlive() {
    if (keepSessionAlive && keepSessionAliveUrl != null) {
        $.ajax({
            type: "POST",
            url: keepSessionAliveUrl,
            success: function () { keepSessionAlive = false; }
        });
    }
    CheckToKeepSessionAlive();
}

, JavaScript 함수를 호출하여이 기능을 초기화합니다.

SetupSessionUpdater('/Home/KeepSessionAlive');

참고하십시오! 권한이있는 사용자 (대부분의 경우 게스트의 세션 상태를 유지할 이유가 없음)에 대해서만이 기능을 구현했으며 세션 상태를 활성 상태로 유지하기위한 결정은 브라우저가 열려 있는지 여부뿐만 아니라 권한이 부여 된 사용자가 일부 활동을 수행해야합니다. (마우스를 움직이거나 키를 입력).


답변

서버에 요청을 할 때마다 세션 시간 초과가 재설정됩니다. 따라서 서버의 빈 HTTP 핸들러에 ajax 호출을 할 수 있지만 핸들러의 캐시가 비활성화되어 있는지 확인하십시오. 그렇지 않으면 브라우저가 핸들러를 캐시하고 새 요청을 만들지 않습니다.

KeepSessionAlive.ashx.cs

public class KeepSessionAlive : IHttpHandler, IRequiresSessionState
    {

        public void ProcessRequest(HttpContext context)
        {
            context.Response.Cache.SetCacheability(HttpCacheability.NoCache);
            context.Response.Cache.SetExpires(DateTime.UtcNow.AddMinutes(-1));
            context.Response.Cache.SetNoStore();
            context.Response.Cache.SetNoServerCaching();
        }
    }

.JS :

window.onload = function () {
        setInterval("KeepSessionAlive()", 60000)
}

 function KeepSessionAlive() {
 url = "/KeepSessionAlive.ashx?";
        var xmlHttp = new XMLHttpRequest();
        xmlHttp.open("GET", url, true);
        xmlHttp.send();
        }

@veggerby-세션에 변수를 저장하는 오버 헤드가 필요하지 않습니다. 서버에 요청을 미리 작성하는 것으로 충분합니다.


답변

세션을 유지해야합니까 (데이터가 있습니까?) 아니면 요청이 들어올 때 세션을 다시 인스턴스화하여이를 위조 할 수 있습니까? 첫 번째 인 경우 위의 방법을 사용하십시오. 두 번째 경우 Session_End 이벤트 처리기를 사용하는 것과 같은 방법을 시도하십시오.

양식 인증이있는 경우 Global.asax.cs에서 다음과 같은 것을 얻을 수 있습니다.

FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(formsCookie.Value);
if (ticket.Expired)
{
    Request.Cookies.Remove(FormsAuthentication.FormsCookieName);
    FormsAuthentication.SignOut();
    ...
     }
else
{   ...
    // renew ticket if old
    ticket = FormsAuthentication.RenewTicketIfOld(ticket);
    ...
     }

그리고 세션 수명보다 훨씬 더 긴 티켓 수명을 설정합니다. 인증하지 않거나 다른 인증 방법을 사용하는 경우 유사한 트릭이 있습니다. Microsoft TFS 웹 인터페이스와 SharePoint는 이러한 기능을 사용하는 것 같습니다. 오래된 페이지의 링크를 클릭하면 팝업 창에 인증 프롬프트가 표시되지만 명령 만 사용하면 작동합니다.


답변

이 코드를 자바 스크립트 파일에 작성할 수 있습니다.

$(document).ready(function () {
        var delay = (20-1)*60*1000;
        window.setInterval(function () {
            var url = 'put the url of some Dummy page';
            $.get(url);
        }, delay);
});

(20-1)*60*1000이 세션 제한 시간을 새로 고쳐집니다, 새로 고침 시간입니다. 새로 고침 시간 제한은 iis = 20 분 중 기본 시간으로 계산됩니다. 즉, 20 × 60000 = 1200000 밀리 초-60000 밀리 초 (세션 만료 1 분 전)가 1140000입니다.


답변

다음은 클라이언트 PC가 절전 모드로 전환되는 경우 살아남 아야하는 대체 솔루션입니다.

로그인 한 사용자가 많으면 서버 메모리를 많이 소모 할 수 있으므로주의해서 사용하십시오.

로그인 후 (로그인 제어의 LoggedIn 이벤트에서 수행)

Dim loggedOutAfterInactivity As Integer = 999 'Minutes

'Keep the session alive as long as the authentication cookie.
Session.Timeout = loggedOutAfterInactivity

'Get the authenticationTicket, decrypt and change timeout and create a new one.
Dim formsAuthenticationTicketCookie As HttpCookie = _
        Response.Cookies(FormsAuthentication.FormsCookieName)

Dim ticket As FormsAuthenticationTicket = _
        FormsAuthentication.Decrypt(formsAuthenticationTicketCookie.Value)
Dim newTicket As New FormsAuthenticationTicket(
        ticket.Version, ticket.Name, ticket.IssueDate,
        ticket.IssueDate.AddMinutes(loggedOutAfterInactivity),
        ticket.IsPersistent, ticket.UserData)
formsAuthenticationTicketCookie.Value = FormsAuthentication.Encrypt(newTicket)


답변

사용자에게 세션을 갱신하거나 만료 할 수있는 옵션을 제공하는 팝업 대화 상자를 통해 WebForms에서 사용자 세션을 연장하는 방법을 알아 내려고 며칠을 보냈습니다. 알아야 할 # 1은 다른 답변에서 진행되는이 멋진 ‘HttpContext’가 필요하지 않다는 것입니다. 필요한 것은 jQuery의 $ .post (); 방법. 예를 들어 디버깅하는 동안 다음을 사용했습니다.

$.post("http://localhost:5562/Members/Location/Default.aspx");

라이브 사이트에서 다음과 같이 사용합니다.

$.post("http://mysite/Members/Location/Default.aspx");

그것만큼 쉽습니다. 또한 사용자에게 세션을 갱신 할 것인지 묻는 메시지를 표시하려면 다음과 같이하십시오.

    <script type="text/javascript">
    $(function () {
        var t = 9;
        var prolongBool = false;
        var originURL = document.location.origin;
        var expireTime = <%= FormsAuthentication.Timeout.TotalMinutes %>;

        // Dialog Counter
        var dialogCounter = function() {
            setTimeout( function() {
                $('#tickVar').text(t);
                    t--;
                    if(t <= 0 && prolongBool == false) {
                        var originURL = document.location.origin;
                        window.location.replace(originURL + "/timeout.aspx");
                        return;
                    }
                    else if(t <= 0) {
                        return;
                    }
                    dialogCounter();
            }, 1000);
        }

        var refreshDialogTimer = function() {
            setTimeout(function() {
                $('#timeoutDialog').dialog('open');
            }, (expireTime * 1000 * 60 - (10 * 1000)) );
        };

        refreshDialogTimer();

        $('#timeoutDialog').dialog({
            title: "Session Expiring!",
            autoOpen: false,
            height: 170,
            width: 350,
            modal: true,
            buttons: {
                'Yes': function () {
                    prolongBool = true;
                    $.post("http://localhost:5562/Members/Location/Default.aspx");
                    refreshDialogTimer();
                    $(this).dialog("close");
                },
                Cancel: function () {
                    var originURL = document.location.origin;
                    window.location.replace(originURL + "/timeout.aspx");
                }
            },
            open: function() {
                prolongBool = false;
                $('#tickVar').text(10);
                t = 9;
                dialogCounter();
            }
        }); // end timeoutDialog
    }); //End page load
</script>

html에 Dialog를 추가하는 것을 잊지 마십시오.

        <div id="timeoutDialog" class='modal'>
            <form>
                <fieldset>
                    <label for="timeoutDialog">Your session will expire in</label>
                    <label for="timeoutDialog" id="tickVar">10</label>
                    <label for="timeoutDialog">seconds, would you like to renew your session?</label>
                </fieldset>
            </form>
        </div>