• 22-04-2022, 01:40:10
    #1
    apiye post gönderdiğimiz bi veri var, sonuç geliyor vs.
    şimdi şöyle bi güvenlik önlemi istiyorum.
    örneğin bi ip üzerinde saatlik x adet post gönderebilsin. daha fazla veri çekmek, bilgi almak istediğinde uyarı versin ve x dakika işlem yapamazsın, lütfen x dakika sonra tekrar dene. gibi bi uyarı istiyorum.
    kabaca

    kişi farklı isimlerle sisteme giriş yapabilir,
    1. veriyi çeker, 5 çeker 10. çeker,
    11. veri çekmek istediğinde bi uyarı olarak "çok hızlı gidiyorsun, 15 dakika sonra tekrar dene"
    gibi birşey.
    nasıl yapabilirim, herhangi bi örneğine rastlamadım.

    + olarak ip adresi yerine nasıl bi garanti önlem alabiliriz?
  • 22-04-2022, 01:48:55
    #2
    Asp.Net Mvc ile geliştirdiğim projede kullandığım yapı. Bu yapıyla controller'a gelen istek sayısını kısıtlayabiliyorum ancak dediğiniz veri çekme olayını metodun içerisinde yaparsanız daha doğru olabilir.
    Örneğin Handle sayfasına bir tarayıcıdan dakikada 40 istek yapıldığında 41. isteği engelliyor. bir sonraki dakikada yine istek yapabiliyor ancak saatte 100 isteği geçerse yine engelliyor, 2. saate geldiğinde istek yapmaya devam edebiliyor, günlük 250 istek yaptığında ertesi gün istek yapmaya devam edebilir.
    Controller.cs:


    [Throttle(TimeUnit = TimeUnit.Minute, Count = 40)]
    [Throttle(TimeUnit = TimeUnit.Hour, Count = 100)]
    [Throttle(TimeUnit = TimeUnit.Day, Count = 250)]
    public class HandleController : Controller
    {
    // kodlar..........
    }

    Throttle.cs:
    public enum TimeUnit
    {
    Minute = 60,
    Hour = 3600,
    Day = 86400
    }

    [AttributeUsage(AttributeTargets.All, AllowMultiple = true)]
    public class ThrottleAttribute : ActionFilterAttribute
    {
    public TimeUnit TimeUnit { get; set; }
    public int Count { get; set; }

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
    var seconds = Convert.ToInt32(TimeUnit);

    var key = string.Join(
    "-",
    seconds,
    filterContext.HttpContext.Request.HttpMethod,
    filterContext.ActionDescriptor.ControllerDescripto r.ControllerName,
    filterContext.ActionDescriptor.ActionName,
    filterContext.HttpContext.Request.UserHostAddress
    );

    // increment the cache value
    var cnt = 1;
    if (HttpRuntime.Cache[key] != null)
    {
    cnt = (int)HttpRuntime.Cache[key] + 1;
    }
    HttpRuntime.Cache.Insert(
    key,
    cnt,
    null,
    DateTime.UtcNow.AddSeconds(seconds),
    Cache.NoSlidingExpiration,
    CacheItemPriority.Low,
    null
    );

    if (cnt > Count)
    {

    filterContext.Result = new JsonResult { ContentType = "application/json", Data = new Mesaj { tur = MesajTuru.Uyari, mesaj = "You are allowed to make only " + Count + " requests per " + TimeUnit.ToString().ToLowerInvariant() }, JsonRequestBehavior = JsonRequestBehavior.AllowGet };
    filterContext.HttpContext.Response.StatusCode = 429;
    return;
    }
    base.OnActionExecuting(filterContext);
    return;
    }

    }
  • 22-04-2022, 01:52:53
    #3
    Tartaros adlı üyeden alıntı: mesajı görüntüle
    apiye post gönderdiğimiz bi veri var, sonuç geliyor vs.
    şimdi şöyle bi güvenlik önlemi istiyorum.
    örneğin bi ip üzerinde saatlik x adet post gönderebilsin. daha fazla veri çekmek, bilgi almak istediğinde uyarı versin ve x dakika işlem yapamazsın, lütfen x dakika sonra tekrar dene. gibi bi uyarı istiyorum.
    kabaca

    kişi farklı isimlerle sisteme giriş yapabilir,
    1. veriyi çeker, 5 çeker 10. çeker,
    11. veri çekmek istediğinde bi uyarı olarak "çok hızlı gidiyorsun, 15 dakika sonra tekrar dene"
    gibi birşey.
    nasıl yapabilirim, herhangi bi örneğine rastlamadım.

    + olarak ip adresi yerine nasıl bi garanti önlem alabiliriz?
    laravel kullanıyorsan kolay yoldan yapabilirsin Rate Limiter.
  • 22-04-2022, 01:53:57
    #4
    emrahe adlı üyeden alıntı: mesajı görüntüle
    Asp.Net Mvc ile geliştirdiğim projede kullandığım yapı. Bu yapıyla controller'a gelen istek sayısını kısıtlayabiliyorum ancak dediğiniz veri çekme olayını metodun içerisinde yaparsanız daha doğru olabilir.
    Örneğin Handle sayfasına bir tarayıcıdan dakikada 40 istek yapıldığında 41. isteği engelliyor. bir sonraki dakikada yine istek yapabiliyor ancak saatte 100 isteği geçerse yine engelliyor, 2. saate geldiğinde istek yapmaya devam edebiliyor, günlük 250 istek yaptığında ertesi gün istek yapmaya devam edebilir.
    Controller.cs:


    [Throttle(TimeUnit = TimeUnit.Minute, Count = 40)]
    [Throttle(TimeUnit = TimeUnit.Hour, Count = 100)]
    [Throttle(TimeUnit = TimeUnit.Day, Count = 250)]
    public class HandleController : Controller
    {
    // kodlar..........
    }

    Throttle.cs:
    public enum TimeUnit
    {
    Minute = 60,
    Hour = 3600,
    Day = 86400
    }

    [AttributeUsage(AttributeTargets.All, AllowMultiple = true)]
    public class ThrottleAttribute : ActionFilterAttribute
    {
    public TimeUnit TimeUnit { get; set; }
    public int Count { get; set; }

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
    var seconds = Convert.ToInt32(TimeUnit);

    var key = string.Join(
    "-",
    seconds,
    filterContext.HttpContext.Request.HttpMethod,
    filterContext.ActionDescriptor.ControllerDescripto r.ControllerName,
    filterContext.ActionDescriptor.ActionName,
    filterContext.HttpContext.Request.UserHostAddress
    );

    // increment the cache value
    var cnt = 1;
    if (HttpRuntime.Cache[key] != null)
    {
    cnt = (int)HttpRuntime.Cache[key] + 1;
    }
    HttpRuntime.Cache.Insert(
    key,
    cnt,
    null,
    DateTime.UtcNow.AddSeconds(seconds),
    Cache.NoSlidingExpiration,
    CacheItemPriority.Low,
    null
    );

    if (cnt > Count)
    {

    filterContext.Result = new JsonResult { ContentType = "application/json", Data = new Mesaj { tur = MesajTuru.Uyari, mesaj = "You are allowed to make only " + Count + " requests per " + TimeUnit.ToString().ToLowerInvariant() }, JsonRequestBehavior = JsonRequestBehavior.AllowGet };
    filterContext.HttpContext.Response.StatusCode = 429;
    return;
    }
    base.OnActionExecuting(filterContext);
    return;
    }

    }
    ByTriSLaSiS adlı üyeden alıntı: mesajı görüntüle
    laravel kullanıyorsan kolay yoldan yapabilirsin Rate Limiter.
    arkadaşlar teşekkür ederim.
    düz php kullanıyorum herhangi bi yapı yok. daha basit anlaşılır birşey bakıyorum.
  • 22-04-2022, 02:00:48
    #5
    kabaca veritabanında bir tablo aç ipler diye ve kişi 10 tane veriyi çektikten sonra ipler tablosuna kişinin ipsini ve 15dk sonrasının tarihini kayıt ettir. Sorgudada api kullanan kişinin ipsini ipler tablosunda arat varsa çekemesin yoksa çeksin. Cronjobada ipler tablosundaki tarihide 1dk veya 2 dk aralıklarla kontrol etttir.
  • 22-04-2022, 03:40:58
    #6
    Tartaros adlı üyeden alıntı: mesajı görüntüle
    apiye post gönderdiğimiz bi veri var, sonuç geliyor vs.
    şimdi şöyle bi güvenlik önlemi istiyorum.
    örneğin bi ip üzerinde saatlik x adet post gönderebilsin. daha fazla veri çekmek, bilgi almak istediğinde uyarı versin ve x dakika işlem yapamazsın, lütfen x dakika sonra tekrar dene. gibi bi uyarı istiyorum.
    kabaca

    kişi farklı isimlerle sisteme giriş yapabilir,
    1. veriyi çeker, 5 çeker 10. çeker,
    11. veri çekmek istediğinde bi uyarı olarak "çok hızlı gidiyorsun, 15 dakika sonra tekrar dene"
    gibi birşey.
    nasıl yapabilirim, herhangi bi örneğine rastlamadım.

    + olarak ip adresi yerine nasıl bi garanti önlem alabiliriz?
    İp adresi dışında alternatif çözümler arasında cookie,session gibi çerez verileri devreye girebilir. Ama bunlar ( cookie ) manipule edilebilir. Ayrıca apiye uzaktan bağlantı yapan kişininde ilgili bağlantı başlığında bunları iletmesi gerekir.

    IP taraflı yapacağınız iş aşağıdaki şekilde olur. Veritabanına gerek yok disktede yapılır.

    Api dosyanız ( Örnek index.php )

    <?php
    function get_ip()
    {
    		 if(getenv("HTTP_CLIENT_IP")) {
    		 $ip = getenv("HTTP_CLIENT_IP");
    		 } elseif(getenv("HTTP_X_FORWARDED_FOR")) {
    		 $ip = getenv("HTTP_X_FORWARDED_FOR");
    		 if (strstr($ip, ',')) {
    		 $tmp = explode (',', $ip);
    		 $ip = trim($tmp[0]);
    		 }
    		 } else {
    		 $ip = getenv("REMOTE_ADDR");
    		 }
    		 return $ip;
    }
    
    
    function ip_counter($limit=5)
    {
    	$result = array();
    	$result['status'] = false;
    	$ip = get_ip();
    	$list = file_get_contents('list.html');
    	$time = time();
    	preg_match_all('@<ip value="(.*?)" time="(.*?)"></ip>@si',$list,$ips);
    	$check_already = array_search($ip, $ips[1]);
    	if($check_already)
    	{
    		$last_time = $ips[2][$check_already];
    		$difference = $time-$last_time;
    		if($difference>=5)
    		{
    			$replace_line = preg_replace('@<ip value="'.$ip.'" time="(.*?)"></ip>@si','<ip value="'.$ip.'" time="'.$time.'"></ip>',$list);
    			file_put_contents('list.html',$replace_line);
    			
    			$result['status'] = true;
    			$result['ip_next_time'] = $limit;
    		}
    		else
    		{
    			$result['status'] = false;
    			$result['ip_next_time'] = $limit-$difference;
    		}
    	}
    	else
    	{
    		$add_line = PHP_EOL.'<ip value="'.$ip.'" time="'.$time.'"></ip>';
    		file_put_contents('list.html',$add_line, FILE_APPEND);
    		$result['status'] = true;
    		$result['ip_next_time'] = $limit;
    	}
    	return $result;
    }
    
    
    
    $ip_counter = ip_counter(5);
    $ip_next_time = $ip_counter['ip_next_time'];
    if($ip_counter['status'])
    {
    	// Burada başarılı api isteğine karşı kodlarınız
    
    	echo 'İstek Başarılı!<br>';
    	echo 'Sonraki İstek İçin Beklenmesi Gereken Süre: '.$ip_next_time.' Sn';
    }
    else
    {
    	// Rate Limit
    	
    	echo 'İstek Başarısız!<br>';
    	echo 'Sonraki İstek İçin Beklenmesi Gereken Süre: '.$ip_next_time.' Sn';
    }
    
    ?>

    Loglar list.html dosyasında tutulur.