فیلتر های امنیت در Web API

سه شنبه 17 آذر 1394

در این مقاله راجع به فیلترهایی که برای تامین امنیت Web Api کاربرد دارند و همچنین سایر روش های امنیتی درWeb Api صحبت خواهیم کرد.

فیلتر های امنیت در  Web API

کاری که فیلتر های احراز هویت انجام می دهند اعتبارسنجی درخواست های ورودی است . هم web Api و هم mvc از فیلترها احراز هویت پشتیبابی می کنند.این فیلتر ها را می توان برای کنترلر ها و action های موجود در برنامه خود استفاده کنید .یعنی احراز هویت در سطوح مختلف از جمله کنترلر و action قابل پیاده سازی است .
فرآیند احراز هویت در وب چگونه است؟

فر آیند احراز هویت در وب به این صورت است که قبل از اجرا شدن Actionمورد نظر وب یک لیستی از فیلتر های احراز هویتی که برای این actionدر نظر گرفته شده است می سازد.این لیست شامل تمام فیلتر های با محدوده کنترلر اکشن و Global است.

پس از این مرحله وب AuthenticateAsync  هر فیلتر را فراخوانی می کند.هر فیلتر می تواند درخواست رسیده را بررسی کرده و از صحت آن مطمئن شود.اگر درخواست درست بود و از فیلتر رد شد فیلتر مورد نظر به انتهای درخواست IPrincipal  را اضافه می کندو اگر درخواست درست نباشد یک خطایی نشان داده میشود.

با فرض اینکه خطایی وجود نداشته باشد درخواست  بقیه مسیر  برای اجرا در سرور و بازگشت پاسخ را ادامه می دهد.

همان طور که می دانید  Authentication یعنی  چه کاربری به سایت وارد شده است. Authorization ، سطح دسترسی کاربر وارد شده به سیستم و اعمالی را که مجاز است انجام دهد را مشخص می‌کند.

برای اعمال جنبه های مختلف امنیت در web Api گزینه های مختلفی وجود دارد از جمله :

HTTP Module

میان افزار OWIN

Message Handler

Action Filter

Authorization Filter

Authentication Filter

HTTP Module

پردازش یک صفحه وب مراحل مختلفی دارد و در هر مرحله یک سری رویدادهای خاصی اجرا می شوند.با کمک HTTP Module می توانیم در این رویدادها تغییراتی ایجاد کنیم .یکی از این عملیات می تواند اعتبار سنجی درخواست ها برای تامین امنیت سرویس Web Api باشد.

دو عدد از مهمترین توابع در این قسمت BeginRequest و EndRequest است .برای نوشتن یک HTTP Moduleباید از اینترفیس مربوط به آن ارث بری کرد و بعد تک تک توابع را بازنویسی کرد .به کد زیر توجه کنید

class SampleHttpModule : IHttpModule
{
    public void Dispose(){}
 
    public void Init(HttpApplication context)
    {
        context.BeginRequest += new EventHandler(context_BeginRequest);
        context.EndRequest += new EventHandler(context_EndRequest);
    }
 
    void context_BeginRequest(object sender, EventArgs e)
    {
        //handle BeginRequest here...
    }
 
    void context_EndRequest(object sender, EventArgs e)
    {
        //handle EndRequest here...
    }
}

بعد از تعریف کردن این HTTP Module باید آنرا به web.config  معرفی کنیم

<configuration>
    <system.web>
        <httpModules>
            <add name="SampleHttpModule" type="MyApplication.SampleHttpModule"/>
        </httpModules>
    </system.web>
</configuration>

Owin MiddleWare

Owin یا Open Web Inteface for .NET یک لایه انتزاعی بین وب  سرور ما و برنامه به وجود می آورد. ASP.NET Web API 2 کاملا از owin پشتیبانی می کند .می توانید در برنامه خود از signalR  هم به همراه web Api استفاده کنید هر دو اینها مشکلی با owin ندارند

در این میان افزار می توانید تعهدات امنیتی برای برنامه خود در نظر بگیرید.

Message Handler

