Openfire 中SASL的认证方式之:PLAIN,DIGEST-MD5,anonymous


SASL  的认证方式包括:
    1. PLAIN: plain是最简单的机制,但同时也是最危险的机制,因为身份证书(登录名称与密码)是以base64字符串格式通过网络,没有任何加密保护措施。因此,使用plain机制时,你可能会想要结合tls。
     
     2.DIGEST-MD5:使用这种机制时,client与server共享同一个隐性密码,而且此密码不通过网络传输。验证过程是从服务器先提出challenge(质询)开始, 客户端使用此challenge与隐性密码计算出一个response(应答)。不同的challenge,不可能计算出相同的response;任何拥 有secret password的一方,都可以用相同的challenge算出相同的response。因此,服务器只要比较客户端返回的response是否与自己算 出的response相同,就可以知道客户端所拥有的密码是否正确。由于真正的密码并没有通过网络,所以不怕网络监测。
      3.   anonymous:   anonymous机制对smtp没有意义,因为smtp验证的用意在于限制转发服务的使用对象,而不是为了形成open relay,sasl之所以提供这种机制,主要是为了支持其他协议。
     

     PLAIN 方式的认证流程:
         由于是在SASL的认证方式,所以客户端必须要打开SASL认证的模式。
           config.setSecurityMode(SecurityMode. enabled );

    config.setSASLAuthenticationEnabled(  true );

  并且在客户端要声明,客户端必须支持PLAIN模式:
   
     SASLAuthentication.supportSASLMechanism( "PLAIN" );

   这样再客户端接下的来的认证过程中就会传输:
     <auth mechanism="PLAIN" xmlns="urn:ietf:params:xml:ns:xmpp-sasl">c3lzYWRtaW4Ac3lzYWRtaW4AMTIz</auth> 数据包,接下来服务器端就会对这个数据包进贤处理。

   我的服务器端是结合中Openfire进行开发的,当数据包到达时,服务器端会进行如下处理:
    if  ( "auth"  .equals(tag)) {
                // User is trying to authenticate using SASL
                startedSASL  =  true ;
                // Process authentication stanza
                saslStatus  = SASLAuthentication.handle( session , doc);

  在服务器端接下来的处理过程中,就是通过SaslServer 来进行客户端用户名和密码的认证。SaslServer进行java.sercurity 中的类。
  

        SaslServer ss = Sasl. createSaslServer (mechanism,
                                        "xmpp" , session.getServerName(), props,
                                        new  XMPPCallbackHandler());

   这里主要使用SaslServer 创建SASL服务器端。
    制创建一个  SaslServer 。 此方法使用  JCA Security Provider Framework (在 "Java Cryptography Architecture API Specification & Reference" 中所有描述)来查找和选择  SaslServer  实现。 首先,它从 "SaslServerFactory" 服务的已注册安全提供者和指定的 SASL 机制中获得  SaslServerFactory  实例的有序列表。然后它在列表中的每个工厂实例上调用  createSaslServer() ,直到某个调用生成一个非 null 的  SaslServer  实例为止。此方法返回非 null 的  SaslServer  实例,如果搜索无法生成非 null 的 SaslServer  实例,则返回 null。

   在这里在Openfire中的:org.jivesoftware.openfire.sasl 中的SaslServerFactoryImpl 类实现了,javax.security.sasl.SaslServerFactory,这样在创建SaslServer的时候,就会调用这个具体的实现来进行创建。
     在这里在 SASLAuthentication 的初始化过程中,在initMechanisms 方法中,就初始化了 SaslServerFactory 的类的路径。
  在程序运行过程中,就会根据客户端发送的PLAIN 模式,创建SaslServer,并进行处理。
  在 SaslServerPlainImpl 类中,可以获得客户端发送过来的用户名和密码,这里都是明文进行了传输,可以获得客户端发送的数据。这样   在 XMPPCallbackHandler 中就可以获得客户端发送的用户名和密码,然后接下来就是对用户的用户名和密码进行认证。


  
DIGEST-MD5 :
    当服务器端支持   DIGEST-MD5 时,如果客户端不明确声明支持的认证方式,默认会使用  DIGEST-MD5 来进行客户端的认证。
    在认证过程中客户端发送: <auth mechanism="DIGEST-MD5" xmlns="urn:ietf:params:xml:ns:xmpp-sasl"></auth>
  服务器端,接收到消息后进行处理:
     if  ( mechanisms  .contains(mechanism)) {
                          // 被选的SASL的机制,需要服务器发送一个 challenge

                        System.  out .println(  "password------------call---back----"
                                  + mechanism);
                          try  {
                             Map<String, String> props =  new  TreeMap<String, String>();
                             props.put(Sasl.  QOP ,  "auth" );
                               if  (mechanism.equals( "GSSAPI"  )) {
                                  props.put(Sasl.  SERVER_AUTH ,  "TRUE" );
                             }
                             SaslServer ss = Sasl.createSaslServer(mechanism,
                                        "xmpp" , session.getServerName(), props,
                                        new  XMPPCallbackHandler());
                               // evaluateResponse doesn't like null parameter
                               byte [] token =  new  byte [0];
                               if  (doc.getText().length() > 0) {
                                    // If auth request includes a value then validate it
                                  token = StringUtils.decodeBase64(doc.getText()
                                           .trim());
                                    if  (token ==  null ) {
                                      token =  new  byte [0];
                                  }
                             }
                               if  (mechanism.equals( "DIGEST-MD5"  )) {
                                    // RFC2831 (DIGEST-MD5) says the client MAY provide
                                    // an initial response on subsequent
                                    // authentication. Java SASL does not (currently)
                                    // support this and thows an exception
                                    // if we try. This violates the RFC, so we just
                                    // strip any initial token.
                                  token =  new  byte [0];
                             }
                               byte [] challenge = ss.evaluateResponse(token);
                               if  (ss.isComplete()) {
                                  System.  out .println(  "ss------------------has---complete--------"  );
                                   authenticationSuccessful(session,
                                           ss.getAuthorizationID(), challenge);
                                  status = Status. authenticated ;
                             }  else  {
                                  System.  out .println(  "ss----------not--------has---complete--------"  );
                                    // Send the challenge
                                   sendChallenge(session, challenge);
                                  status = Status. needResponse ;
                             }
                             session.setSessionData(  "SaslServer" , ss);
 在这里服务器端接收客户端发送的数据信息,并且创建 SaslServer ,在创建  SaslServer server的时候,会在  java.security.Provider 中查询,服务器端设置的进行对认证方式实例化的类, ,在这里继承的 java.security.Provider 的类中,没有定义对   DIGEST-MD5 的具体实现,就采用系统默认的方式来实例化 SaslServer。接下来的过程就是服务器端向客户端发送 challenge 数据包,
      <challenge xmlns="urn:ietf:params:xml:ns:xmpp-sasl">cmVhbG09InNtYXJ0Y29vbCIsbm9uY2U9Ind2aGNoTTFsS0dudXY0dFpOUDZxWlp3dG5WUENkTHRDUDdBNkVLcWoiLHFvcD0iYXV0aCIsY2hhcnNldD11dGYtOCxhbGdvcml0aG09bWQ1LXNlc3M=</challenge>

然后客户端发送,response 数据包进行匹配:
     <response xmlns="urn:ietf:params:xml:ns:xmpp-sasl">dXNlcm5hbWU9InN5c2FkbWluIixyZWFsbT0ic21hcnRjb29sIixjbm9uY2U9IjM3ZjJmNWUwMTQ3MWQ4ZWNkOWFmZWE1MjQyYWIyODMyMjE3MWNjOWNmNzU3MzczNTA1MGY2MjU1MjE2NTUzOTUiLG5jPTAwMDAwMDAxLHFvcD1hdXRoLGRpZ2VzdC11cmk9InhtcHAvc21hcnRjb29sIixyZXNwb25zZT04ODBlMGU5YmYxZDYyMzI4Mjg5Nzg5MDYwNzAyNTQ5ZCxjaGFyc2V0PXV0Zi04LG5vbmNlPSJ3dmhjaE0xbEtHbnV2NHRaTlA2cVpad3RuVlBDZEx0Q1A3QTZFS3FqIg==</response>

  然后也会调用对应的 NameCallBack 和 PasswordCallBack 来验证登录用户的用户名和密码。

  当认证成功后,服务端发送:
      <success xmlns="urn:ietf:params:xml:ns:xmpp-sasl">cnNwYXV0aD1iNWI4YmQ5Y2NjYjAyYjNiMDcxMDgzNzA5NDJiZDA4Yg==</success>
  这样客户端和服务器就认证成功了。

  3. anonymous 匿名登录:
       客户端在登录时,指明登录的方式, connection.loginAnonymously();
    客户端在认证时,发送数据包: <auth mechanism="ANONYMOUS" xmlns="urn:ietf:params:xml:ns:xmpp-sasl"></auth> 指明认证的方式为: ANONYMOUS。
     
      服务器端接收数据后,进行处理:
      

        在处理时:
  
         
     直接向客户端发送认证成功的数据包:
        
[root@yfw ~]# cd /www/wwwroot/szrengjing.com/kefu [root@yfw kefu]# ll total 1808 -rwxr-xr-x 1 www www 1471 Aug 7 11:51 admin.html drwxr-xr-x 2 www www 4096 Aug 7 11:46 api -rwxr-xr-x 1 www www 124 Aug 7 11:25 bosh-config.json -rwxr-xr-x 1 www www 648 Aug 7 11:47 config.js -rw-r--r-- 1 root root 525825 Jun 9 21:42 converse.min.css -rw-r--r-- 1 root root 1297669 Jun 9 21:42 converse.min.js -rwxr-xr-x 1 www www 837 Aug 7 11:54 custom.js -rwxr-xr-x 1 www www 808 Aug 7 11:50 index.html [root@yfw kefu]# 简介设置 客户端连接 服务器到服务器 外部组件 连接管理器 Web 绑定 管理更新 注册和登录 资源策略 离线消息 消息审核策略 专用数据存储 压缩设置 文件传输设置 Presence Service 推送通知 REST API 搜索服务属性 User Service Content Filter User Status Settings 注册设置 使用以下表单更改用户注册和登录的各个方面。 带内账号注册 带内账号注册允许用户使用大多数客户端自动在服务器上创建账号。它不会影响通过此 web 管理界面创建新账号的能力。管理员可能希望禁用此选项,因此要求用户通过其他方式进行注册(例如,向服务器管理员发送请求或通过您自己的自定义 web 界面)。 已启用 - 用户可以自动创建新账号。 已禁用 - 用户无法自动创建新账号。 更改密码 您可以选择是否允许用户更改密码。密码更改独立于带内账号注册。但是,您可能只想在禁用带内账号注册时禁用此功能。 已启用 - 用户可以更改密码。 已禁用 - 不允许用户更改密码。 匿名登录 您可以选择启用或禁用匿名用户登录。如果启用了它,任何人都可以连接到服务器并创建新会话。如果禁用,则只有拥有账号的用户才能连接。 已启用 - 任何人都可以登录到服务器。 已禁用 - 只有注册用户才能登录。 限制登录 使用下表定义不允许登录的 IP 地址或 IP 地址范围。例如:200.120.90.10, 200.125.80.*。将表单留空意味着客户端可以从任何 IP 地址进行连接,除非有白名单(见下文)。请注意,“阻止”列表(此处)上的条目将始终优先于下面“允许”列表上的条目。 不允许来自以下 IP 的任何登录: 使用下表定义允许登录的 IP 地址或 IP 地址范围。例如:200.120.90.10, 200.125.80.*。将表单留空意味着客户端可以从任何 IP 地址进行连接(除非有黑名单)。 限制所有(包括匿名)登录到以下 IP: 将匿名登录限制为以下 IP: 未来用户 在某些配置和/或高度特定的条件下,可以在 Openfire 知道特定用户之前为该用户调用 XMPP 功能。这方面的例子是自动配置用户的场景,同样,在非常特定的条件下,可以允许特定的配置。通常,当 Openfire 不知道某个特定用户时,它会在该用户的上下文中拒绝 XMPP 功能。通过以下配置,可以覆盖此行为:当启用“未来用户”时,Openfire 将不会拒绝其无法识别的用户的某些 XMPP 功能。相反,它假定用户将很快得到配置。例如,这可用于在配置用户之前记录发送给用户的离线消息。 已启用 - 允许与 Openfire 尚未识别的用户相关的 XMPP 功能。 已禁用 - 拒绝与 Openfire 当前未识别的用户相关的 XMPP 功能。 SASL 机制 下面配置的 SASL 机制控制用于身份验证的机制。每种机制都有其自身的特点。下表用于控制在 Openfire 中启用哪些 SASL 机制。要使用的机制必须有一个实施,但即使有,该机制也可能不会提供给客户端:这可能取决于特定于机制的服务器设置。 已启用 名称 描述 实施可用 提供给客户端 ANONYMOUS 用于未经身份验证的访客访问。 CRAM-MD5 基于 HMAC-MD5 的简单质询&mdash;响应方案。 DIGEST-MD5 基于 MD5 的质询&mdash;响应方案。DIGEST-MD5 提供了一个数据安全层。 EXTERNAL 其中身份验证在上下文中是隐式的(例如,对于已经使用 IPsec 或 TLS 的协议)。 GSSAPI 通过 GSSAPI 进行 Kerberos V5 身份验证。GSSAPI 提供了一个数据安全层。 JIVE-SHAREDSECRET 基于共享秘密的专有 Jive 软件 SASL 机制。 NTLM NT LAN Manager 身份验证机制。 PADE (没有可用的描述) PLAIN 简单的明文密码机制。 SCRAM-SHA-1 基于 SHA-1 的加盐质询&mdash;响应方案。 如何配置连接 聊天服务器IP地址: 124.71.230.244 聊天服务器端口号: 9090 HTTP-BIND端口号: 7070 聊天服务器管理员登录账户: admin 聊天服务器管理员登录密码: 留空则不更新 确认密码: 访问聊天服务系统
最新发布
08-08
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值