none
同一セッションで複数ログインされた時、ログイン済みのページをエラーとしたい RRS feed

  • 質問

  • C# 2019
    ASP.NET Core
    .NET Core 3.1
    Razorページ

    下記を同一セッションで実施したとします。

    1.タブ1にて、ログインページからユーザーAとしてログイン。
    2.タブ2にて、ログインページからユーザーBとしてログイン。

    ログイン自体はIdentityを利用し、Cookieによる管理としています。(仕組みよくわかってない)
    超簡易的なログインのみを必要としているため、データベースによるログイン管理は考えていません。
    (実際は、ユーザーIDをクエリストリングで渡して特定ページにアクセスするとログインとみなす)

                await HttpContext.SignInAsync(
                  CookieAuthenticationDefaults.AuthenticationScheme,
                  new ClaimsPrincipal(claimsIdentity),
                  new AuthenticationProperties
                  {
                      IsPersistent = Input.RememberMe
                  });

    上記手順を行ったあと、1.のタブで、認証を要している他ページへアクセスしたとき、
    ログイン情報がユーザーBに書き換わっているので、ユーザーBとしてページを表示してしまいます。

    これを、既にログイン情報が変わったタブからページアクセスした時、セッションが切れたなどの
    エラーページへ遷移させたいのですが、どうやればいいのか全く見当がつきませんでした。

    どのようにすると希望する動作を実現することができるでしょうか?

    2021年3月24日 4:56

回答

  • 撤退したと言いながら一言・・・

    最初に断っておきますが、以下は 100% ASP.NET Core Identity による Cookie ベースの認証の話です。

    ユーザー A がログインすると ASP.NET Core Identity が認証チケットを Cookie に入れてユーザーに送り、ユーザー(ブラウザ)はアクセスする際その Cookie をサーバーに送信するので毎回のアクセスで認証が維持されるという仕組みになっています。ここは先に書いた通り。

    そして、例えばユーザー A がログインしたままブラウザは閉じないで(即ちブラウザが ユーザー A の認証チケット/クッキーを保持したまま)、別タブまたは同じブラウザを立ち上げて Login ペーにアクセスしユーザー B でログインしたとします。

    そうすると ASP.NET Core Identity はユーザー B の認証チケットを作って認証クッキーに入れてブラウザに送信します。それを受けたブラウザはブラウザに保持しているユーザー A の認証クッキーをユーザー B の認証クッキーで上書きします。

    それ以降、そのブラウザでアクセスすればユーザー B の認証クッキーが送られるので、アクセスしてきたのはユーザー B とみなされます。

    それで質問者さんのやりたいこと、

    > ・同一セッションでも、多重ログインが行われたら、先にログインしていたタブはページ操作をできなくする。
    > (後からログインしたタブでのみページ操作ができる。
    >  ログインページ・制御にアクセスした時点で元々ログインしていた情報はすべて破棄され、
    >  先にログインしていたタブはページ操作がエラーとなり、後からログインした情報に引っ張られない。)

    が実現できるかを考えてみてください。

    「先にログインしていたタブはページ操作をできなくする」とか「先にログインしていたタブはページ操作がエラーとなり」というのがどういうことか不明ですが、認証だけ通れば誰でもアクセスできるような作り([Authorize] 属性しか付与してない)になっているとすると、そんなことは不可能という結論になるはずです。

    認証に加えてロールによる承認をシステムに追加し、ユーザー A が見ていたページはロールによる制限でユーザー B にはアクセスできない設定にはできます。それでやりたいこともしくはそれに近いことになるのであれば、ロールの追加を検討してはどうですか。


    • 編集済み SurferOnWww 2021年3月26日 6:03 追記
    • 回答としてマーク takiru 2021年3月29日 4:14
    2021年3月26日 6:01

