تولید عدد صحیح تصادفی در یک بازه در جاوا

تولید عدد صحیح تصادفی در یک بازه در جاوا :

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

  1. java.util.Random.nextInt
  2. Math.random
  3. java.util.Random.ints (جاوا ۸)

۱- کلاس Random و متد nextInt یک عدد از ۰ و شامل صفر تا محدوده ای که تعیین کرده ایم برمیگرداند(یعنی شامل خود عدد محدوده نمی شود). برای اینکه عددی در بازه دلخواه داشته باشیم و اعداد min و max را هم شامل شود باید به این صورت:


private static int getRandomNumberInRange(int min, int max) {

	if (min >= max) {
		throw new IllegalArgumentException("max must be greater than min");
	}

	Random r = new Random();
	return r.nextInt((max - min) + 1) + min;
}

برای درک عبارت ( (مکس – مین)+۱ ) + مین  توجه داشته باشید:


//Random().nextInt(int bound) = Random integer from 0 (inclusive) to bound (exclusive)

//۱٫ nextInt(range) = nextInt(max - min)
new Random().nextInt(5);  // [0...4] [min = 0, max = 4]
new Random().nextInt(6);  // [0...5]
new Random().nextInt(7);  // [0...6]
new Random().nextInt(8);  // [0...7]
new Random().nextInt(9);  // [0...8]
new Random().nextInt(10); // [0...9]
new Random().nextInt(11); // [0...10]

//۲٫ To include the last value (max value) = (range + 1)
new Random().nextInt(5 + 1)  // [0...5] [min = 0, max = 5]
new Random().nextInt(6 + 1)  // [0...6]
new Random().nextInt(7 + 1)  // [0...7]
new Random().nextInt(8 + 1)  // [0...8]
new Random().nextInt(9 + 1)  // [0...9]
new Random().nextInt(10 + 1) // [0...10]
new Random().nextInt(11 + 1) // [0...11]

//۳٫ To define a start value (min value) in a range,
//   For example, the range should start from 10 = (range + 1) + min
new Random().nextInt(5 + 1)  + 10 // [0...5]  + 10 = [10...15]
new Random().nextInt(6 + 1)  + 10 // [0...6]  + 10 = [10...16]
new Random().nextInt(7 + 1)  + 10 // [0...7]  + 10 = [10...17]
new Random().nextInt(8 + 1)  + 10 // [0...8]  + 10 = [10...18]
new Random().nextInt(9 + 1)  + 10 // [0...9]  + 10 = [10...19]
new Random().nextInt(10 + 1) + 10 // [0...10] + 10 = [10...20]
new Random().nextInt(11 + 1) + 10 // [0...11] + 10 = [10...21]

// Range = (max - min)
// So, the final formula is ((max - min) + 1) + min

//۴٫ Test [10...30]
// min = 10 , max = 30, range = (max - min)
new Random().nextInt((max - min) + 1) + min
new Random().nextInt((30 - 10) + 1) + 10
new Random().nextInt((20) + 1) + 10
new Random().nextInt(21) + 10    //[0...20] + 10 = [10...30]

//۵٫ Test [15...99]
// min = 15 , max = 99, range = (max - min)
new Random().nextInt((max - min) + 1) + min
new Random().nextInt((99 - 15) + 1) + 15
new Random().nextInt((84) + 1) + 15
new Random().nextInt(85) + 15    //[0...84] + 15 = [15...99]

//Done, understand?

۲-و متد random از کلاس Math یک عدد بین ۰ تا ۱ و از نوع double بر میگرداند:


static double	random()
Returns a double value with a positive sign, greater than or equal to 0.0 and less than 1.0.

 

و برای به دست آوردن عددی رندم در یک بازه ی خاص مثل روش قبل:


	private static int getRandomNumberInRange(int min, int max) {

		if (min >= max) {
			throw new IllegalArgumentException("max must be greater than min");
		}

		return (int)(Math.random() * ((max - min) + 1)) + min;
	}

۳- در جاوا ۸ متد های جدید به java.util.Random اضافه شده اند. برای این کار از متد ints استفاده میکنیم که یک عدد بین بازه ی min و شامل min و تا max تعیین میشود و چون خود max را شامل نمیشود برای اینکه عددی در بازه دلخواه داشته باشیم و خود اعداد min و max را هم شامل شود باید به این صورت max را بعلاوه یک کنیم:


