Blazor Server でセッション変数を取得するサンプルを作ったので参考にしてほしい。
ソースコードはGitHubで公開しています。
ソースコード構成
Visual Studio プロジェクト の Blazor Server テンプレートに、SessionID.razor を追加し、NavMenu.razor、Startup.cs、_Imports.razor を修正しています。
ソースコード変更内容を解説
_Imports.razor
・razorページ全体で使用する using のリストに、Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage を追加し、各razorページでセッション変数を扱えるようにしている。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
@using System.Net.Http @using Microsoft.AspNetCore.Authorization @using Microsoft.AspNetCore.Components.Authorization @using Microsoft.AspNetCore.Components.Forms @using Microsoft.AspNetCore.Components.Routing @using Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage @using Microsoft.AspNetCore.Components.Web @using Microsoft.AspNetCore.Components.Web.Virtualization @using Microsoft.JSInterop @using WebApplication1 @using WebApplication1.Shared |
Startup.cs
・services.AddHttpContextAccessor() を追加し、IHttpContextAccessor を利用可能にしている。
・services.AddSession(options => ) を追加し、セッションに関係するクッキーを設定している。
Nameでクッキー名を設定。
IsEssentialでクッキーは必須と設定。
・app.UseSession() を追加し、でセッション ミドルウェアを有効にしている。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using WebApplication1.Data; namespace WebApplication1 { public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } // This method gets called by the runtime. Use this method to add services to the container. // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 public void ConfigureServices(IServiceCollection services) { services.AddRazorPages(); services.AddServerSideBlazor(); services.AddSingleton<WeatherForecastService>(); services.AddHttpContextAccessor(); services.AddSession(options => { options.Cookie.Name = "WebApplication1.Session.2021.demo"; options.Cookie.IsEssential = true; }); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/Error"); } app.UseStaticFiles(); app.UseRouting(); app.UseSession(); app.UseEndpoints(endpoints => { endpoints.MapBlazorHub(); endpoints.MapFallbackToPage("/_Host"); }); } } } |
NavMenu.razor
・<NavLink class=”nav-link” href=”SessionID”> を追加し、「セッションID」画面へのリンクを作成している。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
<div class="top-row pl-4 navbar navbar-dark"> <a class="navbar-brand" href="">WebApplication1</a> <button class="navbar-toggler" @onclick="ToggleNavMenu"> <span class="navbar-toggler-icon"></span> </button> </div> <div class="@NavMenuCssClass" @onclick="ToggleNavMenu"> <ul class="nav flex-column"> <li class="nav-item px-3"> <NavLink class="nav-link" href="" Match="NavLinkMatch.All"> <span class="oi oi-home" aria-hidden="true"></span> Home </NavLink> </li> <li class="nav-item px-3"> <NavLink class="nav-link" href="counter"> <span class="oi oi-plus" aria-hidden="true"></span> Counter </NavLink> </li> <li class="nav-item px-3"> <NavLink class="nav-link" href="fetchdata"> <span class="oi oi-list-rich" aria-hidden="true"></span> Fetch data </NavLink> </li> <li class="nav-item px-3"> <NavLink class="nav-link" href="SessionID"> <span class="oi oi-plus" aria-hidden="true"></span> Session ID </NavLink> </li> </ul> </div> @code { private bool collapseNavMenu = true; private string NavMenuCssClass => collapseNavMenu ? "collapse" : null; private void ToggleNavMenu() { collapseNavMenu = !collapseNavMenu; } } |
SessionID.razor
・「セッションID」画面。
・IHttpContextAccessor.HttpContext.Session.Id からセッションIDを取得している。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
@page "/SessionID" @using Microsoft.AspNetCore.Http; <h1>Counter</h1> <h1>セッションID</h1> <br /> <h3>セッションID : @_SessionID</h3> <br /> <button class="btn btn-primary" @onclick="GetSessionID">セッションID</button> @code { [Inject] protected IHttpContextAccessor _HttpContextAccessor { get; set; } private string? _SessionID; private async Task GetSessionID() { var a = _HttpContextAccessor; var b = a.HttpContext; var c = b.Session; // WebSocketが有効じゃないとここでExceptionが発生する。 _SessionID = c.Id; } } |
注意点
Blazor Server でセッション変数を使用する場合 WebSocketが必須
セッションとセッションID について
・セッションIDが変わったタイミングが、セッションが変わったタイミングです。ブラウザを閉じるとセッションは閉じられます。
・ブラウザを閉じなくても、既定値だと20 分でWEBサーバ側のセッションがタイムアウトして閉じられます。
参考=>ASP.NET Core でのセッション | Microsoft Docs
・Visual Studio でWEBアプリをデバッグ実行する際にホストされる IIS Express だと、セッションは継続しているのにブラウザを更新する度にセッションIDが変化しますが、これは IIS Express の特性で、Windows Server OS 上の IIS、Linux OS 上の Kestrel では起こりません。
・ブラウザはタブ毎にセッションを張らず、タブのセッションは共有されています。「全てのタブでクッキーは1つ」と同義。
同じWebサイトへ、Edge、Chromそれぞれからアクセスした場合、Edge、Chromそれぞれ別のセッションになる。ブラウザ側のクッキー が別々に管理されている為。
・同じブラウザを複数立ち上げた場合、同じクッキー、同じセッションIDで接続しに行くので、Webサーバ側のセッションは共有されます。
・一般的には、各画面の全イベントハンドラに、ログイン時のセッションIDと現在の セッションID が違っていたらログイン画面へ遷移させるという、セキュリティロジックを加えます。
コメント