ASP.Net Identity + IODC 解析ReturnUrl
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用来获取token
AllowedGrantTypes = 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/Login
options.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");
#endregion
options.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