Αύξηση του χρονικού ορίου περιόδου λειτουργίας για εφαρμογές πυρήνα ASP.NET που εκτελούνται στις υπηρεσίες IIS

Σελίδα ενημέρωση :
Ημερομηνία δημιουργίας σελίδας :

Περιβάλλον επαλήθευσης λειτουργίας

Οπτικό στούντιο
  • Visual Studio 2022
ASP.NET Πυρήνας
  • 8 (Σελίδες ξυραφιού, MVC)
Διακομιστής των Windows
  • 2022
IIS
  • 10.0

Περιβάλλον λειτουργίας

Δεν το έχουμε δοκιμάσει σε όλες τις περιπτώσεις, αλλά θα πρέπει να λειτουργεί γενικά υπό τις ακόλουθες συνθήκες:

Οπτικό στούντιο
  • Οτιδήποτε μπορεί να αναπτύξει ένα έργο ASP.NET Core
ASP.NET Πυρήνας
  • Οποιαδήποτε έκδοση (MVC, Razor Pages, API)
Διακομιστής των Windows
  • Windows Server 2008 ή νεότερη έκδοση
IIS
  • 7.0 ή νεότερη έκδοση

Αρχικά

Οι εφαρμογές που γράφονται με ASP.NET Core εκτελούνται σε έναν απλό διακομιστή που ονομάζεται "Kestrel" και η διάρκεια, όπως το χρονικό όριο συνεδρίας, ορίζεται κυρίως μέσω προγραμματισμού.

Ωστόσο, εάν φιλοξενείτε στις υπηρεσίες IIS και εκτελείτε μια εφαρμογή ASP.NET Core, ίσως θελήσετε να παρακάμψετε την τιμή που έχει οριστεί στις υπηρεσίες IIS μέσω της ρύθμισης προγραμματισμού.

Το χρονικό όριο περιόδου λειτουργίας λόγω του χρόνου αδράνειας που περιγράφεται αυτήν τη φορά επηρεάζεται από τις ρυθμίσεις των υπηρεσιών IIS, οπότε ας ορίσουμε αυτό. Ωστόσο, λάβετε υπόψη ότι ο χρόνος συνεδρίας επηρεάζεται από πολλές ρυθμίσεις, επομένως, ανάλογα με τη ρύθμιση, το χρονικό όριο της περιόδου λειτουργίας ενδέχεται να μην παραταθεί μόνο με αυτήν τη ρύθμιση.

Αυτό εξηγείται με ένα δοκιμαστικό πρόγραμμα, αλλά αν θέλετε έναν γρήγορο τρόπο για να το ρυθμίσετε, μεταβείτε στο τέλος αυτής της σελίδας.

Προγράμματα σύνδεσης

Αυτή τη φορά, θα ελέγξουμε τη λειτουργία στη συνεδρία σύνδεσης. Μπορείτε να χρησιμοποιήσετε άλλες περιόδους σύνδεσης, αλλά να γνωρίζετε το προεπιλεγμένο χρονικό όριο λήξης των περιόδων σύνδεσης.

Για προγράμματα σύνδεσης, χρησιμοποιούνται σχεδόν πάντα οι παρακάτω συμβουλές, επομένως ανατρέξτε στα παρακάτω για λεπτομέρειες. Δεν έχει σημασία αν είναι Razor Pages ή MVC.

Αυτή η συμβουλή αφορά μόνο τα χρονικά όρια περιόδου λειτουργίας, επομένως δεν θα μπω στον υπόλοιπο κώδικα. Τροποποιήστε το χώρο ονομάτων ώστε να ταιριάζει με το έργο σας.

Κωδικός έργου Razor Pages

Program.cs

using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authorization;

var builder = WebApplication.CreateBuilder(args);

// コンテナにサービスを追加します。
builder.Services.AddRazorPages();

// ※ここから追加

// Cookie による認証スキームを追加する
builder.Services
  .AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
  .AddCookie();

builder.Services.AddAuthorization(options =>
{
  // AllowAnonymous 属性が指定されていないすべての画面、アクションなどに対してユーザー認証が必要となる
  options.FallbackPolicy = new AuthorizationPolicyBuilder()
    .RequireAuthenticatedUser()
    .Build();
});

// ※ここまで追加

var app = builder.Build();

