简体   繁体   English

在QuickFIX接受器中自定义FIX登录过程

[英]Customizing the FIX logon process in a QuickFIX acceptor

I'm using QuickFIX and C# to create a FIX acceptor (server). 我正在使用QuickFIX和C#来创建一个FIX接受器(服务器)。 I want the client (the FIX initiator) to logon using a username and password. 我希望客户端(FIX启动器)使用用户名和密码登录。 However, I'm not sure how I can do that in QuickFIX. 但是,我不确定如何在QuickFIX中做到这一点。

By debugging into the QuickFIX source code I have discovered the following sequence of events: 通过调试QuickFIX源代码,我发现了以下事件序列:

  • QuickFIX will call Session::verify to verify the logon. QuickFIX将调用Session::verify来验证登录。
  • Session::verify will perform various checks of things like comp ID's and sequence numbers and at some point determine that the logon received is valid. Session::verify将对comp ID和序列号等内容进行各种检查,并在某些时候确定收到的登录是否有效。
  • Session::verify will then call the Application::fromAdmin callback which I assume is the natural place to customize things like logon. 然后Session::verify将调用Application::fromAdmin回调,我认为这是自定义登录等内容的自然场所。
  • However, at this point the logon has already been determined to be OK by QuickFIX and a corresponding logon message will be returned by the acceptor when the callback returns. 但是,此时QuickFIX已经确定登录正常,并且当回调返回时,接收器将返回相应的登录消息。

How do I customize the FIX logon process in an acceptor? 如何在接受器中自定义FIX登录过程? Is modifying the QuickFIX code my only option? 修改QuickFIX代码是我唯一的选择吗?

If you are using FIX 4.3 or later, the Logon message can have a Password tag. 如果您使用的是FIX 4.3或更高版本,则登录消息可以具有密码标记。 If you are using a previous version, make it a custom tag and add it to the dictionaries. 如果您使用的是以前的版本,请将其设为自定义标记并将其添加到词典中。

In the fromAdmin handler, check that the password is correct (from a lookup table or elsewhere). fromAdmin处理程序中,检查密码是否正确(从查找表或其他位置)。 If it is not, throw a RejectLogon exception. 如果不是,则抛出RejectLogon异常。 If this exception isn't thrown, QuickFix will assume everything is a-ok and log the user on. 如果没有抛出此异常,QuickFix将假设一切正常并记录用户。

Example (needs more sanity checks): 示例(需要更多健全性检查):

public void fromAdmin(Message message, SessionID id)
{
   var logon = message as QuickFix44.Logon;

   if (logon != null)
   {
      string userName = logon.getUserName().getValue();
      string expectedPassword = PasswordsByUser[userName];

      string suppliedPassword = logon.getPassword().getValue();

      if(expectedPassword != suppliedPassword)
          throw new RejectLogon();
   }     
}

fromAdmin notifies you when an administrative message is sent from a counterparty to your FIX engine. 当管理员消息从交易对手发送到您的FIX引擎时,fromAdmin会通知您。 This can be usefull for doing extra validation on logon messages such as for checking passwords. 这对于对登录消息进行额外验证(例如检查密码)非常有用。 Throwing a RejectLogon exception will disconnect the counterparty. 抛出RejectLogon异常将断开交易对手的连接。

Session verification generally ckecks for the FIX Begin String, SenderCompID and target CompID. 会话验证通常是FIX Begin String,SenderCompID和目标CompID的ckecks。 If this 3 are fine then session is set up(QuickFIXJ has other fields also for subcomp ids). 如果这3个很好,则会话设置(QuickFIXJ还有子组件的其他字段)。

Even after Session has been set up messages wouldn't be accepted at the acceptor, for that specific session, till logon process has been completed. 即使在设置了会话之后,也不会在接受者处接受该特定会话的消息,直到登录过程完成为止。 You will get a reject if you try so. 如果您这样做,您将获得拒绝。

So in fromAdmin you can check for the incoming logon message request and check for the valid password, contained in the logon message, you expect for that connection/session. 因此,在fromAdmin中,您可以检查传入的登录消息请求,并检查登录消息中包含的有效密码,您希望该连接/会话。

Throwing a RejectLogon QuickFIXException breaks the whole code and interrupts the rest of the sessions (if you do have more than one). 抛出RejectLogon QuickFIXException会破坏整个代码并中断其余的会话(如果你有多个会话)。 In my own case, I compose a logout message and have it sent back to the counterparty. 在我自己的情况下,我撰写了一个注销消息并将其发送回交易对手。 Code would be something like this: 代码将是这样的:

public void fromAdmin(Message message, SessionID id)
{
   var logon = message as QuickFix44.Logon;

   if (logon != null)
   {
      string userName = logon.getUserName().getValue();
      string expectedPassword = PasswordsByUser[userName];

      string suppliedPassword = logon.getPassword().getValue();

      if(expectedPassword != suppliedPassword)
          {
                Message _logoutmess = new Message();
                _logoutmess.Header.SetField(new MsgType() { Tag = 35, Obj = "5" });
                _logoutmess.SetField(new Text("Invalid credentials"));
                Session.SendToTarget(_logoutmess, id);
          }
   }     
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM