2017-03-02 239 views
7

遵循一个在线教程以使用OWIN使用基于令牌的身份验证后,我设法让我的测试应用程序根据硬编码的用户名/密码进行身份验证,如演示所做的那样。Asp.Net WebApi 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我的(剔除视图模型)的代码,我尝试这样做:

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” 

在“邮差”,我能够认证硬编码的用户名/密码。

enter image description here

但我不知道如何从我的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方法调用我的身份验证吗?我需要删除/令牌位。

回答

7

你不需要创建一个Login方法,因为你已经拥有了它。这是http://localhost:1234/token。如果用户存在并且密码正确,这将生成一个令牌。但得到这个行为,你需要从OAuthAuthorizationServerProvider

public class DOAuthServerProvider : OAuthAuthorizationServerProvider 

派生来实现自己的AuthServerProvider,然后你会覆盖的方法来实现你的逻辑:

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(路比我更好:))

1

修改内容类型“应用/ JSON的”到 “应用程序/ www-form-urlencoded“

您是Postman”application/www-form-urlencoded“格式的发送数据。但是在你的代码中使用“application/Json”内容类型不匹配。所以,数据不能发送适当的格式。

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