本部分的描述仅适用于单一的Domino平台应用与构异系统实现单点登录。
*
1.1 Domino LTPA Cookie **生成原理
在与 Domino 做 SSO 的时候,会使用 LTPA Token的认证方式,本文描述它的生成原理,通过它我们可以自己编码生成身份认证的 cookie,实现 SSO。
首先,这个 cookie 由以下部分组成:
·LTPA token 版本(4字节)
·创建时间(8字节)
·过期时间(8字节)
·用户名(可变长度)
·Domino LTPA 密钥(20字节)
接下来分别说明各部分的具体内容:
·LTPA token 版本目前 Domino 只有一种值:0x0001
·创建时间为以十六进制方式表示的Unix time,例如:2009-04-09 13:52:42 (GMT +8) =
1239256362 = 49DD8D2A。
·过期时间=创建时间 + SSO 配置文档的过期时间(LTPA_TokenExpiration域)
·用户名为 Names 中用户文档的FullName域值;如:Squall Zhong/Digiwin
·Domino LTPA 密钥通过 Base64编码后,保存在 SSO 配置文档的LTPA_DominoSecret域中
当然不能将密钥直接发送给浏览器,所以将上述部分合并起来(如上图),计算 SHA-1 校验和。
然后用 SHA-1 校验和替换掉 Domino LTPA 密钥,最后再将内容通过 Base64 编码,形成最终的 cookie 发送给浏览器(如上图)。这样如果 cookie 中的任何内容被修改,校验和就不对了,达到了防篡改的效果。所以最终LTPA
Cookie所得到的值为以下公式组成:
SHA-1=LTPA**版本号+创建时间+过期时间+用户名+Domino LTPA 密钥**
LTPA Cookie= Base64(LTPA**版本号+创建时间+过期时间+用户名+SHA-1)**
*
1.2 **异构系统所需信息
·Domino 所使用的DNS域,如:vgolive.com
·过期时间(分钟),如:30
·Domino LTPA 密钥
·Domino验证字名称,如:/O=VGOLive Technology
注:用户名可以通过Domino验证字进行拼接,如异构系统中用户名为SquallZhong,相应在Domino中的DN就是CN=SquallZhong/O=VGOLive
Technology。此类情况仅限于Domino中的CN与异构系统中的用户名一致。如果不一致,需要异构系统做用户对应
*
1.3 **实现
Base64解码/编码所需Jar包:apache-commons-codec-1.3.jar**以上**
SHA-1的校验使用java.security.MessageDigest类
转换字符集使用:Cp850
*
1.3.1 **解析
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">01</span>
import <span lang="EN-US" style="font-size:12.0pt;color:#666666">org.apache.commons.codec.binary.Base64;
</span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">02…... </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">03</span>
final <span lang="EN-US" style="font-size:12.0pt;color:#666666">String CHARSET = </span>
“Cp850”<span lang="EN-US" style="font-size:12.0pt;color:#666666">; </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">04</span>
byte<span lang="EN-US" style="font-size:12.0pt;color:#666666">[] dominoSecret =
Base64.decodeBase64(ltpaDominoSecret.getBytes()); </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">05</span>
byte<span lang="EN-US" style="font-size:12.0pt;color:#666666">[] ltpa =
Base64.decodeBase64(ltpaToken.getBytes()); </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">06ByteArrayInputStream stream = </span>
new <span lang="EN-US" style="font-size:12.0pt;color:#666666">ByteArrayInputStream(ltpa); </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">07</span>
int <span lang="EN-US" style="font-size:12.0pt;color:#666666">usernameLength = ltpa.length
– </span>
40<span lang="EN-US" style="font-size:12.0pt;
color:#666666">; </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">08</span>
byte <span lang="EN-US" style="font-size:12.0pt;color:#666666">header[] = </span>
new byte<span lang="EN-US" style="font-size:12.0pt;color:#666666">[</span>
4<span lang="EN-US" style="font-size:12.0pt;color:#666666">]; </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">09</span>
byte <span lang="EN-US" style="font-size:12.0pt;color:#666666">creation[] = </span>
new byte<span lang="EN-US" style="font-size:12.0pt;color:#666666">[</span>
8<span lang="EN-US" style="font-size:12.0pt;color:#666666">]; </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">10</span>
byte <span lang="EN-US" style="font-size:12.0pt;color:#666666">expires[] = </span>
new byte<span lang="EN-US" style="font-size:12.0pt;color:#666666">[</span>
8<span lang="EN-US" style="font-size:12.0pt;color:#666666">]; </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">11</span>
byte <span lang="EN-US" style="font-size:12.0pt;color:#666666">username[] = </span>
new byte<span lang="EN-US" style="font-size:12.0pt;color:#666666">[usernameLength]; </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">12</span>
byte<span lang="EN-US" style="font-size:12.0pt;color:#666666">[] sha = </span>
new byte<span lang="EN-US" style="font-size:12.0pt;color:#666666">[</span>
20<span lang="EN-US" style="font-size:12.0pt;color:#666666">]; </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">13// </span>``<span style="font-size:12.0pt;
color:#666666">读取<span lang="EN-US">LTPAToken</span>版本号 </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">14stream.read(header, </span>
0<span lang="EN-US" style="font-size:12.0pt;color:#666666">, </span>
4<span lang="EN-US" style="font-size:12.0pt;color:#666666">); </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">15</span>
if <span lang="EN-US" style="font-size:12.0pt;color:#666666">(header[</span>
0<span lang="EN-US" style="font-size:12.0pt;color:#666666">] != </span>
0 <span lang="EN-US" style="font-size:12.0pt;color:#666666">|| header[</span>
1<span lang="EN-US" style="font-size:12.0pt;color:#666666">] != </span>
1 <span lang="EN-US" style="font-size:12.0pt;color:#666666">|| header[</span>
2<span lang="EN-US" style="font-size:12.0pt;color:#666666">] != </span>
2<span lang="EN-US" style="font-size:12.0pt;color:#666666">|| header[</span>
3<span lang="EN-US" style="font-size:12.0pt;color:#666666">] != </span>
3<span lang="EN-US" style="font-size:12.0pt;color:#666666">) </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">16</span>
throw new <span lang="EN-US" style="font-size:12.0pt;color:#666666">IllegalArgumentException(</span>
“Invalid
ltpaToken format”<span lang="EN-US" style="font-size:
12.0pt;color:#666666">); </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">17</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">// </span>``<span style="font-size:12.0pt;color:#666666">读取开始时间 </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">18</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">stream.read(creation, </span>
0<span lang="EN-US" style="font-size:12.0pt;color:#666666">, </span>
8<span lang="EN-US" style="font-size:12.0pt;color:#666666">); </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">19</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">// </span>``<span style="font-size:12.0pt;color:#666666">读取到期时间 </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">20</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">stream.read(expires, </span>
0<span lang="EN-US" style="font-size:12.0pt;color:#666666">, </span>
8<span lang="EN-US" style="font-size:12.0pt;color:#666666">); </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">21</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">// </span>``<span style="font-size:12.0pt;color:#666666">读取<span lang="EN-US">Domino</span>用户<span lang="EN-US">DN </span></span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">22</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">stream.read(username, </span>
0<span lang="EN-US" style="font-size:12.0pt;color:#666666">, usernameLength); </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">23</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">// </span>``<span style="font-size:12.0pt;color:#666666">读取<span lang="EN-US">SHA</span>校验和 </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">24</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">stream.read(sha, </span>
0<span lang="EN-US" style="font-size:12.0pt;color:#666666">, </span>
20<span lang="EN-US" style="font-size:12.0pt;color:#666666">); </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">25</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">// </span>``<span style="font-size:12.0pt;color:#666666">转换用户名 </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">26</span>
char <span lang="EN-US" style="font-size:12.0pt;color:#666666">characters[] = </span>
new char<span lang="EN-US" style="font-size:12.0pt;color:#666666">[usernameLength]; </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">27</span>
try <span lang="EN-US" style="font-size:12.0pt;color:#666666">{ </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">28</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">InputStreamReader isr = </span>
new <span lang="EN-US" style="font-size:12.0pt;color:#666666">InputStreamReader( </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">29</span>
new <span lang="EN-US" style="font-size:12.0pt;color:#666666">ByteArrayInputStream(username),
</span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">30</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">CHARSET); </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">31</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">isr.read(characters); </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">32</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">} </span>
catch <span lang="EN-US" style="font-size:12.0pt;color:#666666">(Exception e) { </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">33</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">} </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">34</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">// </span>``<span style="font-size:12.0pt;color:#666666">获得<span lang="EN-US">Domino</span>用户<span lang="EN-US">DN </span></span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">35</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">String dn = </span>
new <span lang="EN-US" style="font-size:12.0pt;color:#666666">String(characters); </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">36</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">// </span>``<span style="font-size:12.0pt;color:#666666">获得创建时间 </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">37</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">Date creationDate = </span>
new <span lang="EN-US" style="font-size:12.0pt;color:#666666">Date( </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">38</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">Long.parseLong(</span>
new <span lang="EN-US" style="font-size:12.0pt;color:#666666">String(creation), </span>
16<span lang="EN-US" style="font-size:12.0pt;color:#666666">) * </span>
1000<span lang="EN-US" style="font-size:12.0pt;color:#666666">); </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">39</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">// </span>``<span style="font-size:12.0pt;color:#666666">获得到期时间 </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">40</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">Date expiresDate = </span>
new <span lang="EN-US" style="font-size:12.0pt;color:#666666">Date( </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">41</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">Long.parseLong(</span>
new <span lang="EN-US" style="font-size:12.0pt;color:#666666">String(expires), </span>
16<span lang="EN-US" style="font-size:12.0pt;color:#666666">) * </span>
1000<span lang="EN-US" style="font-size:12.0pt;color:#666666">); </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">42…... </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">43// </span>``<span style="font-size:12.0pt;
color:#666666">创建<span lang="EN-US">LTPA Token </span></span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">44</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">ByteArrayOutputStream ostream
= </span>
new <span lang="EN-US" style="font-size:12.0pt;color:#666666">ByteArrayOutputStream(); </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">45</span>
try <span lang="EN-US" style="font-size:12.0pt;color:#666666">{ </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">46</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">// LTPA Token</span>``<span style="font-size:12.0pt;color:#666666">版本号 </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">47</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">ostream.write(header); </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">48</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">// </span>``<span style="font-size:12.0pt;color:#666666">创建时间 </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">49</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">ostream.write(creation); </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">50</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">// </span>``<span style="font-size:12.0pt;color:#666666">过期时间 </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">51</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">ostream.write(expires); </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">52</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">// Domino</span>``<span style="font-size:12.0pt;color:#666666">用户<span lang="EN-US">DN</span>,如<span lang="EN-US">CN=SquallZhong/O=DigiWin </span></span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">53</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">ostream.write(username); </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">54</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">// Domino LTPA </span>``<span style="font-size:12.0pt;color:#666666">密钥 </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">55</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">ostream.write(dominoSecret); </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">56</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">ostream.close(); </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">57</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">} </span>
catch <span lang="EN-US" style="font-size:12.0pt;color:#666666">(IOException e) { </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">58</span>
throw new <span lang="EN-US" style="font-size:12.0pt;color:#666666">RuntimeException(e); </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">59</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">} </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">60</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">// </span>``<span style="font-size:12.0pt;color:#666666">进行<span lang="EN-US"> SHA-1 </span>校验和 </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">61</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">MessageDigest md; </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">62</span>
try <span lang="EN-US" style="font-size:12.0pt;color:#666666">{ </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">63</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">md =
MessageDigest.getInstance(</span>
“SHA-1”<span lang="EN-US" style="font-size:12.0pt;color:#666666">); </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">64</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">md.reset(); </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">65</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">} </span>
catch <span lang="EN-US" style="font-size:12.0pt;color:#666666">(NoSuchAlgorithmException e)
{ </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">66</span>
throw new <span lang="EN-US" style="font-size:12.0pt;color:#666666">RuntimeException(e); </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">67</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">} </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">68</span>
byte<span lang="EN-US" style="font-size:12.0pt;color:#666666">[] digest =
md.digest(ostream.toByteArray()); </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">69</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">// </span>``<span style="font-size:12.0pt;color:#666666">完成<span lang="EN-US"> SHA-1 </span>校验和,<span lang="EN-US">digest</span>长度为<span lang="EN-US">20 </span></span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">70</span>
boolean <span lang="EN-US" style="font-size:12.0pt;color:#666666">valid =
MessageDigest.isEqual(digest, sha);</span>
*
1.3.2 **生成
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">01</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">/** </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">02</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">* </span>``<span style="font-size:12.0pt;color:#666666">为指定用户创建有效的<span lang="EN-US">LTPA Token.</span>创建时间为<span lang="EN-US"><tt>now</tt>. </span></span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">03</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">* </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">04</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">* @param username </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">05</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">* -
</span>``<span style="font-size:12.0pt;color:#666666">用户名,注:使用用户全称,如:<span lang="EN-US">CN=SquallZhong/O=VGOLive Technology </span></span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">06</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">* @param creationTime </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">07</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">* -
</span>``<span style="font-size:12.0pt;color:#666666">创建时间 </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">08</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">* @param durationMinutes </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">09</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">* -
</span>``<span style="font-size:12.0pt;color:#666666">到期时间,单位:分钟 </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">10@param ltpaSecretStr </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">11</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">* -
Domino Ltpa </span>``<span style="font-size:12.0pt;color:#666666">加密字符串
</span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">12</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">* @return - </span>``<span style="font-size:12.0pt;color:#666666">返回已<span lang="EN-US">Base64</span>编码的<span lang="EN-US">Ltpa Cookie. </span></span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">13</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">* @throws
NoSuchAlgorithmException </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">14</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">* @throws
Base64DecodeException </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">15</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">*/</span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">16</span>
public static <span lang="EN-US" style="font-size:12.0pt;color:#666666">String createLtpaToken(String
username, </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">17</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">GregorianCalendar
creationTime, </span>
int <span lang="EN-US" style="font-size:12.0pt;color:#666666">durationMinutes, </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">18</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">String ltpaSecretStr) </span>
throws <span lang="EN-US" style="font-size:12.0pt;color:#666666">NoSuchAlgorithmException { </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">19</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">// Base64</span>``<span style="font-size:12.0pt;color:#666666">解码<span lang="EN-US">ltpaSecretStr </span></span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">20</span>
byte<span lang="EN-US" style="font-size:12.0pt;color:#666666">[] ltpaSecret =
Base64.decodeBase64(ltpaSecretStr.getBytes()); </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">21</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">// </span>``<span style="font-size:12.0pt;color:#666666">用户名字节数组 </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">22</span>
byte<span lang="EN-US" style="font-size:12.0pt;color:#666666">[] usernameArray =
username.getBytes(); </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">23</span>
byte<span lang="EN-US" style="font-size:12.0pt;color:#666666">[] workingBuffer = </span>
new byte<span lang="EN-US" style="font-size:12.0pt;color:#666666">[preUserDataLength </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">24</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">+ usernameArray.length +
ltpaSecret.length]; </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">25 </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">26</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">// </span>``<span style="font-size:12.0pt;color:#666666">设置<span lang="EN-US">ltpaToken</span>版本至<span lang="EN-US">workingBuffer </span></span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">27</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">System.arraycopy(ltpaTokenVersion,
</span>
0<span lang="EN-US" style="font-size:12.0pt;
color:#666666">, workingBuffer, </span>
0<span lang="EN-US" style="font-size:12.0pt;color:#666666">, </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">28</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">ltpaTokenVersion.length); </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">29</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">// </span>``<span style="font-size:12.0pt;color:#666666">获得过期时间,过期时间<span lang="EN-US">=</span>当前时间<span lang="EN-US">+</span>到期时间<span lang="EN-US">(</span>分钟<span lang="EN-US">) </span></span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">30</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">GregorianCalendar
expirationDate = (GregorianCalendar) creationTime </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">31</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">.clone(); </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">32</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">expirationDate.add(Calendar.MINUTE,
durationMinutes); </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">33 </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">34</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">// </span>``<span style="font-size:12.0pt;color:#666666">转换创建时间至<span lang="EN-US">16</span>进制字符串 </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">35</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">String hex = dateStringFiller
</span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">36</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">+ Integer.toHexString( </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">37</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">(</span>
int<span lang="EN-US" style="font-size:12.0pt;color:#666666">)
(creationTime.getTimeInMillis() / </span>
1000<span lang="EN-US" style="font-size:12.0pt;color:#666666">)) </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">38</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">.toUpperCase(); </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">39</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">// </span>``<span style="font-size:12.0pt;color:#666666">设置创建时间至<span lang="EN-US">workingBuffer </span></span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">40</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">System.arraycopy(hex.getBytes(),
hex.getBytes().length </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">41</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">- dateStringLength,
workingBuffer, creationDatePosition, </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">42</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">dateStringLength); </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">43 </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">44</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">// </span>``<span style="font-size:12.0pt;color:#666666">转换过期时间至<span lang="EN-US">16</span>进制字符串 </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">45</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">hex = dateStringFiller </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">46</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">+ Integer.toHexString( </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">47</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">(</span>
int<span lang="EN-US" style="font-size:12.0pt;color:#666666">)
(expirationDate.getTimeInMillis() / </span>
1000<span lang="EN-US" style="font-size:12.0pt;color:#666666">)) </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">48</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">.toUpperCase(); </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">49</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">// </span>``<span style="font-size:12.0pt;color:#666666">设置过期时间至<span lang="EN-US">workingBuffer </span></span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">50</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">System.arraycopy(hex.getBytes(),
hex.getBytes().length </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">51</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">- dateStringLength,
workingBuffer, expirationDatePosition, </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">52</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">dateStringLength); </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">53 </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">54</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">// </span>``<span style="font-size:12.0pt;color:#666666">设置用户全称至<span lang="EN-US">workingBuffer </span></span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">55</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">System.arraycopy(usernameArray,
</span>
0<span lang="EN-US" style="font-size:12.0pt;
color:#666666">, workingBuffer, preUserDataLength, </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">56</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">usernameArray.length); </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">57 </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">58</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">// </span>``<span style="font-size:12.0pt;color:#666666">设置已<span lang="EN-US">Base64</span>解码<span lang="EN-US">ltpaSecret</span>至<span lang="EN-US">workingBuffer </span></span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">59</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">System.arraycopy(ltpaSecret, </span>
0<span lang="EN-US" style="font-size:12.0pt;color:#666666">, workingBuffer, preUserDataLength
</span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">60</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">+ usernameArray.length,
ltpaSecret.length); </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">61</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">// </span>``<span style="font-size:12.0pt;color:#666666">创建<span lang="EN-US">Hash</span>字符串 </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">62</span>
byte<span lang="EN-US" style="font-size:12.0pt;color:#666666">[] hash =
createHash(workingBuffer); </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">63 </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">64</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">// ltpaToken</span>``<span style="font-size:12.0pt;color:#666666">版本<span lang="EN-US">+</span>开始时间<span lang="EN-US">(16</span>进制<span lang="EN-US">)+</span>到期时间<span lang="EN-US">(16</span>进制<span lang="EN-US">)+</span>用户全名<span lang="EN-US">+SHA-1(ltpaToken</span>版本<span lang="EN-US">+</span>开始时间<span lang="EN-US">(16</span>进制<span lang="EN-US">)+</span>到期时间<span lang="EN-US">(16</span>进制<span lang="EN-US">)+</span>用户全名<span lang="EN-US">) </span></span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">65</span>
byte<span lang="EN-US" style="font-size:12.0pt;color:#666666">[] outputBuffer = </span>
new byte<span lang="EN-US" style="font-size:12.0pt;color:#666666">[preUserDataLength +
usernameArray.length </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">66</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">+ hashLength]; </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">67</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">System.arraycopy(workingBuffer,
</span>
0<span lang="EN-US" style="font-size:12.0pt;
color:#666666">, outputBuffer, </span>
0<span lang="EN-US" style="font-size:12.0pt;color:#666666">, preUserDataLength </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">68</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">+ usernameArray.length); </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">69</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">System.arraycopy(hash, </span>
0<span lang="EN-US" style="font-size:12.0pt;color:#666666">, outputBuffer,
preUserDataLength </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">70</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">+ usernameArray.length,
hashLength); </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">71</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">// </span>``<span style="font-size:12.0pt;color:#666666">返回已<span lang="EN-US">Base64</span>编码的<span lang="EN-US">outputBuffer </span></span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">72</span>
return new <span lang="EN-US" style="font-size:12.0pt;color:#666666">String(Base64.encodeBase64(outputBuffer));
</span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">73</span>
<span lang="EN-US" style="font-size:12.0pt;color:#666666">} </span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">74…...</span>
<span lang="EN-US" style="font-size:
12.0pt;color:#666666">
</span>