Хостинг серверов Minecraft playvds.com
  1. Вы находитесь в русском сообществе Bukkit. Мы - администраторы серверов Minecraft, разрабатываем собственные плагины и переводим на русский язык плагины наших собратьев из других стран.
    Скрыть объявление

Туториал Система скинов/плащей в 1.7.9+ и новая авторизация

Тема в разделе "Руководства, инструкции, утилиты", создана пользователем caver, 22 авг 2014.

  1. Автор темы
    caver

    caver Активный участник Пользователь

    Баллы:
    88
    Skype:
    caver15
    Выкладываю свои изыскания по поводу своих разборок с системой авторизации и скинами.
    Некоторое время был оторван от темы, однако пришлось вновь разбираться.
    С удивлением обнаружил что сейчас скины/плащи напрямую завязаны на авторизацию, есть какой то backward compatible со старой системой но в нее даже не стал лезть, т.к. смысла нету.

    В общем схема нынче довольно забавная и в целом логичная, основная преследуемая цель - снижение нагрузки на сервер при запросах текстур с сервера, а так же переход на систему UUID вместо имени пользователя.
    Пойдем по порядку:
    Начну с азов, а именно с авторизации лаунчера:

    1. Лаунчер идет $AUTH_URL/authenticate
    Передает:
    username, password, clientToken
    Получает:
    accessToken, id (uuid)
    2. Лаучер запускает клиента с параметрами
    username, uuid, accessToken
    3. Клиент при коннекте к серверу и обмене ключами (serverId) снова идет к серверу авторизация на $AUTH_URL/join
    Передает:
    accessToken, selectedProfile (uuid), serverId
    4. Сервер проверяет валидность подключения, идя на сервер авторизации $AUTH_URL/hasJoined
    Передает:
    username, serverId
    Принимает:
    а вот тут начинается самое интересное в виде ответ сервера авторизации
    Приведу дословно
    Код:
    The response is a JSON object containing the user's UUID and skin blob
    =====
    {
        "name":"<username>",
        "id":"<uuid>",
        "properties":[
            {
                "name": "textures",
                "value": "<base64 string>"
        ]
    }
    
    Больше информации можно получить тут http://wiki.vg/Authentication и тут http://wiki.vg/Protocol_Encryption

    Самое интересное содержится именно в <base64 string>, эта строка является кодированным base64 Json объектом
    Код:
    {
       "profileId" : "123456786b824147bbfc71f18906ae8a",
       "timestamp" : 1408617303852,
       "profileName" : "vasyapupkin",
       "textures" : {
          "SKIN" : {
             "url" : "http://textures.minecraft.net/texture/1234567879a8524d9e13c9cbddf69c85a345bc15625f2911df866f7fee2ef"
          },
          "CAPE" : {
             "url" : "http://textures.minecraft.net/texture/227412345678524d9e13c9cbddf69c85a345bc15625f2911df866f7fee2ef"
       }
    }
    
    Данный объект судя по всему внутри игрового сервера ассоциируется с UUID пользователя, при встрече двух игроков, через внутренний протокол игры игрокам передаются соответствующие blobы. Т.е. игрок Вася получает блоб Пети, а игрок Петя получает блоб Васи. Таким образом игровой клиент получает информацию о необходимости загрузки текстур скинов/плащей и соответствие UUID игрока -> текстуры. После получения блоба, игровой клиент распаковывает и парсит этот блоб, после чего скачивает нужные текстуры с текстурного сервера.

    Как вы можете заметить все данные по скинам/плащам передаются только /hasJoined
    т.е. требуют авторизации игрока на сервере с online_mode = true
    Так что владельцы/пользователи authme плагина в пролете (насчет скинов ВОЗМОЖНО работает обратная совместимость, однако с плащами полный "пролет фанеры над парижем")

    Proof of concept авторизации с блобами и прочими скинами
    https://dl.dropboxusercontent.com/u/38401250/auth.tar.gz
     
    Последнее редактирование: 22 авг 2014
  2. Хостинг MineCraft
    <
  3. Автор темы
    caver

    caver Активный участник Пользователь

    Баллы:
    88
    Skype:
    caver15
    Примеры формирования блоба да и вообще респонса hasJoined на PHP

    $sqlquery = "select uuid, username, skinfile, capefile from minecraft_profile where username = $name and serverId = $serverId"

    $textures = array (
    'SKIN' => array('url' => 'http://myminecraftserver.ru/textures/skins/' . $skinfile),
    'CAPE' => array('url' => 'http://myminecraftserver.ru/textures/capes/' . $capefile)​
    );

    $forbase64 = array(
    'timestamp' => time(),
    'profileId' => $uuid,
    'profileName' => $username,
    'textures' => $textures​
    );

    $responce = array (
    'name' => $username,
    'id' => $uuid,
    'properties' => array (
    0 => array (
    'name' => 'textures',
    'signature' => '{тут должна быть сигнатура $forbase64}',
    'value' => base64_encode(stripcslashes(json_encode($forbase64)))​
    )​
    )​
    );

    json_encode($responce)
     
    Последнее редактирование: 22 авг 2014
  4. Reality_SC

    Reality_SC Старожил Пользователь

    Баллы:
    123
    Имя в Minecraft:
    Reality_SC
    Да, я тоже как раз расковыриваю это всё =) По верному пути идут, так-то.
     
  5. Автор темы
    caver

    caver Активный участник Пользователь

    Баллы:
    88
    Skype:
    caver15
    Ну в принципе я написал уже полную эмуляцию всей авторизации со всеми свистоперделками, за исключением сигнатуры. Закоментил в коде проверку и все ;)
    И она даже работает ;)

    Кстати ВСЯ система авторизации и теперь связанных с ней скинов/плащей переехала в authlib-*.jar ну или смотреть по пути

    Код:
    com/mojang/authlib/yggdrasil/YggdrasilMinecraftSessionService.java
    
    Отключение проверки сигнатуры в КЛИЕНТЕ

    Код:
    com/mojang/authlib/properties/Property.java
    ===
    public boolean isSignatureValid(PublicKey publicKey) {
        return true;
    }
    
    ===[DOUBLEPOST=1408695955,1408694660][/DOUBLEPOST]Добавил архив с концептом авторизации.
     
    Последнее редактирование: 22 авг 2014
  6. Reality_SC

    Reality_SC Старожил Пользователь

    Баллы:
    123
    Имя в Minecraft:
    Reality_SC
    У меня тоже уже есть своя работающая (на уровне регистрации и аутентификации игроков) реализация Yggdrasil :)
    Мои лаунчер и сервер авторизуют игроков именно им :)
    Может как-то объединим опыт? ))

    P.S. Только что вписал отсылку свойства textures с url с нормальным существующим png скином. Ни я, ни игроки его не видят. Подозреваю, нужно отсылать его всё-таки не/не только в hasJoined, но в другом ответе.
     
    Последнее редактирование: 22 авг 2014
  7. Автор темы
    caver

    caver Активный участник Пользователь

    Баллы:
    88
    Skype:
    caver15
    Тот ответ только для своих скинов посмотри мою поедлку, там все работает
    Как раз там есть обработчик /profile/ через UUID
    [DOUBLEPOST=1408703399,1408703008][/DOUBLEPOST]в серверном и клиентском
    com/mojang/authlib/yggdrasil/YggdrasilMinecraftSessionService.java
    Код:
       private static final URL JOIN_URL = HttpAuthenticationService.constantURL("http://auth.myserver.ru/join.php");
       private static final URL CHECK_URL = HttpAuthenticationService.constantURL("http://auth.myserver.ru/hasJoined.php");
    
    URL e = HttpAuthenticationService.constantURL("http://auth.myserver.ru/profile/" + UUIDTypeAdapter.fromUUID(profile.getId()));
    
    И без этого фикса в текстуры показываться НЕ БУДУТ
    клиентский com/mojang/authlib/properties/Property.java
    Код:
       public boolean isSignatureValid(PublicKey publicKey) {
      /*    try {
             Signature e = Signature.getInstance("SHA1withRSA");
             e.initVerify(publicKey);
             e.update(this.value.getBytes());
             return e.verify(Base64.decodeBase64(this.signature));
          } catch (NoSuchAlgorithmException var3) {
             var3.printStackTrace();
          } catch (InvalidKeyException var4) {
             var4.printStackTrace();
          } catch (SignatureException var5) {
             var5.printStackTrace();
          }
    
          return false;*/
           return true;
       }
    
    [DOUBLEPOST=1408703837][/DOUBLEPOST]
    Ну я лаунчер использую штатный, со всякими затычками/проверками.
    т.е. стараюсь максимально эмулировать штатную схему обновлений и авторизации.
    Есть боевой сервер с приличным онлайном.

    PS: Разбор протокола и написание авторизации заняло два дня, правда крови выпило много. Декомпиленный сервер, 2 декомпиленных клиента + веб сервер и все это под долбагером/IDE. А ну и еще ланчер тоже в сорцах http://www.rubukkit.org/threads/sources-mojang-minecraft-launcher-1-5-1.43987/
     
    Последнее редактирование: 22 авг 2014
  8. Reality_SC

    Reality_SC Старожил Пользователь

    Баллы:
    123
    Имя в Minecraft:
    Reality_SC
    Сейчас попробую.
    Моё направление работы сейчас заключено в том, чтобы не делать ничего с конечными файлами, а подменять всё на лету. Если даже с полями private static final всё просто, запрос профилей идёт по ссылке, содержащейся в пуле констант. Сижу дописываю реалтаймовый редактор пула напрямую в байкоде.
    Со свойствами тоже, видимо, придётся мудрить.
    P.S. Возможно, ещё вариант — сгенерировать свою пару ключей для проверки сигнатуры и поменять файл ключа в джарнике.
     
  9. Автор темы
    caver

    caver Активный участник Пользователь

    Баллы:
    88
    Skype:
    caver15
    Можно но ведь лениво ;)
    Кстати тогда надо будет писать имплементацию подписи в авторизации, что тоже лениво.

    Кстати я лично в клиенте/ванильных либах ничего не меняю, все свои наработки скидываю в jar-ку и в файлике версии 1.7.zzz.json
    просто подцепляю ее первым делом, грубо говоря перекрываю через CLASSPATH, свойство явы таковы - кто первый встал того и тапки. Т.е. при поиске класса авторизации исползуется моя видоизменная копия, нежели класс из "родной" библиотеки. Трудозатрат никаких ;)
     
  10. Reality_SC

    Reality_SC Старожил Пользователь

    Баллы:
    123
    Имя в Minecraft:
    Reality_SC
    Мне не лениво =)
    Мне кажется, это в конечном итоге займёт строчек десять ... но я тоже не хочу этим сейчас заниматься :)
    У меня ситуация немного другая, всё-таки свой лаунчер, но в целом я собираюсь сделать тоже самое. Только не подцеплять либу — у меня её вообще нету, а брать исходную, читать из неё байткод нужного класса, править его на лету и подгружать из памяти, "заняв тапки". Более простые вещи, такие как замену полей, уже полгода решает рефлексия :)
     
  11. Автор темы
    caver

    caver Активный участник Пользователь

    Баллы:
    88
    Skype:
    caver15
    Лень вот честно лень, гораздо проще передать аргумент Java машине -cp MyOverridelib.jar:somelib.jar:foobarlib.jar:minecraft.jar чем чем патчить бинарники на лету.
     
  12. Reality_SC

    Reality_SC Старожил Пользователь

    Баллы:
    123
    Имя в Minecraft:
    Reality_SC
    У меня свои цели, для которых это не лень, а, скорее, необходимость.
    Ну мы друг друга поняли =)
     
  13. Автор темы
    caver

    caver Активный участник Пользователь

    Баллы:
    88
    Skype:
    caver15
    Я вообще очень ленивый, ну и надеюсь что мои изыскания помогли. Во всяком случае при наличии рабочего кода повторить не составит больших проблем.
     
  14. alexandrage

    alexandrage Администратор

    Баллы:
    173
    Skype:
    alexandr0116
    Эту фигню я уже пол года назад разобрал, сигнатуру только было лень выпиливать.
    На счет плащей, имена плащей не должны совпадать с именами скинов, иначе плащ будет пытаться записаться поверх скина. Потому я и не стал ипать могз и портировал старую систему скинов.
     
  15. ErickSkrauch

    ErickSkrauch Активный участник Пользователь

    Баллы:
    68
    Имя в Minecraft:
    ErickSkrauch
    Всем привет. Такой вопросик: если информация об игроке загружается только в момент подключения к серверу, то откуда скин в одиночной игре? И можно ли как-то научить authlib (путём правки исходников, офк) загружать скин по запросу клиента, а не сервера?
     
  16. alexandrage

    alexandrage Администратор

    Баллы:
    173
    Skype:
    alexandr0116
    ТС Ты гонишь пр плащи, я их делал и они работают. Просто у идиотов на виги синтаксис еррор, запятую проиграли.
     
  17. NewRut

    NewRut Активный участник Пользователь

    Баллы:
    63
    Имя в Minecraft:
    NewRut
    Настроил систему скинов под 1.7.10 и ничего не показывает скины, лицензионные ники тоже не показывают[DOUBLEPOST=1446905941,1446901919][/DOUBLEPOST]Все сам разобрался. работает скин, но есть проблема во первый раз установился, во вторый раз установился, там показывает бывший скин.[DOUBLEPOST=1446961407][/DOUBLEPOST]Проблема в assets: папка skins надо удалить при заходе лаунчера.
     
    Последнее редактирование: 7 ноя 2015
  18. alexandrage

    alexandrage Администратор

    Баллы:
    173
    Skype:
    alexandr0116
    Ты прям америку открыл.
     

Поделиться этой страницей