IIS पर चल रहे ASP.NET कोर अनुप्रयोगों के लिए सत्र टाइमआउट बढ़ाना

पेज अद्यतन :
पेज निर्माण की तारीख :

ऑपरेशन सत्यापन वातावरण

विजुअल स्टूडियो
  • विजुअल स्टूडियो 2022
ASP.NET कोर
  • 8 (रेजर पेज, एमवीसी)
विंडोज सर्वर
  • 2022
आईआईएस
  • 10.0

परिचालन का वातावरण

हमने सभी मामलों में इसका परीक्षण नहीं किया है, लेकिन इसे आमतौर पर निम्नलिखित परिस्थितियों में काम करना चाहिए:

विजुअल स्टूडियो
  • कुछ भी जो एक ASP.NET कोर परियोजना विकसित कर सकता है
ASP.NET कोर
  • कोई भी संस्करण (एमवीसी, रेजर पेज, एपीआई)
विंडोज सर्वर
  • Windows Server 2008 या बाद का संस्करण
आईआईएस
  • 7.0 या बाद में

पहले

ASP.NET कोर के साथ लिखे गए एप्लिकेशन "केस्ट्रेल" नामक एक साधारण सर्वर पर चलते हैं, और सत्र टाइमआउट जैसी अवधि मुख्य रूप से प्रोग्रामेटिक रूप से सेट की जाती है।

हालाँकि, यदि आप IIS पर होस्ट कर रहे हैं और एक ASP.NET कोर अनुप्रयोग चला रहे हैं, तो आप प्रोग्राम सेटिंग पर IIS में सेट मान को ओवरराइड करना चाह सकते हैं।

इस समय वर्णित निष्क्रिय समय के कारण सत्र टाइमआउट आईआईएस सेटिंग्स से प्रभावित होता है, तो चलिए इसे सेट करते हैं। हालाँकि, कृपया ध्यान दें कि सत्र का समय कई सेटिंग्स से प्रभावित होता है, इसलिए सेटिंग के आधार पर, सत्र टाइमआउट को अकेले इस सेटिंग के साथ नहीं बढ़ाया जा सकता है।

यह एक परीक्षण कार्यक्रम के साथ समझाया गया है, लेकिन यदि आप इसे सेट करने का एक त्वरित तरीका चाहते हैं, तो कृपया इस पृष्ठ के अंत में जाएं।

लॉगिन प्रोग्राम

इस बार, हम लॉगिन सत्र में ऑपरेशन की जांच करेंगे। आप अन्य सत्रों का उपयोग कर सकते हैं, लेकिन सत्रों के लिए डिफ़ॉल्ट टाइमआउट के बारे में ध्यान रखें.

लॉगिन कार्यक्रमों के लिए, निम्नलिखित युक्तियों का लगभग हमेशा उपयोग किया जाता है, इसलिए कृपया विवरण के लिए निम्नलिखित देखें। इससे कोई फर्क नहीं पड़ता कि यह रेजर पेज या एमवीसी है।

यह टिप केवल सत्र टाइमआउट के बारे में है, इसलिए मैं बाकी कोड में नहीं जाऊंगा। अपने प्रोजेक्ट से मेल खाने के लिए नामस्थान संशोधित करें।

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"); }
}

Pages/Index.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 पर परिनियोजित अनुप्रयोगों के लिए सत्र टाइमआउट की जाँच करना

अब तक, न तो प्रोग्राम और न ही आईआईएस ने सत्र टाइमआउट सेट किया है, इसलिए सब कुछ डिफ़ॉल्ट होना चाहिए। सबसे पहले, लॉग इन करें और इसे कम से कम 20 मिनट के लिए छोड़ दें, और फिर Index और पृष्ठ तक पहुंचने का Privacy प्रयास करें। आप इसे 20 मिनट तक एक्सेस कर सकते हैं, लेकिन अगर यह समय समाप्त हो जाता है, तो आपको लॉगिन पेज पर ले जाया जाना चाहिए।

IIS प्रबंधक में टाइम-आउट अवधि बढ़ाएँ

यदि आपने अपने प्रोग्राम में टाइमआउट सेट नहीं किया है, तो आपको अपने एप्लिकेशन पूल सेटिंग्स में टाइमआउट समय बढ़ाने में सक्षम होना चाहिए।

जब आप IIS प्रबंधक प्रारंभ करते हैं, तो बाईं ओर मेनू से अनुप्रयोग पूल का चयन करें। उस अनुप्रयोग पूल का चयन करें जिसका उपयोग आप अपनी साइट संचालित करने के लिए कर रहे हैं, और फिर दाईं ओर मेनू से उन्नत सेटिंग्स का चयन करें.

प्रोसेस मॉडल समूह में, आइडल टाइमआउट (मिनट) नामक एक आइटम है, इसलिए इसे मिनटों में किसी भी समय सेट करें।

सेट करने के बाद, ओके बटन से पुष्टि करें।

उसके बाद, कृपया सत्र टाइमआउट के संचालन की जांच करें। यदि आप इसे 60 मिनट पर सेट करते हैं, तो यह सफल होगा यदि आप लॉग आउट नहीं हैं, भले ही लॉग इन करने के 50 मिनट बाद पृष्ठ संक्रमण हो।

जबकि कुछ लोग सत्र टाइमआउट के बीच के समय को यथासंभव बढ़ाना चाह सकते हैं, अधिकतम जो सेट किया जा सकता है वह 29 घंटे है। यह उस समय के संगत होता है जब अनुप्रयोग पूल पुनर्नवीनीकरण किया जाता है। आप एप्लिकेशन पूल के रीसायकल समय को बढ़ाकर टाइमआउट समय भी बढ़ा सकते हैं। एक चिंता यह भी है कि उपयोग की गई मेमोरी बनी रहेगी, इसलिए यदि आप इसे बदलते हैं, तो कृपया इसे ऑपरेशन के अनुसार समायोजित करें।

इसके अलावा, भले ही आप टाइमआउट से पहले बड़ी मात्रा में समय निर्धारित करते हैं, यह अक्सर उससे पहले समय समाप्त हो जाता है। ऐसा इसलिए है क्योंकि टाइमआउट समाप्त होने से पहले अनुप्रयोग पूल को पुनर्नवीनीकरण किया जाता है, या यदि इसे कुछ समय के लिए एक्सेस नहीं किया गया है, तो यह रुकी हुई स्थिति में चला जाता है। यदि आप यह सुनिश्चित करना चाहते हैं कि सत्र निर्दिष्ट समय के लिए बनाए रखा गया है, तो आपको अन्य उपाय करने की आवश्यकता है।