30

ASP.Net Web API'sinde bir REST API geliştiriyorum. API'mime yalnızca tarayıcı tabanlı olmayan müşteriler üzerinden erişilebilir. API'm için güvenliği uygulamam gerekiyor, bu yüzden Token tabanlı kimlik doğrulamaya gitmeye karar verdim. Jeton tabanlı kimlik doğrulaması konusunda adil bir anlayışa sahibim ve birkaç öğretici okudum, ancak hepsinin giriş için bazı kullanıcı arayüzü var. Giriş bilgileri, veritabanımızdan yetkilendirilecek olan HTTP POST yoluyla istemci tarafından iletileceğinden, giriş için herhangi bir UI'ye ihtiyacım yoktur. API'mda jeton tabanlı kimlik doğrulamayı nasıl uygularım? Lütfen not edin - API'm yüksek frekansta erişilebilmem için performansa da dikkat etmeliyim. Lütfen daha iyi açıklayabilir miyim, lütfen bildirin.Kullanıcı arabirimi olmadan Web API'sinde Token tabanlı kimlik doğrulaması

+1

Birisi, bir yere, başlangıç ​​doğrulamasını yapmak için kullanıcı adı ve parola koymak zorunda kalacaktı; uygulamanızın bir kopyasını alan herkesin aynı kullanıcı adı ve şifreyi kullanacağını mı söylüyorsunuz? ve eğer durum buysa, kodunuzdaki kullanıcı adı ve şifre değerlerini kodlamak mı istiyorsunuz? – Claies

+0

Birden çok kayıtlı kullanıcım olabilir, bu yüzden ilk giriş bilgileri HTTP POST yoluyla iletilecektir. Sırada ne var? –

+0

, bu hiç mantıklı değil. Sunucu, müşterinize kimlik bilgilerini nasıl iletebilir? Sunucu hangi müşterinin hangisi olduğunu bilmek ister? – Claies

cevap

36

MVC ve Web Api arasındaki fark konusunda bazı karışıklık olduğunu düşünüyorum. Kısacası, MVC için bir giriş formu kullanabilir ve çerezleri kullanarak bir oturum oluşturabilirsiniz. Web Api için oturum yok. Bu yüzden jetonu kullanmak istiyorsun.

Giriş formuna ihtiyacınız yok. Token son nokta ihtiyacınız olan her şeydir. Win'in tarif ettiği gibi, kimlik bilgilerini ele alındığı belirteç son noktasına gönderirsiniz. İşte

bir jetonu almak üzere bazı istemci tarafı C# kod:

istek başlığına eklemek belirteci kullanmak için
//using System; 
    //using System.Collections.Generic; 
    //using System.Net; 
    //using System.Net.Http; 
    //string token = GetToken("https://localhost:<port>/", userName, password); 

    static string GetToken(string url, string userName, string password) { 
     var pairs = new List<KeyValuePair<string, string>> 
        { 
         new KeyValuePair<string, string>("grant_type", "password"), 
         new KeyValuePair<string, string>("username", userName), 
         new KeyValuePair<string, string> ("Password", password) 
        }; 
     var content = new FormUrlEncodedContent(pairs); 
     ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true; 
     using (var client = new HttpClient()) { 
      var response = client.PostAsync(url + "Token", content).Result; 
      return response.Content.ReadAsStringAsync().Result; 
     } 
    } 

:

//using System; 
    //using System.Collections.Generic; 
    //using System.Net; 
    //using System.Net.Http; 
    //var result = CallApi("https://localhost:<port>/something", token); 

    static string CallApi(string url, string token) { 
     ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true; 
     using (var client = new HttpClient()) { 
      if (!string.IsNullOrWhiteSpace(token)) { 
       var t = JsonConvert.DeserializeObject<Token>(token); 

       client.DefaultRequestHeaders.Clear(); 
       client.DefaultRequestHeaders.Add("Authorization", "Bearer " + t.access_token); 
      } 
      var response = client.GetAsync(url).Result; 
      return response.Content.ReadAsStringAsync().Result; 
     } 
    } 

Simgeniz:

//using Newtonsoft.Json; 

class Token 
{ 
    public string access_token { get; set; } 
    public string token_type { get; set; } 
    public int expires_in { get; set; } 
    public string userName { get; set; } 
    [JsonProperty(".issued")] 
    public string issued { get; set; } 
    [JsonProperty(".expires")] 
    public string expires { get; set; } 
} 

Şimdi sunucu tarafı için:

Aslında verir veya erişimi reddeder kod
 var oAuthOptions = new OAuthAuthorizationServerOptions 
     { 
      TokenEndpointPath = new PathString("/Token"), 
      Provider = new ApplicationOAuthProvider("self"), 
      AccessTokenExpireTimeSpan = TimeSpan.FromDays(14), 
      // https 
      AllowInsecureHttp = false 
     }; 
     // Enable the application to use bearer tokens to authenticate users 
     app.UseOAuthBearerTokens(oAuthOptions); 

Startup.Auth.cs

In And ApplicationOAuthProvider.cs içinde

:

//using Microsoft.AspNet.Identity.Owin; 
//using Microsoft.Owin.Security; 
//using Microsoft.Owin.Security.OAuth; 
//using System; 
//using System.Collections.Generic; 
//using System.Security.Claims; 
//using System.Threading.Tasks; 

