首页 文章

如何在成为旧版ASP.NET MVC应用程序的一部分时在Web API 2中对用户进行身份验证?

提问于
浏览
6

我有一个Web API,目前AngularJS应用程序在ASP.NET MVC Web应用程序中使用 . 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();
}

我的问题是,如果这应该如何解决或者是否有更好的方法?

1 回答

  • 3

    您可以使用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 Authorization标头传递 . 他们需要使用承载方案,例如:

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

    一旦您拥有用户名,就可以在此处添加所有其他自定义授权逻辑 .

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

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

相关问题