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
点击 是,允许 确认授权后,就进入系统主页了
点击 退出登录 会跳转到如下页
然后点击 “这里” 返回登录
就又回到了认证授权中心的登录页了