IT-Swarm.Net

কীভাবে একটি এএসপি.নেট ওয়েব এপিআই সুরক্ষিত করবেন

তৃতীয় পক্ষের বিকাশকারীরা আমার অ্যাপ্লিকেশনটির ডেটা অ্যাক্সেস করতে ব্যবহার করবে এমন এএসপি.নেট ওয়েব এপিআই ব্যবহার করে আমি একটি আরএসএফুল ওয়েব পরিষেবা তৈরি করতে চাই।.

আমি ওআউথ সম্পর্কে প্রচুর পড়েছি এবং এটি স্ট্যান্ডার্ড বলে মনে হচ্ছে তবে এটি কীভাবে কাজ করে তা ব্যাখ্যা করে ডকুমেন্টেশন সহ একটি ভাল নমুনা খুঁজে পেয়েছি (এবং এটি আসলে কাজ করে!) অবিশ্বাস্যরূপে কঠিন বলে মনে হচ্ছে (বিশেষত ওউথের নবজাতকের জন্য)।.

এমন কোনও নমুনা আছে যা বাস্তবে তৈরি করে এবং কাজ করে এবং এটি কীভাবে বাস্তবায়ন করতে পারে তা দেখায়?

আমি অসংখ্য নমুনা ডাউনলোড করেছি:

  • ডটনেটঅউথ - ডকুমেন্টেশন একটি নবাগত দৃষ্টিভঙ্গি থেকে নিরাশ
  • চিন্তাধারা - এটি নির্মাণ করতে পারে না

আমি একটি সাধারণ টোকেন-ভিত্তিক স্কিম প্রস্তাব করার মতো ব্লগগুলিতেও দেখেছি (যেমন এটি ) - এটি হুইলটি পুনরায় আবিষ্কার করার মতো বলে মনে হচ্ছে তবে এটি ধারণাগতভাবে মোটামুটি সহজ হওয়ার সুবিধা রয়েছে have.

মনে হচ্ছে SO তে এরকম অনেকগুলি প্রশ্ন রয়েছে তবে কোনও ভাল উত্তর নেই।.

সবাই এই জায়গায় কি করছে?

371
Craig Shearer

আপডেট:

আমি আমার আর একটি উত্তর রেখেছি কীভাবে জেডব্লিউটি আগ্রহী প্রত্যেকের জন্য ওয়েব এপিআইয়ের জন্য জেডাব্লুটি প্রমাণীকরণটি কীভাবে ব্যবহার করবেন:

Asp.Net Web Api এর জন্য JWT প্রমাণীকরণ


ওয়েব এপিআই সুরক্ষিত করার জন্য আমরা এইচএমএসি প্রমাণীকরণ প্রয়োগ করতে পেরেছি এবং এটি ঠিক আছে। এইচএমএসি প্রমাণীকরণ প্রতিটি গ্রাহকের জন্য একটি গোপন কী ব্যবহার করে যা গ্রাহক এবং সার্ভার উভয়ই হ্যাশ করতে একটি বার্তা জানতে জানে, এইচএমএসি 256 ব্যবহার করা উচিত। বেশিরভাগ ক্ষেত্রে গ্রাহকের হ্যাশ পাসওয়ার্ড একটি গোপন কী হিসাবে ব্যবহৃত হয়।.

বার্তাটি সাধারণত HTTP অনুরোধের ডেটা থেকে তৈরি করা হয়, বা এমনকী কাস্টমাইজড ডেটা যা HTTP শিরোনামে যুক্ত হয়, বার্তায় অন্তর্ভুক্ত থাকতে পারে:

  1. টাইমস্ট্যাম্প: অনুরোধটি প্রেরণের সময় (ইউটিসি বা জিএমটি)
  2. HTTP ক্রিয়া: GET, POST, PUT, মুছে ফেলুন।.
  3. পোস্ট ডেটা এবং কোয়েরি স্ট্রিং,
  4. URL টি

ফণা অধীনে, এইচএমএসি প্রমাণীকরণ হবে:

গ্রাহক ওয়েব সার্ভারে এইচটিটিপি অনুরোধ প্রেরণ করে, স্বাক্ষর তৈরির পরে (এইচএমএসি হ্যাশের আউটপুট), এইচটিটিপি অনুরোধের টেম্পলেট:

User-Agent: {agent}   
Host: {Host}   
Timestamp: {timestamp}
Authentication: {username}:{signature}

জিইটি অনুরোধের উদাহরণ:

GET /webapi.hmac/api/values

