2012-02-07 6 views
5

どのように私はこの種の攻撃から私の変数を保護することができます。悪いプログラマーからPythonのクラス変数を保護するには?

MyClass.__dict__ = {} 
MyClass.__dict__.__setitem__('_MyClass__protectedVariable','...but it is not') 

上記は、変数の辞書を変更し、その後、すべての変数を変更するにはチャイルズプレイです。このためには上の行が重要です。あなたの辞書の__setitem__が以下のように調整されている場合、上記は機能しません)。

ユーザーに私のメソッドsetProtectedVariable(value)を使用させて変数を変更させたいのですが、私はPython 2.7でこれを行う方法がないようです。何か案は?

以下のコードから他の同様の穴が見つかった場合は、私も感謝します。inspect.stackのチェックにファイル名と行番号を追加する必要があることに気付きました(myDict.__setitem__)。

import inspect 

class ProtectionTest: 

    __myPrivate = 0 

    def __init__(self): 
     md = myDict() 
     setattr(self,'__dict__', md) 

    def __setattr__(self, name, val):  
     if name == '__myPrivate': 
      print "failed setattr attempt: __myPrivate" 
      pass 
     elif name == '_ProtectionTest__myPrivate': 
      print "failed setattr attempt: _ProtectionTest__myPrivate" 
      pass 
     elif name == '__dict__': 
      print "failed setattr attempt: __dict__" 
      pass 
     else: 
      self.__dict__[name] = val    

    def getMyPrivate(self): 
     return self.__myPrivate 

    def setMyPrivate(self, myPrivate): 
     #self.__dict__['_ProtectionTest__stack'] = inspect.stack()[0][1:] 
     self.__dict__['_ProtectionTest__myPrivate'] = -myPrivate 

class myDict(dict): 

    def __init__(self): 
     dict.__init__(self) 

    def __setitem__(self, key, value): 
     if inspect.stack()[1][3] == 'setMyPrivate': 
      dict.__setitem__(self,key,value) 
     else: 
      print "failed dict attempt" 
      pass 

pt = ProtectionTest() 

print "trying to change... (success: 1): " 
pt.__myPrivate = 1 
print pt.getMyPrivate(), '\n' 

print "trying to change... (success: 2): " 
pt._ProtectionTest__myPrivate = 2 
print pt.getMyPrivate() , '\n' 

print "trying to change... (success: 3): " 
pt.__dict__['_ProtectionTest__myPrivate'] = 3 
print pt.getMyPrivate() , '\n' 

print "trying to change the function (success: 4): " 
def setMyPrivate(self, myPrivate): 
    self.__dict__['_ProtectionTest__myPrivate'] = 4 
pt.setMyPrivate = setMyPrivate 
pt.setMyPrivate(0) 
print pt.getMyPrivate(), '\n' 

print "trying to change the dict (success: 5): " 
pt.__dict__ = {} 
pt.__dict__.__setitem__('_ProtectionTest__myPrivate',5) 
print pt.getMyPrivate(), '\n' 

print "Still working (correct output = -input = -100): "  
pt.setMyPrivate(100) 
print pt.getMyPrivate() 
+5

なぜこれをやりたいですか?あなたはなぜ、他のプログラマーがあなたのクラスで何をしているのか気にしますか?あなたは仕様に従ってコードを正しく動作させることを担当しています。別のプログラマがそれを悪用しようとしているのであれば、それはそうですか? –

+0

悪意のあるユーザーが悪用する可能性があることを防ぐための防弾方法を見つけることはできません。今もあきらめるかもしれない。 – NPE

+1

あなたは今日好意的です...これは、プライベート変数とメソッドがPythonで存在するのか、なぜそれらが存在しないのかという質問に対する答えです。 – Juha

答えて

18

