当前位置: 首页 > news >正文

旅游手机网站模板网店运营推广

旅游手机网站模板,网店运营推广,深圳室内装修公司,设计网站制作ABP vNext OpenIddict:自定义 OAuth2/OpenID Connect 认证策略 🚀 📑 目录 ABP vNext OpenIddict:自定义 OAuth2/OpenID Connect 认证策略 🚀🧠 背景与核心设计思路🛠 依赖注入与启动配置&…

ABP vNext + OpenIddict:自定义 OAuth2/OpenID Connect 认证策略 🚀


📑 目录

  • ABP vNext + OpenIddict:自定义 OAuth2/OpenID Connect 认证策略 🚀
    • 🧠 背景与核心设计思路
    • 🛠 依赖注入与启动配置
    • 🔑 系统配置:注册 Token 授权管道
    • 🔧 自定义授权处理器:ApiKeyGrantHandler
    • 🏢 租户解析与多租户 SSO
      • Contributor 实现
      • 注入配置
      • 上下文切换
        • 🌀 多租户解析流程
    • 📋 接口定义:IApiKeyValidator
    • 📈 Scope & Client 动态管理
        • 🔄 Client 管理流程
    • 🧪 接口调用示例
      • 1. API Key 授权成功
      • 2. 刷新令牌示例
        • 🔄 刷新流程图
    • 🔐 安全加固建议
    • 📁 项目结构推荐


🧠 背景与核心设计思路

大型 SaaS 系统常见需求:

  1. 自定义身份来源(API Key、Device Flow)
  2. 多租户隔离与 SSO
  3. 精细化 Scope/资源管理

ABP 的 OpenIddict 模块提供 Handler 模型 插槽,轻松插入自定义授权逻辑。


🛠 依赖注入与启动配置

