[C#] एएसपी.नेट कोर में टोकन आधारित प्रमाणीकरण



Answers

मैट डेक्रे के शानदार जवाब से काम करते हुए, मैंने एएसपी.नेट कोर (1.0.1) के खिलाफ काम करते हुए टोकन-आधारित प्रमाणीकरण का एक पूरी तरह से काम कर रहा उदाहरण बनाया है। आप 1.0.0-rc1 ( 1.0.0-rc1 , Beta8 1.0.0-rc1 , Beta8 1.0.0-rc1 लिए वैकल्पिक शाखाओं) github.com/mrsheepuk/ASPNETSelfCreatedTokenAuthExample पूरा कोड पा सकते हैं, लेकिन संक्षेप में, महत्वपूर्ण कदम हैं:

अपने आवेदन के लिए एक कुंजी उत्पन्न करें

मेरे उदाहरण में, जब भी ऐप शुरू होता है, मैं एक यादृच्छिक कुंजी उत्पन्न करता हूं, आपको इसे उत्पन्न करने और उसे कहीं भी स्टोर करने और इसे अपने एप्लिकेशन में प्रदान करने की आवश्यकता होगी। इस फ़ाइल को देखें कि मैं एक यादृच्छिक कुंजी कैसे बना रहा हूं और आप इसे .json फ़ाइल से कैसे आयात कर सकते हैं । जैसा कि @kspearrin द्वारा टिप्पणियों में सुझाया गया है, डेटा प्रोटेक्शन एपीआई "सही तरीके से" कुंजी के प्रबंधन के लिए एक आदर्श उम्मीदवार की तरह प्रतीत होता है, लेकिन अगर यह अभी तक संभव है तो मैंने काम नहीं किया है। यदि आप इसे काम करते हैं तो कृपया एक पुल अनुरोध सबमिट करें!

Startup.cs - सेवा कॉन्फ़िगर करें

यहां, हमें हमारे टोकन के साथ हस्ताक्षरित होने के लिए एक निजी कुंजी लोड करने की आवश्यकता है, जिसे हम टोकन को प्रस्तुत करने के लिए भी उपयोग करेंगे। हम एक क्लास-स्तरीय वैरिएबल कुंजी में कुंजी संग्रहीत कर रहे हैं जिसे हम नीचे कॉन्फ़िगर विधि में दोबारा उपयोग करेंगे। TokenAuthOptions एक साधारण वर्ग है जिसमें हस्ताक्षर पहचान, दर्शक और जारीकर्ता है कि हमारी टोकरी बनाने के लिए हमें टोकन कंट्रोलर में आवश्यकता होगी।

// Replace this with some sort of loading from config / file.
RSAParameters keyParams = RSAKeyUtils.GetRandomKey();

// Create the key, and a set of token options to record signing credentials 
// using that key, along with the other parameters we will need in the 
// token controlller.
key = new RsaSecurityKey(keyParams);
tokenOptions = new TokenAuthOptions()
{
    Audience = TokenAudience,
    Issuer = TokenIssuer,
    SigningCredentials = new SigningCredentials(key, SecurityAlgorithms.Sha256Digest)
};

// Save the token options into an instance so they're accessible to the 
// controller.
services.AddSingleton<TokenAuthOptions>(tokenOptions);

// Enable the use of an [Authorize("Bearer")] attribute on methods and
// classes to protect.
services.AddAuthorization(auth =>
{
    auth.AddPolicy("Bearer", new AuthorizationPolicyBuilder()
        .AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme‌​)
        .RequireAuthenticatedUser().Build());
});

हमने एंडपॉइंट्स और कक्षाओं पर हम [Authorize("Bearer")] का उपयोग करने की अनुमति देने के लिए एक प्राधिकरण नीति भी स्थापित की है जिसे हम संरक्षित करना चाहते हैं।

Startup.cs - कॉन्फ़िगर करें

यहां, हमें JwtBearer प्रमाणीकरण को कॉन्फ़िगर करने की आवश्यकता है:

