You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 06:05:19