7.2 账号系统

limax通过Auany提供一个支持子账号的凭证式账号系统,分配sessionid。


  • 基本概念

    1. credential,字符串表示的由auany的key签名的凭证,当前系统提供Session凭证和Temporary凭证。

    2. authcode,用户授权码,参与凭证签名。

    3. serial,凭证序列号,凭证更新之后,序列号加一,系统通过序列号确认凭证有效性,拒绝过期凭证。

    4. loginConfig,登录配置对象。

    5. mainid,主账号的sessionid

    6. uid,系统内用户标识,为username@platflag转换为小写的字符串。

    7. appid,应用标识,aunay下的每一个应用分配一个appid,同一uid下,不同appid映射了不同的mainid。

    8. derive,创建未绑定主账号,或者在主帐号下派生子账号。

    9. bind,创建绑定主账号,或者进行帐号绑定,或者更新凭证序列号。


  • Session凭证

    为了支持子账号,下面的方法可能返回一个形为credential[,subid]+的字符串,该字符串为完全的Session凭证表示,其中subid即是子账号。

    • 非绑定账号的创建


      AuanyService.derive(String httpHost, int httpPort, int appid, String authcode, long timeout, Result onresult);
      

      在这里httpHost, httpPort为auany提供的http服务器地址,appid指明了请求的应用。

      如果onresult.errorSource == ErrorSource.LIMAX && onresult.errorCode == SUCCEED,则onresult.result为返回的初始Session凭证。


    • 绑定账号的创建


      AuanyService.bind(String httpHost, int httpPort, int appid, String authcode, LoginConfig loginConfig, long timeout, Result onresult);
      

      与非绑定账号的创建相比,这里多出了loginConfig参数,使用这个参数执行认证,认证成功之后创建一个已经绑定好的Session凭证。

      特别的,如果username,token,platflag认证之后映射的uid下appid已经关联上一个mainid,则递增相应的serial之后返回完全的Session凭证表示。这个功能可以用于账号找回。


    • 派生子账号


      AuanyService.derive(String credential, String authcode, long timeout, Result onresult);
      

      该方法如果执行成功,则onresult.result返回完全的Session凭证表示,如果之前有N个subid,则返回之后包含N+1个subid,最后一个subid即为派生出来的新的子账号。

      派生子账号上限由应用的配置参数maxSubordinates决定。详见,service-auany.xml


    • 账号的绑定


      AuanyService.bind(String credential, String authcode, LoginConfig loginConfig, long timeout, Result onresult);
      

      该方法通过loginConfig认证之后进行绑定,返回Session凭证的完全表示。

      该方法除了对未绑定账号(凭证)进行绑定外,也可以使用与绑定时相同的loginConfig进行重复绑定,目的是返回Session凭证的完全表示。


    • Provider的影响

      ProviderTransport 接口提供2个方法


      long getMainId();
      String getUid();
      

      其中,通过getMainId()返回mainid与当前的sessionid比较,可以得知当前的登录是在主帐号下还是子账号下。


    • Session凭证的登录

      登录参数中username指定为Session凭证,token指定为authcode,platflag指定为"credential",如果登录子账号,platflag后缀":subid"。尽可能使用LoginConfig.credentialLogin方法。


    • 移动客户端的考虑

      凭证方式适合移动客户端实现,满足有需要时再进行帐号绑定的需求。

      返回的Session凭证应该进行本地存储,便于下一次访问时直接登录。如果支持子账号,多数情况下需要考虑与相应UI资源的关联。

      这里要注意的一个问题就是未绑定账号在登录后执行绑定时的可能出现的意外情况——发起bind操作之后,网络断开——这种情况下不能确定是否绑定成功,所以下一次登录时应该首先是用原来的凭证进行登录,如果不成功,则使用非凭证方式进行登录,登录完成后再次进行bind,直到获得Session凭证的完全表示,完成本地存储。


    • pc,web客户端的的考虑

      这两种客户端通常不会在本地存储凭证,可以使用普通方式进行登录,如果有子账号需求,可以通过bind方式获取Session凭证的完全表示,再派生子账号;或者登录主账号,使用空凭证,空authcode,调用derive,这种情况下onresult.result仅返回新的子账号串。


    • 子账号的考虑

      使用子账号功能的系统内,Provider通常会维护子账号,主账号的关系。这里要注意2个问题。

      1. 需要验证ProviderTransport提供的mainid, sessionid关系,如果是子账号登录,则验证从属关系是否改变,如果改变应该进行相应的修改,因为有可能发生了子账号迁移。

      2. 不能信任客户端提供的子账号id,例如客户端派生了子账号,不应该提供给Provider要求在其上创建对应记录。正确的解决办法应该是客户端派生了子账号以后,使用子账号进行登录,Provider发现对应sessionid的相关记录没有创建,则创建之。


  • Temporary凭证

    Temporary凭证,在Session凭证的基础上添加了时效性,过期则失效;添加subid属性,可以直接标识子账号;添加用法属性,支持两种用法——临时登录,账号传送。

    • 创建Temporary凭证


      1.	AuanyService.temporary(String credential, String authcode, String authcode2, long millisecond, byte usage, String subid, long timeout, Result onresult);
      2.	AuanyService.temporary(String httpHost, int httpPort, int appid, String credential, String authcode, String authcode2, long millisecond, byte usage, String subid, long timeout, Result onresult);
      3.	AuanyService.temporary(LoginConfig loginConfig, int appid, String authcode,long millisecond, byte usage, String subid, long timeout, Result onresult);
      4.	AuanyService.temporary(String httpHost, int httpPort, int appid, LoginConfig loginConfig, String authcode, long millisecond, byte usage, String subid, long timeout, Result onresult);
      

      方法1,2,通过Session凭证创建临时凭证,方法2无需在登录状态下执行。

      方法3,4,通过登录账号方式创建临时凭证,方法4无需在登录状态下执行。

      方法1,3的authcode2参数与方法2,4的authcode参数,指定了临时凭证的authcode。

      millisecond参数指明了临时凭证自创建开始计算的有效时间,单位毫秒。

      usage参数指明了临时凭证用法,USAGE_LOGIN = 1,指示该临时凭证用于登录,USAGE_TRANSFER = 2,指示该临时凭证用于账号传送。

      subid参数指明了子账号标识串,空串代表临时凭证作用于主账号。

      执行成功后onresult.result返回了临时凭证。


    • Temporary凭证的登录

      类似Session凭证的登录,不同的是platflag中的子账号后缀无意义,因为临时凭证本身包含了subid。


    • 账号传送


      AuanyService.transfer(String httpHost, int httpPort, int appid, LoginConfig loginConfig, String authcode, String temp, String authtemp, long timeout, Result onresult);
      

      在这里httpHost, httpPort为auany提供的http服务器地址,appid指明了请求的应用。

      loginConfig,指明了接收账号,authcode为账号接收之后生成的Session凭证的授权码。

      temp, authtemp,为临时凭证及其授权码。

      执行成功之后onresult.result返回接收账号的Session凭证的完全表示。


      这里需要注意:

      1. 必须通过一个有效账号来接收传递账号。

      2. 临时凭证指定的账号被传递,可以是主账号——这种情况连同所有子账号一起被传递,接收账号必须没有绑定过该应用,否则报告appid冲突;可以是子账号,这种情况下如果接收账号没有绑定过该应用,则首先建立主账号,再添加该子账号,如果绑定过,在不违反maxSubordinates限制的前提下添加子账号。

      3. 如果应用提供了子账号传送支持,则Provider实现时必须验证mainid,sessionid的关系。


  • 注意事项

    1. 以httpHost,httpPort,appid三个参数开头的方法不需要在账号登录的状态下执行,这些方法为同步方法,onresult被触发之后返回;其它方法均为异步方法。。

    2. 只要账号进行了绑定,任何时候都可以使用绑定时的账号参数调用bind方法获取Session凭证的完全表示。

    3. 通过方法EndpointManager.getAccountFlags(), ProviderTransport.getAccountFlags()的调用, Provider与Endpoint均可获取当前登录帐号的标记,该标记与SessionFlags.FLAG_ACCOUNT_BOUND = 1和SessionFlags.FLAG_TEMPORARY_LOGIN = 2进行掩码运算即可获知当前登录帐号是否绑定, 是否临时登录帐号, 从而采取特定应对。

    4. 临时凭证主要提供给他人使用,如果有效期之内反悔,可以使用绑定时的账号参数调用bind方法,递增serial,使得之前生成的临时凭证全部失效。没有绑定过的账号没有机会反悔,原因在于没有绑定过的账号禁止递增serial,一旦递增serial,新凭证因为网络原因丢失,老凭证又无法登录,就意味着账号的丢失。


上一页 下一页