app.UseJwtBearerAuthentication(new JwtBearerOptions {
    TokenValidationParameters = new TokenValidationParameters {
        IssuerSigningKey = key,
        ValidAudience = tokenOptions.Audience,
        ValidIssuer = tokenOptions.Issuer,

        // When receiving a token, check that it is still valid.
        ValidateLifetime = true,

        // This defines the maximum allowable clock skew - i.e.
        // provides a tolerance on the token expiry time 
        // when validating the lifetime. As we're creating the tokens 
        // locally and validating them on the same machines which 
        // should have synchronised time, this can be set to zero. 
        // Where external tokens are used, some leeway here could be 
        // useful.
        ClockSkew = TimeSpan.FromMinutes(0)
    }
});

TokenController

टोकन नियंत्रक में, आपको Startup.cs में लोड की गई कुंजी का उपयोग करके हस्ताक्षरित कुंजी उत्पन्न करने के लिए एक विधि की आवश्यकता होती है। हमने स्टार्टअप में एक टोकनऑथऑप्शन इंस्टेंस पंजीकृत किया है, इसलिए हमें टोकन कंट्रोलर के निर्माता में इंजेक्ट करने की आवश्यकता है:

[Route("api/[controller]")]
public class TokenController : Controller
{
    private readonly TokenAuthOptions tokenOptions;

