1. 程式人生 > 其它 >aps.net core mvc 使用 id4 單點登入登出

aps.net core mvc 使用 id4 單點登入登出

1 在 identity server 4 管理頁面 中新建使用 單點登入登出的客戶端 HybridWebMvcClient

給客戶端新增作用域

並設定啟用離線訪問(獲取 refresh token)

設定 client secret 為HybridWebMvcClient_Secret

設定登入的重定向uri和授權型別

設定 前端通道登出uri 和 登出重定向uri

2 建立 asp.net core web mvc5 專案

配置launchSettings.json 如下

{
  "profiles": {
    "HybridWebMvcClient": {
      
"commandName": "Project", "dotnetRunMessages": "true", "launchBrowser": true, "applicationUrl": "https://localhost:9002", "launchUrl": "Home/Index", // 啟動url "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development", "ASPNETCORE_HOSTINGSTARTUPASSEMBLIES
": "Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" } } } }

appsettings.json 配置檔案如下

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*",
  "AuthServer": {
    
"Authority": "https://localhost:44310", // 認證授權伺服器地址 "RequireHttpsMetadata": "false", // 是否需要 https "ClientId": "HybridWebMvcClient", "ClientSecret": "HybridWebMvcClient_Secret" } }

安裝依賴包

System.IdentityModel.Tokens.Jwt

Microsoft.AspNetCore.Authentication.OpenIdConnect

IdentityModel

修改專案 Startup.cs 設定配置檔案,使用oidc認證,新增認證和授權中介軟體

using Demo.Share.Config;
using IdentityModel;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
using System;
using System.IdentityModel.Tokens.Jwt;

namespace HybridWebMvcClient
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            // 設定配置檔案
            var configBuilder = new ConfigurationBuilder()
                .AddJsonFile("appsettings.json", false, true)
                .AddEnvironmentVariables();

            Configuration = configBuilder.Build();

            // 配置 ConfigurationHelper
            ConfigurationHelper.Configure(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.AddControllersWithViews();

            #region 使用 oidc 認證
            JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); // 包 System.IdentityModel.Tokens.Jwt;
            services.AddAuthentication(options =>
            {
                options.DefaultScheme = "Cookies";
                options.DefaultChallengeScheme = "oidc";
            })
            .AddCookie("Cookies", options =>
            {
                options.ExpireTimeSpan = TimeSpan.FromDays(365);
            })
            .AddOpenIdConnect("oidc", options => // 安裝包 Microsoft.AspNetCore.Authentication.OpenIdConnect
            {
                options.Authority = Configuration["AuthServer:Authority"]; // identity server 伺服器地址
                options.SignInScheme = "Cookies";
                options.ClientId = Configuration["AuthServer:ClientId"];
                options.ClientSecret = Configuration["AuthServer:ClientSecret"];
                //options.SignedOutCallbackPath = "";
                //options.ResponseType = "code"; // 對應授權型別 authorization_code
                options.ResponseType = OpenIdConnectResponseType.CodeIdToken; // 對應授權型別 hybrid
                options.RequireHttpsMetadata = Convert.ToBoolean(Configuration["AuthServer:RequireHttpsMetadata"]);
                options.SaveTokens = true; // 把獲取到的token寫入到cookie
                options.GetClaimsFromUserInfoEndpoint = true;
                options.Scope.Clear();
                options.Scope.Add("openid");
                options.Scope.Add("profile");
                options.Scope.Add(OidcConstants.StandardScopes.OfflineAccess); // 安裝 IdentityModel
            });
            #endregion
        }

        // 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("/Home/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.UseHttpsRedirection();
            app.UseStaticFiles();

            app.UseRouting();

            // 新增認證和授權
            app.UseAuthentication(); 
            app.UseAuthorization();

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

修改HomeController需要認證

using HybridWebMvcClient.Models;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using System.Diagnostics;
using System.Linq;

namespace HybridWebMvcClient.Controllers
{
    [Authorize]
    public class HomeController : Controller
    {
        private readonly ILogger<HomeController> _logger;

        public HomeController(ILogger<HomeController> logger)
        {
            _logger = logger;
        }

        public IActionResult Index()
        {
            // 獲取登入使用者賬號即ids使用者id
            var user = this.HttpContext.User;
            var userName = user.Claims.FirstOrDefault(t => t.Type == "name")?.Value;
            var sub = user.Claims.FirstOrDefault(t => t.Type == "sub")?.Value;
            ViewData["userName"] = userName;
            ViewData["sub"] = sub;

            return View();
        }

        public IActionResult Privacy()
        {
            return View();
        }

        [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
        public IActionResult Error()
        {
            return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
        }
    }
}

主頁退出登入頁面程式碼如下

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

<p>使用者id:@ViewData["sub"]</p>
<p>使用者賬號:@ViewData["userName"]</p>
<a href="/Login/LogOut">退出登入</a>

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

新增LoginController 登出功能

using Demo.Share.Config;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
using System.Threading.Tasks;

namespace HybridWebMvcClient.Controllers
{
    public class LoginController : Controller
    {
        [HttpGet]
        public async Task<ActionResult> LogOut()
        {
            // 本地登出退出登入
            await HttpContext.SignOutAsync("Cookies");

            // id4 認證授權中心 登出
            var accessToken = await HttpContext.GetTokenAsync(OpenIdConnectParameterNames.AccessToken);
            var idToken = await HttpContext.GetTokenAsync(OpenIdConnectParameterNames.IdToken);
            var refreshToken = await HttpContext.GetTokenAsync(OpenIdConnectParameterNames.RefreshToken);     
            string post_logout_redirect_uri = "https://localhost:9002"; // 需要與授權中心配置的 登出重定向 Uri 一致
            string url = $"{ConfigurationHelper.GetSection("AuthServer:Authority")}/connect/endsession?post_logout_redirect_uri={post_logout_redirect_uri}&id_token_hint={idToken}";
            return Redirect(url);
        }
    }
}

3 測試

啟動專案,啟動連結為進入 /home/index ,這個時候由於 HomeController 添加了 Authorize標記所以會跳轉到認證授權伺服器登入,

登入連結:

https://localhost:44310/Account/Login?ReturnUrl=%2Fconnect%2Fauthorize%2Fcallback%3Fclient_id%3DHybridWebMvcClient%26redirect_uri%3Dhttps%253A%252F%252Flocalhost%253A9002%252Fsignin-oidc%26response_type%3Dcode%2520id_token%26scope%3Dopenid%2520profile%2520offline_access%26response_mode%3Dform_post%26nonce%3D637821435442037020.ZGUyNGRjZmQtMTcxZS00YTkwLWE0MTctMDk2MjkyNWQ5MDQzYzM1YWNmOGYtNzYwNS00NzY5LWFiZTktZTJkZjU4OTIzNjM5%26state%3DCfDJ8MxL4yIiuUZDpjL1HGMXa9GuD36UXnfWaR2ohMimLw30C6FA82YVsXjFCpr3E4CqvQfZ-_a8VG7Q89FA9OtRsmZmcr1yoAeEQ9wSckNCGX-dXIsH3YbEMp7_DhGXYPlSDi_mIb3AQtF-ZxBEqdT6dD__sPbFN7FOsdS-03uvZi_thBh6PrO-2S8Y9tHJ1bZ-euReadQc9IHvUyxAT6wF5nyyXQAYFVhE5tS5otAdJ4WvYonWRc6qZR6QxirbKJadQV8NINJP___5ICHKAvL7M68NF26GMvyte_3WZHxS6V6cilxYxq7fnSm-fdttNkBR7w%26x-client-SKU%3DID_NETSTANDARD2_0%26x-client-ver%3D6.7.1.0

輸入正確的使用者名稱和使用者密碼後會彈出確認授權框,

確認授權頁面連結如下

https://localhost:44310/consent?returnUrl=%2Fconnect%2Fauthorize%2Fcallback%3Fclient_id%3DHybridWebMvcClient%26redirect_uri%3Dhttps%253A%252F%252Flocalhost%253A9002%252Fsignin-oidc%26response_type%3Dcode%2520id_token%26scope%3Dopenid%2520profile%2520offline_access%26response_mode%3Dform_post%26nonce%3D637821435442037020.ZGUyNGRjZmQtMTcxZS00YTkwLWE0MTctMDk2MjkyNWQ5MDQzYzM1YWNmOGYtNzYwNS00NzY5LWFiZTktZTJkZjU4OTIzNjM5%26state%3DCfDJ8MxL4yIiuUZDpjL1HGMXa9GuD36UXnfWaR2ohMimLw30C6FA82YVsXjFCpr3E4CqvQfZ-_a8VG7Q89FA9OtRsmZmcr1yoAeEQ9wSckNCGX-dXIsH3YbEMp7_DhGXYPlSDi_mIb3AQtF-ZxBEqdT6dD__sPbFN7FOsdS-03uvZi_thBh6PrO-2S8Y9tHJ1bZ-euReadQc9IHvUyxAT6wF5nyyXQAYFVhE5tS5otAdJ4WvYonWRc6qZR6QxirbKJadQV8NINJP___5ICHKAvL7M68NF26GMvyte_3WZHxS6V6cilxYxq7fnSm-fdttNkBR7w%26x-client-SKU%3DID_NETSTANDARD2_0%26x-client-ver%3D6.7.1.0

點選 是,允許 確認授權後,就進入系統主頁了

點選 退出登入 會跳轉到如下頁

然後點選 “這裡” 返回登入

就又回到了認證授權中心的登入頁了