Asp.Net WebApi OWIN身份验证

时间:2017-03-02 04:07:20

标签: c# asp.net authentication asp.net-web-api knockout.js

在使用OWIN使用基于令牌的身份验证的在线教程之后,我设法让我的测试应用程序根据硬编码的用户名/密码进行身份验证,就像演示一样。

但是,现在我希望使用我的Web应用程序中的模型。

我的身份验证正如演示所说,在这段代码中发生。

namespace UI
{
    public class AuthorisationServerProvider : OAuthAuthorizationServerProvider
    {
        public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
        {
            context.Validated(); // Means I have validated the client.
        }

        public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
        {
            // Here we validate the user...
            var identity = new ClaimsIdentity(context.Options.AuthenticationType);
            if (context.UserName == "user" && context.Password == "password")
            {
                identity.AddClaim(new Claim(ClaimTypes.Role, "admin"));
                identity.AddClaim(new Claim("username", "user"));
                identity.AddClaim(new Claim(ClaimTypes.Name, "My Full Name"));
                context.Validated(identity);
            }
            else
            {
                context.SetError("Invalid grant", "Username or password are incorrect");
                return;
            }
        }

    }
}

我有一个WebAPI控制器,我收到了一个模型,并且......不确定如何从我的webapi控制器调用上面的代码。目前,上面的代码需要调用myurl / token - 这是在启动代码中定义的。

 public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            // Enables cors origin requests.
            app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);

            // Config OAuth authorisation server;

            var myProvider = new AuthorisationServerProvider();
            OAuthAuthorizationServerOptions options = new OAuthAuthorizationServerOptions
            {
                AllowInsecureHttp = true, // Live version should use HTTPS...
                TokenEndpointPath = new PathString("/token"),
                AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
                Provider = myProvider
            };

            app.UseOAuthAuthorizationServer(options);
            app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());

            HttpConfiguration config = new HttpConfiguration();
            WebApiConfig.Register(config);
        }
    }

所以,我猜我的webapi调用的url应该是/ token吗?所以,在我的UI上的(Knockout View模型)代码中,我尝试了这个:

 Login()
    {
        var data = {
            username : this.login.emailAddress(),
            password : this.login.password(),
            RememberMe: this.login.rememberMe(),
            grant_type: "password"
        }

        return $.ajax({
            type: "POST",
            data: data ? JSON.stringify(data) : null,
            dataType: "json",
            url: "/token",
            contentType: "application/json"
        }).done((reply) => {
            alert("Done!");
        });

    }

但是,我得到一个例外:

“error”: “unsupported_grant_type”

在'Postman'中,我可以验证硬编码的用户名/密码。

enter image description here

但我不知道如何从我的UI连接我的api电话,进行身份验证。

我希望在我的api控制器(ASP.Net WebAPI)上创建一个'Login'方法,如下所示:

[Route("login"), HttpPost, AllowAnonymous]
public ReplyDto Login(LoginRequest login)
{
    ReplyDto reply = _userService.Login(login.Email, login.Password);
    return reply;
}

因此,我的_userService会检查用户是否在数据库中......如果是,请在此处调用我的OAuth身份验证,并传递一些参数。但不确定这是可能的。我可以通过这种api方法调用我的身份验证吗?我需要删除/ token位。

2 个答案:

答案 0 :(得分:6)

您不需要创建Login方法,因为您已经拥有它。这是http://localhost:1234/token。如果用户存在且密码正确,则会生成令牌。但要获得此行为,您需要通过派生 OAuthAuthorizationServerProvider

来实现您自己的AuthServerProvider
public class DOAuthServerProvider : OAuthAuthorizationServerProvider

然后你将覆盖一个方法来实现你的逻辑:

public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
    {

        try
        {
            string allowedOrigin = context.OwinContext.Get<string>(DOAuthStatic.ALLOWED_CORS_ORIGINS_KEY);

            if (allowedOrigin != null)
            {
                context.OwinContext.Response.Headers[DOAuthStatic.CORS_HEADER] = allowedOrigin;
            }

            DAuthenticationResponse authResponse = await _authRepository.Authenticate(context.UserName, context.Password);

            if (!authResponse.IsAuthenticated)
            {
                context.SetError(OAuthError.InvalidGrant, $"{(int)authResponse.AuthenticateResult}:{authResponse.AuthenticateResult}");

                return;
            }

            if (authResponse.User.ChangePasswordOnLogin)
            {
                _userAuthenticationProvider.GeneratePasswordResetToken(authResponse.User);
            }

            IDictionary<string, string> props = new Dictionary<string, string>
            {
                {
                    DOAuthStatic.CLIENT_NAME_KEY, context.ClientId ?? string.Empty
                }
            };

            ValidateContext(context, authResponse, props);
        }
        catch (Exception ex)
        {
            DLogOAuth.LogException(ex, "DCO0407E", "OAuthServerProvider - Error validating user");

            throw;
        }
    }

你几乎就在那里,你只需再做两个步骤:

  1. 在您的方法或控制器上添加AuthorizeAttribute,以限制未经身份验证的用户访问。
  2. 添加您请求标头的访问令牌。如果您跳过此步骤,您应该获得401 HTTP状态代码,这意味着未经授权。这是您可以确认在步骤1中添加的authorize属性的方法。
  3. 这是一系列很好的教程,可以很好地解释一切:Token based authentication(比我的方式更好:) :)

答案 1 :(得分:1)

  

更改内容类型&#34; application / json&#34;至   &#34;应用/万维网窗体-urlencoded&#34;

你是Postman&#34; application / www-form-urlencoded&#34;格式。但是在你的代码中使用&#34; application / Json&#34; 内容类型不匹配。因此,数据不会发送正确的格式。

如果工作正常,你可以改变。