Spec-Zone.ru › MySQL Connectors 1.0

5.8 Создание пользовательского плагина аутентификации

Пользователи с особыми требованиями к безопасности могут создавать собственные плагины аутентификации для приложений MySQL Connector/NET. Вы можете расширить протокол рукопожатия, добавив пользовательскую логику. Дополнительную информацию об использовании плагинов аутентификации MySQL см. в Документации по написанию плагинов аутентификации.

Для написания пользовательского плагина аутентификации вам потребуется ссылка на сборку MySql.Data.dll. Классы, относящиеся к написанию плагинов аутентификации, доступны в пространстве имен MySql.Data.MySqlClient.Authentication.

Как работает пользовательский плагин аутентификации

В какой-то момент во время рукопожатия вызывается внутренний метод

void Authenticate(bool reset)

класса MySqlAuthenticationPlugin. Этот метод, в свою очередь, вызывает несколько переопределяемых методов текущего плагина.

Создание класса плагина аутентификации

Логику плагина аутентификации поместите в новый класс, производный от класса MySql.Data.MySqlClient.Authentication.MySqlAuthenticationPlugin. Доступны следующие переопределяемые методы:

protected virtual void CheckConstraints()
protected virtual void AuthenticationFailed(Exception ex)
protected virtual void AuthenticationSuccessful()
protected virtual byte[] MoreData(byte[] data)
protected virtual void AuthenticationChange()
public abstract string PluginName { get; }
public virtual string GetUsername()
public virtual object GetPassword()
protected byte[] AuthData;

Ниже приведено краткое описание каждого из них:

/// <summary>
/// This method must check authentication method specific constraints in the
environment and throw an Exception
/// if the conditions are not met. The default implementation does nothing.
/// </summary>
protected virtual void CheckConstraints()

/// <summary>
/// This method, called when the authentication failed, provides a chance to
plugins to manage the error
/// the way they consider decide (either showing a message, logging it, etc.).
/// The default implementation wraps the original exception in a MySqlException
with an standard message and rethrows it.
/// </summary>
/// <param name="ex">The exception with extra information on the error.</param>
protected virtual void AuthenticationFailed(Exception ex)

/// <summary>
/// This method is invoked when the authentication phase was successful accepted
by the server.
/// Derived classes must override this if they want to be notified of such
condition.
/// </summary>
/// <remarks>The default implementation does nothing.</remarks>
protected virtual void AuthenticationSuccessful()

/// <summary>
/// This method provides a chance for the plugin to send more data when the
server requests so during the
/// authentication phase. This method will be called at least once, and more
than one depending upon whether the
/// server response packets have the 0x01 prefix.
/// </summary>
/// <param name="data">The response data from the server, during the
authentication phase the first time is called is null, in
subsequent calls contains the server response.</param>
/// <returns>The data generated by the plugin for server consumption.</returns>
/// <remarks>The default implementation always returns null.</remarks>
protected virtual byte[] MoreData(byte[] data)

/// <summary>
/// The plugin name.
/// </summary>
public abstract string PluginName { get; }

/// <summary>
/// Gets the user name to send to the server in the authentication phase.
/// </summary>
/// <returns>An string with the user name</returns>
/// <remarks>Default implementation returns the UserId passed from the
connection string.</remarks>
public virtual string GetUsername()

/// <summary>
/// Gets the password to send to the server in the authentication phase. This
can be a string or a
/// </summary>
/// <returns>An object, can be byte[], string or null, with the password.
</returns>
/// <remarks>Default implementation returns null.</remarks>
public virtual object GetPassword()

/// <summary>
/// The authentication data passed when creating the plugin.
/// For example in mysql_native_password this is the seed to encrypt the
password.
/// </summary>
protected byte[] AuthData;

Пример плагина аутентификации

