gpt4 book ai didi

asp.net-web-api2 - 使用 OWIN 和 ASP.NET WEB API 的基本身份验证中间件

转载 作者:行者123 更新时间:2023-12-02 07:54:30 25 4
gpt4 key购买 nike

我创建了一个 ASP.NET WEB API 2.2 项目。我将基于 Windows Identity Foundation 的模板用于 Visual Studio see it here 中提供的个人帐户。 .

Web 客户端(用 AngularJS 编写)使用 OAUTH 实现和 Web 浏览器 cookie 来存储 token 和刷新 token 。我们受益于有用的 UserManagerRoleManager 类来管理用户及其角色。OAUTH 和 Web 浏览器客户端一切正常。

但是,对于基于桌面的客户端的一些复古兼容性问题,我还需要支持基本身份验证。理想情况下,我希望 [Authorize][Authorize(Role = "administrators")] 等属性能够与 OAUTH 和基本身份验证方案一起使用。

因此,遵循 LeastPrivilege 中的代码我创建了一个继承自 AuthenticationMiddleware 的 OWIN BasicAuthenticationMiddleware。 我来到了下面的实现。对于BasicAuthenticationMiddleWare,与 Leastprivilege 的代码相比,仅处理程序发生了变化。实际上我们使用 ClaimsIdentity 而不是一系列Claim

 class BasicAuthenticationHandler: AuthenticationHandler<BasicAuthenticationOptions>
{
private readonly string _challenge;

public BasicAuthenticationHandler(BasicAuthenticationOptions options)
{
_challenge = "Basic realm=" + options.Realm;
}

protected override async Task<AuthenticationTicket> AuthenticateCoreAsync()
{
var authzValue = Request.Headers.Get("Authorization");
if (string.IsNullOrEmpty(authzValue) || !authzValue.StartsWith("Basic ", StringComparison.OrdinalIgnoreCase))
{
return null;
}

var token = authzValue.Substring("Basic ".Length).Trim();
var claimsIdentity = await TryGetPrincipalFromBasicCredentials(token, Options.CredentialValidationFunction);

if (claimsIdentity == null)
{
return null;
}
else
{
Request.User = new ClaimsPrincipal(claimsIdentity);
return new AuthenticationTicket(claimsIdentity, new AuthenticationProperties());
}
}

protected override Task ApplyResponseChallengeAsync()
{
if (Response.StatusCode == 401)
{
var challenge = Helper.LookupChallenge(Options.AuthenticationType, Options.AuthenticationMode);
if (challenge != null)
{
Response.Headers.AppendValues("WWW-Authenticate", _challenge);
}
}

return Task.FromResult<object>(null);
}

async Task<ClaimsIdentity> TryGetPrincipalFromBasicCredentials(string credentials,
BasicAuthenticationMiddleware.CredentialValidationFunction validate)
{
string pair;
try
{
pair = Encoding.UTF8.GetString(
Convert.FromBase64String(credentials));
}
catch (FormatException)
{
return null;
}
catch (ArgumentException)
{
return null;
}

var ix = pair.IndexOf(':');
if (ix == -1)
{
return null;
}

var username = pair.Substring(0, ix);
var pw = pair.Substring(ix + 1);

return await validate(username, pw);
}

然后在 Startup.Auth 中,我声明以下委托(delegate)来验证身份验证(仅检查用户是否存在以及密码是否正确并生成关联的 ClaimsIdentity)

 public void ConfigureAuth(IAppBuilder app)
{
app.CreatePerOwinContext(DbContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);

Func<string, string, Task<ClaimsIdentity>> validationCallback = (string userName, string password) =>
{
using (DbContext dbContext = new DbContext())
using(UserStore<ApplicationUser> userStore = new UserStore<ApplicationUser>(dbContext))
using(ApplicationUserManager userManager = new ApplicationUserManager(userStore))
{
var user = userManager.FindByName(userName);
if (user == null)
{
return null;
}
bool ok = userManager.CheckPassword(user, password);
if (!ok)
{
return null;
}
ClaimsIdentity claimsIdentity = userManager.CreateIdentity(user, DefaultAuthenticationTypes.ApplicationCookie);
return Task.FromResult(claimsIdentity);
}
};

var basicAuthOptions = new BasicAuthenticationOptions("KMailWebManager", new BasicAuthenticationMiddleware.CredentialValidationFunction(validationCallback));
app.UseBasicAuthentication(basicAuthOptions);
// Configure the application for OAuth based flow
PublicClientId = "self";
OAuthOptions = new OAuthAuthorizationServerOptions
{
TokenEndpointPath = new PathString("/Token"),
Provider = new ApplicationOAuthProvider(PublicClientId),
//If the AccessTokenExpireTimeSpan is changed, also change the ExpiresUtc in the RefreshTokenProvider.cs.
AccessTokenExpireTimeSpan = TimeSpan.FromHours(2),
AllowInsecureHttp = true,
RefreshTokenProvider = new RefreshTokenProvider()
};

// Enable the application to use bearer tokens to authenticate users
app.UseOAuthBearerTokens(OAuthOptions);
}

但是,即使在处理程序的 AuthenticationAsyncCore 方法中设置 Request.User[Authorize] 属性也无法按预期工作:响应每次我尝试使用基本身份验证方案时,都会出现错误 401 未经授权。知道出了什么问题吗?

最佳答案

我找到了罪魁祸首,在 WebApiConfig.cs 文件中,“个人用户”模板插入了以下几行。

//// Web API configuration and services
//// Configure Web API to use only bearer token authentication.
config.SuppressDefaultHostAuthentication();
config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));

因此我们还必须注册我们的BasicAuthenticationMiddleware

config.SuppressDefaultHostAuthentication();
config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
config.Filters.Add(new HostAuthenticationFilter(BasicAuthenticationOptions.BasicAuthenticationType));

其中BasicAuthenticationType是常量字符串“Basic”,它被传递给BasicAuthenticationOptions的基本构造函数

public class BasicAuthenticationOptions : AuthenticationOptions
{
public const string BasicAuthenticationType = "Basic";

public BasicAuthenticationMiddleware.CredentialValidationFunction CredentialValidationFunction { get; private set; }

public BasicAuthenticationOptions( BasicAuthenticationMiddleware.CredentialValidationFunction validationFunction)
: base(BasicAuthenticationType)
{
CredentialValidationFunction = validationFunction;
}
}

关于asp.net-web-api2 - 使用 OWIN 和 ASP.NET WEB API 的基本身份验证中间件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31549855/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com