Chr*_*ian 6 c# authentication asp.net-mvc asp.net-web-api asp.net-web-api2
我有一个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();
}
Run Code Online (Sandbox Code Playgroud)
我的问题是,如果这应该如何解决或者是否有更好的方法?
您可以使用WebApi2的令牌认证机制。
流程将是这样的:
用户向您发送 https 请求:
请求的内容类型应该是:
application/x-www-form-urlencoded
Run Code Online (Sandbox Code Playgroud)
正文应包括:
grant_type=password&username=yourWebsFormsUsername&password=yourWebFormsPassword
Run Code Online (Sandbox Code Playgroud)
你的 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);
}
}
Run Code Online (Sandbox Code Playgroud)
请注意上面的 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;
}
}
}
Run Code Online (Sandbox Code Playgroud)
您的用户对上述内容的响应将是一个令牌,其中包括用户名或您在上述方法中添加到上下文中的任何其他信息:
id.AddClaim(new Claim("username", context.UserName));
Run Code Online (Sandbox Code Playgroud)
上述令牌 api 调用的响应将如下所示:
{
"access_token": "9TIpW2m2rUbB_Bmb7kKAQ9GH4hgfnKF8g3fL0tAre2gcFjI45fajmG6qdOJe-A",
"token_type": "bearer",
"expires_in": 1209599
}
Run Code Online (Sandbox Code Playgroud)
然后,您的用户必须将此令牌作为所有 API 调用的 Http 授权标头传递。他们需要使用承载方案来传递它,例如:
Bearer 9TIpW2m2rUbB_Bmb7kKAQ9GH4hgfnKF8g3fL0tAre2gcFjI45fajmG6qdOJe-A
Run Code Online (Sandbox Code Playgroud)
由于此令牌包含用户名,因此您将能够知道用户是谁。现在最后一件事是读取此令牌并检索用户名。为此,您需要创建一个自定义 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);
}
}
Run Code Online (Sandbox Code Playgroud)
一旦您拥有用户名,所有其他自定义授权逻辑都可以添加到此处。
您可以在生成token时传入其他自定义信息,并在此处读取。(如果您需要任何其他特殊授权逻辑。)
它的方法很冗长,但适用于任何凭据存储。
| 归档时间: |
|
| 查看次数: |
1539 次 |
| 最近记录: |