این گزینه توسط web Api ارائه شده است .استفاده از این مورد برای امنیت فواید بسیاری دارد.Message Handler تنها برای درخواست هایی از نوع web Api کاربرد دارد. از Message Handler می توانید به عنوان یک Handler کلی هم استفاده کنید و بعد این handler کلی را برای بررسی امنیت در درخواست ها و کنترلر های خود به کار گیرید.البته این نکته را در نظر داشته باشید که پایین ترین سطح امینت در این گزینه هایی که گفته شد مربوط به Message Handler می باشد.

فیلتر های Action

به صورت پیش فرض همه کنترلر ها و Action ها قابل دسترسی توسط همه کاربران هستند .متدهای public  در واقع دسترسی را به همه می دهند و هیچ اعتبارسنجی به صورت پیش فرض انجام نمی دهند.برای اینکه از کنترلر ها و action ها محافظت کنیم از یک صفتی به نام authorize باید استفاده کنیم .

فیلتر دیگری هم در web api اضافه شده است که نام Authentication است .این فیلتر بعد از message handlers و قبل از تمام فیلتر های دیگر اجرا می شود. برای Authentication روش های سنتی و بر مبنای token وجود دارد .در سیستم سنتی کاربر درخواست دیدن صفحه ای را به سرور ارسال می کند بعد از اینکه درخواست به سمت سرور ارسال شد اطلاعات این کاربر در بانک چک می شود اگر این کاربر وجود داشت یک session برای او ایجاد می گردیدو بعد  بر اساس سطوح دسترسی یا همان role اجازه دسترسی به صفحه را به کاربر می دهیم .اما در حال حاضر  با توجه به اینکه کاربران موبایل و اندروید در حال افزایش هستند استفاده از session جوابگوی احراز هویت نیست .در این حالت از Token استفاده می کنیم .در روش جدید پس از وارد کردن کلمه عبور و نام کاربری ، اگر این کاربر در دیتابیس ما وجود داشت یک توکن ایجاد کرده و در سمت کلاینت ذخیره می کنیم .از توکن در web api بسیار استفاده می شود.

با استفاده از فیلتر Authentication در web api می توانیم از حملات XSRF جلوگیری کنیم .این حملات از اعتماد سایت ها به کاربرانشان سواستفاده کرده و به جای کاربر به انجام عملیاتی می پردازند .کاربر از این عملیات هیچ اطلاعی ندارد.


ساختن فیلتر های Authentication  و Authorization  به صورت پشت سر هم

کلا ترتیب اجرا فیلتر ها در mvc و web api   به این صورت است که فیلتر های از نوع Authentication   قبل از همه اجرا می شوند .بعد از آن فیلتر های از نوع Action  اجرا می شوند .بعد از فیلتر ها از نوع action فیلترهایی از نوع Result اجرا میشوند یعنی درست قبل از بازگرداندن نتیجه متد این فیلتر ها اجرا می شوند .

در شکل زیر نحوه ای که درخواست کاربر برای دیدن صفحه ای به سرور ارسال می شود و از فیلتر های احراز هویت عبور می کند نشان داده شده است .


ساخت فیلتر Authentication

برای اینکه خودتان فیلتر ایجاد کنید باید یک اینترفیس بسازید که این اینترفیس از Ifilter ارث بری می کند .کد زیر را ببینید

public interface IAuthenticationFilter : IFilter
{
  Task AuthenticateAsync(HttpAuthenticationContext context, 
    CancellationToken cancellationToken);
  Task ChallengeAsync(HttpAuthenticationChallengeContext context,
    CancellationToken cancellationToken);
}

حال برای انجام احراز هویت یک متد به نام AuthenticateAsync می نویسیم .کد های این تابع در زیر اَورده شده است .

public Task AuthenticateAsync(HttpAuthenticationContext context,
  CancellationToken cancellationToken)
{
  var req = context.Request;
  // Get credential from the Authorization header 
  //(if present) and authenticate
  if (req.Headers.Authorization != null &&
    "somescheme".Equals(req.Headers.Authorization.Scheme,
      StringComparison.OrdinalIgnoreCase))
  {
    var creds = req.Headers.Authorization.Parameter;
    if(creds == "opensesame") // Replace with a real check
    {
      var claims = new List<Claim>()
      {
        new Claim(ClaimTypes.Name, "badri"),
        new Claim(ClaimTypes.Role, "admin")
      };
      var id = new ClaimsIdentity(claims, "Token");
      var principal = new ClaimsPrincipal(new[] { id });
      // The request message contains valid credential
      context.Principal = principal;
    }
    else
    {
      // The request message contains invalid credential
      context.ErrorResult = new UnauthorizedResult(
        new AuthenticationHeaderValue[0], context.Request);
    }
  }
  return Task.FromResult(0);
}

