Programming

ASP.NET 세션 열기 / 활성화

procodes 2020. 7. 28. 21:57
반응형

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를 추가하는 것입니다. 그렇지 않으면 Session을 사용할 수 없습니다 (= 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 파일의 일부 수정이 필요하지 않습니다. Home / Common 컨트롤러에 간단한 동작을 추가하기 만하면됩니다.

[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에서 이러한 기능을 사용하는 것 같습니다. 오래된 페이지에서 링크를 클릭하면 팝업 창에 인증 프롬프트가 표시되지만 명령 만 사용하면 작동합니다.


이 코드를 Java 스크립트 파일로 작성할 수 있습니다.

$(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에서 사용자 세션을 연장하여 세션을 갱신하거나 만료 할 수있는 옵션을 찾는 방법을 알아 보았습니다. 가장 먼저 알아야 할 것은 다른 답변 중 일부에서 진행되는이 멋진 '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에 대화 상자를 추가하는 것을 잊지 마십시오 :

        <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>

In regards to veggerby's solution, if you are trying to implement it on a VB app, be careful trying to run the supplied code through a translator. The following will work:

Imports System.Web
Imports System.Web.Services
Imports System.Web.SessionState

Public Class SessionHeartbeatHttpHandler
    Implements IHttpHandler
    Implements IRequiresSessionState

    ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable
        Get
            Return False
        End Get
    End Property

    Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
        context.Session("Heartbeat") = DateTime.Now
    End Sub
End Class

Also, instead of calling like heartbeat() function like:

 setTimeout("heartbeat()", 300000);

Instead, call it like:

 setInterval(function () { heartbeat(); }, 300000);

Number one, setTimeout only fires once whereas setInterval will fire repeatedly. Number two, calling heartbeat() like a string didn't work for me, whereas calling it like an actual function did.

And I can absolutely 100% confirm that this solution will overcome GoDaddy's ridiculous decision to force a 5 minute apppool session in Plesk!


Here JQuery plugin version of Maryan solution with handle optimization. Only with JQuery 1.7+!

(function ($) {
    $.fn.heartbeat = function (options) {
        var settings = $.extend({
            // These are the defaults.
            events: 'mousemove keydown'
            , url: '/Home/KeepSessionAlive'
            , every: 5*60*1000
        }, options);

        var keepSessionAlive = false
         , $container = $(this)
         , handler = function () {
             keepSessionAlive = true;
             $container.off(settings.events, handler)
         }, reset = function () {
             keepSessionAlive = false;
             $container.on(settings.events, handler);
             setTimeout(sessionAlive, settings.every);
         }, sessionAlive = function () {
             keepSessionAlive && $.ajax({
                 type: "POST"
                 , url: settings.url
                 ,success: reset
                });
         };
        reset();

        return this;
    }
})(jQuery)

and how it does import in your *.cshtml

$('body').heartbeat(); // Simple
$('body').heartbeat({url:'@Url.Action("Home", "heartbeat")'}); // different url
$('body').heartbeat({every:6*60*1000}); // different timeout

[Late to the party...]

Another way to do this without the overhead of an Ajax call or WebService handler is to load a special ASPX page after a given amount of time (i.e., prior to the session state time-out, which is typically 20 minutes):

// Client-side JavaScript
function pingServer() {
    // Force the loading of a keep-alive ASPX page
    var img = new Image(1, 1);
    img.src = '/KeepAlive.aspx';
}

The KeepAlive.aspx page is simply an empty page which does nothing but touch/refresh the Session state:

// KeepAlive.aspx.cs
public partial class KeepSessionAlive: System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        // Refresh the current user session
        Session["refreshTime"] = DateTime.UtcNow;
    }
}

This works by creating an img (image) element and forcing the browser to load its contents from the KeepAlive.aspx page. Loading that page causes the server to touch (update) the Session object, extending the session's expiration sliding time window (typically by another 20 minutes). The actual web page contents are discarded by the browser.

Activity on the page itself can be detected by intercepting mouse and keyboard actions for the entire page body:

// Called when activity is detected
function activityDetected(evt) {
    ...
}

// Watch for mouse or keyboard activity
function watchForActivity() {
    var opts = { passive: true };
    document.body.addEventListener('mousemove', activityDetected, opts);
    document.body.addEventListener('keydown', activityDetected, opts);
}

I cannot take credit for this idea; see: https://www.codeproject.com/Articles/227382/Alert-Session-Time-out-in-ASP-Net.

참고URL : https://stackoverflow.com/questions/1431733/keeping-asp-net-session-open-alive

반응형