// HTTP リクエスト パイプラインを構成します。
if (!app.Environment.IsDevelopment())
{
  app.UseExceptionHandler("/Error");
  // デフォルトの HSTS 値は 30 日です。 運用シナリオではこれを変更することもできます。https://aka.ms/aspnetcore-hsts を参照してください。
  app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthentication(); // [追加] 認証
app.UseAuthorization(); // 認可

app.MapRazorPages();

app.Run();

Σελίδες/Λογαριασμός/Login.cshtml.cs

using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Security.Claims;

namespace SessionTimeoutExtensionIisRazorPages.Pages
{
  [AllowAnonymous]
  public class LoginModel : PageModel
  {
    /// <summary>ユーザー名。</summary>
    [BindProperty]
    [Required]
    [DisplayName("ユーザー名")]
    public string UserName { get; set; } = "";

    /// <summary>パスワード。</summary>
    [BindProperty]
    [Required]
    [DataType(DataType.Password)]
    [DisplayName("パスワード")]
    public string Password { get; set; } = "";

    /// <summary>仮のユーザーデータベースとする。</summary>
    private Dictionary<string, string> UserAccounts { get; set; } = new Dictionary<string, string>
    {
      { "user1", "password1" },
      { "user2", "password2" },
    };

    /// <summary>ログイン処理。</summary>
    public async Task<ActionResult> OnPost()
    {
      // 入力内容にエラーがある場合は処理を中断してエラー表示
      if (ModelState.IsValid == false) return Page();

      // ユーザーの存在チェックとパスワードチェック (仮実装)
      // 本 Tips は Cookie 認証ができるかどうかの確認であるため入力内容やパスワードの厳密なチェックは行っていません
      if (UserAccounts.TryGetValue(UserName, out string? getPass) == false || Password != getPass)
      {
        ModelState.AddModelError("", "ユーザー名またはパスワードが一致しません。");
        return Page();
      }

      // サインインに必要なプリンシパルを作る
      var claims = new[] { new Claim(ClaimTypes.Name, UserName) };
      var identity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
      var principal = new ClaimsPrincipal(identity);

      // 認証クッキーをレスポンスに追加
      await HttpContext.SignInAsync(principal);

      // ログインが必要な画面にリダイレクトします
      return RedirectToPage("/Index");
    }

    /// <summary>ログアウト処理。</summary>
    public async Task OnGetLogout()
    {
      // 認証クッキーをレスポンスから削除
      await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
    }
  }
}

Σελίδες/Λογαριασμός/Login.cshtml

@page
@model LoginModel
@{}

<form asp-action="Login">
  <div class="row m-1 g-3">
    <div class="col-sm-6 offset-sm-3">
      <div asp-validation-summary="ModelOnly" class="text-danger"></div>
    </div>
  </div>

  <div class="row m-1 g-3">
    <div class="col-sm-6 offset-sm-3">
      <label asp-for="UserName" class="form-label"></label>
      <input asp-for="UserName" class="form-control" value="user1" />
      <span asp-validation-for="UserName" class="text-danger"></span>
    </div>
  </div>
  <div class="row m-1 g-3">
    <div class="col-sm-6 offset-sm-3">
      <label asp-for="Password" class="form-label"></label>
      <input asp-for="Password" class="form-control" value="password1" />
      <span asp-validation-for="Password" class="text-danger"></span>
    </div>
  </div>
  <div class="row m-1 g-3">
    <div class="col-sm-6 offset-sm-3">
      <button type="submit" class="btn btn-primary">ログイン</button>
    </div>
  </div>
  <div class="row m-1 g-3">
    <div class="col-sm-6 offset-sm-3">
      <a asp-page="/Index">認証が必要な画面へ直接リンク</a>
    </div>
  </div>
</form>

@section Scripts {
  @{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); }
}

Σελίδες/Ευρετήριο.cshtml

@page
@model IndexModel
@{
  ViewData["Title"] = "Home page";
}

<div class="text-center">
  <h1 class="display-4">Welcome</h1>
  <p>Learn about <a href="https://learn.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
</div>

<p>アクセス日時:@DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")</p>

Σελίδες/Κοινόχρηστα/_Layout.cshtml

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>@ViewData["Title"] - SessionTimeoutExtensionIisRazorPages</title>
  <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
  <link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
  <link rel="stylesheet" href="~/SessionTimeoutExtensionIisRazorPages.styles.css" asp-append-version="true" />
