Seanso skirtojo laiko padidinimas ASP.NET pagrindinėms programoms, veikiančioms IIS
Veikimo tikrinimo aplinka
- Vizualinė studija
-
- "Visual Studio 2022"
- ASP.NET branduolys
-
- 8 (skustuvo puslapiai, MVC)
- "Windows" serveris
-
- 2022
- IIS
-
- 10.0
Darbo aplinka
Mes ne visais atvejais jį išbandėme, tačiau jis paprastai turėtų veikti šiomis sąlygomis:
- Vizualinė studija
-
- Viskas, kas gali sukurti "ASP.NET Core" projektą
- ASP.NET branduolys
-
- Bet kuri versija (MVC, "Razor" puslapiai, API)
- "Windows" serveris
-
- "Windows Server 2008" arba naujesnė versija
- IIS
-
- 7.0 arba naujesnė versija
Iš pradžių
Programos, parašytos naudojant "ASP.NET Core", veikia paprastame serveryje, vadinamame "Kestrel", o trukmė, pvz., Seanso skirtasis laikas, daugiausia nustatoma programiškai.
Tačiau jei nuomojate išteklius IIS ir naudojate "ASP.NET Core" taikomąją programą, galbūt norėsite perrašyti IIS nustatytą reikšmę per programinį parametrą.
Šį kartą aprašytam seanso skirtajam laikui dėl neveikos laiko įtakos turi IIS nustatymai, todėl nustatykime šį. Tačiau atminkite, kad seanso laikui įtakos turi keli nustatymai, todėl, atsižvelgiant į nustatymą, seanso skirtasis laikas negali būti pratęstas vien naudojant šį nustatymą.
Tai paaiškinama bandomąja programa, bet jei norite greito būdo ją nustatyti, pereikite prie šio puslapio pabaigos.
Prisijungimo programos
Šį kartą mes patikrinsime operaciją prisijungimo sesijoje. Galite naudoti kitus seansus, tačiau atkreipkite dėmesį į numatytąjį seansų skirtąjį laiką.
Prisijungimo programoms beveik visada naudojami šie patarimai, todėl išsamesnės informacijos ieškokite toliau. Nesvarbu, ar tai "Razor Pages", ar MVC.
Šis patarimas skirtas tik seanso skirtajam laikui, todėl nesigilinsiu į likusį kodą. Modifikuokite vardų sritį, kad ji atitiktų jūsų projektą.
"Razor Pages" projekto kodas
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();
Puslapiai / paskyra / 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);
}
}
}
Puslapiai/Paskyra/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"); }
}
Puslapiai/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>
Puslapiai/Bendrinama/_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">
© 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 projekto kodas
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();
Modeliai/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; } = "";
}
}
Valdikliai / 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));
}
}
}
Peržiūros/Paskyra/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"); }
}
Peržiūros/Pagrindinis/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>
Peržiūros/Bendrinama/_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">
© 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>
Operacijos tikrinimas derinant
Patikrinkite prisijungimo elgseną ir įsitikinkite, kad negalite pasiekti kitų puslapių, jei nesate prisijungę. Skirtojo laiko laikas, kai derinama vietoje, skiriasi nuo tada, kai veikia IIS, todėl derinant nereikia tikrinti skirtojo laiko.
Programų diegimas IIS
Nustatykite IIS ir įdiekite sukurtą programą. IIS nustatymas čia neaptariamas, nes jis būtų nereikalingas. Išsamių paaiškinimų ieškokite toliau pateiktuose patarimuose ir kitoje informacijoje.
- Informacinių interneto paslaugų (IIS) nustatymas "Windows Server"
- Nuotolinis pagrindinių programų ASP.NET publikavimas IIS žiniatinklio serveryje internete
IIS įdiegtų taikomųjų programų seanso skirtojo laiko tikrinimas
Iki šiol nei programa, nei IIS nenustatė sesijos skirtojo laiko, todėl viskas turėtų būti numatytoji.
Pirmiausia prisijunkite ir palikite jį mažiausiai 20 minučių, tada Index
pabandykite pasiekti ir Privacy
puslapį.
Jį galite pasiekti iki 20 minučių, bet jei baigiasi laikas, turėtumėte būti nukreipti į prisijungimo puslapį.
Skirtojo laiko laikotarpio pratęsimas IIS tvarkytuve
Jei programoje nenustatėte skirtojo laiko, turėtumėte turėti galimybę pratęsti skirtojo laiko laiką savo programų telkinio nustatymuose.
Paleidę IIS tvarkytuvą, kairėje esančiame meniu pasirinkite Programų telkiniai. Pasirinkite taikomųjų programų telkinį, kurį naudojate svetainei valdyti, tada dešinėje esančiame meniu pasirinkite Išplėstiniai parametrai.
Grupėje Proceso modelis yra elementas, vadinamas Neveikos skirtasis laikas (minutėmis), todėl nustatykite bet kokį laiką minutėmis.
Po nustatymo patvirtinkite mygtuku Gerai.
Po to patikrinkite seanso skirtojo laiko veikimą. Jei nustatysite jį į 60 minučių, jis bus sėkmingas, jei nebūsite atsijungę, net jei puslapis pereis praėjus 50 minučių po prisijungimo.
Nors kai kurie žmonės gali norėti kuo labiau pailginti laiką tarp seanso skirtojo laiko, maksimalus kiekis, kurį galima nustatyti, yra 29 valandos. Tai atitinka laiką, kai taikomųjų programų telkinys yra perdirbamas. Taip pat galite pratęsti skirtojo laiko laiką pratęsdami programų telkinio apdorojimo laiką. Taip pat nerimaujama, kad naudojama atmintis ir toliau išliks, todėl, jei ją pakeisite, sureguliuokite ją pagal operaciją.
Be to, net jei nustatote daug laiko prieš pasibaigiant skirtajam laikui, jis dažnai baigiasi prieš tai. Taip yra todėl, kad programų telkinys perdirbamas prieš pasibaigiant skirtajam laikui arba jis pereina į pristabdytą būseną, jei kurį laiką nebuvo pasiekiamas. Jei norite įsitikinti, kad seansas palaikomas tam tikrą laiką, turite imtis kitų priemonių.