すべての返信

  • > 1.タブ1にて、ログインページからユーザーAとしてログイン。
    > 2.タブ2にて、ログインページからユーザーBとしてログイン。

    「タブ」とは何ですか?

    > ログイン自体はIdentityを利用し、Cookieによる管理としています。(仕組みよくわかってない)
    > 超簡易的なログインのみを必要としているため、データベースによるログイン管理は考えていません。
    > (実際は、ユーザーIDをクエリストリングで渡して特定ページにアクセスするとログインとみなす)

    Cookie と言いながらクエリ文字列で渡すってどういうことですか? (何も分かってなくて書いているとしか思えないのですが・・・)

    何にせよ、質問者の独自認証ではその中身を知る由もない第三者は答えようがないのは理解できますか? ユーザー情報のストアにデータベースは使ってないということでも良いのですが、それ以外は 100% ASP.NET Core Identity による Cookie ベースの認証というような条件にしてもらわないと話ができないです。


    2021年3月24日 6:58
  • タブとはブラウザのタブです。
    同一ブラウザ、同一セッション、複数タブでログインが実施された場合の質問になります。

    ログイン用URLへアクセスする際にユーザーIDがクエリストリングとして渡されます。
    そのユーザーIDの検証をもってIdentityの仕組みでログインとみなしています。

    ログインするための情報がクエリストリングで渡されてアクセスされるだけであり、
    一般的なログイン画面が存在して、ログインするための情報を入力してPOSTする仕組みと
    同じであると考えているため、
    仰っている『100% ASP.NET Core Identity による Cookie ベースの認証』である
    と考えていますが、間違っていますでしょうか?

    実際Identityの仕組みも何も分かっていませんので、希望する動作を実現できるコードを
    ご提示いただけると助かります。

    2021年3月24日 7:25
  • > 仰っている『100% ASP.NET Core Identity による Cookie ベースの認証』であると考えていますが、間違っていますでしょうか?

    違います。ASP.NET Core Identity は認証にクエリ文字列は使いません。ユーザーがログインすると ASP.NET Core Identity が認証チケットを Cookie に入れてユーザーに送り、ユーザーはアクセスする際その Cookie をサーバーに送信するので毎回のアクセスで認証が維持されるという仕組みになっています。

    2021年3月24日 7:39
  • ログインの入り口として、ログインするためのIDやパスワードがPOSTされるのと、
    GETされるので違いがあって、GETではIdentityを利用することはできないのでしょうか?

    先に記したコードでログインを実施させ、IdentityのCookieとしては動作し、
    認証を要する([Authorize]属性が設定されている)各ページへのアクセスは
    正しく行われているように思えますが。

    後ほどコードを最小レベルに整理し、現時点での主要部分のコードをご提示いたします。

    2021年3月24日 7:56
  • 下記に主要部分のミニマムコードを記載します。

    1つめのタブで
    (A)
    ttp://loalhost:xxxx/account/login/test
    にアクセスすると認証を要するprivacyページへ飛びます。
    privacyページはブラウザでページ更新しても、ログイン済みなのでエラーとはならず、privacyページが常に表示されます。

    その後に2つめのタブで
    (B)
    ttp://loalhost:xxxx/account/login/test2
    にアクセスすると、(A)と同様の動作をします。
    ただし、ここで(A)について、ブラウザでページ更新、ページ遷移をするとtest2扱いになってしまいます。

    (B)を実施後、(A)で何か別ページへ遷移したりした時には、認証NGとしてエラーページへリダイレクトしたいです。

    Startup.cs

    using Microsoft.AspNetCore.Authentication.Cookies;
    using Microsoft.AspNetCore.Builder;
    using Microsoft.AspNetCore.CookiePolicy;
    using Microsoft.AspNetCore.Hosting;
    using Microsoft.AspNetCore.Http;
    using Microsoft.AspNetCore.Routing;
    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.DependencyInjection;
    using Microsoft.Extensions.Hosting;
    
    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.
            public void ConfigureServices(IServiceCollection services)
            {
                services.AddRazorPages();
    
                // Cookie認証する
                services.Configure<CookiePolicyOptions>(options =>
                {
                    options.CheckConsentNeeded = context => !context.User.Identity.IsAuthenticated;
                    options.MinimumSameSitePolicy = Microsoft.AspNetCore.Http.SameSiteMode.None;
                    options.HttpOnly = HttpOnlyPolicy.Always;
                });
                services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
                    .AddCookie((options) =>
                    {
                        options.LoginPath = new PathString("/statuserror/400");
                        options.AccessDeniedPath = new PathString("/statuserror/400");
                    });
    
    
                // URLのパス情報は小文字で表現する
                services.Configure<RouteOptions>(options =>
                {
                    options.LowercaseUrls = 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");
                    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                    app.UseHsts();
                }
    
                // カスタムエラーページの設定
                app.UseStatusCodePagesWithReExecute("/statuserror/{0}");
    
                app.UseHttpsRedirection();
                app.UseStaticFiles();
    
                // Cookie認証する
                app.UseCookiePolicy();
                app.UseAuthentication();
    
                app.UseRouting();
    
                app.UseAuthorization();
    
                app.UseEndpoints(endpoints =>
                {
                    endpoints.MapRazorPages();
                });
            }
        }
    }
    

    Pages/Account/Login.cshtml

    @page "{id}"
    @model LoginModel

    Pages/Account/Login.cshtml.cs

    using Microsoft.AspNetCore.Authentication;
    using Microsoft.AspNetCore.Authentication.Cookies;
    using Microsoft.AspNetCore.Http;
    using Microsoft.AspNetCore.Mvc;
    using Microsoft.AspNetCore.Mvc.RazorPages;
    using System.Linq;
    using System.Security.Claims;
    using System.Threading.Tasks;
    
    namespace WebApplication1.Pages.Account
    {
        public class LoginModel : PageModel
        {
            public async Task<IActionResult> OnGet(string id)
            {
                // ダミーの認証処理(実際にはDBを使います)
                var mockDB = new[] {
                    "test", "test2"
                  };
                var record = mockDB.SingleOrDefault(x => x == id);
                bool isValid = true;
                if (record == default)
                {
                    isValid = false;
                }
                if (!isValid) return BadRequest();
    
    
                Claim[] claims = {
                    new Claim(ClaimTypes.NameIdentifier, id),
                    new Claim(ClaimTypes.Name, id),
                  };
                var claimsIdentity = new ClaimsIdentity(
                  claims, CookieAuthenticationDefaults.AuthenticationScheme);
    
                await HttpContext.SignInAsync(
                  CookieAuthenticationDefaults.AuthenticationScheme,
                  new ClaimsPrincipal(claimsIdentity),
                  new AuthenticationProperties
                  {
                      IsPersistent = false
                  });
    
                return LocalRedirect("/privacy");
            }
        }
    }
    

    Pages/Privacy.cshtml.cs

    using Microsoft.AspNetCore.Authorization;
    using Microsoft.AspNetCore.Mvc;
    using Microsoft.AspNetCore.Mvc.RazorPages;
    using Microsoft.Extensions.Logging;
    using System.Threading.Tasks;
    
    namespace WebApplication1.Pages
    {
        [Authorize]
        public class PrivacyModel : PageModel
        {
            private readonly ILogger<PrivacyModel> _logger;
    
            public PrivacyModel(ILogger<PrivacyModel> logger)
            {
                _logger = logger;
            }
    
            public void OnGet()
            {
            }
    
            public async Task<IActionResult> OnPostAsync()
            {
                return Page();
            }
        }
    }
    


    2021年3月24日 8:47
  • > GETではIdentityを利用することはできないのでしょうか?

    セキュリティ上の問題があるのでやりません。

    > 現時点での主要部分のコードをご提示いたします。

    それを見るのは自分には負担が大きすぎますのでご容赦ください。

    2021年3月24日 9:12
  • セキュリティの問題は、理解していることと、利用における環境や制約の観点から、問題なしとなっております。また、当質問とは逸脱した観点になるため、セキュリティについて、べき論などの話を詰めるつもりはございません。 ご助言頂けず大変残念です。
    2021年3月24日 10:20
  • > セキュリティの問題は、理解していることと、利用における環境や制約の観点から、問題なしとなっております。
    > また、当質問とは逸脱した観点になるため、セキュリティについて、べき論などの話を詰めるつもりはございません

    そこまで言い切る自信と知識があるならなら何で自力でできないの? 不思議ですね。

    私には「問題なし」と判断したあなた事情はどうでもいいことですし、あなたと「べき論」の話をするつもりなど毛頭ありません。

    標準と離れてあなたの事情をベースに話はするつもりはありませんので、質問者さんの事情ベースの普通ではない話は自分で考えてやってくださいということです。

    ということで、私はこのスレッドからは撤退します。悪しからず。
    2021年3月24日 11:41
  • 自信があるとかではなく、そういう風になっているとしか言いようがありません。
    ですからセキュリティ観点については、目下の私の課題としてもどうでもいいことです。

    私はただ、これから作り上げるWebアプリケーションの全ページを、
    ログインされていなければアクセスできないようにしたかっただけです。
    それはそれほど特殊なことではないでしょう。
    Authorize属性を付与するだけで済むであろうIdentityが最も簡単に思えたので検討しているのです。

    ただ対話式のログイン画面が存在せず、別システムから渡されてくる認証情報について、
    別システムのDB宛へ認証情報に誤りがないことを確認した上で、その情報をログイン情報
    として扱うようにします。
    受け取った情報が認証情報であるという点は、対話式のログイン画面があろうがなかろうが
    変わりはないため、こうじゃないとダメ、ああじゃないとダメ、ということはないかと考えております。

    その中で、先の質問となっております。
    Identityを利用するにあたって、画面がなければダメだ、POSTでなければダメだ、認証情報が
    こうでなければダメだ、などと様々な制約があるということでしたら、質問以前に、実現要件に
    合致しないためIdentityの利用は諦めるまでとなります。

    お気を悪くされたなら申し訳ありませんでした。
    お付き合いくださりありがとうございました。
    2021年3月24日 13:49
  • よくわからない話なのですが、Cookie でセッション管理してログオン状態を保持しているのであれば、同じブラウザー ウィンドウ内で

    1.タブ1にて、ログインページからユーザーAとしてログイン。
    2.タブ2にて、ログインページからユーザーBとしてログイン。

    という動作は原理的にできません。このような動作が可能なのは独自の(クエリ文字列を使った)認証管理が原因ですね。

    ※ブラウザーはウィンドウ単位でセッションを共有するので、Cookie のみ使った認証ならタブ1でユーザーAとしてログインしていれば、タブ2で同じサイトを開いた時点でAでログイン済みとして開きます。



    Hebikuzure aka Murachi Akira

    2021年3月25日 4:33
  • 画面を設けた検証も行っていましたが、記した手順の動作ができてしまいます。
    特にログイン画面には、ログインされていたら、というような実装はありませんので、
    再度ログイン画面が表示されることは個人的には自然なことのように思えます。
    ログイン画面の実装として何か足りないということでしょうか?

    アニメーションgifがなぜかアップロードできなかったので、2分割になってしまいましたがnoteにムリヤリあげました。
    状況がご確認できるかと思います。
    https://note.com/preview/n293364fa126f?prev_access_key=ba79a3ee23c77ccc353fab1406ec9b93
    (IEだと見れないっぽい)

    『独自ではない認証管理』とは、もしかしてVSでプロジェクトを作る時に選択できる『個別のユーザーアカウント』などを
    指定した場合のことでしょうか?
    そのプロジェクトを作って試したところ、
    1.タブ1とタブ2でログイン用ページを表示しておく。
    2.タブ1とタブ2で異なるユーザーでログイン。
    これは確かに__RequestVerificationTokenが異なるもので実施したため、タブ2でログインを行った時、ステータスコード400が帰ってきました。
    ただ、
    1.タブ1でログイン。
    2.タブ2でログイン用URLを張り付けてムリヤリ表示し、異なるユーザーでログイン。
    を実施すると、後勝ちのログインになるようでした。
    また、この方法でプロジェクトを作ると、ログインページなどのプログラムが見えてこないようなので、何しているのか皆目見当がつきません。

    私がやりたいことは下記の2つです。
     ・ログインしなければ全ページにアクセスすることはできない。
     ・同一セッションでも、多重ログインが行われたら、先にログインしていたタブはページ操作をできなくする。
      (後からログインしたタブでのみページ操作ができる。
       ログインページ・制御にアクセスした時点で元々ログインしていた情報はすべて破棄され、
       先にログインしていたタブはページ操作がエラーとなり、後からログインした情報に引っ張られない。)

    なんだかんだ色々調べてみましたが、後勝ちを許さない場合は、かなり色々ゴリゴリ考えないとムリそうということでしょうか?方法論は何も想像つきませんが・・・。

    【画面を設けて検証してみた時の主要コード】

    Startup.cs

    using Microsoft.AspNetCore.Authentication.Cookies;
    using Microsoft.AspNetCore.Builder;
    using Microsoft.AspNetCore.CookiePolicy;
    using Microsoft.AspNetCore.Hosting;
    using Microsoft.AspNetCore.Routing;
    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.DependencyInjection;
    using Microsoft.Extensions.Hosting;
    
    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.
            public void ConfigureServices(IServiceCollection services)
            {
                services.AddRazorPages();
    
                // Cookie認証する
                services.Configure<CookiePolicyOptions>(options =>
                {
                    options.CheckConsentNeeded = context => !context.User.Identity.IsAuthenticated;
                    options.MinimumSameSitePolicy = Microsoft.AspNetCore.Http.SameSiteMode.None;
                    options.HttpOnly = HttpOnlyPolicy.Always;
                });
                services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
                    .AddCookie();
    
                // URLのパス情報は小文字で表現する
                services.Configure<RouteOptions>(options =>
                {
                    options.LowercaseUrls = 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");
                    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                    app.UseHsts();
                }
    
                // カスタムエラーページの設定
                app.UseStatusCodePagesWithReExecute("/statuserror/{0}");
    
                app.UseHttpsRedirection();
                app.UseStaticFiles();
    
                // Cookie認証する
                app.UseCookiePolicy();
                app.UseAuthentication();
    
                app.UseRouting();
    
                app.UseAuthorization();
    
                app.UseEndpoints(endpoints =>
                {
                    endpoints.MapRazorPages();
                });
            }
        }
    }
    

    Pages/Account/Login.cshtml
    @page
    @model WebApplication1.Pages.Account.LoginModel
    @{
        Layout = "_TestLayout";   // 指定したものを、利用するレイアウトとする
        ViewData["Title"] = "Login";
    }
    <h2>Login</h2>
    <form method="post">
        <div class="form-group">
            <label asp-for="Input.Email">Email address</label>
            <input asp-for="Input.Email" class="form-control" placeholder="Enter email">
        </div>
        <div class="form-group">
            <label asp-for="Input.Password">Password</label>
            <input asp-for="Input.Password" class="form-control" placeholder="Password">
        </div>
        <div class="form-check">
            <input asp-for="Input.RememberMe" class="form-check-input">
            <label asp-for="Input.RememberMe" class="form-check-label">Remember Me</label>
        </div>
        <button type="submit" class="btn btn-primary">Submit</button>
    </form>

    Pages/Accunt/Login.cshtml.cs
    using Microsoft.AspNetCore.Authentication;
    using Microsoft.AspNetCore.Authentication.Cookies;
    using Microsoft.AspNetCore.Http;
    using Microsoft.AspNetCore.Mvc;
    using Microsoft.AspNetCore.Mvc.RazorPages;
    using System.ComponentModel.DataAnnotations;
    using System.Linq;
    using System.Security.Claims;
    using System.Threading.Tasks;
    
    namespace WebApplication1.Pages.Account
    {
        public class LoginModel : PageModel
        {
            [BindProperty]
            public InputModel Input { get; set; }
    
            public async Task<IActionResult> OnPostAsync(string returnUrl = null)
            {
                // 必須入力がないなどの場合ログインさせない。(ログインページに戻る)
                if (!ModelState.IsValid) return Page();
    
                // ダミーの認証処理(実際にはDBを使います)
                var mockDB = new[] {
                    (email: "test", password: "test"),
                    (email: "test2", password: "test2"),
                  };
                var record = mockDB.SingleOrDefault(x => x.email == Input.Email && x.password == Input.Password);
                bool isValid = true;
                if (record == default)
                {
                    isValid = false;
                }
                if (!isValid) return Page();
    
                Claim[] claims = {
                    new Claim(ClaimTypes.NameIdentifier, Input.Email), // ユニークID
                    new Claim(ClaimTypes.Name, Input.Email),
                    new Claim("Value", Input.Email),
                  };
    
                var claimsIdentity = new ClaimsIdentity(
                  claims, CookieAuthenticationDefaults.AuthenticationScheme);
    
                // ログイン
                await HttpContext.SignInAsync(
                  CookieAuthenticationDefaults.AuthenticationScheme,
                  new ClaimsPrincipal(claimsIdentity),
                  new AuthenticationProperties
                  {
                      IsPersistent = Input.RememberMe
                  });
    
                return LocalRedirect(returnUrl ?? Url.Content("~/"));
            }
        }
    
        public class InputModel
        {
            [Required]
            //[EmailAddress]
            public string Email { get; set; }
    
            [Required]
            [DataType(DataType.Password)]
            public string Password { get; set; }
    
            [Display(Name = "Remember me?")]
            public bool RememberMe { get; set; }
        }
    }

    Pages/Privacy.cshtml
    @page
    @model PrivacyModel
    @{
        ViewData["Title"] = "Privacy Policy";
    }
    <h1>@ViewData["Title"]</h1>
    
    <p>Use this page to detail your site's privacy policy.</p>
    @if (User.Identity.IsAuthenticated)
    {
        var claim = User.FindFirst(@"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name");
        if (claim != null)
        {
            var name = claim.Value;
            <input type="text" value="@name" />
        }
    }

    2021年3月25日 8:09
  • 撤退したと言いながら一言・・・

    最初に断っておきますが、以下は 100% ASP.NET Core Identity による Cookie ベースの認証の話です。

    ユーザー A がログインすると ASP.NET Core Identity が認証チケットを Cookie に入れてユーザーに送り、ユーザー(ブラウザ)はアクセスする際その Cookie をサーバーに送信するので毎回のアクセスで認証が維持されるという仕組みになっています。ここは先に書いた通り。

    そして、例えばユーザー A がログインしたままブラウザは閉じないで(即ちブラウザが ユーザー A の認証チケット/クッキーを保持したまま)、別タブまたは同じブラウザを立ち上げて Login ペーにアクセスしユーザー B でログインしたとします。

    そうすると ASP.NET Core Identity はユーザー B の認証チケットを作って認証クッキーに入れてブラウザに送信します。それを受けたブラウザはブラウザに保持しているユーザー A の認証クッキーをユーザー B の認証クッキーで上書きします。

    それ以降、そのブラウザでアクセスすればユーザー B の認証クッキーが送られるので、アクセスしてきたのはユーザー B とみなされます。

    それで質問者さんのやりたいこと、

    > ・同一セッションでも、多重ログインが行われたら、先にログインしていたタブはページ操作をできなくする。
    > (後からログインしたタブでのみページ操作ができる。
    >  ログインページ・制御にアクセスした時点で元々ログインしていた情報はすべて破棄され、
    >  先にログインしていたタブはページ操作がエラーとなり、後からログインした情報に引っ張られない。)

    が実現できるかを考えてみてください。

    「先にログインしていたタブはページ操作をできなくする」とか「先にログインしていたタブはページ操作がエラーとなり」というのがどういうことか不明ですが、認証だけ通れば誰でもアクセスできるような作り([Authorize] 属性しか付与してない)になっているとすると、そんなことは不可能という結論になるはずです。

    認証に加えてロールによる承認をシステムに追加し、ユーザー A が見ていたページはロールによる制限でユーザー B にはアクセスできない設定にはできます。それでやりたいこともしくはそれに近いことになるのであれば、ロールの追加を検討してはどうですか。


    • 編集済み SurferOnWww 2021年3月26日 6:03 追記
    • 回答としてマーク takiru 2021年3月29日 4:14
    2021年3月26日 6:01
  • 度々ご回答ありがとうございます。

    やはりIdentityではそういった制御はできないんですね。
    世間のシステムでそれが実現できている仕組みはどうやっているのか不明ですが、
    決まりきった利用環境の中で、ひたすらそこに拘っても仕方ないので、
    運用として理解してもらうこととしました。

    せいぜい、既に認証済みのユーザーと異なるユーザーで新たにログインしようとされた時は、
    ログアウトしないとダメよエラーにでもしようかと思います。

    ありがとうございました。

    2021年3月29日 4:14