NETCORE - OpenId 鉴权模式
NETCORE - OpenId 鉴权模式
环境:.net8 + efcore8 + mysql8 + openIddict7 ,不集成ASP.NET Core Identity ,使用自已的用户表登录
一、 修改数据库
数据库使用 mysql,创建数据库 openauth,字符集为 utf8mb3
二、 创建服务端
1. 项目搭建
项目框架:.net8 + webapi
项目插件:EfCore8 + OpenIddict7
  
2. 配置文件
{ "Logging": { "LogLevel": { "Default": "Information", "Microsoft.AspNetCore": "Warning" } }, "AllowedHosts": "*", "ConnectionStrings": { "DefaultConnection": "Server=localhost;Port=3306;Database=openauth;Uid=root;Pwd=123456;Charset=utf8mb3;SslMode=Preferred;AllowPublicKeyRetrieval=true;" } }
3. 生成数据库上下文文件
在程序包管理器控制台中执行:
Scaffold-DbContext -Connection "server=localhost;userid=root;password=123456;database=openauth;" -Provider Pomelo.EntityFrameworkCore.MySql -OutputDir Models -ContextDir Context -Context DataBaseOpenAuth -UseDatabaseNames -Force -NoOnConfiguring
创建部分类 Context / DataBaseOpenAuth.OpenIddict.cs
using Microsoft.EntityFrameworkCore; using OpenIddict.EntityFrameworkCore.Models; namespace Rail.AuthServer.Context { public partial class DataBaseOpenAuth { // OpenIddict实体集 public DbSet<OpenIddictEntityFrameworkCoreApplication> Applications { get; set; } public DbSet<OpenIddictEntityFrameworkCoreAuthorization> Authorizations { get; set; } public DbSet<OpenIddictEntityFrameworkCoreScope> Scopes { get; set; } public DbSet<OpenIddictEntityFrameworkCoreToken> Tokens { get; set; } partial void OnModelCreatingPartial(ModelBuilder modelBuilder) { // 配置OpenIddict modelBuilder.UseOpenIddict(); // 这里可以添加其他自定义配置 } } }
4. 注入OpenId
编辑 Program.cs
using Microsoft.EntityFrameworkCore; using OpenIddict.Abstractions; using OpenIddict.Validation.AspNetCore; using Rail.AuthServer.Context; using static OpenIddict.Abstractions.OpenIddictConstants; var builder = WebApplication.CreateBuilder(args); // Add services to the container. //Scaffold-DbContext -Connection "server=localhost;userid=root;password=123456;database=openauth;" -Provider Pomelo.EntityFrameworkCore.MySql -OutputDir Models -ContextDir Context -Context DataBaseOpenAuth -UseDatabaseNames -Force -NoOnConfiguring // 添加数据库上下文 var connectionString = builder.Configuration.GetConnectionString("DefaultConnection"); builder.Services.AddDbContext<DataBaseOpenAuth>(options => { options.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString)); options.UseOpenIddict(); }); // 添加OpenIddict服务 builder.Services.AddOpenIddict() .AddCore(options => { options.UseEntityFrameworkCore() .UseDbContext<DataBaseOpenAuth>(); }) .AddServer(options => { // 设置端点 options.SetTokenEndpointUris("connect/token"); options.SetAuthorizationEndpointUris("connect/authorize"); // 配置支持的授权类型 options.AllowPasswordFlow() .AllowRefreshTokenFlow() .AllowClientCredentialsFlow() .AllowAuthorizationCodeFlow(); // 各种token的默认过期时间 options.SetAccessTokenLifetime(TimeSpan.FromHours(1)); // 访问令牌:1小时 options.SetRefreshTokenLifetime(TimeSpan.FromDays(30)); // 刷新令牌:30天 options.SetAuthorizationCodeLifetime(TimeSpan.FromMinutes(10)); // 授权码:10分钟 options.SetIdentityTokenLifetime(TimeSpan.FromHours(1)); // 身份令牌:1小时 options.SetUserCodeLifetime(TimeSpan.FromMinutes(5)); // 用户码:5分钟 options.SetDeviceCodeLifetime(TimeSpan.FromMinutes(15)); // 设备码:15分钟 // 刷新令牌设置 ,滚动刷新令牌配置 - OpenIddict 7 方式 options.SetRefreshTokenReuseLeeway(TimeSpan.Zero); // 设置为0表示禁用重用 // 注册签名和加密证书 options.AddDevelopmentEncryptionCertificate() .AddDevelopmentSigningCertificate(); // 注册范围 options.RegisterScopes( Scopes.Email, Scopes.Profile, Scopes.Roles, Scopes.OfflineAccess); // 包含刷新令牌 // 注册ASP.NET Core主机并配置选项 options.UseAspNetCore() .EnableTokenEndpointPassthrough() .EnableAuthorizationEndpointPassthrough(); }) .AddValidation(options => { options.UseLocalServer(); options.UseAspNetCore(); }); // 添加认证服务 builder.Services.AddAuthentication(options => { options.DefaultAuthenticateScheme = OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme; options.DefaultChallengeScheme = OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme; }); // 添加授权服务 builder.Services.AddAuthorization(); builder.Services.AddControllers(); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); var app = builder.Build(); // 初始化OpenIddict数据库 using (var scope = app.Services.CreateScope()) { var context = scope.ServiceProvider.GetRequiredService<DataBaseOpenAuth>(); await context.Database.EnsureCreatedAsync(); var manager = scope.ServiceProvider.GetRequiredService<IOpenIddictApplicationManager>(); // 创建客户端应用(如果不存在) if (await manager.FindByClientIdAsync("console_app") is null) { await manager.CreateAsync(new OpenIddictApplicationDescriptor { ClientId = "console_app", ClientSecret = "console_app_secret", DisplayName = "Console Application", Permissions = { Permissions.Endpoints.Token, Permissions.Endpoints.Authorization, Permissions.GrantTypes.Password, Permissions.GrantTypes.RefreshToken, Permissions.GrantTypes.ClientCredentials, Permissions.ResponseTypes.Code, Permissions.Scopes.Email, Permissions.Scopes.Profile, Permissions.Scopes.Roles } }); } } // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } app.UseHttpsRedirection(); app.UseAuthentication(); app.UseAuthorization(); app.MapControllers(); app.Run();
5. 运行
运行后自动生成4张权限表
  
6. 发现文档
https://localhost:7231/.well-known/openid-configuration
返回结果:
{ "issuer": "https://localhost:7231/", "authorization_endpoint": "https://localhost:7231/connect/authorize", "token_endpoint": "https://localhost:7231/connect/token", "jwks_uri": "https://localhost:7231/.well-known/jwks", "grant_types_supported": [ "password", "refresh_token", "client_credentials" ], "scopes_supported": [ "openid", "offline_access" ], "claims_supported": [ "aud", "exp", "iat", "iss", "sub" ], "id_token_signing_alg_values_supported": [ "RS256" ], "subject_types_supported": [ "public" ], "prompt_values_supported": [ "consent", "login", "none", "select_account" ], "token_endpoint_auth_methods_supported": [ "client_secret_post", "private_key_jwt", "client_secret_basic" ], "require_pushed_authorization_requests": false, "claims_parameter_supported": false, "request_parameter_supported": false, "request_uri_parameter_supported": false, "tls_client_certificate_bound_access_tokens": false, "authorization_response_iss_parameter_supported": true }
7. 创建Token控制器
using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using OpenIddict.Abstractions; using OpenIddict.Server.AspNetCore; using System.Security.Claims; namespace Rail.AuthServer.Controllers { [ApiController] [Route("connect")] public class TokenController : ControllerBase { private readonly IOpenIddictApplicationManager _applicationManager; public TokenController(IOpenIddictApplicationManager applicationManager) { _applicationManager = applicationManager; } [HttpPost("token")] public async Task<IActionResult> Exchange() { var request = HttpContext.GetOpenIddictServerRequest(); if (request == null) { return BadRequest("Invalid OpenID Connect request."); } if (request.IsPasswordGrantType()) { return await HandlePasswordGrantType(request); } else if (request.IsClientCredentialsGrantType()) { return await HandleClientCredentialsGrantType(request); } else if (request.IsRefreshTokenGrantType()) { return await HandleRefreshTokenGrantType(request); } return BadRequest("The specified grant type is not supported."); } private async Task<IActionResult> HandlePasswordGrantType(OpenIddictRequest request) { // 这里实现您的用户验证逻辑 // 注意:这不使用ASP.NET Core Identity var username = request.Username; var password = request.Password; // 示例:验证用户凭据 if (username == "admin" && password == "password") { var identity = new ClaimsIdentity( OpenIddictServerAspNetCoreDefaults.AuthenticationScheme, OpenIddictConstants.Claims.Name, OpenIddictConstants.Claims.Role); // 添加声明 identity.AddClaim(OpenIddictConstants.Claims.Subject, username); identity.AddClaim(OpenIddictConstants.Claims.Name, username); identity.AddClaim(ClaimTypes.Role, "Administrator"); var principal = new ClaimsPrincipal(identity); principal.SetScopes(new[] { OpenIddictConstants.Scopes.OpenId, OpenIddictConstants.Scopes.Email, OpenIddictConstants.Scopes.Profile, OpenIddictConstants.Scopes.Roles }); return SignIn(principal, OpenIddictServerAspNetCoreDefaults.AuthenticationScheme); } return BadRequest("Invalid username or password."); } private async Task<IActionResult> HandleClientCredentialsGrantType(OpenIddictRequest request) { // 验证客户端凭据 var application = await _applicationManager.FindByClientIdAsync(request.ClientId); if (application == null) { return BadRequest("The specified client identifier is invalid."); } var identity = new ClaimsIdentity( OpenIddictServerAspNetCoreDefaults.AuthenticationScheme, OpenIddictConstants.Claims.Name, OpenIddictConstants.Claims.Role); identity.AddClaim(OpenIddictConstants.Claims.Subject, request.ClientId); identity.AddClaim(OpenIddictConstants.Claims.Name, await _applicationManager.GetDisplayNameAsync(application)); var principal = new ClaimsPrincipal(identity); principal.SetScopes(request.GetScopes()); return SignIn(principal, OpenIddictServerAspNetCoreDefaults.AuthenticationScheme); } private async Task<IActionResult> HandleRefreshTokenGrantType(OpenIddictRequest request) { // 获取当前用户信息(从认证信息中) var result = await HttpContext.AuthenticateAsync(OpenIddictServerAspNetCoreDefaults.AuthenticationScheme); if (!result.Succeeded) { return BadRequest("Invalid refresh token."); } var identity = new ClaimsIdentity(result.Principal.Claims, OpenIddictServerAspNetCoreDefaults.AuthenticationScheme, OpenIddictConstants.Claims.Name, OpenIddictConstants.Claims.Role); var principal = new ClaimsPrincipal(identity); principal.SetScopes(request.GetScopes()); return SignIn(principal, OpenIddictServerAspNetCoreDefaults.AuthenticationScheme); } } }
8. 创建受保护的API控制器
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; namespace Rail.AuthServer.Controllers { [ApiController] [Route("api/[controller]")] [Authorize] public class ProtectedController : ControllerBase { [HttpGet] public IActionResult Get() { return Ok(new { Message = "This is a protected resource!", User = User.Identity.Name, Claims = User.Claims.Select(c => new { c.Type, c.Value }) }); } } }
9. 测试
测试1
https://localhost:7231/connect/token

测试2

测试3

10. 过期时间设置
1) 全局设置
// 添加OpenIddict服务 builder.Services.AddOpenIddict() .AddCore(options => { options.UseEntityFrameworkCore() .UseDbContext<DataBaseOpenAuth>(); }) .AddServer(options => { // 各种token的默认过期时间 options.SetAccessTokenLifetime(TimeSpan.FromHours(1)); // 访问令牌:1小时 options.SetRefreshTokenLifetime(TimeSpan.FromDays(30)); // 刷新令牌:30天 options.SetAuthorizationCodeLifetime(TimeSpan.FromMinutes(10)); // 授权码:10分钟 options.SetIdentityTokenLifetime(TimeSpan.FromHours(1)); // 身份令牌:1小时 options.SetUserCodeLifetime(TimeSpan.FromMinutes(5)); // 用户码:5分钟 options.SetDeviceCodeLifetime(TimeSpan.FromMinutes(15)); // 设备码:15分钟 // 刷新令牌设置 ,滚动刷新令牌配置 - OpenIddict 7 方式 options.SetRefreshTokenReuseLeeway(TimeSpan.Zero); // 设置为0表示禁用重用 })
2)为特定客户端设置
// Client Credentials 客户端 if (await manager.FindByClientIdAsync("service_app") is null) { await manager.CreateAsync(new OpenIddictApplicationDescriptor { ClientId = "service_app", ClientSecret = "service_secret", DisplayName = "Service Application", Permissions = { Permissions.Endpoints.Token, Permissions.GrantTypes.ClientCredentials }, Settings = { // 为特定客户端设置不同的过期时间 [OpenIddictConstants.Settings.TokenLifetimes.AccessToken] = "01:00:00", // 1小时 [OpenIddictConstants.Settings.TokenLifetimes.RefreshToken] = "30.00:00:00" // 30天 } }); }
3)动态设置
在TokenController中动态设置过期时间private async Task<IActionResult> HandlePasswordGrantType(OpenIddictRequest request) { var username = request.Username; var password = request.Password; // 自定义用户验证逻辑 if (await ValidateUserCredentialsAsync(username, password)) { var identity = new ClaimsIdentity( authenticationType: TokenValidationParameters.DefaultAuthenticationType, nameType: Claims.Name, roleType: Claims.Role); // 添加声明 identity.AddClaim(Claims.Subject, username); identity.AddClaim(Claims.Name, username); identity.AddClaim(Claims.Email, $"{username}@example.com"); identity.AddClaim(Claims.Role, "User"); // 设置主体和范围 var principal = new ClaimsPrincipal(identity); principal.SetScopes( Scopes.OpenId, Scopes.Email, Scopes.Profile, Scopes.OfflineAccess); // 包含刷新令牌 principal.SetResources("resource_server"); //return SignIn(principal, OpenIddictServerAspNetCoreDefaults.AuthenticationScheme); // OpenIddict 7 中设置自定义属性的新方式 var properties = new AuthenticationProperties(new Dictionary<string, string?> { // 使用新的常量名称 ["oi_atm"] = TimeSpan.FromHours(2).TotalSeconds.ToString(), // Access Token Lifetime ["oi_rtm"] = TimeSpan.FromDays(14).TotalSeconds.ToString(), // Refresh Token Lifetime ["oi_itim"] = TimeSpan.FromHours(2).TotalSeconds.ToString() // Identity Token Lifetime }); return SignIn(principal, properties, OpenIddictServerAspNetCoreDefaults.AuthenticationScheme); }
期于角色设置
private async Task<IActionResult> HandlePasswordGrantType(OpenIddictRequest request) { var username = request.Username; var password = request.Password; // 自定义用户验证逻辑 if (await ValidateUserCredentialsAsync(username, password)) { var identity = new ClaimsIdentity( authenticationType: TokenValidationParameters.DefaultAuthenticationType, nameType: Claims.Name, roleType: Claims.Role); // 添加声明 identity.AddClaim(Claims.Subject, username); identity.AddClaim(Claims.Name, username); identity.AddClaim(Claims.Email, $"{username}@example.com"); identity.AddClaim(Claims.Role, "User"); // 设置主体和范围 var principal = new ClaimsPrincipal(identity); principal.SetScopes( Scopes.OpenId, Scopes.Email, Scopes.Profile, Scopes.OfflineAccess); // 包含刷新令牌 principal.SetResources("resource_server"); //return SignIn(principal, OpenIddictServerAspNetCoreDefaults.AuthenticationScheme); //// OpenIddict 7 中设置自定义属性的新方式 TimeSpan accessTokenLifetime; TimeSpan refreshTokenLifetime; // 根据用户角色设置不同的过期时间 if (principal.IsInRole("Administrator")) { accessTokenLifetime = TimeSpan.FromHours(4); // 管理员4小时 refreshTokenLifetime = TimeSpan.FromDays(60); // 管理员60天 } else { accessTokenLifetime = TimeSpan.FromHours(1); // 普通用户1小时 refreshTokenLifetime = TimeSpan.FromDays(7); // 普通用户7天 } var properties = new AuthenticationProperties(new Dictionary<string, string?> { // 使用新的常量名称 ["oi_atm"] = accessTokenLifetime.TotalSeconds.ToString(), // Access Token Lifetime ["oi_rtm"] = refreshTokenLifetime.TotalSeconds.ToString(), // Refresh Token Lifetime }); return SignIn(principal, properties, OpenIddictServerAspNetCoreDefaults.AuthenticationScheme); } return BadRequest(new OpenIddictResponse { Error = Errors.InvalidGrant, ErrorDescription = "Invalid username or password." }); }
10. 使令牌失效
在Program.cs里面使用 Reference Token 模式
//使用 Reference Token options.UseReferenceAccessTokens(); options.UseReferenceRefreshTokens();
创建退出登录接口、管理员使用户退出接口
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using OpenIddict.Abstractions; using OpenIddict.Validation.AspNetCore; using static OpenIddict.Abstractions.OpenIddictConstants; namespace Rail.AuthServer.Controllers { [ApiController] [Route("api/[controller]")] [Authorize] public class LogoutController : ControllerBase { private readonly IOpenIddictTokenManager _tokenManager; public LogoutController(IOpenIddictTokenManager tokenManager) { _tokenManager = tokenManager; } [HttpPost("logout")] public async Task<IActionResult> Logout() { // 这里的 sub 是用户的唯一标识(UserId) var userId = User.FindFirst(OpenIddictConstants.Claims.Subject)?.Value; if (string.IsNullOrEmpty(userId)) { return BadRequest("User id not found in token."); } await foreach (var token in _tokenManager.FindBySubjectAsync(userId)) { await _tokenManager.TryRevokeAsync(token); } return Ok(new { message = "User logged out, all tokens revoked." }); } [HttpPost("revoke-user-tokens")] public async Task<IActionResult> RevokeUserTokens([FromBody] string userId) { await foreach (var token in _tokenManager.FindBySubjectAsync(userId)) { await _tokenManager.TryRevokeAsync(token); } return Ok(new { message = $"All tokens for user {userId} revoked." }); } [HttpPost("revoke-client")] public async Task<IActionResult> RevokeClientTokens([FromBody] string clientId, [FromServices] IOpenIddictApplicationManager applicationManager, [FromServices] IOpenIddictTokenManager tokenManager) { // 先找到 Application var application = await applicationManager.FindByClientIdAsync(clientId); if (application == null) { return NotFound(new { message = $"Client {clientId} not found." }); } // 再查这个 Application 下面的所有 Token await foreach (var token in tokenManager.FindByApplicationIdAsync(await applicationManager.GetIdAsync(application))) { await tokenManager.TryRevokeAsync(token); } return Ok(new { message = $"All tokens for client {clientId} revoked." }); } } }
11. 使刷新令牌
通过用户登录获取到刷新令牌


12. 集成到 Swagger
在 Program.cs 里面中配置
builder.Services.AddSwaggerGen(options => { options.SwaggerDoc("v1", new() { Title = "My API", Version = "v1" }); // 定义 Bearer 安全方案 options.AddSecurityDefinition("Bearer", new Microsoft.OpenApi.Models.OpenApiSecurityScheme { Name = "Authorization", Type = Microsoft.OpenApi.Models.SecuritySchemeType.Http, Scheme = "bearer", BearerFormat = "JWT", In = Microsoft.OpenApi.Models.ParameterLocation.Header, Description = "在下方输入 'Bearer {token}'" }); // 在每个请求中应用安全要求 options.AddSecurityRequirement(new Microsoft.OpenApi.Models.OpenApiSecurityRequirement { { new Microsoft.OpenApi.Models.OpenApiSecurityScheme { Reference = new Microsoft.OpenApi.Models.OpenApiReference { Type = Microsoft.OpenApi.Models.ReferenceType.SecurityScheme, Id = "Bearer" } }, new string[] {} } }); });
if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(options => { options.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1"); options.DocumentTitle = "My API Docs"; }); }

13. 获取用户信息
增加控制器 UserInfoController
[ApiController] [Route("connect")] public class UserInfoController : ControllerBase { [HttpGet("userinfo")] [HttpPost("userinfo")] [Authorize(AuthenticationSchemes = OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme)] public async Task<IActionResult> UserInfo() { var claims = new Dictionary<string, object> { [Claims.Subject] = User.FindFirst(Claims.Subject)?.Value ?? "", [Claims.Name] = User.FindFirst(Claims.Name)?.Value ?? "", [Claims.Email] = User.FindFirst(Claims.Email)?.Value ?? "", [Claims.Role] = User.FindFirst(Claims.Role)?.Value ?? "User" }; return Ok(claims); } }

14. 单独客户端项目 使用权限服务
1)鉴权服务项目
并不需要 /connect/authorize 这个控制器
需要设置 resource_server ,在/connect/token接口里面,每个登录校验里面 设置
principal.SetResources("resource_server");
2)API 项目
创建 .net8 客户端项目 Rail.TmClient
增加 nuget 包 OpenIddict.Validation.AspNetCore ,版本:7.0.0
增加 nuget 包 OpenIddict.Validation.SystemNetHttp ,版本:7.0.0

调整Program.cs
using OpenIddict.Validation.AspNetCore; var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddControllers(); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); builder.Services.AddOpenIddict() .AddValidation(options => { options.SetIssuer("https://localhost:7231/"); // 授权服务器的地址 options.AddAudiences("resource_server"); // 资源服务器的标识 // Reference Token → 必须用 introspection options.UseIntrospection() .SetClientId("service_app") // 你在 AuthServer 注册的 client_id .SetClientSecret("service_secret"); // 你在 AuthServer 注册的 client_secret options.UseSystemNetHttp(); // 使用 System.Net.Http 进行 HTTP 请求 options.UseAspNetCore(); // 与 ASP.NET Core 集成 }); // 添加认证服务 builder.Services.AddAuthentication(options => { options.DefaultAuthenticateScheme = OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme; options.DefaultChallengeScheme = OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme; }); builder.Services.AddAuthorization(); var app = builder.Build(); // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } app.UseHttpsRedirection(); app.UseAuthentication(); // 注意顺序 app.UseAuthorization(); app.MapControllers(); app.Run();
增加控制器
[ApiController] [Route("api/[controller]")] public class OrdersController : ControllerBase { // 需要 token 才能访问 [HttpGet] [Authorize] public IActionResult GetOrders() { return Ok(new[] { "Order1", "Order2" }); } // 允许匿名访问 [HttpGet("public")] [AllowAnonymous] public IActionResult PublicInfo() { return Ok("任何人都能访问,不需要 Token"); } }
调用结果

15. scopes 的使用
在 授权服务器配置里,需要注册可用 Scope
// 添加OpenIddict服务 builder.Services.AddOpenIddict() .AddServer(options => { // 注册范围 options.RegisterScopes( Scopes.Email, Scopes.Profile, Scopes.Roles, Scopes.OfflineAccess,// 包含刷新令牌 "api", "client_tm_server.read", "client_tm_server.write"); })
Scope 和 Resource/Audience 在 OpenIddict 中对齐
在 /connect/token 获取token校验接口里面设置,这里以客户端凭据为例,还需要设置 密码凭据,refresh_token 凭据
private async Task<IActionResult> HandleClientCredentialsGrantType(OpenIddictRequest request) { var application = await _applicationManager.FindByClientIdAsync(request.ClientId); if (application is null) { return BadRequest(new OpenIddictResponse { Error = Errors.InvalidClient, ErrorDescription = "The specified client identifier is invalid." }); } var identity = new ClaimsIdentity( authenticationType: TokenValidationParameters.DefaultAuthenticationType, nameType: Claims.Name, roleType: Claims.Role); identity.AddClaim(Claims.Subject, request.ClientId); identity.AddClaim(Claims.Name, await _applicationManager.GetDisplayNameAsync(application)); var principal = new ClaimsPrincipal(identity); principal.SetScopes(request.GetScopes()); //principal.SetResources("client_tm_server"); // 根据 Scope 设置 Resource / Audience var resources = new List<string>(); if (principal.HasScope("client_tm_server.read") || principal.HasScope("client_tm_server.write")) { resources.Add("client_tm_server"); } return SignIn(principal, OpenIddictServerAspNetCoreDefaults.AuthenticationScheme); }
待优化
3. 反代
end
 
                     
                    
                 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号