.NET Framework 4.8 Web API多认证方式需设为OR而非AND
在.NET Framework 4.8 Web API中实现多认证方案的OR逻辑
在.NET Framework 4.8的OWIN Web API中,默认认证机制是链式AND逻辑(按注册顺序依次验证,需全部通过),但可以通过自定义授权属性实现OR逻辑(任意指定认证方案通过即可)。以下是具体实现步骤:
1. 明确各认证方案的标识
先确认现有认证的方案名称:
- Salesforce:配置中已指定
AuthenticationType = "Salesforce" - Okta:对应
ApiAuthenticationScheme(你的启动代码中传入的参数) - Basic认证:若通过OWIN中间件实现,需指定
AuthenticationType = "Basic";若为自定义Autofac Filter,需保留原有验证逻辑并兼容后续判断
2. 自定义支持OR逻辑的授权属性
重写AuthorizeAttribute,遍历指定的认证方案,逐个尝试认证,只要有一个通过即允许访问:
public class MultiSchemeAuthorizeAttribute : AuthorizeAttribute { public string[] AllowedSchemes { get; set; } protected override bool AuthorizeCore(HttpContextBase httpContext) { if (httpContext == null) throw new ArgumentNullException(nameof(httpContext)); var owinContext = httpContext.GetOwinContext(); // 遍历所有允许的认证方案,尝试认证 foreach (var scheme in AllowedSchemes) { // 先检查当前用户是否已通过该方案认证 if (httpContext.User.Identity.IsAuthenticated && httpContext.User.Identity.AuthenticationType == scheme) { return true; } // 触发该方案的认证流程 var authResult = owinContext.Authentication.AuthenticateAsync(scheme).Result; if (authResult != null && authResult.Identity != null && authResult.Identity.IsAuthenticated) { // 将通过认证的身份赋值给当前用户 httpContext.User = new ClaimsPrincipal(authResult.Identity); return true; } } // 所有方案都未通过认证 return false; } }
3. 调整认证中间件为被动模式
将Salesforce和Okta认证中间件的AuthenticationMode设为Passive,避免主动触发认证干扰逻辑:
// Salesforce认证配置 var saleforceoption = new SalesforceAuthenticationOptions { ClientId = authSettings.SaleforceClientId, ClientSecret = authSettings.SaleforceClientSecret, AuthenticationType = "Salesforce", AuthenticationMode = AuthenticationMode.Passive, // 改为被动模式 Prompt = "login", Endpoints = new SalesforceAuthenticationOptions.SalesforceAuthenticationEndpoints { AuthorizationEndpoint = $"https://{authSettings.SalesforceCompanyDomain}/services/oauth2/authorize", TokenEndpoint = $"https://{authSettings.SalesforceCompanyDomain}/services/oauth2/token" } }; app.UseSalesforceAuthentication(saleforceoption); // Okta认证配置 public static void AddAuthenticationConfiguration(this IAppBuilder app) { var oktaOptions = new OktaWebApiOptions { OktaDomain = "https://some.domain.com", AuthorizationServerId = "default" }; app.UseOktaWebApi(ApiAuthenticationScheme, oktaOptions); }
兼容原有Basic认证
若Basic认证通过IAutofacAuthorizationFilter实现,需确保:
- 该Filter优先于自定义授权属性执行
- 在
MultiSchemeAuthorizeAttribute的AuthorizeCore方法中,额外检查Basic认证的结果(例如判断httpContext.User是否已通过Basic认证)
若改为OWIN Basic认证中间件,配置如下:
app.UseBasicAuthentication(new BasicAuthenticationOptions { AuthenticationType = "Basic", AuthenticationMode = AuthenticationMode.Passive, Provider = new BasicAuthenticationProvider { OnValidateCredentials = async context => { // 原有Basic认证逻辑:验证用户名密码 bool isValid = /* 你的验证逻辑 */; if (isValid) { context.Identity = new ClaimsIdentity(new[] { new Claim(ClaimTypes.Name, context.UserName) }, "Basic"); } await Task.CompletedTask; } } });
4. 在控制器上应用自定义授权属性
- 原需Salesforce认证的控制器:支持Salesforce或Okta认证
[MultiSchemeAuthorize(AllowedSchemes = new[] { "Salesforce", ApiAuthenticationScheme })] public class SalesforceProtectedController : ApiController { // 控制器逻辑 }
- 原需Basic认证的控制器:支持Basic或Okta认证
[MultiSchemeAuthorize(AllowedSchemes = new[] { "Basic", ApiAuthenticationScheme })] public class BasicProtectedController : ApiController { // 控制器逻辑 }
内容的提问来源于stack exchange,提问作者waching
相关产品推荐
相关产品推荐

