`
yongshuai0314
  • 浏览: 19205 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类

LTPA Cookie原理

 
阅读更多

1. 什么是LTPA?

Lightweight Third-Party Authentication (LTPA)是IBM Websphere和Domino产品中使用单点登录技术。当服务器配置好LTPA认证方式,用户通过浏览器成功登录后,服务器会自动发送一个session cookie给浏览器;此cookie中包含一个LTPA Token。


2. WebSphere部分

本部分描述适用于已实施WebSphere系列产品应用和Domino平台应用,或WebSphere与Domino之间已完成单点登录。在这样的环境中与构异系统实现单点登录。

一个通过有效的LTPA Cookie能够在同一个认证域中所有服务器被自动认证。此Cookie中包含认证信息和时间戳。这些信息通过共享的3DES Key进行了bis 加密。使用公共密钥/私有密钥进行签名。
LTPA Cookie通过3DES密钥使用DESede/ECB/PKCS5P进行加密。此密钥也是采用DESede/ECB/PKCS5P进行加密,加密后再使用提供的密码再进行SHA Hash,生成24个字节的密钥,再进行Base64编码。
 
如果你要解析LTPA Token,先得使用Key的密码,生成3DES密钥;再使用3DES密钥解密Token Cookie。也可以使用公共/私有密钥来签名或验证LTPA Cookie。

2.1 WebSphere LTPA 生成原理

首先,这个 cookie 由以下部分组成,以%进行分隔:
  • 用户信息,格式为u:user\:<RealmName>/<UserDN>,如:u:user\:VGOLiveRealm/CN=squallzhong,O=VGOLive Technology
  • 过期时间
  • 签名信息,如:
    u:user\:VGOLiveRealm/CN=squallzhong,O=VGOLive Technology%1301558320666%Cy2CAeru5kEElGj0hrvYsKW2ZVsvvcu6Un573aeX55OO4G3EMYWc0e/ZbqDp1z7MS+dLzniuUH4sYWCMpnKdm7ZGabwmV+WcraBl+y+yzwcl722gHVMOnDZAW7U3jEay9Tk2yG4yXkMWU+617xndpVxke2jtS5wIyVVM3q7UDPw=

2.2 异构系统所需信息

从WebSphere系统中导出ltpa的key文件,使用文本文件打开,如:

com.ibm.websphere.CreationDate=Thu Mar 31 11\:08\:09 GMT+08\:00 2011 com.ibm.websphere.ltpa.version=1.0 com.ibm.websphere.ltpa.3DESKey=7dH4i81YepbVe+gF9XVUzE4C1Ca5g6A4Q69OFobJV9g\= com.ibm.websphere.CreationHost=wasserver com.ibm.websphere.ltpa.PrivateKey=N3bnOE1IbiXNsHXxxemC98iiCnmtw3JUuQvdFjEyh9r2gu+FlQRmG8xp5RBltqc6raI4EgYFhTr+t5/tmRQrFqfNKgvujeJZODeCspohi1V4C0qit7DOoqD9xOOn9Rzdb4PIuJM3ekwuBiZZYTYu7q0TANDygc7VbmwoD3xMPCk5svyvFJ/VshPyg5f7Q+VNM8dlIitU4gK9Qp8VZEqjGoXsYYzYYTQgnwAVtR2GfZtXKlf24EPXSkgUz9j8FwTvcylcKwjS22d6eVjciyAzInnxPqxE2iMRPEFDatHZFox3flsqBswmeDQrAGv8zIiffgP1DLKdjozUyAG+50v97xx7u1RtIrB4B01ik8DuLhw\= com.ibm.websphere.ltpa.Realm=VGOLiveRealm com.ibm.websphere.ltpa.PublicKey=AM04If2+ElGSyVRF0ZEesgvC59vGw8gSIfptjfoXj8iz4C7Ip/KVAu2PDkpQi3LUN/FgVF696tmsegBThks9rmMMHzOix/vGP2721dQZKbD7plOLdWtiY2AYZChsBVkOF26DfiWJ6euxD+a+KNcrfDnu2AXRC/tKncIUJV4LbeJdAQAB
  • 所使用的DNS域,如:vgolive.com
  • 过期时间(分钟),如:30
  • LTPA 3DESKey 密钥及密钥的保护密码
  • Base DN,如:O=VGOLive Technology或DC=vgolive,DC=com
注:
  • 在3DESKey中的反斜杠只是为了在JAVA中可解释等于号,所以正确的3DESKey为7dH4i81YepbVe+gF9XVUzE4C1Ca5g6A4Q69OFobJV9g=
  • 用户名可以通过Base Dn验证字进行拼接,如异构系统中用户名为SquallZhong,相应在Domino中的DN就是CN=SquallZhong,O=DigiWin。此类情况仅限于LDAP中的CN与异构系统中的用户名一致。如果不一致,需要异构系统做用户对应

2.3 实现

Base64解码/编码所需Jar包:apache-commons-codec-1.3.jar以上
SHA-1的校验使用java.security.MessageDigest

2.3.1 解析

以下代码为解析从WebSphere或Domino发送过来的LTPAToken Cookie以Java为例:

 
01
02        // LTPA 3DES 密钥
03        String ltpa3DESKey = "7dH4i81YepbVe+gF9XVUzE4C1Ca5g6A4Q69OFobJV9g=";
04        // LTPA 密钥密码
05        String ltpaPassword = "Passw0rd";
06        try {
07            // 获得加密key
08            byte[] secretKey = getSecretKey(ltpa3DESKey, ltpaPassword);
09            // 使用加密key解密ltpa Cookie
10            String ltpaPlaintext = new String(decryptLtpaToken(tokenCipher,
11                    secretKey));
12            displayTokenData(ltpaPlaintext);
13        } catch (Exception e) {
14            System.out.println("Caught inner: " + e);
15        }
16
17    //获得安全Key
18    private static byte[] getSecretKey(String ltpa3DESKey, String password)
19            throws Exception {
20        // 使用SHA获得key密码的hash值
21        MessageDigest md = MessageDigest.getInstance("SHA");
22        md.update(password.getBytes());
23        byte[] hash3DES = new byte[24];
24        System.arraycopy(md.digest(), 0, hash3DES, 0, 20);
25        // 使用0替换后4个字节
26        Arrays.fill(hash3DES, 20, 24, (byte) 0);
27        // BASE64解码 ltpa3DESKey
28        byte[] decode3DES = Base64.decodeBase64(ltpa3DESKey.getBytes());
29        // 使用key密码hash值解密已Base64解码的ltpa3DESKey
30        return decrypt(decode3DES, hash3DES);
31    }
32    //解密LtpaToken
33    public static byte[] decryptLtpaToken(String encryptedLtpaToken, byte[] key)
34            throws Exception {
35        // Base64解码LTPAToken
36        final byte[] ltpaByteArray = Base64.decodeBase64(encryptedLtpaToken
37                .getBytes());
38        // 使用key解密已Base64解码的LTPAToken
39        return decrypt(ltpaByteArray, key);
40    }
41    // DESede/ECB/PKC5Padding解方法
42    public static byte[] decrypt(byte[] ciphertext, byte[] key)
43            throws Exception {
44        final Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");
45        final KeySpec keySpec = new DESedeKeySpec(key);
46        final Key secretKey = SecretKeyFactory.getInstance("TripleDES")
47                .generateSecret(keySpec);
48        cipher.init(Cipher.DECRYPT_MODE, secretKey);
49        return cipher.doFinal(ciphertext);
50    }
51

解析出来的LTPAToken信息以%分隔


2.3.2 生成

Websphere LTPA生成时的签名信息是由用户DN和一些用户其他信息组成字符串,使用私有密钥进行签名,由于不清楚这些信息的组成,故无法产生正确的LTPA。


3. Domino部分

本部分的描述仅适用于单一的Domino平台应用与构异系统实现单点登录。


3.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)

3.2 异构系统所需信息

  • Domino 所使用的DNS域,如:vgolive.com
  • 过期时间(分钟),如:30
  • Domino LTPA 密钥
  • Domino验证字名称,如:/O=VGOLive Technology
注:用户名可以通过Domino验证字进行拼接,如异构系统中用户名为SquallZhong,相应在Domino中的DN就是CN=SquallZhong/O=VGOLive Technology。此类情况仅限于Domino中的CN与异构系统中的用户名一致。如果不一致,需要异构系统做用户对应

3.3 实现

Base64解码/编码所需Jar包:apache-commons-codec-1.3.jar以上

SHA-1的校验使用java.security.MessageDigest
转换字符集使用:Cp850

3.3.1 解析

 
01    import org.apache.commons.codec.binary.Base64;
02…...
03final String CHARSET = "Cp850";
04byte[] dominoSecret = Base64.decodeBase64(ltpaDominoSecret.getBytes());
05byte[] ltpa = Base64.decodeBase64(ltpaToken.getBytes());
06ByteArrayInputStream stream = new ByteArrayInputStream(ltpa);
07int usernameLength = ltpa.length – 40;
08byte header[] = new byte[4];
09byte creation[] = new byte[8];
10byte expires[] = new byte[8];
11byte username[] = new byte[usernameLength];
12byte[] sha = new byte[20];
13// 读取LTPAToken版本号
14stream.read(header, 0, 4);
15if (header[0] != 0 || header[1] != 1 || header[2] != 2|| header[3] != 3)
16        throw new IllegalArgumentException("Invalid ltpaToken format");
17    // 读取开始时间
18   stream.read(creation, 0, 8);
19   // 读取到期时间
20   stream.read(expires, 0, 8);
21   // 读取Domino用户DN
22   stream.read(username, 0, usernameLength);
23   // 读取SHA校验和
24   stream.read(sha, 0, 20);
25    // 转换用户名
26   char characters[] = new char[usernameLength];
27   try {
28        InputStreamReader isr = new InputStreamReader(
29            new ByteArrayInputStream(username),
30            CHARSET);
31        isr.read(characters);
32    } catch (Exception e) {
33    }
34    // 获得Domino用户DN
35    String dn = new String(characters);
36    // 获得创建时间
37   Date creationDate = new Date(
38        Long.parseLong(new String(creation), 16) * 1000);
39    // 获得到期时间
40   Date expiresDate = new Date(
41        Long.parseLong(new String(expires), 16) * 1000);
42…...
43// 创建LTPA Token
44    ByteArrayOutputStream ostream = new ByteArrayOutputStream();
45    try {
46        // LTPA Token版本号
47        ostream.write(header);
48        // 创建时间
49        ostream.write(creation);
50        // 过期时间
51        ostream.write(expires);
52        // Domino用户DN,如CN=SquallZhong/O=DigiWin
53        ostream.write(username);
54        // Domino LTPA 密钥
55        ostream.write(dominoSecret);
56        ostream.close();
57    } catch (IOException e) {
58        throw new RuntimeException(e);
59    }
60    // 进行 SHA-1 校验和
61    MessageDigest md;
62    try {
63        md = MessageDigest.getInstance("SHA-1");
64        md.reset();
65    } catch (NoSuchAlgorithmException e) {
66        throw new RuntimeException(e);
67    }
68    byte[] digest = md.digest(ostream.toByteArray());
69    // 完成 SHA-1 校验和,digest长度为20
70    boolean valid = MessageDigest.isEqual(digest, sha);

3.3.2 生成

 
01    /**
02     * 为指定用户创建有效的LTPA Token.创建时间为<tt>now</tt>.
03     *
04     * @param username
05     *            - 用户名,注:使用用户全称,如:CN=SquallZhong/O=VGOLive Technology
06     * @param creationTime
07     *            - 创建时间
08     * @param durationMinutes
09     *            - 到期时间,单位:分钟
10@param ltpaSecretStr
11     *            - Domino Ltpa 加密字符串
12     * @return - 返回已Base64编码的Ltpa Cookie.
13     * @throws NoSuchAlgorithmException
14     * @throws Base64DecodeException
15     */
16    public static String createLtpaToken(String username,
17            GregorianCalendar creationTime, int durationMinutes,
18            String ltpaSecretStr) throws NoSuchAlgorithmException {
19        // Base64解码ltpaSecretStr
20        byte[] ltpaSecret = Base64.decodeBase64(ltpaSecretStr.getBytes());
21        // 用户名字节数组
22        byte[] usernameArray = username.getBytes();
23        byte[] workingBuffer = new byte[preUserDataLength
24                + usernameArray.length + ltpaSecret.length];
25 
26        // 设置ltpaToken版本至workingBuffer
27        System.arraycopy(ltpaTokenVersion, 0, workingBuffer, 0,
28                ltpaTokenVersion.length);
29        // 获得过期时间,过期时间=当前时间+到期时间(分钟)
30        GregorianCalendar expirationDate = (GregorianCalendar) creationTime
31                .clone();
32        expirationDate.add(Calendar.MINUTE, durationMinutes);
33 
34        // 转换创建时间至16进制字符串
35        String hex = dateStringFiller
36                + Integer.toHexString(
37                        (int) (creationTime.getTimeInMillis() / 1000))
38                        .toUpperCase();
39        // 设置创建时间至workingBuffer
40        System.arraycopy(hex.getBytes(), hex.getBytes().length
41                - dateStringLength, workingBuffer, creationDatePosition,
42                dateStringLength);
43 
44        // 转换过期时间至16进制字符串
45        hex = dateStringFiller
46                + Integer.toHexString(
47                        (int) (expirationDate.getTimeInMillis() / 1000))
48                        .toUpperCase();
49        // 设置过期时间至workingBuffer
50        System.arraycopy(hex.getBytes(), hex.getBytes().length
51                - dateStringLength, workingBuffer, expirationDatePosition,
52                dateStringLength);
53 
54        // 设置用户全称至workingBuffer
55        System.arraycopy(usernameArray, 0, workingBuffer, preUserDataLength,
56                usernameArray.length);
57 
58        // 设置已Base64解码ltpaSecret至workingBuffer
59        System.arraycopy(ltpaSecret, 0, workingBuffer, preUserDataLength
60                + usernameArray.length, ltpaSecret.length);
61        // 创建Hash字符串
62        byte[] hash = createHash(workingBuffer);
63 
64        // ltpaToken版本+开始时间(16进制)+到期时间(16进制)+用户全名+SHA-1(ltpaToken版本+开始时间(16进制)+到期时间(16进制)+用户全名)
65        byte[] outputBuffer = new byte[preUserDataLength + usernameArray.length
66                + hashLength];
67        System.arraycopy(workingBuffer, 0, outputBuffer, 0, preUserDataLength
68                + usernameArray.length);
69        System.arraycopy(hash, 0, outputBuffer, preUserDataLength
70                + usernameArray.length, hashLength);
71        // 返回已Base64编码的outputBuffer
72        return new String(Base64.encodeBase64(outputBuffer));
73    }
74…...

4. 通过F5 BIG-IP创建Domino LTPAToken

F5 iRule代码如下:

when RULE_INIT {

 
01set cookie_name "LtpaToken"           # 不更改
02 set ltpa_version "\x00\x01\x02\x03"   # 不更改
03 set ltpa_secret "b64encodedsecretkey" # 从Domino SSO文档获得ltpa密钥
04 set ltpa_timeout "1800"               # 从Domino SSO文档中获得过期时间,单位:秒
05}
06 
07when HTTP_REQUEST {
08 #
09 # Do your usual F5 HTTP authentication here
10 #
11 # Initial values
12 set creation_time_temp [clock seconds]
13 set creation_time [format %X $creation_time_temp]
14 set expr_time_temp [expr { $creation_time_temp + $::ltpa_timeout}]
15 set expr_time [format %X $expr_time_temp]
16 set username [HTTP::username]
17 set ltpa_secret_decode [b64decode $::ltpa_secret]
18 # First part of token
19 set cookie_data_raw {}
20 append cookie_data_raw $::ltpa_version
21 append cookie_data_raw $creation_time
22 append cookie_data_raw $expr_time
23 append cookie_data_raw $username
24 append cookie_data_raw $ltpa_secret_decode
25 # SHA1 of first part of token
26 set sha_cookie_raw [sha1 $cookie_data_raw]
27 # Final not yet encoded token
28 set ltpa_token_raw {}
29 append ltpa_token_raw $::ltpa_version
30 append ltpa_token_raw $creation_time
31 append ltpa_token_raw $expr_time
32 append ltpa_token_raw $username
33 append ltpa_token_raw $sha_cookie_raw
34 # Final Base64 encoded token
35 set ltpa_token_final [b64encode $ltpa_token_raw]
36 # Insert the cookie
37 HTTP::cookie insert name $::cookie_name value $ltpa_token_final
38 }
39 # Remove Authorization HTTP header to avoid using basic authentication
40 if { [HTTP::header exists "Authorization"] } {
41 HTTP::header remove "Authorization"
42 }
43}

 

 

 

来源连接http://www.cnblogs.com/hannover/archive/2011/05/29/2061798.html

分享到:
评论

相关推荐

    LTPA245热敏打印机STC89C58单片机驱动程序C源码.zip

    LTPA245热敏打印机STC89C58单片机驱动程序C源码,可以做为你的学习设计参考。 LOCAL void Do_PrintNRealCurve( void ) { byte tmp[CURVE_MAX_ID],i; #if MACHINE_NO == TR50B byte offset[CURVE_MAX_ID]; byte *...

    Domino服务器SSO原理

    5. **Domino读取LTPA Token**:Domino从Cookie中读取LTPA Token,并验证其有效性。 6. **完成Domino登录**:若LTPA Token有效,Domino则允许用户无需重新输入凭证即可登录。 ##### 2.2 实现SSO的关键要素 - **LTPA...

    Domino单点登录LTPAtoken生成原理

    - **LTPA_TokenName**:指定存储在Cookie中的LtpaToken的名称。 通过查看Domino的WebSSO配置文档,我们可以了解到上述配置的具体设置情况。 ##### 2. Domino解析LtpaToken的过程 Domino解析LtpaToken的过程大致...

    sso的原理与java实现

    5. **会话管理**:确保在用户访问不同SP时能共享会话状态,例如使用cookie或者JWT令牌来传递用户信息。 6. **异常处理**:处理各种可能的异常情况,如票据无效、用户未登录等。 ### 总结 SSO的核心在于通过中央...

    WAS6.1+LTAP单点登陆配置

    在WebSphere Application Server (WAS) 6.1版本中,可以利用 Lightweight Third-Party Authentication (LTPA) 令牌来实现SSO。下面将详细介绍如何配置WAS 6.1与LTAP进行单点登录。 **1. LTPA 协议设置** LTPA是一种...

    Portal培訓教材之第7章_常见SSO原理及其实现_FromIBM(7)

    5. **Cookie-Based认证** 这种方式通常用于Sun Portal(AM)或Oracle Portal与其他应用之间的SSO。要求用户的UID必须一致。 #### LTPA配置详解 LTPA是一种广泛使用的SSO技术,主要应用于IBM的产品系列中。下面是...

    单点登录技术

    LTPA的工作原理是通过在多个服务器间建立信任关系,一旦用户在一个服务器上成功认证,其LTPA Token可以在其他信任服务器间传递,无需再次认证。 - 配置过程: - 在WAS上生成LTPA密钥,并启用LTPA认证。 - 在...

    SSO.rar_domino_sso

    LTPA是一种加密的令牌,当用户在J2EE应用服务器上成功登录后,服务器会生成一个LTPA token,并将其存储在用户的浏览器cookie中。当用户访问Domino服务器时,Domino会检查该cookie中的LTPA token,如果验证通过,用户...

    ltpalibrary

    LTPA令牌的工作原理如下:当用户成功登录到一个系统(例如,Windows域环境)后,系统会生成一个LTPA令牌,并将其发送给客户端(通常是浏览器)。这个令牌包含了用户的认证信息,且被加密。当用户访问其他信任该令牌...

    TAMeb单点登录的几种方式

    LTPA(Lightweight Third Party Authentication)是一种基于cookie的轻量级认证机制,特别适用于IBM的各种中间件环境。LTPA利用共享密钥加密cookie中的用户凭证,确保在信任域内的不同系统间传递用户身份信息时的...

    金蝶EAS portal单点登录到SHR文档

    LTPA Token 加密和校验接口是指实现LTPA Token加密和校验的接口。 3.1.3 第三方应用集成 s-HR(即:在第三方应用中打开 s-HR)的实现步骤 第三方应用集成 s-HR 是指在第三方应用中打开 s-HR。该步骤需要实现LTPA ...

    portal ,tam 单点登录说明文档

    - 支持LTPA的系统应首选LTPA。 - 若不支持LTPA,考虑使用Http Header方法。 - 对于既不支持LTPA又无法修改的系统,建议采用表单基础的单点方式。 2. **仅实施Portal的情况**: - Domino单点登录必须使用LTPA,...

    为 WebSphere Application Server 配置 SSO

    **一、SSO的工作原理** SSO的核心是共享一个中央认证服务(Central Authentication Service,CAS)。当用户首次访问受保护的应用时,会被重定向到CAS进行身份验证。一旦验证成功,CAS将生成一个票证(Ticket),该...

    其他系统与domino系统单点登录的实现方式.docx

    - **LTPAToken简介**:LTPA(Lightweight Third Party Authentication)是一种轻量级第三方认证协议,它允许应用程序之间共享用户的身份信息。在本方案中,通过生成LTPAToken来实现在Domino系统与其他系统之间的单...

    TAMSSO阶段总结[汇编].pdf

    总结,IBM Tivoli Access Manager通过WebSEAL、Policy Server和存储系统的协作,构建了一个强大的安全访问框架,其中LTPA和GSO提供了灵活且安全的单点登录解决方案,优化了用户体验,同时增强了企业的信息安全防护...

    ( SSO解决方案

    SSO解决方案--提醒:文档只是作为一个基础的参考,愿意了解的朋友可以随时咨询。 第一节:单点登录简介 第一步:了解单点登录 SSO主要特点是: SSO应用之间... SSO的体系中有下面三种角色: ...SSO实现包含以下三个原则:

    IBM portal与Domino单点配置

    7. **自定义SSO服务**:对于特定的需求,可能需要编写自己的SSO服务,这需要深入理解SSO的工作原理和编程接口。 8. **技术讨论**:"WebSphere Portal 和 Lotus Domino之间单点登录的技术讨论.doc"可能包含了对不同...

    移动基站动力环境监测系统

    本文将深入探讨该系统的组成部分、工作原理、源代码的应用及开发过程。 一、系统组成 移动基站动力环境监测系统通常由以下几个部分构成: 1. 传感器:负责采集基站内的动力和环境参数,如电流、电压、温度、湿度等...

Global site tag (gtag.js) - Google Analytics