Этот пример демонстрирует создание плагина аутентификации и его включение посредством конфигурационного файла.

  1. Создайте консольное приложение, добавив ссылку на MySql.Data.dll.

  2. Разработайте основной C# программу следующим образом:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using MySql.Data.MySqlClient;
    
    namespace AuthPluginTest
    {
      class Program
      {
        static void Main(string[] args)
        {
          // Customize the connection string as necessary.
          MySqlConnection con = new MySqlConnection("server=localhost;
          database=test; user id=myuser; password=mypass");
          con.Open();
          con.Close();
        }
      }
    }
    
  3. Создайте класс плагина. В этом примере мы добавляем «альтернативное» реализацию плагина Native password, просто используя тот же код, что и в исходном плагине.

    Примечание

    Плагин по умолчанию отключен с версии MySQL Server 8.4.0 и удален с версии MySQL Server 9.0.0.

    Мы назовем наш класс MySqlNativePasswordPlugin2:

    using System.IO;
    using System;
    using System.Text;
    using System.Security.Cryptography;
    using MySql.Data.MySqlClient.Authentication;
    using System.Diagnostics;
    
    namespace AuthPluginTest
    {
      public class MySqlNativePasswordPlugin2 : MySqlAuthenticationPlugin
      {
        public override string PluginName
        {
          get { return "mysql_native_password"; }
        }
    
        public override object GetPassword()
        {
          Debug.WriteLine("Calling MySqlNativePasswordPlugin2.GetPassword");
          return Get411Password(Settings.Password, AuthData);
        }
    
        /// <summary>
        /// Returns a byte array containing the proper encryption of the
        /// given password/seed according to the new 4.1.1 authentication scheme.
        /// </summary>
        /// <param name="password"></param>
        /// <param name="seed"></param>
        /// <returns></returns>
        private byte[] Get411Password(string password, byte[] seedBytes)
        {
          // if we have no password, then we just return 1 zero byte
          if (password.Length == 0) return new byte[1];
    
          SHA1 sha = new SHA1CryptoServiceProvider();
    
          byte[] firstHash = sha.ComputeHash(Encoding.Default.GetBytes(password));
          byte[] secondHash = sha.ComputeHash(firstHash);
    
          byte[] input = new byte[seedBytes.Length + secondHash.Length];
          Array.Copy(seedBytes, 0, input, 0, seedBytes.Length);
          Array.Copy(secondHash, 0, input, seedBytes.Length, secondHash.Length);
          byte[] thirdHash = sha.ComputeHash(input);
    
          byte[] finalHash = new byte[thirdHash.Length + 1];
          finalHash[0] = 0x14;
          Array.Copy(thirdHash, 0, finalHash, 1, thirdHash.Length);
    
          for (int i = 1; i < finalHash.Length; i++)
            finalHash[i] = (byte)(finalHash[i] ^ firstHash[i - 1]);
          return finalHash;
        }
      }
    }
    

    Обратите внимание, что реализация плагина просто переопределяет метод GetPassword и предоставляет реализацию шифрования пароля с использованием протокола 4.1. Добавьте следующую строку в тело GetPassword, чтобы подтвердить, что плагин был успешно использован.

    Debug.WriteLine("Calling MySqlNativePasswordPlugin2.GetPassword");
    
    Подсказка

    Также можно установить точку останова в этом методе.

  4. Включите новый плагин в конфигурационном файле:

    <?xml version="1.0"?>
    <configuration>
      <configSections>
        <section name="MySQL" type="MySql.Data.MySqlClient.MySqlConfiguration,
    MySql.Data"/>
      </configSections>
      <MySQL>
        <AuthenticationPlugins>
          <add name="mysql_native_password"
    type="AuthPluginTest.MySqlNativePasswordPlugin2, AuthPluginTest"></add>
        </AuthenticationPlugins>
      </MySQL>
    <startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
    </startup></configuration>
    
  5. Запустите приложение. В окне отладки Visual Studio вы увидите сообщение Calling MySqlNativePasswordPlugin2.GetPassword.

Продолжайте улучшать логику аутентификации, переопределяя больше методов при необходимости.

© 2025 Oracle
Licensed under the GPLv2 License.
https://docs.oracle.com/cd/E17952_01/connector-net-en/connector-net-programming-authentication-user-plugin.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API