public class ApplicationOAuthProvider : OAuthAuthorizationServerProvider 
{ 
    private readonly string _publicClientId; 

    public ApplicationOAuthProvider(string publicClientId) 
    { 
     if (publicClientId == null) 
      throw new ArgumentNullException("publicClientId"); 

     _publicClientId = publicClientId; 
    } 

    public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context) 
    { 
     var userManager = context.OwinContext.GetUserManager<ApplicationUserManager>(); 

     var user = await userManager.FindAsync(context.UserName, context.Password); 
     if (user == null) 
     { 
      context.SetError("invalid_grant", "The user name or password is incorrect."); 
      return; 
     } 

     ClaimsIdentity oAuthIdentity = await user.GenerateUserIdentityAsync(userManager); 
     var propertyDictionary = new Dictionary<string, string> { { "userName", user.UserName } }; 
     var properties = new AuthenticationProperties(propertyDictionary); 

     AuthenticationTicket ticket = new AuthenticationTicket(oAuthIdentity, properties); 
     // Token is validated. 
     context.Validated(ticket); 
    } 

    public override Task TokenEndpoint(OAuthTokenEndpointContext context) 
    { 
     foreach (KeyValuePair<string, string> property in context.Properties.Dictionary) 
     { 
      context.AdditionalResponseParameters.Add(property.Key, property.Value); 
     } 
     return Task.FromResult<object>(null); 
    } 

    public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context) 
    { 
     // Resource owner password credentials does not provide a client ID. 
     if (context.ClientId == null) 
      context.Validated(); 

     return Task.FromResult<object>(null); 
    } 

    public override Task ValidateClientRedirectUri(OAuthValidateClientRedirectUriContext context) 
    { 
     if (context.ClientId == _publicClientId) 
     { 
      var expectedRootUri = new Uri(context.Request.Uri, "/"); 

      if (expectedRootUri.AbsoluteUri == context.RedirectUri) 
       context.Validated(); 
     } 
     return Task.FromResult<object>(null); 
    } 

} 

simgeyi alınırken dahil hiçbir denetleyici yoktur görebileceğiniz gibi. Aslında, sadece bir Web API'sı istiyorsanız tüm MVC referanslarını kaldırabilirsiniz. Daha okunabilir hale getirmek için sunucu tarafı kodunu basitleştirdim. Güvenliği yükseltmek için kod ekleyebilirsiniz.

Yalnızca SSL kullandığınızdan emin olun. Bunu zorlamak için RequireHttpsAttribute'yi uygulayın.

Web Api'nizi güvenceye almak için Authorize/AllowAnonymous özniteliklerini kullanabilirsiniz. Ek olarak, Web Api'nizi daha güvenli hale getirmek için filtreler (RequireHttpsAttribute gibi) ekleyebilirsiniz. Umarım bu yardımcı olur.

+0

u "MVC için bir giriş formu kullanabilir ve çerezleri kullanarak bir oturum oluşturabilirsiniz. Web Api için herhangi bir oturum yok", ancak form auth'u web API'sı içinde uygulanabilir. Böylece istemci web api'ye kimlik bilgilerini gönderebilir ve web api istemciye kimlik doğrulama bilgisi gönderir. sonraki tüm çağrı istemcileri için auth çerezini web api'ye iletmesi gerekir ...... sanırım bu mümkün. –

+0

kodunuzu aşağıdaki gibi seçin. 'yeni KeyValuePair ("grant_type", "şifre"), yeni KeyValuePair ("kullanıcı adı", userName), yeni KeyValuePair ("Parola", şifre) 'grant_type = parola?' ne anlama geliyor? 'Href = password yerine grant_type ile hangi seçeneği kullanabiliriz? lütfen bilgileri paylaşın. Teşekkürler –

11

ASP.Net Web API'sı, zaten Yetkilendirme Sunucusu hazırlığına sahiptir. Web API şablonuyla yeni bir ASP.Net Web Uygulaması oluşturduğunuzda Startup.cs'un içinde görebilirsiniz.

OAuthOptions = new OAuthAuthorizationServerOptions 
{ 
    TokenEndpointPath = new PathString("/Token"), 
    Provider = new ApplicationOAuthProvider(PublicClientId), 
    AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"), 
    AccessTokenExpireTimeSpan = TimeSpan.FromDays(14), 
    // In production mode set AllowInsecureHttp = false 
    AllowInsecureHttp = true 
}; 

yapmanız gereken tek şey sorgu dizesi içine URL kodlanmış adı ve şifrenizi göndermektir. Eğer daha fazla ayrıntı öğrenmek istiyorsanız

/Token/userName=johndoe%40example.com&password=1234&grant_type=password 

, sen User Registration and Login - Angular Front to Back with Web API by Deborah Kurata izleyebilirsiniz.

+0

Yani/TOKEN için HTTP Header/Body'da kullanıcı adı ve parola ile bir POST isteği oluşturacağım? Uygulama veritabanımdaki tüm kullanıcılar için kullanıcı adı ve şifre aldım. Bunu nasıl uygulamalıyım? –

+0

ASP.Net Kimliğine * gereksiniminiz var (Zaten sahip olduğunuza inanıyorum) *. Değilse, bir ASP.Net Web API projesi oluşturun ve kaynak kodunu görün. – Win

+1

grant_type = şifre nedir? lütfen bilgi paylaşın. teşekkürler –

İlgili konular