</head>
<body>
  <header>
    <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
      <div class="container">
        <a class="navbar-brand" asp-area="" asp-page="/Index">SessionTimeoutExtensionIisRazorPages</a>
        <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" aria-controls="navbarSupportedContent"
                aria-expanded="false" aria-label="Toggle navigation">
          <span class="navbar-toggler-icon"></span>
        </button>
        <div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
          <ul class="navbar-nav flex-grow-1">
            <li class="nav-item">
              <a class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a>
            </li>
            <li class="nav-item">
              <a class="nav-link text-dark" asp-area="" asp-page="/Privacy">Privacy</a>
            </li>
            @* ここから追加 *@
            <li class="nav-item">
              <a class="nav-link text-dark" asp-page="/Account/Login" asp-page-handler="Logout">ログアウト</a>
            </li>
            <li class="nav-item">
              <a class="nav-link text-dark" asp-page="/Account/Login">ログアウトせずログインへ</a>
            </li>
            @* ここまで追加 *@
          </ul>
        </div>
      </div>
    </nav>
  </header>
  <div class="container">
    <main role="main" class="pb-3">
      @RenderBody()
    </main>
  </div>

  <footer class="border-top footer text-muted">
    <div class="container">
      &copy; 2024 - SessionTimeoutExtensionIisRazorPages - <a asp-area="" asp-page="/Privacy">Privacy</a>
    </div>
  </footer>

  <script src="~/lib/jquery/dist/jquery.min.js"></script>
  <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
  <script src="~/js/site.js" asp-append-version="true"></script>

  @await RenderSectionAsync("Scripts", required: false)
</body>
</html>

Κωδικός έργου MVC

Program.cs

using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authorization;

var builder = WebApplication.CreateBuilder(args);

// コンテナにサービスを追加します。
builder.Services.AddControllersWithViews();

// ※ここから追加

// Cookie による認証スキームを追加する
builder.Services
  .AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
  .AddCookie();

builder.Services.AddAuthorization(options =>
{
  // AllowAnonymous 属性が指定されていないすべての画面、アクションなどに対してユーザー認証が必要となる
  options.FallbackPolicy = new AuthorizationPolicyBuilder()
    .RequireAuthenticatedUser()
    .Build();
});

// ※ここまで追加

var app = builder.Build();

// HTTP リクエスト パイプラインを構成します。
if (!app.Environment.IsDevelopment())
{
  app.UseExceptionHandler("/Home/Error");
  // デフォルトの HSTS 値は 30 日です。 運用シナリオではこれを変更することもできます。https://aka.ms/aspnetcore-hsts を参照してください。
  app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthentication(); // [追加] 認証
app.UseAuthorization(); // 認可

app.MapControllerRoute(name: "default", pattern: "{controller=Home}/{action=Index}/{id?}");

app.Run();

Μοντέλα/LoginModel.cs

using System.ComponentModel;
using System.ComponentModel.DataAnnotations;

namespace SessionTimeoutExtensionIisMvc.Models
{
  public class LoginModel
  {
    /// <summary>ユーザー名。</summary>
    [Required]
    [DisplayName("ユーザー名")]
    public string UserName { get; set; } = "";

    /// <summary>パスワード。</summary>
    [Required]
    [DataType(DataType.Password)]
    [DisplayName("パスワード")]
    public string Password { get; set; } = "";
  }
}

Ελεγκτές/AccountController.cs

using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using SessionTimeoutExtensionIisMvc.Models;
using System.Security.Claims;

namespace SessionTimeoutExtensionIisMvc.Controllers
{
  /// <remarks>
  /// <see cref="AllowAnonymous"/> 属性は Cookie 認証していなくてもアクセスできる Action (Controller) であることを示す。
  /// </remarks>
  [AllowAnonymous]
  public class AccountController : Controller
  {
    /// <summary>仮のユーザーデータベースとする。</summary>
    private Dictionary<string, string> UserAccounts { get; set; } = new Dictionary<string, string>
    {
      { "user1", "password1" },
      { "user2", "password2" },
    };

    /// <summary>ログイン画面を表示します。</summary>
    public IActionResult Login() => View();

    /// <summary>ログイン処理を実行します。</summary>
    [HttpPost]
    public async Task<IActionResult> Login(LoginModel model)
    {
      // 入力内容にエラーがある場合は処理を中断してエラー表示
      if (ModelState.IsValid == false) return View(model);

      // ユーザーの存在チェックとパスワードチェック (仮実装)
      // 本 Tips は Cookie 認証ができるかどうかの確認であるため入力内容やパスワードの厳密なチェックは行っていません
      if (UserAccounts.TryGetValue(model.UserName, out string? getPass) == false || model.Password != getPass)
      {
        ModelState.AddModelError("", "ユーザー名またはパスワードが一致しません。");
        return View(model);
      }

      // サインインに必要なプリンシパルを作る
      var claims = new[] { new Claim(ClaimTypes.Name, model.UserName) };
      var identity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
      var principal = new ClaimsPrincipal(identity);

      // 認証クッキーをレスポンスに追加
      await HttpContext.SignInAsync(principal);

      // ログインが必要な画面にリダイレクトします
      return RedirectToAction(nameof(HomeController.Index), "Home");
    }

    /// <summary>ログアウト処理を実行します。</summary>
    public async Task<IActionResult> Logout()
    {
      // 認証クッキーをレスポンスから削除
      await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);

      // ログイン画面にリダイレクト
      return RedirectToAction(nameof(Login));
    }
  }
}

