Spec-Zone .ru
спецификации, руководства, описания, API
|
Усовершенствованные пользователи со специальными требованиями к защите могут создать свои собственные плагины аутентификации для приложений Соединителя/Сети. Можно расширить протокол квитирования, добавляя пользовательскую логику. Эта возможность требует Соединителя/Сети 6.6.3 или выше, и MySQL 5.5.16 или выше. Для фона и информации об использовании о плагинах аутентификации MySQL, см., Раздел 22.2.3.7, "Плагины Аутентификации" и Раздел 22.2.4.9, "Пишущий Плагины Аутентификации".
Чтобы записать пользовательский плагин аутентификации, Вы будете нуждаться в ссылке на блок MySql.Data.dll
. Классы, важные для записи плагинов аутентификации, доступны в
пространстве имен MySql.Data.MySqlClient.Authentication
.
В некоторый момент во время квитирования, внутреннего метода
void Authenticate(bool reset)
Вы помещаете логику плагина аутентификации в новом class, полученном из 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 can be an 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;
Вот пример, показывающий, как создать плагин аутентификации, затем включите этому посредством конфигурационного файла. Следуйте за этими шагами:
Создайте консольное приложение, добавляя ссылку на MySql.Data.dll
.
Разработайте основную программу следующим образом:
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(); } }}
Создайте свой сменный class. В этом примере мы добавляем "альтернативную" реализацию Собственного плагина пароля,
только используя тот же самый код от исходного плагина. Мы называем наш class 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");
Включите новому плагину в конфигурационном файле:
<?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>
Запустите приложение. В Visual Studio Вы будете видеть сообщение Calling MySqlNativePasswordPlugin2.GetPassword
в окне отладки.
Продолжайте улучшать логику аутентификации, переопределяя больше методов, если Вы потребовали.