    public TokenController(TokenAuthOptions tokenOptions)
    {
        this.tokenOptions = tokenOptions;
    }
...

फिर आपको लॉगिन हैंडपॉइंट के लिए अपने हैंडलर में टोकन जेनरेट करने की आवश्यकता होगी, मेरे उदाहरण में मैं एक उपयोगकर्ता नाम और पासवर्ड ले रहा हूं और अगर कथन का उपयोग कर उन लोगों को मान्य कर रहा हूं, लेकिन आपको जो महत्वपूर्ण चीज करने की ज़रूरत है वह दावों को बना या लोड करना है आधारित पहचान और उस के लिए टोकन उत्पन्न:

public class AuthRequest
{
    public string username { get; set; }
    public string password { get; set; }
}

/// <summary>
/// Request a new token for a given username/password pair.
/// </summary>
/// <param name="req"></param>
/// <returns></returns>
[HttpPost]
public dynamic Post([FromBody] AuthRequest req)
{
    // Obviously, at this point you need to validate the username and password against whatever system you wish.
    if ((req.username == "TEST" && req.password == "TEST") || (req.username == "TEST2" && req.password == "TEST"))
    {
        DateTime? expires = DateTime.UtcNow.AddMinutes(2);
        var token = GetToken(req.username, expires);
        return new { authenticated = true, entityId = 1, token = token, tokenExpires = expires };
    }
    return new { authenticated = false };
}

private string GetToken(string user, DateTime? expires)
{
    var handler = new JwtSecurityTokenHandler();

    // Here, you should create or look up an identity for the user which is being authenticated.
    // For now, just creating a simple generic identity.
    ClaimsIdentity identity = new ClaimsIdentity(new GenericIdentity(user, "TokenAuth"), new[] { new Claim("EntityID", "1", ClaimValueTypes.Integer) });

    var securityToken = handler.CreateToken(new Microsoft.IdentityModel.Tokens.SecurityTokenDescriptor() {
        Issuer = tokenOptions.Issuer,
        Audience = tokenOptions.Audience,
        SigningCredentials = tokenOptions.SigningCredentials,
        Subject = identity,
        Expires = expires
    });
    return handler.WriteToken(securityToken);
}

और यह होना चाहिए। बस किसी भी विधि या वर्ग को [Authorize("Bearer")] जोड़ें, जिसे आप संरक्षित करना चाहते हैं, और यदि आप किसी टोकन के बिना इसे एक्सेस करने का प्रयास करते हैं तो आपको एक त्रुटि मिलनी चाहिए। यदि आप 500 त्रुटि के बजाय 401 वापस करना चाहते हैं, तो आपको मेरे उदाहरण में एक कस्टम अपवाद हैंडलर पंजीकृत करना होगा।

Question

मैं एएसपी.नेट कोर एप्लिकेशन के साथ काम कर रहा हूं। मैं टोकन आधारित प्रमाणीकरण को लागू करने की कोशिश कर रहा हूं लेकिन यह पता नहीं लगा सकता कि मेरे मामले के लिए नई सुरक्षा प्रणाली का उपयोग कैसे करें। मैं examples माध्यम से गया लेकिन उन्होंने मुझे बहुत मदद नहीं की, वे या तो कुकी प्रमाणीकरण या बाहरी प्रमाणीकरण (गिटहब, माइक्रोसॉफ्ट, ट्विटर) का उपयोग कर रहे हैं।

मेरा परिदृश्य क्या है: angularjs एप्लिकेशन को उपयोगकर्ता नाम और पासवर्ड उत्तीर्ण करने के लिए यूआरएल अनुरोध करना चाहिए। WebApi को उपयोगकर्ता को अधिकृत करना चाहिए और access_token वापस करना चाहिए जिसका उपयोग निम्नलिखित अनुरोधों में angularjs ऐप द्वारा किया जाएगा।

मुझे एएसपी.नेट के मौजूदा संस्करण में जो कुछ चाहिए, उसे लागू करने के बारे में मुझे बहुत अच्छा लेख मिला है - एएसपी.नेट वेब एपीआई 2, ओविन और पहचान का उपयोग करके टोकन आधारित प्रमाणीकरण । लेकिन यह मेरे लिए स्पष्ट नहीं है कि एएसपी.नेट कोर में एक ही चीज़ कैसे करें।

मेरा सवाल है: टोकन आधारित प्रमाणीकरण के साथ काम करने के लिए ASP.NET कोर WebApi एप्लिकेशन को कॉन्फ़िगर कैसे करें?




ओपनआईडिक्ट पर एक नज़र डालें - यह एक नई परियोजना है (लेखन के समय) जो जेडब्ल्यूटी टोकन के निर्माण को कॉन्फ़िगर करना और एएसपी.NET 5 में टोकन रीफ्रेश करना आसान बनाता है। टोकन की सत्यापन अन्य सॉफ़्टवेयर द्वारा संभाली जाती है।

मान लें कि आप Entity Framework साथ Identity उपयोग करते हैं, आखिरी पंक्ति वह है जिसे आप अपनी ConfigureServices विधि में जोड़ना चाहते हैं:

services.AddIdentity<ApplicationUser, ApplicationRole>()
    .AddEntityFrameworkStores<ApplicationDbContext>()
    .AddDefaultTokenProviders()
    .AddOpenIddictCore<Application>(config => config.UseEntityFramework());

Configure , आपने JWT टोकन की सेवा के लिए OpenIddict सेट अप किया है:

app.UseOpenIddictCore(builder =>
{
    // tell openiddict you're wanting to use jwt tokens
    builder.Options.UseJwtTokens();
    // NOTE: for dev consumption only! for live, this is not encouraged!
    builder.Options.AllowInsecureHttp = true;
    builder.Options.ApplicationCanDisplayErrors = true;
});

आप कॉन्फ़िगर में टोकन के सत्यापन को भी कॉन्फ़िगर करते हैं:

// use jwt bearer authentication
app.UseJwtBearerAuthentication(options =>
{
    options.AutomaticAuthenticate = true;
    options.AutomaticChallenge = true;
    options.RequireHttpsMetadata = false;
    options.Audience = "http://localhost:58292/";
    options.Authority = "http://localhost:58292/";
});

एक या दो अन्य मामूली चीजें हैं, जैसे कि आपके डीबीकॉन्टेक्स्ट को OpenIddictContext से प्राप्त करने की आवश्यकता है।

आप इस ब्लॉग पोस्ट पर पूर्ण लंबाई स्पष्टीकरण देख सकते हैं: http://capesean.co.za/blog/asp-net-5-jwt-tokens/

एक कार्यशील डेमो यहां उपलब्ध है: https://github.com/capesean/openiddict-test




Links