User-Agent: Fiddler    
Host: localhost    
Timestamp: Thursday, August 02, 2012 3:30:32 PM 
Authentication: cuongle:LohrhqqoDy6PhLrHAXi7dUVACyJZilQtlDzNbLqzXlw=

স্বাক্ষর পেতে হ্যাশ বার্তা:

GET\n
Thursday, August 02, 2012 3:30:32 PM\n
/webapi.hmac/api/values\n

POST এর জন্য ক্যোয়ারী স্ট্রিং সহ অনুরোধ (নীচে স্বাক্ষর সঠিক নয়, কেবল একটি উদাহরণ)

POST /webapi.hmac/api/values?key2=value2

User-Agent: Fiddler    
Host: localhost    
Content-Type: application/x-www-form-urlencoded
Timestamp: Thursday, August 02, 2012 3:30:32 PM 
Authentication: cuongle:LohrhqqoDy6PhLrHAXi7dUVACyJZilQtlDzNbLqzXlw=

key1=value1&key3=value3

স্বাক্ষর পেতে হ্যাশ বার্তা

GET\n
Thursday, August 02, 2012 3:30:32 PM\n
/webapi.hmac/api/values\n
key1=value1&key2=value2&key3=value3

দয়া করে নোট করুন যে ফর্ম ডেটা এবং ক্যোয়ারী স্ট্রিংটি ক্রমযুক্ত হওয়া উচিত, সুতরাং সার্ভারের কোডটি সঠিক বার্তাটি তৈরি করতে কোয়েরি স্ট্রিং এবং ফর্ম ডেটা পান।.

যখন HTTP অনুরোধটি সার্ভারে আসে, তথ্যের জন্য অনুরোধটিকে বিশ্লেষণের জন্য একটি প্রমাণীকরণ ক্রিয়া ফিল্টার প্রয়োগ করা হয়: এইচটিটিপি ক্রিয়া, টাইমস্ট্যাম্প, ইউরি, ফর্ম ডেটা এবং ক্যোয়ারিং স্ট্রিং, তারপরে স্বাক্ষরের সাথে স্বাক্ষর তৈরি করতে এইচএমসি হ্যাশ ব্যবহার করুন) সার্ভারে কী (হ্যাশ পাসওয়ার্ড)।.

অনুরোধে ব্যবহারকারীর নাম সহ ডাটাবেস থেকে গোপন কীটি পাওয়া যায়।.

তারপরে সার্ভার কোড অনুরোধে স্বাক্ষরের সাথে স্বাক্ষরের সাথে তুলনা করে; যদি সমান হয় তবে প্রমাণীকরণটি পাস হয়ে যায়, অন্যথায় এটি ব্যর্থ হয়।.

স্বাক্ষর তৈরির কোড:

private static string ComputeHash(string hashedPassword, string message)
{
    var key = Encoding.UTF8.GetBytes(hashedPassword.ToUpper());
    string hashString;

    using (var hmac = new HMACSHA256(key))
    {
        var hash = hmac.ComputeHash(Encoding.UTF8.GetBytes(message));
        hashString = Convert.ToBase64String(hash);
    }

    return hashString;
}

তাহলে কীভাবে রিপ্লে আক্রমণ রোধ করবেন?

টাইমস্ট্যাম্পের জন্য সীমাবদ্ধতা যুক্ত করুন, এরকম কিছু:

servertime - X minutes|seconds  <= timestamp <= servertime + X minutes|seconds 

(সার্ভারটাইম: অনুরোধের সময়টি সার্ভারে আসবে)

এবং, অনুরোধের স্বাক্ষরটিকে মেমোরিতে ক্যাশে করুন (মেমোরিচিচি ব্যবহার করুন, সময়ের সীমাতে রাখা উচিত)। পরবর্তী অনুরোধটি যদি আগের অনুরোধের সাথে একই স্বাক্ষর নিয়ে আসে তবে তা প্রত্যাখ্যান করা হবে।.

ডেমো কোডটি এখানে দেওয়া হয়েছে: https://github.com/cuongle/Hmac.WebApi

278
cuongle

আমি প্রথমে সবচেয়ে সরল সমাধানগুলি দিয়ে শুরু করার পরামর্শ দেব - সম্ভবত আপনার দৃশ্যে সাধারণ HTTP বেসিক প্রমাণীকরণ + এইচটিটিপিএসই যথেষ্ট।.

