Identity + Ids4 配置 成认证服务
一、创建 Identity身份验证 项目
创建的项目结构中 没有 注册和登录的 控制器和视图
配置数据库地址
》》默认已经生成了Miagratin 直接update-database
二、在Identity项目 配置 IdentityServer4
Nuget 两个包
》》》配置Config 类
using Duende.IdentityServer.Models;
using Duende.IdentityServer.Test;
using Duende.IdentityServer;
using System.Security.Claims;namespace IdentityDemo
{public static class Config{/// <summary>/// api作用域/// </summary>/// public static IEnumerable<ApiScope> ApiScopes => new[]{new ApiScope{Name = "sample_api",DisplayName = "Sample API"}};// 这个 Authorization Server 保护了哪些 API (资源)public static IEnumerable<ApiResource> ApiResources(){return new[]{new ApiResource("api", "My API"){Scopes = { "api1scope", "api2scope" }}};}// 哪些客户端 Client(应用) 可以使用这个 Authorization Server/// <summary>/// 客户端/// </summary>public static IEnumerable<Client> ApiClients => new[]{new Client{//协议类型ProtocolType = "oidc",ClientName = "测试",ClientId = "zen",//定义客户端 Id 要唯一ClientSecrets = { new Secret("abc123zenabres89jijkomnlj".Sha256()) },//Client用来获取token// 混合模式AllowedGrantTypes = GrantTypes.Code, // web程序客户端 RedirectUris = { "http://localhost:2004/signin-oidc"},PostLogoutRedirectUris = { "http://localhost:2004/signout-callback-oidc"},AllowedCorsOrigins = { "http://localhost:2004" }, AllowedScopes = { //必须的IdentityServerConstants.StandardScopes.OpenId,//非必须IdentityServerConstants.StandardScopes.Profile,IdentityServerConstants.StandardScopes.Email,"sample_api" ,"offline_access"},//必须用户授权同意RequireConsent =true,AlwaysIncludeUserClaimsInIdToken =true,AllowOfflineAccess =true,RequirePkce =false,AccessTokenLifetime = 31536000,IdentityTokenLifetime = 300,},资源拥有者模式(又称密码模式)new Client{ClientId = "zen-password",//定义客户端 Id 要唯一ClientSecrets = { new Secret("abc123zenabres89jijkomnlj".Sha256()) },//Client用来获取tokenAllowedGrantTypes = GrantTypes.ResourceOwnerPassword,//可以关闭录入密码RequireClientSecret = false,AllowedScopes = {"sample_api" ,IdentityServerConstants.StandardScopes.OpenId,IdentityServerConstants .StandardScopes.Profile,}// 允许访问的 API 资源}};/// <summary>/// identityserver 提供的测试用的/// </summary>public static List<TestUser> Users => new List<TestUser>(){new TestUser{ //用户的唯一标识SubjectId="Zen001",Username = "Admin",Password = "123"}};/// <summary>/// 认证资源/// </summary>public static IEnumerable<IdentityResource> IdentityResources =>new List<IdentityResource>{new IdentityResources.OpenId(),new IdentityResources.Profile(),new IdentityResources.Email(),};}
}
》》》Program
using IdentityDemo.Data;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;namespace IdentityDemo
{public class Program{public static void Main(string[] args){var builder = WebApplication.CreateBuilder(args);// Add services to the container.var connectionString = builder.Configuration.GetConnectionString("DefaultConnection") ?? throw new InvalidOperationException("Connection string 'DefaultConnection' not found.");builder.Services.AddDbContext<ApplicationDbContext>(options =>options.UseSqlServer(connectionString));builder.Services.AddDatabaseDeveloperPageExceptionFilter();builder.Services.AddDefaultIdentity<IdentityUser>(options =>{options.SignIn.RequireConfirmedAccount = false;options.Password.RequireNonAlphanumeric = false;options.Password.RequireDigit = false;options.Password.RequireLowercase = false;options.Password.RequiredLength = 3;}).AddEntityFrameworkStores<ApplicationDbContext>();builder.Services.AddControllersWithViews();builder.Services.AddIdentityServer(options=>{//因Identity登录地址和Ids4 默认不一致 需要重新定义// ids4 默认 是 /Account/Loginoptions.UserInteraction.LoginUrl = @"/Identity/Account/Login";}).AddDeveloperSigningCredential().AddInMemoryApiScopes(Config.ApiScopes).AddInMemoryIdentityResources(Config.IdentityResources).AddTestUsers(Config.Users) .AddInMemoryClients(Config.ApiClients);var app = builder.Build();// Configure the HTTP request pipeline.if (app.Environment.IsDevelopment()){app.UseMigrationsEndPoint();}else{app.UseExceptionHandler("/Home/Error");}app.UseStaticFiles();app.UseRouting();app.UseAuthorization();app.UseIdentityServer();app.MapControllerRoute(name: "default",pattern: "{controller=Home}/{action=Index}/{id?}");app.MapRazorPages();app.Run();}}
}
三、客户端 配置Ids4
》》Program中
using Duende.IdentityModel;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
using System.IdentityModel.Tokens.Jwt;namespace WebApp
{public class Program{public static void Main(string[] args){var builder = WebApplication.CreateBuilder(args);#region Ids4//禁止JWT身份映射JwtSecurityTokenHandler.DefaultMapInboundClaims = false;builder.Services.AddAuthentication(options =>{//两套认证方案 先 第一个,不行在 第二个options.DefaultScheme = "Cookies";options.DefaultChallengeScheme = "oidc";})// options.DefaultScheme = "Cookies"; 要跟这个名称保持一致.AddCookie("Cookies")//options.DefaultChallengeScheme = "oidc"; 要跟这个名称保持一致.AddOpenIdConnect(authenticationScheme: "oidc", options =>{#region oidc 相关options.Authority = "https://localhost:5053/";options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;options.RequireHttpsMetadata = true;options.ClientId = "zen";options.ClientSecret = "abc123zenabres89jijkomnlj";options.ResponseType = OpenIdConnectResponseType.Code;options.GetClaimsFromUserInfoEndpoint = true;options.UsePkce = false;options.SaveTokens = true;#endregion#region 需要授权信息options.Scope.Add("sample_api");options.Scope.Add("offline_access");#endregionoptions.Events = new Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectEvents(){OnRemoteFailure = context => {//跳转到错误引导页context.Response.Redirect("xxx");context.HandleResponse();return Task.CompletedTask;}//OnAccessDenied//OnRemoteSignOut};});# endregion// Add services to the container.builder.Services.AddControllersWithViews();var app = builder.Build();// Configure the HTTP request pipeline.if (!app.Environment.IsDevelopment()){app.UseExceptionHandler("/Home/Error");}app.UseStaticFiles();app.UseRouting();app.UseAuthorization();app.MapControllerRoute(name: "default",pattern: "{controller=Home}/{action=Index}/{id?}");app.Run();}}
}
解析 ReturnUrl