public class AuthServerModule : AbpModule
{public override void ConfigureServices(ServiceConfigurationContext context){var services = context.Services;// ➤ 注册 OpenIddict 核心 + Server + Validationservices.AddOpenIddict().AddCore(options => { /* 实体存储等 */ }).AddServer(options => { /* 稍后配置 */ }).AddValidation(options => { /* 稍后配置 */ });// ➤ 多租户解析services.Configure<AbpTenantResolveOptions>(opts =>{opts.Resolvers.Insert(0, new HeaderTenantResolveContributor());opts.Resolvers.Insert(1, new DomainTenantResolveContributor());});}
}

🔑 系统配置:注册 Token 授权管道

PreConfigure<OpenIddictBuilder>(builder =>
{builder.AddServer(options =>{// —— 端点 ——  options.SetTokenEndpointUris("/connect/token").SetAuthorizationEndpointUris("/connect/authorize").SetDeviceEndpointUris("/connect/device");// —— Grant & Scope ——  options.RegisterGrantType("api_key_grant").AllowPasswordFlow().AllowClientCredentialsFlow().AllowRefreshTokenFlow().AllowExtensionGrantType("api_key_grant").SetDefaultScopes("api", "profile");// —— 有效期 ——  options.SetAccessTokenLifetime(TimeSpan.FromHours(2)).SetRefreshTokenLifetime(TimeSpan.FromDays(7));// —— ASP.NET Core 集成 ——  options.UseAspNetCore().EnableTokenEndpointPassthrough();// —— 自定义 Handler ——  options.AddEventHandler<HandleTokenRequestContext>(cfg =>cfg.UseScopedHandler<ApiKeyGrantHandler>().SetOrder(OpenIddictServerHandlers.Authentication.ValidateTokenRequest.Descriptor.Order + 1).SetFilter(ctx => ctx.Request.GrantType == "api_key_grant"));});builder.AddValidation(options =>{options.UseLocalServer();options.UseAspNetCore();});
});

🔧 自定义授权处理器:ApiKeyGrantHandler

public class ApiKeyGrantHandler : IOpenIddictServerHandler<HandleTokenRequestContext>
{private readonly IApiKeyValidator _apiKeyValidator;private readonly ICurrentTenant   _currentTenant;private readonly ILogger<ApiKeyGrantHandler> _logger;public ApiKeyGrantHandler(IApiKeyValidator apiKeyValidator,ICurrentTenant   currentTenant,ILogger<ApiKeyGrantHandler> logger){_apiKeyValidator = apiKeyValidator;_currentTenant   = currentTenant;_logger          = logger;}public async ValueTask HandleAsync(HandleTokenRequestContext context){using var scope = _logger.BeginScope(new { GrantType = "api_key" });try{var apiKey = context.Request.GetParameter("api_key")?.ToString();if (string.IsNullOrWhiteSpace(apiKey)){context.Reject(Errors.InvalidRequest, "Missing API Key");return;}var userId = await _apiKeyValidator.ValidateAsync(apiKey);if (string.IsNullOrEmpty(userId)){context.Reject(Errors.InvalidGrant, "Invalid API Key");return;}var tenantId = _currentTenant.Id?.ToString() ?? "default";var claims = new[]{new Claim(Claims.Subject,  userId),new Claim("tenant_id",    tenantId),new Claim(Claims.Name,     "API Key User")};var identity  = new ClaimsIdentity(claims, OpenIddictServerAspNetCoreDefaults.AuthenticationScheme);var principal = new ClaimsPrincipal(identity);// 设置 Scopes & Resource  principal.SetScopes(context.Request.GetScopes());principal.SetResources("api");// 顶层返回 tenant_id  context.AddParameter("tenant_id", tenantId);context.Validate(principal);context.HandleRequest();}catch (Exception ex){_logger.LogError(ex, "API Key grant failed.");context.Reject(Errors.ServerError, "Internal error.");}}
}

🏢 租户解析与多租户 SSO

Contributor 实现

public class DomainTenantResolveContributor : HttpTenantResolveContributorBase
{public override Task<string> ResolveAsync(HttpContext context){var sub = context.Request.Host.Host.Split('.').FirstOrDefault();return Task.FromResult(string.IsNullOrWhiteSpace(sub) ? "default" : sub);}
}public class HeaderTenantResolveContributor : HttpTenantResolveContributorBase
{public override Task<string> ResolveAsync(HttpContext context){var header = context.Request.Headers["X-Tenant-Id"].FirstOrDefault();return Task.FromResult(string.IsNullOrWhiteSpace(header) ? "default" : header);}
}

注入配置

services.Configure<AbpTenantResolveOptions>(opts =>
{opts.Resolvers.Insert(0, new HeaderTenantResolveContributor());opts.Resolvers.Insert(1, new DomainTenantResolveContributor());
});

上下文切换

using (_currentTenant.Change(tenantId))
{// 此作用域内,TenantId 生效  
}
🌀 多租户解析流程
Yes
No
Yes
No
Incoming HTTP Request
Has X-Tenant-Id Header?
Use HeaderTenantResolveContributor
Host Subdomain Exists?
Use DomainTenantResolveContributor
Fallback to default
Set CurrentTenant

📋 接口定义:IApiKeyValidator

public interface IApiKeyValidator
{/// <summary>/// 校验 API Key 并返回对应用户ID;失败返回 null/empty/// 实现可结合 IMemoryCache/IDistributedCache 缓存/// </summary>Task<string> ValidateAsync(string apiKey);
}

📈 Scope & Client 动态管理

[Authorize(Roles = "Admin")]
public class ScopeAppService : ApplicationService
{private readonly IOpenIddictScopeManager _scopeManager;public async Task<List<string>> GetScopesAsync(){var list = new List<string>();await foreach (var s in _scopeManager.ListAsync())list.Add(s.Name);return list;}
}[Authorize(Roles = "Admin")]
public class ClientAppService : ApplicationService
{private readonly IOpenIddictApplicationManager _appManager;public async Task CreateMobileClientAsync(){var desc = new OpenIddictApplicationDescriptor{ClientId    = "mobile_app",DisplayName = "Mobile App",Permissions ={Permissions.Endpoints.Token,Permissions.GrantTypes.Password}};await _appManager.CreateAsync(desc);}public async Task DeleteClientAsync(string clientId){var app = await _appManager.FindByClientIdAsync(clientId);if (app != null) await _appManager.DeleteAsync(app);}
}
🔄 Client 管理流程
Admin API Manager POST /api/clients (Create) CreateAsync(descriptor) App Created 201 Created DELETE /api/clients/{id} DeleteAsync(app) App Deleted 204 No Content Admin API Manager

🧪 接口调用示例

1. API Key 授权成功

POST /connect/token
Content-Type: application/x-www-form-urlencodedgrant_type=api_key_grant
api_key=valid-api-key
client_id=default
client_secret=secret
scope=api

成功响应:

{"access_token":"eyJhbGciOiJSUzI1NiIs...","token_type":"Bearer","expires_in":7200,"refresh_token":"eyJhbGciOiJIUzI1NiIs...","tenant_id":"tenant1"
}

错误示例:

{"error":"invalid_grant","error_description":"Invalid API Key"
}

2. 刷新令牌示例

POST /connect/token
grant_type=refresh_token
refresh_token={your_refresh_token}
client_id=default
client_secret=secret

刷新成功:

{"access_token":"…","token_type":"Bearer","expires_in":7200,"refresh_token":"…"
}

刷新失败:

{"error":"invalid_grant","error_description":"Refresh token is expired."
}
🔄 刷新流程图
Valid
Invalid
Client sends refresh_token
Server Validate Refresh Token
Issue new access_token & refresh_token
Return invalid_grant error

🔐 安全加固建议

🔒 类型🛡️ 实践建议
API Key哈希存储 + 过期 + 重放防护
限流使用 AspNetCoreRateLimit 保护 /connect/token
审计日志所有 Reject() 写入审计表,方便追踪
签名密钥DataProtection/RSA 证书 + 定期轮换
监控指标OpenTelemetry Meter/Counter 统计授权成功/失败

📁 项目结构推荐

AuthServer.Host
├── CustomGrants/
│   └── ApiKeyGrantHandler.cs
├── Tenanting/
│   ├── DomainTenantResolveContributor.cs
│   └── HeaderTenantResolveContributor.cs
├── Scopes/
│   └── ScopeAppService.cs
├── Clients/
│   └── ClientAppService.cs
├── Validation/
│   └── IApiKeyValidator.cs
├── OpenIddict/
│   └── PreConfiguration.cs
└── Program.cs

http://www.mmbaike.com/news/75359.html

相关文章:

  • wordpress上传失败独立站seo是什么意思
  • 甘肃做网站多少钱seo发展前景怎么样啊
  • 手机app软件开发公司排名seo推广系统
  • 衡水网站建设浩森宇特网络科技公司骗了我36800
  • 成华网站制作高级seo优化招聘
  • 西安网站建设优化青岛建站seo公司
  • 公众号做视频网站吗seo优化教程自学网
  • 保定软件开发公司网络seo培训
  • discuz 企业网站排名优化软件
  • 网站开发与系统开发网络营销方案ppt
  • 百度网站推广关键词怎么查网络营销公司招聘
  • 怎么做化妆品网站内容规划如何开展网络营销
  • 猫咪官网18点击进入专业seo服务商
  • 软件技术开发合同范本绍兴seo排名收费
  • 成都网站建设市场厦门seo网站排名优化
  • 淄博网络公司做网站的电话网络运营具体做什么
  • 华为云网站建设怎么设置选择项seo技术教学视频
  • 网站建设推广运营昆明seo关键字推广
  • wordpress 优惠码主题广东seo点击排名软件哪家好
  • 拱墅网站建设肥城市区seo关键词排名
  • 苏州网络推广苏州网站建设搜索引擎排名
  • 如何做网站的登录日志虎门今日头条新闻
  • 跨境供应链网站建设模板吴中seo页面优化推广
  • 做网站收入来源表免费建站哪个比较好
  • 免费网站建设网站有那些宁波营销型网站建设优化建站
  • 哪家公司的网站做得好aso安卓优化
  • 人才招聘网站建设方案seo包年优化平台
  • 网站模版免费seo学习论坛
  • 网站上百度要怎么做的怎么做产品推广和宣传
  • 南京网站建设网站设计北京优化seo排名优化