使用两种方式为 web api 2 中的用户创建不记名令牌与 owin 上下文

Use two way to create bearer token for users in web api 2 with owin context

我有一个 Asp.net web api 2 项目。在这个项目中,我使用 OWIN 身份验证。 我有两种用户。

一类是用用户名和密码登录,一类是手机号和一个四字词登录

我希望这两个用户都去地址 /token 获取他们的令牌,到目前为止我的实现是这样的:

这是启动 class :

var provider = new AuthorizationServerProvider();
var options = new OAuthAuthorizationServerOptions()
{
    AllowInsecureHttp = true,
    TokenEndpointPath = new PathString("/token"),
    AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
    Provider = provider
};
public class AuthorizationServerProvider : OAuthAuthorizationServerProvider
{
    public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
    {
        context.Validated();
    }

    public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
    {
        var identity = new ClaimsIdentity(context.Options.AuthenticationType);
        using (DbContext dbContext = new DbContext ())
        {
            var user = dbContext.User
                .Where(a => a.UserName == context.UserName)
                .Where(a => a.Password == context.Password)
                .Select(a => new UserClaim
                {
                    Id = a.Id,
                    UserName = a.UserName,
                    FirstName = a.FirstName,
                    LastName = a.LastName,
                    Roles = a.UserInRoles.Select(w => w.Role.Id).ToList()
                }).FirstOrDefault();

            if (user == null)
            {
                context.SetError("invalid grant", "Provided username and password is incorrect.");
                return;
            }
            identity.AddUserClaim(user);
            context.Validated(identity);
            return;
        }
    }
}

此解决方案适用于想用用户名登录的用户,但是想用手机号登录的用户怎么办?

您需要提供两个 OAuthAuthorizationServerOptions 实例,一个用于使用用户名和密码进行授权,一个用于手机号码和代码,然后通过授权中间件将这两个选项添加到您的 owin 管道中。

public partial class Startup
{
    public void Configuration(IAppBuilder app)
    {
        // rest of your code

        var userAndPasswordOptions = new OAuthAuthorizationServerOptions(){ ... };
        var mobileAndCodeOptions = new OAuthAuthorizationServerOptions(){ ... };

        app.UseOAuthAuthorizationServer(userAndPasswordOptions);
        app.UseOAuthAuthorizationServer(mobileAndCodeOptions);

        // rest of your code
    }
} 

但您应该知道在这种情况下,这两个提供商对不同的请求端点做出响应。

如果您需要一个端点来提供两种类型的授权,您可以在 OAuthAuthorizationServerProvider 中更改 GrantResourceOwnerCredentials 方法。

public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
    var identity = new ClaimsIdentity(context.Options.AuthenticationType);

    var form = await context.Request.ReadFormAsync().Result;
    if (form["type"] == "mobile")
    {
        //validate mobileNumber and code
    }
    else
    {
        //validate username and password
    }

    identity.AddUserClaim(user);
    context.Validated(identity);
    return;

}