Προβολές/Λογαριασμός/Login.cshtml

@model LoginModel
@{}

<form asp-action="Login">
  <div class="row m-1 g-3">
    <div class="col-sm-6 offset-sm-3">
      <div asp-validation-summary="ModelOnly" class="text-danger"></div>
    </div>
  </div>

  <div class="row m-1 g-3">
    <div class="col-sm-6 offset-sm-3">
      <label asp-for="UserName" class="form-label"></label>
      <input asp-for="UserName" class="form-control" value="user1" />
      <span asp-validation-for="UserName" class="text-danger"></span>
    </div>
  </div>
  <div class="row m-1 g-3">
    <div class="col-sm-6 offset-sm-3">
      <label asp-for="Password" class="form-label"></label>
      <input asp-for="Password" class="form-control" value="password1" />
      <span asp-validation-for="Password" class="text-danger"></span>
    </div>
  </div>
  <div class="row m-1 g-3">
    <div class="col-sm-6 offset-sm-3">
      <button type="submit" class="btn btn-primary">ログイン</button>
    </div>
  </div>
  <div class="row m-1 g-3">
    <div class="col-sm-6 offset-sm-3">
      <a asp-controller="Home" asp-action="Index">認証が必要な画面へ直接リンク</a>
    </div>
  </div>
</form>

@section Scripts {
  @{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); }
}

Προβολές/Αρχική σελίδα/Index.cshtml

@{
  ViewData["Title"] = "Home Page";
}

<div class="text-center">
  <h1 class="display-4">Welcome</h1>
  <p>Learn about <a href="https://learn.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
</div>

<p>アクセス日時:@DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")</p>

Προβολές/Κοινόχρηστα/_Layout.cshtml

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>@ViewData["Title"] - SessionTimeoutExtensionIisMvc</title>
  <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
  <link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
  <link rel="stylesheet" href="~/SessionTimeoutExtensionIisMvc.styles.css" asp-append-version="true" />
</head>
<body>
  <header>
    <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
      <div class="container-fluid">
        <a class="navbar-brand" asp-area="" asp-controller="Home" asp-action="Index">SessionTimeoutExtensionIisMvc</a>
        <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" aria-controls="navbarSupportedContent"
                aria-expanded="false" aria-label="Toggle navigation">
          <span class="navbar-toggler-icon"></span>
        </button>
        <div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
          <ul class="navbar-nav flex-grow-1">
            <li class="nav-item">
              <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Index">Home</a>
            </li>
            <li class="nav-item">
              <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
            </li>
            @* ここから追加 *@
            <li class="nav-item">
              <a class="nav-link text-dark" asp-controller="Account" asp-action="Logout">ログアウト</a>
            </li>
            <li class="nav-item">
              <a class="nav-link text-dark" asp-controller="Account" asp-action="Login">ログアウトせずログインへ</a>
            </li>
            @* ここまで追加 *@
          </ul>
        </div>
      </div>
    </nav>
  </header>
  <div class="container">
    <main role="main" class="pb-3">
      @RenderBody()
    </main>
  </div>

  <footer class="border-top footer text-muted">
    <div class="container">
      &copy; 2024 - SessionTimeoutExtensionIisMvc - <a asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
    </div>
  </footer>
  <script src="~/lib/jquery/dist/jquery.min.js"></script>
  <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
  <script src="~/js/site.js" asp-append-version="true"></script>
  @await RenderSectionAsync("Scripts", required: false)
</body>
</html>

Έλεγχος της λειτουργίας με εντοπισμό σφαλμάτων

Ελέγξτε τη συμπεριφορά σύνδεσης και βεβαιωθείτε ότι δεν μπορείτε να αποκτήσετε πρόσβαση σε άλλες σελίδες αν δεν είστε συνδεδεμένοι. Ο χρόνος λήξης χρονικού ορίου κατά τον τοπικό εντοπισμό σφαλμάτων είναι διαφορετικός από την εκτέλεση στις υπηρεσίες IIS, επομένως δεν χρειάζεται να ελέγξετε το χρονικό όριο κατά τον εντοπισμό σφαλμάτων.