import java.util.Random;

public class TestRandom {

	public static void main(String[] args) {

		for (int i = 0; i < 10; i++) {
			System.out.println(getRandomNumberInRange(33, 38));
		}

	}

	private static int getRandomNumberInRange(int min, int max) {

		Random r = new Random();
		return r.ints(min, (max + 1)).limit(1).findFirst().getAsInt();

	}

}

 

تولید عدد صحیح تصادفی در یک بازه در جاوا
تولید عدد صحیح تصادفی در یک بازه در جاوا

 

آسیب پذیری تزریق کد

تزریق کد معمولا زمانی اتفاق می افتد که ورودی های نامطمعن و بدون اعتبار سنجی مستقیما در برنامه اجرا شود. یکی از منابع بالقوه ی آسیب پذیریِ تزریق کد استفاده از جاوا اسکریپت در کد جاوا است. بسته javax.script شامل اینترفیس ها و کلاس هایی است که موتورهای اسکریپت جاوا را تعریف می کنند و چارچوبی برای استفاده از آن در کد جاوا است.

مهاجم با سوء استفاده از api این پکیج قادر به اجرای کد های مخرب در سیستم هدف است. این تقریبا مثل SQL injection است.

مثال :

این متد یک رشته به عنوان نام کاربر دریافت و نتیجه را در خروجی چاپ میکند:


private static void evalScript(String firstName) throws ScriptException {
  ScriptEngineManager manager = new ScriptEngineManager();
  ScriptEngine engine = manager.getEngineByName("javascript");
  engine.eval("print('"+ firstName + "')");
}

یک مهاجم می تواند یک نمونه ی مخرب از کد را به عنوان آرگومان به این متد تزریق کند، و مثلا اگر این کد جاوا اسکریپت را به متد evalScript بدهیم ابتدا “dummy” چاپ میشود و بعد در فایل تنظیمات فرضی عبارت “some text” رو نوشته خواهد شد…


dummy\');
var bw = new JavaImporter(java.io.BufferedWriter);
var fw = new JavaImporter(java.io.FileWriter);
with(fw) with(bw) {
   bwr = new BufferedWriter(new FileWriter(\"config.cfg\"));
   bwr.write(\"some text\"); bwr.close();
}
// ;

روش های مقابله:

۱- لیست سفید (Whitelisting):

بهترین روش برای مقابله با این آسیب پذیری استفاده از لیست سفید کاراکتر های مجاز است. کافیه قبل از اجرا بررسی بشه که  کاراکتر غیر مجازی در رشته وجود نداشته باشد:


private static void evalScript(String firstName) throws ScriptException {
  // Allow only alphanumeric and underscore chars in firstName
  // (modify if firstName may also include special characters)
  if (!firstName.matches("[\\w]*")) {
    // String does not match whitelisted characters
    throw new IllegalArgumentException();
  }
 
  ScriptEngineManager manager = new ScriptEngineManager();
  ScriptEngine engine = manager.getEngineByName("javascript");
  engine.eval("print('"+ firstName + "')");
}

۲- جعبه شنی امن (Secure Sandbox):

یک روش جایگزین استفاده از مدیر امنیت (security manager ) برای ایجاد یک جعبه شنی امن است. برنامه باید از اجرای دستورات دلخواه توسط اسکریپت مانند پرس و جو از سیستم فایل محلی جلوگیری کند.


class ACC {
  private static class RestrictedAccessControlContext {
    private static final AccessControlContext INSTANCE;
   
    static {
      INSTANCE = new AccessControlContext(
                   new ProtectionDomain[] {
                     new ProtectionDomain(null, null) // No permissions
                   });
    }
  }
   
  private static void evalScript(final String firstName)
      throws ScriptException {
    ScriptEngineManager manager = new ScriptEngineManager();
    final ScriptEngine engine = manager.getEngineByName("javascript");
    // Restrict permission using the two-argument form of doPrivileged()
    try {
      AccessController.doPrivileged(
        new PrivilegedExceptionAction<0bject>() {
                         
          public Object run() throws ScriptException {
            engine.eval("print('" + firstName + "')");
            return null;
          }
        },
        // From nested class
        RestrictedAccessControlContext.INSTANCE);
                                                                     
    } catch (PrivilegedActionException pae) {
      // Handle error
    }
  }
}

این رویکرد می تواند با لیست سفید برای امنیت بیشتر ترکیب شود.