In Unity 3.0 implementiert der Webplayer ein Sicherheitsmodell, das dem des Adobe Flash Players™ sehr ähnlich ist. Diese Sicherheitseinschränkungen gelten nur für den Webplayer und für den Editor, wenn das aktive Build-Ziel WebPlayer ist. Das Sicherheitsmodell besteht aus mehreren Teilen:
- Einschränkungen für den Zugriff auf Daten in einer anderen Domäne als der Domäne, in der Sie gehostet werden .unity3d-Datei.
- Einige Einschränkungen bei der Verwendung der Sockets.
- Verbot des Aufrufs einer Methode, die wir für unzulässig hielten. (dinge wie Datei.Löschen usw.).
- Die Verwendung des Systems nicht zulassen.Reflexion.* um private / interne Methoden in Klassen aufzurufen, die Sie nicht selbst geschrieben haben.
Derzeit werden nur die ersten beiden Teile des Sicherheitsmodells im Editor emuliert.
Die integrierte Muti-Player-Netzwerkfunktionalität von Unity (UnityEngine.Network
, UnityEngine.NetworkView
Klassen usw.) ist nicht betroffen.
In diesem Dokument wird beschrieben, wie Sie sicherstellen, dass Ihre Inhalte mit Version 3.0 des Unity Webplayers weiterhin funktionieren.
- Informationen zur WWW-Klasse finden Sie in der Unity-API-Referenz.
- Informationen zur .NET-Socket-Klasse finden Sie in der .NET-API-Referenz.
Die WWW-Klasse und die Sockets verwenden dasselbe Richtlinienschema, sind aber außerdem völlig getrennte Systeme. Die WWW-Richtlinie definiert nur Berechtigungen für den Webdienst, in dem die Richtlinie gehostet wird, aber Socket-Richtlinien gelten für alle TCP / UDP-Socket-Verbindungen.
Der Unity-Editor verfügt über eine Funktion „Emulieren von Web-Sicherheit“, die das Sicherheitsmodell des Webplayers auferlegt.Dies macht es einfach, Probleme bequem vom Editor aus zu erkennen. Sie finden diese Einstellung inEdit->Projekteinstellungen->Editor. Siehe auch die Editor-Einstellungen.
Der Unity Webplayer erwartet, dass eine http-Richtliniendatei mit dem Namen crossdomain.xml
in der Domäne verfügbar ist, auf die Sie mit der WWW-Klasse zugreifen möchten (obwohl dies nicht erforderlich ist, wenn es sich um dieselbe Domäne handelt, in der die unity3d-Datei gehostet wird).
Stellen Sie sich beispielsweise ein Tetris-Spiel vor, das unter der folgenden URL gehostet wird:
http://gamecompany.com/games/tetris.unity3d
muss über die folgende URL auf eine Highscore-Liste zugreifen:
http://highscoreprovider.net/gethighscore.php
In diesem Fall müssten Sie eine crossdomain.xml
-Datei im Stammverzeichnis des highscoreprovider.net domain wie diese: http://highscoreprovider.net/crossdomain.xml
Der Inhalt der crossdomain.xml
-Datei hat das vom Flash Player verwendete Format. Es ist sehr wahrscheinlich, dass Sie die crossdomain.xml
-Datei bereits finden. Die Richtlinie in der Datei sieht folgendermaßen aus:
<?xml version="1.0"?><cross-domain-policy><allow-access-from domain="*"/></cross-domain-policy>
Wenn diese Datei unter http://highscoreprovider.net/crossdomain.xml platziert wird, erklärt der Eigentümer dieser Domain, dass auf den Inhalt des Webservers von jedem Webplayer zugegriffen werden kann, der von jeder Domain aus kommt.
Der Unity Webplayer unterstützt die Tags <allow-http-request-headers-from domain> und <site-control permitted-cross-domain-policies> nicht. Beachten Sie, dass crossdomain.xml
eine ASCII-Datei sein sollte.
Debuggen
Wenn Sie eine Umgebungsvariable ENABLE_CROSSDOMAIN_LOGGING
auf 1
setzen, werden Konsolennachrichten generiert, wenn die Unity-Laufzeit die crossdomain.xml
-Datei abruft und dekodiert. Auf einem Mac können Sie globale Umgebungsvariablen in /etc/launchd.conf
. Verwenden Sie auf einem PC Systemsteuerung- >System und Sicherheit- >System- >Erweiterte Systemeinstellungen- >Umgebungsvariablen…
Hier ist eine Beispielausgabe mit dieser Umgebungsvariablen, wenn der Webplayer versucht, ein Bild von einem Remote-Server abzurufen:
Determining crossdomain.xml location for request: http://www.remoteserver.com/image.jpgAbout to parse url: http://www.remoteserver.com/image.jpgDetermining crossdomain.xml location for request: http://www.remoteserver.com/image.jpgAbout to parse url: http://www.remoteserver.com/crossdomain.xmlAbout to parse url: http://www.remoteserver.com/image.jpgDetermining crossdomain.xml location for request: http://www.remoteserver.com/image.jpgDownload had OK statuscodeReceived the following crossdomain.xml--------------------------------------<?xml version="1.0"?><cross-domain-policy><allow-access-from domain="*"/></cross-domain-policy>----------------------received policyParsing: cross-domain-policycross-domain-policyParsing: allow-access-fromallow-access-from domain: *done parsing policycrossdomain.xml was succesfully parsedAbout to parse url: http://www.remoteserver.com/image.jpgChecking if http://www.remoteserver.com/image.jpg is a valid domainChecking request-host: www.remoteserver.com against valid domain: *All requirements met, the request is approved
Beim Ausführen im Editor werden diese Nachrichten in den Editor geschrieben.log. Der Versuch, eine crossdomain.xml
-Datei zu lesen, die falsch als utf16
mit einer BOM
gespeichert ist, führt dazu, dass die XML-Datei nicht analysiert werden kann:
BuildFlashPolicy caught an exception while parsing http://www.remoteserver.com/crossdomain.xml: Expected element
Dies liegt daran, dass BOM
nicht erwartet wird. Die Verwendung einer nicht unterstützten utf16
-Datei ohne BOM
führt zu:
BuildFlashPolicy caught an exception while parsing http://www.remoteserver.com/crossdomain.xml: Policy can't be constructed from empty stream.
Dies liegt daran, dass das erste Byte in der Datei Null ist, wodurch der Parser glaubt, das Ende der Datei erreicht zu haben. Crossdomain.xml
muss eine ASCII-Datei sein.
Auswirkungen auf die Verwendung von Sockets:
Ein Unity Webplayer benötigt eine Socket Served Policy, um eine Verbindung zu einem bestimmten Host herzustellen. Diese Richtlinie wird standardmäßig vom Zielhost auf Port 843 gehostet, kann aber auch auf anderen Ports gehostet werden. Der funktionale Unterschied zu einem nicht standardmäßigen Port besteht darin, dass er manuell mit Sicherheit abgerufen werden muss.PrefetchSocketPolicy () API-Aufruf und wenn es auf einem Port höher als 1024 gehostet wird, kann die Richtlinie nur Zugriff auf andere Ports höher als 1024 gewähren.
Wenn Sie den Standardport verwenden, funktioniert dies folgendermaßen: Ein Unity-Webplayer versucht, eine TCP-Socket-Verbindung zu einem Host herzustellen, und prüft zunächst, ob der Hostserver die connection.It öffnet dazu einen TCP-Socket an Port 843, gibt eine Anforderung aus und erwartet, dass eine Socket-Richtlinie über die neue Verbindung empfangen wird. Der Unity Webplayer überprüft dann, ob die Richtlinie des Hosts die Verbindung zulässt, und wird in diesem Fall fehlerfrei fortgesetzt. Dieser Vorgang erfolgt transparent für den Code des Benutzers, der nicht geändert werden muss, um dieses Sicherheitsmodell zu verwenden. Ein Beispiel für eine Socket-Richtlinie sieht folgendermaßen aus:
<?xml version="1.0"?><cross-domain-policy> <allow-access-from domain="*" to-ports="1200-1220"/> </cross-domain-policy>"
Diese Richtlinie besagt effektiv: „Inhalte von jeder Domain können Socket-Verbindungen an den Ports 1200-1220 herstellen“. Der Unity Webplayer respektiert dies und lehnt jede versuchte Socket-Verbindung ab, die einen Port außerhalb dieses Bereichs verwendet (eine SecurityException wird ausgelöst).
Bei Verwendung von UDP-Verbindungen kann die Richtlinie auch automatisch abgerufen werden, wenn sie auf ähnliche Weise wie bei TCP erzwungen werden müssen. Der Unterschied besteht darin, dass das automatische Abrufen mit TCP erfolgt, wenn Sie eine Verbindung zu etwas herstellen (stellt sicher, dass Sie eine Verbindung zu einem Server herstellen dürfen), aber mit UDP, da es verbindungslos ist, geschieht dies auch, wenn Sie einen API-Punkt aufrufen, der Daten sendet oder empfängt (stellt sicher, dass Sie Datenverkehr zu / von einem Server senden / empfangen dürfen).
Das Format, das für die Socket-Richtlinie verwendet wird, entspricht dem Format, das vom Flash Player verwendet wird, außer dass einige Tags nicht unterstützt werden. Der Unity Webplayer unterstützt nur „*“ als gültigen Wert für die Domäneneinstellung und die Einstellung „to-ports“ ist obligatorisch.
<?xml version="1.0" encoding="ISO-8859-1"?><!ELEMENT cross-domain-policy (allow-access-from*)><!ELEMENT allow-access-from EMPTY><!ATTLIST allow-access-from domain CDATA #REQUIRED><!ATTLIST allow-access-from to-ports CDATA #REQUIRED>
Die Socket-Richtlinie gilt sowohl für TCP- als auch für UDP-Verbindungstypen, sodass sowohl UDP- als auch TCP-Datenverkehr von einem Richtlinienserver gesteuert werden können.
Für Ihre Bequemlichkeit stellen wir ein kleines Programm zur Verfügung, das einfach an Port 843 lauscht; Wenn es auf einer Verbindung eine Anforderungszeichenfolge empfängt, antwortet es mit einer gültigen Socket-Richtlinie.Der Servercode befindet sich im Installationsordner von Unity unter Data / Tools / SocketPolicyServer unter Windows oder / Unity.app / Contents / Tools / SocketPolicyServer unter OS X. Beachten Sie, dass die vorgefertigte ausführbare Datei auf dem Mac ausgeführt werden kann, da es sich um eine Mono-ausführbare Datei handelt. Geben Sie einfach „mono sockpol.exe“, um es auszuführen. Beachten Sie, dass dieser Beispielcode das korrekte Verhalten eines Socket-Richtlinienservers zeigt. Insbesondere erwartet der Server einen nullterminierten String, der <policy-file-request/> . Das XML-Dokument der Socket-Richtlinie wird nur dann an den Client gesendet, wenn diese Zeichenfolge (und genau diese Zeichenfolge) empfangen wurde. Ferner ist es erforderlich, dass der XML-Header und der XML-Body mit einem einzigen Socket-Schreibvorgang gesendet werden. Das Aufteilen von Header und Body in separate Socket-Schreibvorgänge kann zu Sicherheitsausnahmen führen, da Unity eine unvollständige Richtlinie erhält. Wenn Sie Probleme mit Ihrem eigenen Server haben, verwenden Sie bitte das von uns bereitgestellte Beispiel. Dies sollte Ihnen bei der Diagnose helfen, ob Sie Server- oder Netzwerkprobleme haben.
Netzwerkbibliotheken von Drittanbietern, die häufig für Multiplayer-Spielnetzwerke verwendet werden, sollten mit diesen Anforderungen arbeiten können, solange sie nicht von der Peer-2-Peer-Funktionalität abhängen (siehe unten), sondern dedizierte Server verwenden. Diese kommen manchmal sogar mit Unterstützung für Hosting-Richtlinien aus der Box.
Hinweis: Während die crossdomain.xml
– und Socket-Richtliniendateien beide XML-Dokumente sind und sich weitgehend ähneln, ist die Art und Weise, wie diese Dokumente bereitgestellt werden, sehr unterschiedlich. Crossdomain.xml
(was auf http-Anforderungen zutrifft) wird mit http an Port 80 abgerufen, wobei – wie die Socket-Richtlinie von Port 843 mit einem trivialen Server abgerufen wird, der die <policy-file-request/> implementiert. Sie können weder einen http-Server verwenden, um die Socket-Richtliniendatei auszugeben, noch einen Server einrichten, der die Socket-Richtliniendatei einfach als Antwort auf eine Socket-Verbindung an Port 843 sendet. Beachten Sie auch, dass jeder Server, mit dem Sie eine Verbindung herstellen, einen eigenen Socket-Richtlinienserver benötigt.
Debugging
Sie können telnet
verwenden, um eine Verbindung zum Socket-Richtlinienserver herzustellen. Eine Beispielsitzung wird unten gezeigt:
host$ telnet localhost 843Trying 127.0.0.1...Connected to localhost.Escape character is '^]'.<policy-file-request/><?xml version='1.0'?><cross-domain-policy> <allow-access-from domain="*" to-ports="*" /></cross-domain-policy>Connection closed by foreign host.host$
In dieser Beispielsitzung wird Telnet verwendet, um eine Verbindung zum localhost auf Port 843 herzustellen. Telnet antwortet mit den ersten drei Zeilen und wartet dann darauf, dass der Benutzer etwas eingibt. Der Benutzer hat die Richtlinienanforderungszeichenfolge <policy-file-request/> eingegeben, die der Socket-Richtlinienserver empfängt und mit der Socket-Richtlinie antwortet. Der Server trennt dann die Verbindung und Telnet meldet, dass die Verbindung geschlossen wurde.
Listening Sockets
Sie können im Webplayer keine Listening Sockets erstellen, er kann nicht als Server fungieren. Daher können Webplayer nicht direkt miteinander kommunizieren (Peer 2 Peer). Wenn Sie TCP-Sockets verwenden, können Sie nur eine Verbindung zu Remote-Endpunkten herstellen, sofern dies über das Socket-Richtliniensystem zulässig ist. Für UDP funktioniert es genauso, aber das Konzept ist ein bisschen anders, da es sich um ein verbindungsloses Protokoll handelt. Es funktioniert, indem erzwungen wird, dass Sie nur Pakete von einem Server empfangen können, wenn er zuerst mit einer gültigen Richtlinie mit dem allow-access-from domain
-Tag geantwortet hat.
Das ist alles nur so nervig, warum gibt es all dieses Zeug?
Die Socket- und WWW-Sicherheitsfunktionen schützen Personen, die den Unity Web Player installieren. Ohne diese Einschränkungen wäre ein Angriff wie der folgende möglich:
- Bob arbeitet im weißen Haus.
- Frank ist böse. Er schreibt ein Unity-Webgame, das vorgibt, ein Spiel zu sein, aber im Hintergrund eine WWW-Anfrage an http://internal.whitehouse.gov/LocationOfNuclearBombs.pdf . intern.whitehouse.gov ist ein Server, der nicht vom Internet aus erreichbar ist, aber von Bobs Workstation aus erreichbar ist, weil er im weißen Haus arbeitet.
- Frank sendet diese PDF-Bytes an http://frank.com/secretDataUploader.php
- Frank platziert dieses Spiel auf http://www.frank.com/coolgame.unity3d
- Frank überzeugt Bob irgendwie, das Spiel zu spielen.
- Bob spielt das Spiel.
- Das Spiel lädt das geheime Dokument stillschweigend herunter und sendet es an Frank.
Mit den Sicherheitsfunktionen WWW und Socket schlägt dieser Angriff fehl, da Unity vor dem Herunterladen der PDF-Datei http://internal.whitehouse.gov/crossdomain.xml überprüft, um diesen Server zu fragen: „sind die Daten, die Sie auf Ihrem Server haben, für die öffentliche Nutzung verfügbar?“. Platzieren einer Crossdomain.xml auf einem Webserver kann als Antwort auf diese Frage angesehen werden. Im Falle dieses Beispiels wird der Systembetreiber von internal.whitehouse.gov wird keine Crossdomain platzieren.xml auf seinem Server, was dazu führt, dass Unity das PDF nicht herunterlädt.
Leider müssen Personen, die in Unity entwickeln, diese Sicherheitsmaßnahmen bei der Entwicklung von Inhalten berücksichtigen, um die Personen zu schützen, die den Unity Web Player installieren. Die gleichen Einschränkungen sind in allen wichtigen Plugin-Technologien vorhanden. (Flash, Silverlight, Shockwave)
Ausnahmen
Um die richtige Balance zwischen dem Schutz von Web Player-Benutzern und der Erleichterung des Lebens von Inhaltsentwicklern zu finden, haben wir eine Ausnahme für den oben beschriebenen Sicherheitsmechanismus implementiert:
Sie dürfen Bilder von Servern herunterladen, die keine Crossdomain haben.xml-Datei. Das einzige, was Sie mit diesen Bildern tun dürfen, ist, sie als Texturen in Ihrer Szene zu verwenden. Sie dürfen GetPixel () nicht verwenden. Sie dürfen auch nicht vom Bildschirm zurücklesen. Beide Versuche führen dazu, dass eine SecurityException ausgelöst wird:
SecurityException: No read access to the texture data: at (wrapper managed-to-native) UnityEngine.Texture2D:GetPixel (int,int)
Der Grund dafür ist, dass es in Ordnung ist, das Bild herunterzuladen, solange der Inhaltsentwickler keinen Zugriff darauf erhält. Sie können es also dem Benutzer anzeigen, aber Sie können die Bytes des Bildes nicht an einen anderen Server zurücksenden. Wenn Sie Zugriff auf die Pixeldaten benötigen, platzieren Sie eine crossdomain.xml
-Datei auf dem Server, von dem die Bilder abgerufen werden.