6.5. Пример клиент-сервер
Следующий пример показывает схему обмена данными при аутентификации клиента сервером с привлечением SASL, это делается в норме после согласования применения TLS (заметим: альтернативные шаги, показанные ниже, приведены для иллюстрации работы протокола в случае ошибок).
Шаг 1: Клиент формирует поток до сервер:
<stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' to='example.com' version='1.0'>
Шаг 2: Сервер реагирует посылкой клиенту тэга потока:
<stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' id='c2s_234' from='example.com' version='1.0'>
Шаг 3: Сервер информирует клиента об имеющихся механизмах аутентификации:
<stream:features> <mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'> <mechanism>DIGEST-MD5</mechanism> <mechanism>PLAIN</mechanism> </mechanisms> </stream:features>
Шаг 4: Клиент выбирает механизм аутентификации:
<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='DIGEST-MD5'/>
Шаг 5: Сервер посылает закодированный вызов [BASE64] клиенту:
<challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'> cmVhbG09InNvbWVyZWFsbSIsbm9uY2U9Ik9BNk1HOXRFUUdtMmhoIixxb3A9ImF1dGgi LGNoYXJzZXQ9dXRmLTgsYWxnb3JpdGhtPW1kNS1zZXNzCg== </challenge>
Декодированный вызов имеет вид:
realm="somerealm",nonce="OA6MG9tEQGm2hh",\ qop="auth",charset=utf-8,algorithm=md5-sess
Шаг 5 (alt): Сервер возвращает клиенту сообщение об ошибке:
<failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'> <incorrect-encoding/> </failure> </stream:stream>
Шаг 6: Клиент посылает закодированный отклик [BASE64] на вызов:
<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'> dXNlcm5hbWU9InNvbWVub2RlIixyZWFsbT0ic29tZXJlYWxtIixub25jZT0i T0E2TUc5dEVRR20yaGgiLGNub25jZT0iT0E2TUhYaDZWcVRyUmsiLG5jPTAw MDAwMDAxLHFvcD1hdXRoLGRpZ2VzdC11cmk9InhtcHAvZXhhbXBsZS5jb20i LHJlc3BvbnNlPWQzODhkYWQ5MGQ0YmJkNzYwYTE1MjMyMWYyMTQzYWY3LGNo YXJzZXQ9dXRmLTgK </response>
Декодированный отклик имеет вид:
username="somenode",realm="somerealm",\ nonce="OA6MG9tEQGm2hh",cnonce="OA6MHXh6VqTrRk",\ nc=00000001,qop=auth,digest-uri="xmpp/example.com",\ response=d388dad90d4bbd760a152321f2143af7,charset=utf-8
Шаг 7: Сервер посылает еще один закодированный [BASE64] вызов клиенту:
<challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'> cnNwYXV0aD1lYTQwZjYwMzM1YzQyN2I1NTI3Yjg0ZGJhYmNkZmZmZAo= </challenge>
Декодированный вызов имеет вид:
rspauth=ea40f60335c427b5527b84dbabcdfffd
Шаг 7 (alt): Сервер посылалает клиенту сообщение об ошибке:
<failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'> <temporary-auth-failure/> </failure> </stream:stream>
Шаг 8: Клиент откликается на вызов:
<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>
Шаг 9: Сервер информирует клиента об успешной аутентификации:
<success xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>
Шаг 9 (alt): Сервер информирует клиента об ошибке аутентификации:
<failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'> <temporary-auth-failure/> </failure> </stream:stream>
Шаг 10: Клиент формирует новый поток к серверу:
<stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' to='example.com' version='1.0'>
Шаг 11: Сервер откликается посылкой заголовка потока клиенту, сообщая о любых дополнительных имеющихся возможностях (если таких возможностей нет, посылается пустой элемент):
<stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' id='c2s_345' from='example.com' version='1.0'> <stream:features> <bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'/> <session xmlns='urn:ietf:params:xml:ns:xmpp-session'/> </stream:features>