私はこの質問を動機付ける深い混乱があると感じます。プライベート変数は、悪意の "ハッカー"を遠ざけるためのものではありません。彼らはセキュリティとは何の関係もありません。彼らはmaintaining low couplingのような良いプログラミング実践を促進するためにそこにいる。

「悪意のあるプログラマ」がソースコードにアクセスできる場合、彼または彼女はそれを使って何でもしても構いません。変数 "private"を呼び出してもそれは変更されません。もし、悪いプログラマが別のシステムで実行しているあなたのプログラムを妥協しようとしているならば...変数を "private"と呼ぶことは良いことではありません。プログラムがメモリに格納され操作される方法については何も変わりません。それは(不必要に複雑な方法でIMO)separation of concernsを実行するだけです。

また、保護されたVARに割り当てる... ...

MyClass.__dict__ = {} 
MyClass.__dict__.__setitem__('_MyClass__protectedVariable','...but it is not') 

を通常の状況下では、あなたがこれらすべての悪ふざけを通過する必要がないということは注目に値します。 __dict__を上書きする必要はありません。それは本当にではありません原因

MyClass._MyClass__protectedVariable = '...but it is not' 

:あなたはこれを行うことができます。保護された、私は意味する。名前マングリングの主な目的は、namespace collisionsを防ぐことです。 「プライベート」属性が必要な場合は、単に接頭辞として単一のアンダースコアを付けます。あなたの習慣に敬意を払うようにユーザーに期待し、虐待者が何をしてもそれを壊すことを期待してください。

+0

私はあなたの答えを勉強していましたが、私が気付いたのは、あなたが言いたい2つの"嫌悪感 " .__ dict __.__ setitem__'を呼び出し、後者は 'object .__ setattr__'を呼び出します。これは全体的な結果に大きな違いはありませんが、(この場合のように)わずかにエキゾチックなシステムがあれば言及する価値があると思います。とにかく、良い答え、ありがとう。 – Juha

+0

@Juha、OK、あなたが何を意味しているのか分かります。あなたがカスタマイズした '' __setattr__'の "この種の攻撃"について話していたことは私には分かりませんでした。私は、上記のことをその理解で妥協するように変更しました。 – senderle

7

は、私の知る限り、実際にPythonでこれを行う方法はありません。

は、これは私がこれまでにしようとしているものです。あなたが何をしていても、誰でもあなたのソースをコピーしてハックを取り除くことができます。(ほとんどの場合)クラスから継承してオーバーライドするか、直接メソッドを再割り当てします。

しかし、どうしてそんなに気にしますか?あなたが__whateverという名前を付けると、ユーザーがこれを混乱させると、何か悪いことが起きるのは、自分の気が間違っているという非常に明確な文書です。

8

Pythonでは、このように属性を「保護」することはできません。なぜあなたはあなたの発信者と敵対関係にありますか?あなたと彼はいくつかのことに同意する必要があります、これはそれらの一つです。より良い文書を書いて、彼とより良い友達になれます。あなたの本当の問題は何か分かりませんが、コードでは解決できません。

JavaやC++のような他の言語では、privateなどの区切りを提供していますが、Pythonはそれほど単純ではありません。あなたは事実の後にそれをボルトで締め付けることはできません。

この悪意のあるプログラマが誰であるか、そしてあなたとコードがどのように使用されるべきかについてあなたが意見を述べる場合、私たちは解決策について他のアイデアを提供するかもしれません。

+6

少なくともC++でも 'private'はプラットフォームに依存しない方法で回避できます:) –

3

この種のデータ変更に関して、Pythonはあまり保護的ではありません。しかしこれは特徴であると考えられる。 `final` keyword equivalent for variables in Python?の定数/決勝戦に関する別の質問が役に立つかもしれません。 質問に答えるには:おそらく、同じ実行可能ファイルで外部コードを使用して実行しているクラスの操作に対するデータを保護する方法はありません。データを別のプロセスに格納し、外部プロセスとデータをやりとりするために何らかのAPIを用意する必要があります。