شما می توانید از این متد برای پیاده سازی هسته Authentication استفاده کنید . این متد به نوبه خود authentication challenge را اضافه می کند . authentication challenge زمانی که فرآیند Authentication با شکست مواجه شود به پاسخ 401 سرور اضافه می شود.در زیر کدهای مربوط به  authentication challenge آورده شده است

public Task ChallengeAsync(HttpAuthenticationChallengeContext context,
  CancellationToken cancellationToken)
{
  context.Result = new ResultWithChallenge(context.Result);
  return Task.FromResult(0);
}
public class ResultWithChallenge : IHttpActionResult
{
  private readonly IHttpActionResult next;
  public ResultWithChallenge(IHttpActionResult next)
  {
    this.next = next;
  }
  public async Task<HttpResponseMessage> ExecuteAsync(
    CancellationToken cancellationToken)
  {
    var response = await next.ExecuteAsync(cancellationToken);
    if (response.StatusCode == HttpStatusCode.Unauthorized)
    {
      response.Headers.WwwAuthenticate.Add(
        new AuthenticationHeaderValue("somescheme", "somechallenge"));
    }
    return response;
  }
}

نحوه استفاده از این فیلتر هایی که تعریف کردیم به این صورت است که در بالای هر فیلتر و یا کنترلر دلخواهی این فیلتر ها را قرار می دهیم .

public static class WebApiConfig
{
  public static void Register(HttpConfiguration config)
  {
    // Other Web API configuration code goes here
    config.Filters.Add(new AuthorizeAttribute()); // Global level
  }
}
[Authorize(Roles="admin")] // Controller level
public class EmployeesController : ApiController
{
  [Authorize(Users="badri")] // Action method level
  public string Get(int id)
  {
    return “Hello World”;
  }
}

فیلتر AllowAnonymous

این فیلتر اجازه دسترسی تمام کاربران حتی آنهایی که احراز هویت نشده اند را ، به action مورد نظر می دهد. زمانی استفاده می شود که کل یک کنترلر را به role خاصی محدود کرده اید و می خواهید در این کنترلر تنها یک action به صورت آزاد باشد و هر کاربری بتواند از آن استفاده کند.نحوه استفاده از این فیلتر به صورت زیر است

public static class WebApiConfig
{
  public static void Register(HttpConfiguration config)
  {
    // Other Web API configuration code goes here
    config.Filters.Add(new AuthorizeAttribute()); // Global level
  }
}
[AllowAnonymous]
public class PublicResourcesController : ApiController
{
  public string Get(int id)
  {
    return “Hello World”;
  }
}

برای اینکه تنها کاربرانی که از سیستم احراز هویت Token (برای آشنایی با مبحث token به مقاله محافظت برنامه های MVC از حملات CSRF با استفاده از Antiforgery token مراجعه کنید )استفاده می کنند بتوانند به action دسترسی داشته باشند باید ابتدا تمام فیلتر های احراز هویتی که داریم را غیر فعال کنیم و بعد از فیلتر TokenAuthenticator برای احراز هویت کاربران Token استفاده می کنیم .به کد زیر توجه کنید

public class EmployeesController : ApiController
{
  [OverrideAuthentication] // Removes all authentication filters
  [TokenAuthenticator] // Puts back only the token authenticator
  public string GetAllowedForTokenOnly(int id)
  {
    return “Hello World”;
  }
}

 

برنامه نویسان

نویسنده 3355 مقاله در برنامه نویسان

کاربرانی که از نویسنده این مقاله تشکر کرده اند

در صورتی که در رابطه با این مقاله سوالی دارید، در تاپیک های انجمن مطرح کنید