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

点击 是,允许 确认授权后,就进入系统主页了

 

 

点击 退出登录 会跳转到如下页

 

 然后点击 “这里” 返回登录

就又回到了认证授权中心的登录页了

 

posted @ 2022-03-06 14:32  温故纳新  阅读(878)  评论(0编辑  收藏  举报