【问题标题】:Asp.Net WebApi OWIN AuthenticationAsp.Net WebApi OWIN 身份验证
【发布时间】:2017-03-02 04:07:20
【问题描述】:

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

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

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

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 上的(淘汰视图模型)代码中,我尝试了这个:

 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”

在“邮递员”中,我能够验证硬编码的用户名/密码。

但我不确定如何从我的 UI 连接我的 api 调用以进行身份​​验证。

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

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

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

【问题讨论】:

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


    【解决方案1】:

    您不需要创建登录方法,因为您已经拥有它。这是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 状态码,这意味着未经授权。这样您就可以确认您在第一步中添加的授权属性是否有效。

    这里有一系列很好的教程,可以很好地解释一切:Token based authentication(比我的好多了:))

    【讨论】:

      【解决方案2】:

      将内容类型 "application/json" 更改为 “应用程序/www-form-urlencoded”

      您以 Postman “application/www-form-urlencoded” 格式发送数据。但是在您使用“application/Json”的代码中,Content Type 不匹配。所以,数据发送的格式不正确。

      如果工作正常,您可以更改。

      【讨论】:

        猜你喜欢
        • 2014-08-19
        • 2014-05-08
        • 2014-01-02
        • 2012-10-23
        • 2018-12-20
        • 2015-10-09
        • 2017-12-17
        • 2020-07-28
        • 1970-01-01
        相关资源
        最近更新 更多