Ανάπτυξη προγραμμάτων στις υπηρεσίες IIS

Ρυθμίστε τις υπηρεσίες IIS και αναπτύξτε το πρόγραμμα που δημιουργήσατε. Η εγκατάσταση των υπηρεσιών IIS δεν καλύπτεται εδώ, επειδή θα ήταν περιττή. Για λεπτομερείς εξηγήσεις, ανατρέξτε στην ενότητα Συμβουλές και άλλες πληροφορίες παρακάτω.

Έλεγχος χρονικού ορίου περιόδου λειτουργίας για εφαρμογές που αναπτύσσονται στις υπηρεσίες IIS

Μέχρι στιγμής, ούτε το πρόγραμμα ούτε οι υπηρεσίες IIS έχουν ορίσει το χρονικό όριο της περιόδου λειτουργίας, επομένως όλα θα πρέπει να είναι προεπιλεγμένα. Πρώτα, συνδεθείτε και αφήστε το για τουλάχιστον 20 λεπτά και, στη συνέχεια Index , προσπαθήστε να αποκτήσετε πρόσβαση στη σελίδα and Privacy . Μπορείτε να έχετε πρόσβαση σε αυτό για έως και 20 λεπτά, αλλά αν λήξει το χρονικό όριο, θα πρέπει να μεταφερθείτε στη σελίδα σύνδεσης.

Επέκταση της περιόδου χρονικού ορίου στη Διαχείριση IIS

Εάν δεν έχετε ορίσει χρονικό όριο στο πρόγραμμά σας, θα πρέπει να μπορείτε να παρατείνετε το χρονικό όριο στις ρυθμίσεις του χώρου συγκέντρωσης εφαρμογών.

Όταν ξεκινάτε τη Διαχείριση των υπηρεσιών IIS, επιλέξτε Χώροι συγκέντρωσης εφαρμογών από το μενού στα αριστερά. Επιλέξτε το χώρο συγκέντρωσης εφαρμογών που χρησιμοποιείτε για τη λειτουργία της τοποθεσίας σας και, στη συνέχεια, επιλέξτε Ρυθμίσεις για προχωρημένους από το μενού στα δεξιά.

Στην ομάδα Μοντέλο διεργασίας, υπάρχει ένα στοιχείο που ονομάζεται Χρονικό όριο αδράνειας (λεπτά), επομένως ορίστε το σε οποιοδήποτε χρονικό διάστημα σε λεπτά.

Μετά τη ρύθμιση, επιβεβαιώστε με το OK κουμπί.

Μετά από αυτό, ελέγξτε τη λειτουργία του χρονικού ορίου της συνεδρίας. Εάν το ορίσετε σε 60 λεπτά, θα είναι επιτυχές εάν δεν αποσυνδεθείτε ακόμα και αν η σελίδα μεταβαίνει 50 λεπτά μετά τη σύνδεση.

Ενώ μερικοί άνθρωποι μπορεί να θέλουν να επεκτείνουν όσο το δυνατόν περισσότερο το χρονικό διάστημα μεταξύ των χρονικών ορίων περιόδου λειτουργίας, το μέγιστο που μπορεί να οριστεί είναι 29 ώρες. Αυτό αντιστοιχεί στο χρόνο ανακύκλωσης του χώρου συγκέντρωσης εφαρμογών. Μπορείτε επίσης να παρατείνετε το χρονικό όριο επεκτείνοντας το χρόνο ανακύκλωσης του χώρου συγκέντρωσης εφαρμογών. Υπάρχει επίσης ανησυχία ότι η χρησιμοποιούμενη μνήμη θα συνεχίσει να παραμένει, οπότε αν την αλλάξετε, προσαρμόστε την ανάλογα με τη λειτουργία.

Επίσης, ακόμα κι αν ορίσετε μεγάλο χρονικό διάστημα πριν από το χρονικό όριο, συχνά λήγει πριν από αυτό. Αυτό συμβαίνει επειδή ο χώρος συγκέντρωσης εφαρμογών ανακυκλώνεται πριν λήξει το χρονικό όριο ή μεταβαίνει σε κατάσταση παύσης, εάν δεν έχει γίνει πρόσβαση σε αυτό για λίγο. Εάν θέλετε να βεβαιωθείτε ότι η συνεδρία διατηρείται για συγκεκριμένο χρονικό διάστημα, πρέπει να λάβετε άλλα μέτρα.