যদি না হয় (উদাহরণস্বরূপ আপনি https ব্যবহার করতে পারবেন না, বা আরও জটিল কী পরিচালনার প্রয়োজন রয়েছে), আপনার অন্যদের পরামর্শ অনুসারে এইচএমএসি-ভিত্তিক সমাধানগুলি দেখে নিতে পারেন। এই জাতীয় এপিআইয়ের একটি ভাল উদাহরণ হ'ল অ্যামাজন এস 3 ( http://s3.amazonaws.com/doc/s3-developer-guide/RESTAuthentication.html) )

আমি এএসপি.নেট ওয়েব এপিআই তে এইচএমএসি ভিত্তিক প্রমাণীকরণ সম্পর্কে একটি ব্লগ পোস্ট লিখেছিলাম। এটি উভয় ওয়েব এপিআই পরিষেবা এবং ওয়েব এপিআই ক্লায়েন্ট নিয়ে আলোচনা করে কোডটি বিটবাকেটে উপলভ্য। http://www.piotrwalat.net/hmac-authentication-in-asp-net-web-api/

ওয়েব এপিআই-তে বেসিক প্রমাণীকরণ সম্পর্কিত একটি পোস্ট এখানে রয়েছে: http://www.piotrwalat.net/basic-http-authentication-in-asp-net-web-api- using-message-handlers/

মনে রাখবেন যে আপনি যদি তৃতীয় পক্ষগুলিতে একটি এপিআই সরবরাহ করতে চলেছেন তবে আপনি ক্লায়েন্ট লাইব্রেরি সরবরাহের জন্যও সম্ভবত দায়বদ্ধ থাকবেন। বেসিক প্রমাণীকরণের এখানে উল্লেখযোগ্য সুবিধা রয়েছে কারণ এটি বক্সের বাইরে বেশিরভাগ প্রোগ্রামিং প্ল্যাটফর্মগুলিতে সমর্থিত। অন্যদিকে, এইচএমএসি তেমন মানক নয় এবং কাস্টম বাস্তবায়ন প্রয়োজন। এগুলি তুলনামূলক সহজবোধ্য হওয়া উচিত তবে এখনও কাজের প্রয়োজন require.

গীত। এইচটিটিপিএস + শংসাপত্রগুলি ব্যবহার করার একটি বিকল্পও রয়েছে। http://www.piotrwalat.net/client-certificate-authentication-in-asp-net-web-api-and-windows-store-apps/

30
Piotr Walat

আপনি ডেভডিফাইন্ড.আউথ চেষ্টা করেছেন?

আমি এটি 2-লেগড ওআউথ দিয়ে আমার ওয়েবএপি সুরক্ষিত করতে ব্যবহার করেছি। আমি PHP ক্লায়েন্টদের সাথেও এটি সফলভাবে পরীক্ষা করেছি।.

এই লাইব্রেরিটি ব্যবহার করে OAuth এর জন্য সমর্থন যুক্ত করা বেশ সহজ। আপনি কীভাবে এএসপি.নেট এমভিসি ওয়েব API এর সরবরাহকারীর প্রয়োগ করতে পারেন তা এখানে:

1) ডেভডফাইন্ডড.অউথের সোর্স কোড পান: https://github.com/bittercoder/DevDefined.OAuth - নতুন সংস্করণটি OAuthContextBuilderএক্সটেনসিবিলিটির জন্য মঞ্জুরি দেয়।.

2) গ্রন্থাগারটি তৈরি করুন এবং এটি আপনার ওয়েব এপিআই প্রকল্পে উল্লেখ করুন।.

3) HttpRequestMessageথেকে একটি প্রসঙ্গ তৈরিতে সমর্থন করার জন্য একটি কাস্টম প্রসঙ্গ বিল্ডার তৈরি করুন:

using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Net.Http;
using System.Web;

using DevDefined.OAuth.Framework;

public class WebApiOAuthContextBuilder : OAuthContextBuilder
{
    public WebApiOAuthContextBuilder()
        : base(UriAdjuster)
    {
    }

