10bet网址
MySQL Connector/NET Developer Guide
Related Documentation Download this Manual

5.3.2 Writing a Custom Authentication Plugin

Advanced users with special security requirements can create their own authentication plugins for MySQL Connector/NET applications. You can extend the handshake protocol, adding custom logic. For background and usage information about MySQL authentication plugins, seeAuthentication PluginsandWriting Authentication Plugins.

To write a custom authentication plugin, you will need a reference to the assemblyMySql.Data.dll. The classes relevant for writing authentication plugins are available at the namespaceMySql.Data.MySqlClient.Authentication.

How the Custom Authentication Plugin Works

At some point during handshake, the internal method

void Authenticate(bool reset)

ofMySqlAuthenticationPluginis called. This method in turns calls several overridable methods of the current plugin.

Creating the Authentication Plugin Class

You put the authentication plugin logic inside a new class derived fromMySql.Data.MySqlClient.Authentication.MySqlAuthenticationPlugin. The following methods are available to be overridden:

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;

The following is a brief explanation of each one:

> / / / <总结/ / /此方法必须检查真实的ation method specific constraints in the environment and throw an Exception /// if the conditions are not met. The default implementation does nothing. ///  protected virtual void CheckConstraints() ///  /// 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. ///  /// The exception with extra information on the error. protected virtual void AuthenticationFailed(Exception ex) ///  /// 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. ///  /// The default implementation does nothing. protected virtual void AuthenticationSuccessful() ///  /// 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. ///  /// The response data from the server, during the authentication phase the first time is called is null, in subsequent calls contains the server response. /// The data generated by the plugin for server consumption. /// The default implementation always returns null. protected virtual byte[] MoreData(byte[] data) ///  /// The plugin name. ///  public abstract string PluginName { get; } ///  /// Gets the user name to send to the server in the authentication phase. ///  /// An string with the user name /// Default implementation returns the UserId passed from the connection string. public virtual string GetUsername() ///  /// Gets the password to send to the server in the authentication phase. This can be a string or a ///  /// An object, can be byte[], string or null, with the password.  /// Default implementation returns null. public virtual object GetPassword() ///  /// The authentication data passed when creating the plugin. /// For example in mysql_native_password this is the seed to encrypt the password. ///  protected byte[] AuthData;

Sample Authentication Plugin

Here is an example showing how to create the authentication plugin, then enable it by means of a configuration file. Follow these steps:

  1. Create a console app, adding a reference toMySql.Data.dll.

  2. Design the main program as follows:

    使用系统;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. Create your plugin class. In this example, we add analternativeimplementation of the Native password plugin by just using the same code from the original plugin. We name our classMySqlNativePasswordPlugin2:

    使用先;使用系统;使用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); } ///  /// Returns a byte array containing the proper encryption of the /// given password/seed according to the new 4.1.1 authentication scheme. ///  ///  ///  ///  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; } } }
  4. Notice that the plugin implementation just overridesGetPassword, and provides an implementation to encrypt the password using the 4.1 protocol. We also put the following line in theGetPasswordbody:

    Debug.WriteLine("Calling MySqlNativePasswordPlugin2.GetPassword");

    to provide confirmation that the plugin was effectively used. (You could also put a breakpoint on that method.)

  5. Enable the new plugin in the configuration file:

       
  6. Run the application. In Visual Studio, you will see the messageCalling MySqlNativePasswordPlugin2.GetPasswordin the debug window.

  7. Continue enhancing the authentication logic, overriding more methods if you required.