我有一个 Web API,目前由 ASP.NET MVC Web 应用程序中的 AngularJS 应用程序使用。 MVC 应用程序使用 ASP.NET Forms Authentication 作为身份验证机制。 当客户端不是 Web 客户端而是例如,我应该如何对 Web API 的用户进行身份验证一个独立的服务。我现在所做的是向 Web API 添加一个登录方法,让任何拥有正确凭据的人都可以访问:
[Route("api/v2/login"), HttpPost]
[AllowAnonymous]
public IHttpActionResult Post([FromBody]Credentials credentials)
{
var principal = FindPrincipal(credentials);
if (principal != null)
{
FormsAuthentication.SetAuthCookie(principal.Identity.Name, false);
return Ok();
}
return Unauthorized();
}
我的问题是这是应该如何解决还是有更好的方法?
最佳答案
WebApi2可以使用token认证机制。
流程将是这样的:
用户向您发送 https 请求:
请求的内容类型应该是:
application/x-www-form-urlencoded
正文应该包括:
grant_type=password&username=yourWebsFormsUsername&password=yourWebFormsPassword
您的 OWIN 启动类看起来像这样:
public partial class Startup
{
public static OAuthAuthorizationServerOptions OAuthOptions { get; private set; }
public static string PublicClientId { get; private set; }
public void ConfigureAuth(IAppBuilder app)
{
app.UseCookieAuthentication(new CookieAuthenticationOptions());
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
PublicClientId = "self";
OAuthOptions = new OAuthAuthorizationServerOptions
{
TokenEndpointPath = new PathString("/Token"),
Provider = new YourOAuthProvider(),
AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
AllowInsecureHttp = true,
};
app.UseOAuthBearerTokens(OAuthOptions);
}
}
注意上面的 YourOAuthProvider,这是重要的部分。这是您的自定义提供程序,它将根据您拥有的任何凭证存储来验证您的用户名/密码。在您的情况下是 aspnet_membership 表。此验证在下面的 RequestHasValidCredentials 方法中完成:
public class YourOAuthProvider : OAuthAuthorizationServerProvider
{
public string apikey = string.Empty;
public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
context.Validated();
}
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
if (RequestHasValidCredentials(context.UserName, context.Password))
{
var id = new ClaimsIdentity(context.Options.AuthenticationType);
id.AddClaim(new Claim("username", context.UserName));
context.Validated(id);
}
else
{
context.SetError("invalid_grant", "The user name or password is incorrect.");
return;
}
}
}
您的用户对上述内容的响应将是一个 token ,其中将包括用户名或您在上述方法中添加到上下文中的任何其他信息:
id.AddClaim(new Claim("username", context.UserName));
上述 token api 调用的响应将如下所示:
{
"access_token": "9TIpW2m2rUbB_Bmb7kKAQ9GH4hgfnKF8g3fL0tAre2gcFjI45fajmG6qdOJe-A",
"token_type": "bearer",
"expires_in": 1209599
}
然后您的用户必须将此 token 作为所有 API 调用的 Http 授权 header 传递。他们需要使用 Bearer 方案传递它,例如:
Bearer 9TIpW2m2rUbB_Bmb7kKAQ9GH4hgfnKF8g3fL0tAre2gcFjI45fajmG6qdOJe-A
由于此 token 包含用户名,您将能够知道用户是谁。现在最后一件事是读取此 token 并检索用户名。为此,您需要创建自定义 Authorize 属性,并用它装饰您的 Controller 或方法。
public class YourAuthorizeAttribute : AuthorizationFilterAttribute
{
public override void OnAuthorization(HttpActionContext actionContext)
{
var ticket = Startup.OAuthOptions.AccessTokenFormat.Unprotect(actionContext.Request.Headers.Authorization.Parameter);
string username = claims.Where(x => x.Type == "username").FirstOrDefault();
base.OnAuthorization(actionContext);
}
}
一旦您拥有用户名,就可以在此处添加所有其他自定义授权逻辑。
可以在生成token的时候传入其他自定义信息,在这里读取。 (如果您需要任何其他特殊授权逻辑。)
它的方法很冗长,但适用于任何凭据存储。
关于c# - 作为遗留 ASP.NET MVC 应用程序的一部分时,如何在 Web API 2 中对用户进行身份验证?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31105246/