    public IOAuthContext FromHttpRequest(HttpRequestMessage request)
    {
        var context = new OAuthContext
            {
                RawUri = this.CleanUri(request.RequestUri), 
                Cookies = this.CollectCookies(request), 
                Headers = ExtractHeaders(request), 
                RequestMethod = request.Method.ToString(), 
                QueryParameters = request.GetQueryNameValuePairs()
                    .ToNameValueCollection(), 
            };

        if (request.Content != null)
        {
            var contentResult = request.Content.ReadAsByteArrayAsync();
            context.RawContent = contentResult.Result;

            try
            {
                // the following line can result in a NullReferenceException
                var contentType = 
                    request.Content.Headers.ContentType.MediaType;
                context.RawContentType = contentType;

                if (contentType.ToLower()
                    .Contains("application/x-www-form-urlencoded"))
                {
                    var stringContentResult = request.Content
                        .ReadAsStringAsync();
                    context.FormEncodedParameters = 
                        HttpUtility.ParseQueryString(stringContentResult.Result);
                }
            }
            catch (NullReferenceException)
            {
            }
        }

        this.ParseAuthorizationHeader(context.Headers, context);

        return context;
    }

    protected static NameValueCollection ExtractHeaders(
        HttpRequestMessage request)
    {
        var result = new NameValueCollection();

        foreach (var header in request.Headers)
        {
            var values = header.Value.ToArray();
            var value = string.Empty;

            if (values.Length > 0)
            {
                value = values[0];
            }

            result.Add(header.Key, value);
        }

        return result;
    }

    protected NameValueCollection CollectCookies(
        HttpRequestMessage request)
    {
        IEnumerable<string> values;

        if (!request.Headers.TryGetValues("Set-Cookie", out values))
        {
            return new NameValueCollection();
        }

        var header = values.FirstOrDefault();

        return this.CollectCookiesFromHeaderString(header);
    }

    /// <summary>
    /// Adjust the URI to match the RFC specification (no query string!!).
    /// </summary>
    /// <param name="uri">
    /// The original URI. 
    /// </param>
    /// <returns>
    /// The adjusted URI. 
    /// </returns>
    private static Uri UriAdjuster(Uri uri)
    {
        return
            new Uri(
                string.Format(
                    "{0}://{1}{2}{3}", 
                    uri.Scheme, 
                    uri.Host, 
                    uri.IsDefaultPort ?
                        string.Empty :
                        string.Format(":{0}", uri.Port), 
                    uri.AbsolutePath));
    }
}

৪) এই টিউটোরিয়ালটি একটি OAuth সরবরাহকারী তৈরি করার জন্য ব্যবহার করুন: http://code.google.com/p/devdefined-tools/wiki/OAuthProvider । শেষ পদক্ষেপে (সুরক্ষিত উত্স উদাহরণে অ্যাক্সেস করা) আপনি এই কোডটি আপনার AuthorizationFilterAttributeবৈশিষ্ট্যে ব্যবহার করতে পারেন:

public override void OnAuthorization(HttpActionContext actionContext)
{
    // the only change I made is use the custom context builder from step 3:
    OAuthContext context = 
        new WebApiOAuthContextBuilder().FromHttpRequest(actionContext.Request);

    try
    {
        provider.AccessProtectedResourceRequest(context);

        // do nothing here
    }
    catch (OAuthException authEx)
    {
        // the OAuthException's Report property is of the type "OAuthProblemReport", it's ToString()
        // implementation is overloaded to return a problem report string as per
        // the error reporting OAuth extension: http://wiki.oauth.net/ProblemReporting
        actionContext.Response = new HttpResponseMessage(HttpStatusCode.Unauthorized)
            {
               RequestMessage = request, ReasonPhrase = authEx.Report.ToString()
            };
    }
}

আমি আমার নিজস্ব সরবরাহকারীর প্রয়োগ করেছি তাই আমি উপরের কোডটি পরীক্ষা করে নিই না (অবশ্যই WebApiOAuthContextBuilderযা আমি আমার সরবরাহকারীর মধ্যে ব্যবহার করছি) তবে এটি ঠিকঠাক কাজ করা উচিত।.

22
Maksymilian Majer

সুরক্ষা প্রদানের জন্য ওয়েব এপিআই একটি অ্যাট্রিবিউট [Authorize] প্রবর্তন করেছে। এটি বিশ্বব্যাপী সেট করা যেতে পারে (Global.asx)

public static void Register(HttpConfiguration config)
{
    config.Filters.Add(new AuthorizeAttribute());
}

বা নিয়ামক প্রতি:

