如何在Web API 2中验证作为遗留ASP.NET MVC应用程序一部分的用户

本文关键字:NET ASP MVC 应用程序 用户 一部分 Web API 验证 | 更新日期: 2023-09-27 18:00:18

我有一个Web API,AngularJS应用程序目前正在ASP.NET MVC Web应用程序中使用它。MVC应用程序正在使用ASP.NET窗体身份验证作为身份验证机制。当客户端不是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();
}

我的问题是,这是应该如何解决的,还是有更好的方法?

如何在Web API 2中验证作为遗留ASP.NET MVC应用程序一部分的用户

您可以使用WebApi2的令牌身份验证机制。

流程将是这样的:

用户在上向您发送https请求

https://yourApiUrl/Token

请求的内容类型应为:

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;
        }            
    }
}

您的用户对上述内容的响应将是一个令牌,其中将包括用户名或您在上述方法中添加到上下文中的任何其他信息:

id.AddClaim(new Claim("username", context.UserName));

上面的令牌api调用的响应如下:

{
    "access_token": "9TIpW2m2rUbB_Bmb7kKAQ9GH4hgfnKF8g3fL0tAre2gcFjI45fajmG6qdOJe-A",
    "token_type": "bearer",
    "expires_in": 1209599
}

然后,您的用户必须将此令牌作为所有API调用的Http授权头传递。他们需要在使用Bearer方案时通过这一点,例如:

Bearer 9TIpW2m2rUbB_Bmb7kKAQ9GH4hgfnKF8g3fL0tAre2gcFjI45fajmG6qdOJe-A

由于此令牌包含用户名,您将能够知道用户是谁。最后一件事是读取此令牌并检索用户名。为此,您需要创建一个自定义Authorize属性,并用它装饰您的控制器或方法。

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);
    }
}

一旦您有了用户名,就可以在这里添加所有其他自定义授权逻辑。

您可以在生成令牌时传入其他自定义信息,并在此处读取。(如果您需要任何其他特殊授权逻辑。)

它的方法很长,但将工作的任何凭据存储。