2017-03-09 88 views
0

我正在製作一個遊戲,玩家必須編寫自己的課程來控制屏幕上的單位。但是,我想阻止他們在播放器類中使用靜態變量,以便他們的單元必須通過我開發的通信系統(即傳輸1s和0s)來傳遞信息,而不是隻訪問靜態「unitsTargeted」變量或任何其他地方有可能。我可以阻止他們以某種方式使用靜態修飾符嗎?防止使用靜態修飾符

+1

不是真的,除非你想編寫你自己的編譯器。 – shmosel

+0

將行爲部分卸載到玩家必須實現的抽象類或接口。防止他們接觸玩家類。 – anacron

+0

目前還不清楚爲什麼靜態變量在玩家類中無效。如果他們做一個非靜態的'unitsTargeted'變量會不會也不好? –

回答

0

這取決於。如果你無法控制源代碼或運行環境,那麼你不能阻止它們編譯他們想要的東西或執行它。

如果您可以控制構建(即:將源發送到您控制的系統並控制編譯),那麼您可以構建自定義編譯器。

如果您以某種方式控制運行環境,則可以檢查提供的類以查看其中包含的內容。你可以使用一些字節碼工具,或者更好的是使用反射API,並檢查是否有任何成員是靜態的。一旦您使用反射來獲取成員列表,請遍歷它們並檢查它們的isStatic。如果該類包含任何靜態成員,則可以拒絕它。

就你而言,由於你是從客戶端上傳類到服務器,所以你可以簡單地通過使用Java的反射API來檢查它。如果客戶端提交源代碼,那麼您需要首先編譯它,不過我假設您在使用它之前仍然這樣做。

下面是測試情況下,我只是跑:

package test.tmp; 

import java.lang.reflect.Field; 
import java.lang.reflect.Method; 
import java.lang.reflect.Modifier; 
import java.util.ArrayList; 
import java.util.List; 

public class StaticChecker 
{ 
    public static void main(String[] args) 
    { 
     for(Class c : new Class[]{StaticChecker.class, ClassWithStatics.class, ClassWithoutStatics.class}) 
     { 
      System.out.println("For " + c + "..."); 

      boolean hasStatic = hasStaticMembers(c); 
      System.out.println("\tIt contains static members: " + hasStatic); 

      if(hasStatic) 
      { 
       System.out.println("\tThe static members are:"); 
       for(String s : checkStaticMembers(c)) 
        System.out.println("\t\t" + s); 
      } 
     } 
    } 

    public static boolean hasStaticMembers(Class c) 
    { 
     return checkStaticMembers(c).size() > 0; 
    } 

    public static List<String> checkStaticMembers(Class c) 
    { 
     List<String> staticMemberNames = new ArrayList<String>(); 

     for(Field field : c.getDeclaredFields()) 
      if(Modifier.isStatic(field.getModifiers())) 
       staticMemberNames.add(field.toString()); 

     for(Method method : c.getDeclaredMethods()) 
      if(Modifier.isStatic(method.getModifiers())) 
       staticMemberNames.add(method.toString()); 

     return staticMemberNames; 
    } 
} 

class ClassWithStatics 
{ 
    public static int N = 3; 
    private static String S = "?"; 

    private int n; 

    void f() { System.out.println("f()"); } 
    static void g() { System.out.println("g()"); } 
    public static void h() { System.out.println("h()"); } 
} 

class ClassWithoutStatics 
{ 
    int a; 
    String b; 
    void f() { System.out.println("f()"); } 
} 

當我運行上面的測試,我得到以下的輸出:

For class test.tmp.StaticChecker... 
    It contains static members: true 
    The static members are: 
     public static void test.tmp.StaticChecker.main(java.lang.String[]) 
     public static java.util.List test.tmp.StaticChecker.checkStaticMembers(java.lang.Class) 
     public static boolean test.tmp.StaticChecker.hasStaticMembers(java.lang.Class) 
For class test.tmp.ClassWithStatics... 
    It contains static members: true 
    The static members are: 
     public static int test.tmp.ClassWithStatics.N 
     private static java.lang.String test.tmp.ClassWithStatics.S 
     static void test.tmp.ClassWithStatics.g() 
     public static void test.tmp.ClassWithStatics.h() 
For class test.tmp.ClassWithoutStatics... 
    It contains static members: false 

請注意,您在做什麼,可能是危險的並且應該非常小心地限制服務器端可以執行的代碼。所有需要做的事情都是爲了毀掉你的日子而提交的一個類,它會刪除文件或安裝不需要的文件或任何其他惡意行爲。

+0

這聽起來像我需要做的。你能指出我對如何切實執行這個任何好的資源嗎?我的計劃是讓玩家通過網頁將他們的課程上傳到我控制的服務器,我的源代碼將運行遊戲並返回結果。所以我理論上應該能夠在運行源代碼之前檢查玩家是否使用了任何靜態變量。謝謝! –

0

不要在程序中使用靜態變量,或者如果您確實需要靜態變量,請將其設置爲ThreadLocal並將其保留在無法從用戶類訪問的線程中。

如果你希望你的程序比較安全,你還應該建立一些類驗證器來確保這些類只使用允許的類,一個很短的白名單允許的類。

您可以使用ASM來製作此類驗證程序。

+0

謝謝,這聽起來像我需要做的事情。我會檢查ASM。 –