[Authorize]
public class ValuesController : ApiController{
...

অবশ্যই আপনার প্রমাণীকরণের ধরন পৃথক হতে পারে এবং আপনি নিজের প্রমাণীকরণ সম্পাদন করতে চাইতে পারেন, যখন এটি ঘটে তখন আপনি অনুমোদনের বৈশিষ্ট্য থেকে উত্তরাধিকার সূচনা পেতে এবং আপনার প্রয়োজনীয়তাগুলি পূরণ করতে এটি বাড়িয়ে নিতে পারেন:

public class DemoAuthorizeAttribute : AuthorizeAttribute
{
    public override void OnAuthorization(System.Web.Http.Controllers.HttpActionContext actionContext)
    {
        if (Authorize(actionContext))
        {
            return;
        }
        HandleUnauthorizedRequest(actionContext);
    }

    protected override void HandleUnauthorizedRequest(System.Web.Http.Controllers.HttpActionContext actionContext)
    {
        var challengeMessage = new System.Net.Http.HttpResponseMessage(System.Net.HttpStatusCode.Unauthorized);
        challengeMessage.Headers.Add("WWW-Authenticate", "Basic");
        throw new HttpResponseException(challengeMessage);
    }

    private bool Authorize(System.Web.Http.Controllers.HttpActionContext actionContext)
    {
        try
        {
            var someCode = (from h in actionContext.Request.Headers where h.Key == "demo" select h.Value.First()).FirstOrDefault();
            return someCode == "myCode";
        }
        catch (Exception)
        {
            return false;
        }
    }
}

এবং আপনার নিয়ামক মধ্যে:

[DemoAuthorize]
public class ValuesController : ApiController{

ওয়েবএপিআই অনুমোদনের জন্য অন্যান্য কাস্টম প্রয়োগের একটি লিঙ্ক এখানে রয়েছে:

http://www.piotrwalat.net/basic-http-authentication-in-asp-net-web-api-using-membership-provider/

20
Dalorzo

আপনি যদি সার্ভারে আপনার এপিআইটিকে সার্ভার ফ্যাশনে সুরক্ষিত করতে চান (2 লেগড প্রমাণীকরণের জন্য ওয়েবসাইটে কোনও পুনঃনির্দেশ নয়)। আপনি OAuth2 ক্লায়েন্ট শংসাপত্রগুলি অনুদান প্রোটোকলটি দেখতে পারেন।.

https://dev.Twitter.com/docs/auth/application-only-auth

আমি একটি লাইব্রেরি তৈরি করেছি যা আপনাকে সহজেই আপনার ওয়েবএপিআইতে এই ধরণের সমর্থন যোগ করতে সহায়তা করতে পারে। আপনি এটি একটি নিউগেট প্যাকেজ হিসাবে ইনস্টল করতে পারেন:

https://nuget.org/packages/OAuth2ClientCredentialsGrant/1.0.0.

গ্রন্থাগারটি। নেট ফ্রেমওয়ার্ক 4.5 লক্ষ্য করে।.

আপনি একবার আপনার প্রকল্পে প্যাকেজ যুক্ত করলে এটি আপনার প্রকল্পের মূলটিতে একটি রিডমি ফাইল তৈরি করবে। এই প্যাকেজটি কীভাবে কনফিগার/ব্যবহার করতে হয় তা দেখতে আপনি সেই রিডমে ফাইলটি দেখতে পারেন।.

চিয়ার্স!

5
Varun Chatterji

@ কুওং লে-এর উত্তরের ধারাবাহিকতায়, রিপ্লে আক্রমণ প্রতিরোধ করার জন্য আমার পদ্ধতি হবে

// শেয়ারকৃত ব্যক্তিগত কী (বা ব্যবহারকারীর পাসওয়ার্ড) ব্যবহার করে ক্লায়েন্টের পাশে ইউনিক্স সময় এনক্রিপ্ট করুন

// এটি সার্ভারে অনুরোধ শিরোনামের অংশ হিসাবে প্রেরণ করুন (WEB API)

// ভাগ করা ব্যক্তিগত কী (বা ব্যবহারকারীর পাসওয়ার্ড) ব্যবহার করে ইউনিক্স টাইম এ সার্ভারে (ডাব্লুইবি এপিআই) ডিক্রিপ্ট করুন

// ক্লায়েন্টের ইউনিক্স সময় এবং সার্ভারের ইউনিক্স সময়ের মধ্যে সময়ের পার্থক্য পরীক্ষা করুন, এক্স সেকেন্ডের চেয়ে বেশি হওয়া উচিত নয়

// যদি ইউজার আইডি/হ্যাশ পাসওয়ার্ড সঠিক হয় এবং ডিক্রিপ্টেড ইউনিক্সটাইম সার্ভার সময়ের X সেকেন্ডের মধ্যে থাকে তবে এটি একটি বৈধ অনুরোধ

2
refactor