日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java ltpa_LTPA Cookie原理

發(fā)布時(shí)間:2025/4/16 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java ltpa_LTPA Cookie原理 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

1. 什么是LTPA?

Lightweight Third-Party Authentication (LTPA)是IBM Websphere和Domino產(chǎn)品中使用單點(diǎn)登錄技術(shù)。當(dāng)服務(wù)器配置好LTPA認(rèn)證方式,用戶通過瀏覽器成功登錄后,服務(wù)器會(huì)自動(dòng)發(fā)送一個(gè)session cookie給瀏覽器;此cookie中包含一個(gè)LTPA Token。

2. WebSphere部分

本部分描述適用于已實(shí)施WebSphere系列產(chǎn)品應(yīng)用和Domino平臺(tái)應(yīng)用,或WebSphere與Domino之間已完成單點(diǎn)登錄。在這樣的環(huán)境中與構(gòu)異系統(tǒng)實(shí)現(xiàn)單點(diǎn)登錄。

一個(gè)通過有效的LTPA Cookie能夠在同一個(gè)認(rèn)證域中所有服務(wù)器被自動(dòng)認(rèn)證。此Cookie中包含認(rèn)證信息和時(shí)間戳。這些信息通過共享的3DES Key進(jìn)行了bis 加密。使用公共密鑰/私有密鑰進(jìn)行簽名。

LTPA Cookie通過3DES密鑰使用DESede/ECB/PKCS5P進(jìn)行加密。此密鑰也是采用DESede/ECB/PKCS5P進(jìn)行加密,加密后再使用提供的密碼再進(jìn)行SHA Hash,生成24個(gè)字節(jié)的密鑰,再進(jìn)行Base64編碼。

如果你要解析LTPA Token,先得使用Key的密碼,生成3DES密鑰;再使用3DES密鑰解密Token Cookie。也可以使用公共/私有密鑰來簽名或驗(yàn)證LTPA Cookie。

2.1 WebSphere LTPA 生成原理

首先,這個(gè) cookie 由以下部分組成,以%進(jìn)行分隔:

用戶信息,格式為u:user\:/,如:u:user\:VGOLiveRealm/CN=squallzhong,O=VGOLive Technology

過期時(shí)間

簽名信息,如:

u:user\:VGOLiveRealm/CN=squallzhong,O=VGOLive Technology%1301558320666%Cy2CAeru5kEElGj0hrvYsKW2ZVsvvcu6Un573aeX55OO4G3EMYWc0e/ZbqDp1z7MS+dLzniuUH4sYWCMpnKdm7ZGabwmV+WcraBl+y+yzwcl722gHVMOnDZAW7U3jEay9Tk2yG4yXkMWU+617xndpVxke2jtS5wIyVVM3q7UDPw=

2.2 異構(gòu)系統(tǒng)所需信息

從WebSphere系統(tǒng)中導(dǎo)出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

過期時(shí)間(分鐘),如:30

LTPA 3DESKey 密鑰及密鑰的保護(hù)密碼

Base DN,如:O=VGOLive Technology或DC=vgolive,DC=com

注:

在3DESKey中的反斜杠只是為了在JAVA中可解釋等于號(hào),所以正確的3DESKey為7dH4i81YepbVe+gF9XVUzE4C1Ca5g6A4Q69OFobJV9g=

用戶名可以通過Base Dn驗(yàn)證字進(jìn)行拼接,如異構(gòu)系統(tǒng)中用戶名為SquallZhong,相應(yīng)在Domino中的DN就是CN=SquallZhong,O=DigiWin。此類情況僅限于LDAP中的CN與異構(gòu)系統(tǒng)中的用戶名一致。如果不一致,需要異構(gòu)系統(tǒng)做用戶對(duì)應(yīng)

2.3 實(shí)現(xiàn)

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

SHA-1的校驗(yàn)使用java.security.MessageDigest類

2.3.1 解析

以下代碼為解析從WebSphere或Domino發(fā)送過來的LTPAToken Cookie以Java為例:

01…

02// LTPA 3DES 密鑰

03String ltpa3DESKey ="7dH4i81YepbVe+gF9XVUzE4C1Ca5g6A4Q69OFobJV9g=";

04// LTPA 密鑰密碼

05String ltpaPassword ="Passw0rd";

06try {

07// 獲得加密key

08byte[] secretKey = getSecretKey(ltpa3DESKey, ltpaPassword);

09// 使用加密key解密ltpa Cookie

10String ltpaPlaintext =new String(decryptLtpaToken(tokenCipher,

11secretKey));

12displayTokenData(ltpaPlaintext);

13}catch (Exception e) {

14System.out.println("Caught inner: " + e);

15}

16…

17//獲得安全Key

18private static byte[] getSecretKey(String ltpa3DESKey, String password)

19throws Exception {

20// 使用SHA獲得key密碼的hash值

21MessageDigest md = MessageDigest.getInstance("SHA");

22md.update(password.getBytes());

23byte[] hash3DES =new byte[24];

24System.arraycopy(md.digest(),0, hash3DES,0,20);

25// 使用0替換后4個(gè)字節(jié)

26Arrays.fill(hash3DES,20,24, (byte)0);

27// BASE64解碼 ltpa3DESKey

28byte[] decode3DES = Base64.decodeBase64(ltpa3DESKey.getBytes());

29// 使用key密碼hash值解密已Base64解碼的ltpa3DESKey

30return decrypt(decode3DES, hash3DES);

31}

32//解密LtpaToken

33public static byte[] decryptLtpaToken(String encryptedLtpaToken,byte[] key)

34throws Exception {

35// Base64解碼LTPAToken

36final byte[] ltpaByteArray = Base64.decodeBase64(encryptedLtpaToken

37.getBytes());

38// 使用key解密已Base64解碼的LTPAToken

39return decrypt(ltpaByteArray, key);

40}

41// DESede/ECB/PKC5Padding解方法

42public static byte[] decrypt(byte[] ciphertext,byte[] key)

43throws Exception {

44final Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");

45final KeySpec keySpec =new DESedeKeySpec(key);

46final Key secretKey = SecretKeyFactory.getInstance("TripleDES")

47.generateSecret(keySpec);

48cipher.init(Cipher.DECRYPT_MODE, secretKey);

49return cipher.doFinal(ciphertext);

50}

51…

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

2.3.2 生成

Websphere LTPA生成時(shí)的簽名信息是由用戶DN和一些用戶其他信息組成字符串,使用私有密鑰進(jìn)行簽名,由于不清楚這些信息的組成,故無法產(chǎn)生正確的LTPA。

3. Domino部分

本部分的描述僅適用于單一的Domino平臺(tái)應(yīng)用與構(gòu)異系統(tǒng)實(shí)現(xiàn)單點(diǎn)登錄。

3.1 Domino LTPA Cookie 生成原理

在與 Domino 做 SSO 的時(shí)候,會(huì)使用 LTPA Token的認(rèn)證方式,本文描述它的生成原理,通過它我們可以自己編碼生成身份認(rèn)證的 cookie,實(shí)現(xiàn) SSO。

首先,這個(gè) cookie 由以下部分組成:

LTPA token 版本(4字節(jié))

創(chuàng)建時(shí)間(8字節(jié))

過期時(shí)間(8字節(jié))

用戶名(可變長度)

Domino LTPA 密鑰(20字節(jié))

接下來分別說明各部分的具體內(nèi)容:

LTPA token 版本目前 Domino 只有一種值:0x0001

創(chuàng)建時(shí)間為以十六進(jìn)制方式表示的Unix time,例如:2009-04-09 13:52:42 (GMT +8) = 1239256362 = 49DD8D2A。

過期時(shí)間=創(chuàng)建時(shí)間 + SSO 配置文檔的過期時(shí)間(LTPA_TokenExpiration域)

用戶名為 Names 中用戶文檔的FullName域值;如:Squall Zhong/Digiwin

Domino LTPA 密鑰通過 Base64編碼后,保存在 SSO 配置文檔的LTPA_DominoSecret域中

當(dāng)然不能將密鑰直接發(fā)送給瀏覽器,所以將上述部分合并起來(如上圖),計(jì)算 SHA-1 校驗(yàn)和。

然后用 SHA-1 校驗(yàn)和替換掉 Domino LTPA 密鑰,最后再將內(nèi)容通過 Base64 編碼,形成最終的 cookie 發(fā)送給瀏覽器(如上圖)。這樣如果 cookie 中的任何內(nèi)容被修改,校驗(yàn)和就不對(duì)了,達(dá)到了防篡改的效果。所以最終LTPA Cookie所得到的值為以下公式組成:

SHA-1=LTPA版本號(hào)+創(chuàng)建時(shí)間+過期時(shí)間+用戶名+Domino LTPA 密鑰

LTPA Cookie= Base64(LTPA版本號(hào)+創(chuàng)建時(shí)間+過期時(shí)間+用戶名+SHA-1)

3.2 異構(gòu)系統(tǒng)所需信息

Domino 所使用的DNS域,如:vgolive.com

過期時(shí)間(分鐘),如:30

Domino LTPA 密鑰

Domino驗(yàn)證字名稱,如:/O=VGOLive Technology

注:用戶名可以通過Domino驗(yàn)證字進(jìn)行拼接,如異構(gòu)系統(tǒng)中用戶名為SquallZhong,相應(yīng)在Domino中的DN就是CN=SquallZhong/O=VGOLive Technology。此類情況僅限于Domino中的CN與異構(gòu)系統(tǒng)中的用戶名一致。如果不一致,需要異構(gòu)系統(tǒng)做用戶對(duì)應(yīng)

3.3 實(shí)現(xiàn)

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

SHA-1的校驗(yàn)使用java.security.MessageDigest類

轉(zhuǎn)換字符集使用:Cp850

3.3.1 解析

01import 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版本號(hào)

14stream.read(header,0,4);

15if (header[0] !=0 || header[1] !=1 || header[2] !=2|| header[3] !=3)

16throw new IllegalArgumentException("Invalid ltpaToken format");

17// 讀取開始時(shí)間

18stream.read(creation,0,8);

19// 讀取到期時(shí)間

20stream.read(expires,0,8);

21// 讀取Domino用戶DN

22stream.read(username,0, usernameLength);

23// 讀取SHA校驗(yàn)和

24stream.read(sha,0,20);

25// 轉(zhuǎn)換用戶名

26char characters[] =new char[usernameLength];

27try {

28InputStreamReader isr =new InputStreamReader(

29new ByteArrayInputStream(username),

30CHARSET);

31isr.read(characters);

32}catch (Exception e) {

33}

34// 獲得Domino用戶DN

35String dn =new String(characters);

36// 獲得創(chuàng)建時(shí)間

37Date creationDate =new Date(

38Long.parseLong(new String(creation),16) *1000);

39// 獲得到期時(shí)間

40Date expiresDate =new Date(

41Long.parseLong(new String(expires),16) *1000);

42…...

43// 創(chuàng)建LTPA Token

44ByteArrayOutputStream ostream =new ByteArrayOutputStream();

45try {

46// LTPA Token版本號(hào)

47ostream.write(header);

48// 創(chuàng)建時(shí)間

49ostream.write(creation);

50// 過期時(shí)間

51ostream.write(expires);

52// Domino用戶DN,如CN=SquallZhong/O=DigiWin

53ostream.write(username);

54// Domino LTPA 密鑰

55ostream.write(dominoSecret);

56ostream.close();

57}catch (IOException e) {

58throw new RuntimeException(e);

59}

60// 進(jìn)行 SHA-1 校驗(yàn)和

61MessageDigest md;

62try {

63md = MessageDigest.getInstance("SHA-1");

64md.reset();

65}catch (NoSuchAlgorithmException e) {

66throw new RuntimeException(e);

67}

68byte[] digest = md.digest(ostream.toByteArray());

69// 完成 SHA-1 校驗(yàn)和,digest長度為20

70boolean valid = MessageDigest.isEqual(digest, sha);

3.3.2 生成

01/**

02* 為指定用戶創(chuàng)建有效的LTPA Token.創(chuàng)建時(shí)間為now.

03*

04* @param username

05*????????????- 用戶名,注:使用用戶全稱,如:CN=SquallZhong/O=VGOLive Technology

06* @param creationTime

07*????????????- 創(chuàng)建時(shí)間

08* @param durationMinutes

09*????????????- 到期時(shí)間,單位:分鐘

10@param ltpaSecretStr

11*????????????- Domino Ltpa 加密字符串

12* @return - 返回已Base64編碼的Ltpa Cookie.

13* @throws NoSuchAlgorithmException

14* @throws Base64DecodeException

15*/

16public static String createLtpaToken(String username,

17GregorianCalendar creationTime,int durationMinutes,

18String ltpaSecretStr)throws NoSuchAlgorithmException {

19// Base64解碼ltpaSecretStr

20byte[] ltpaSecret = Base64.decodeBase64(ltpaSecretStr.getBytes());

21// 用戶名字節(jié)數(shù)組

22byte[] usernameArray = username.getBytes();

23byte[] workingBuffer =new byte[preUserDataLength

24+ usernameArray.length + ltpaSecret.length];

25

26// 設(shè)置ltpaToken版本至workingBuffer

27System.arraycopy(ltpaTokenVersion,0, workingBuffer,0,

28ltpaTokenVersion.length);

29// 獲得過期時(shí)間,過期時(shí)間=當(dāng)前時(shí)間+到期時(shí)間(分鐘)

30GregorianCalendar expirationDate = (GregorianCalendar) creationTime

31.clone();

32expirationDate.add(Calendar.MINUTE, durationMinutes);

33

34// 轉(zhuǎn)換創(chuàng)建時(shí)間至16進(jìn)制字符串

35String hex = dateStringFiller

36+ Integer.toHexString(

37(int) (creationTime.getTimeInMillis() /1000))

38.toUpperCase();

39// 設(shè)置創(chuàng)建時(shí)間至workingBuffer

40System.arraycopy(hex.getBytes(), hex.getBytes().length

41- dateStringLength, workingBuffer, creationDatePosition,

42dateStringLength);

43

44// 轉(zhuǎn)換過期時(shí)間至16進(jìn)制字符串

45hex = dateStringFiller

46+ Integer.toHexString(

47(int) (expirationDate.getTimeInMillis() /1000))

48.toUpperCase();

49// 設(shè)置過期時(shí)間至workingBuffer

50System.arraycopy(hex.getBytes(), hex.getBytes().length

51- dateStringLength, workingBuffer, expirationDatePosition,

52dateStringLength);

53

54// 設(shè)置用戶全稱至workingBuffer

55System.arraycopy(usernameArray,0, workingBuffer, preUserDataLength,

56usernameArray.length);

57

58// 設(shè)置已Base64解碼ltpaSecret至workingBuffer

59System.arraycopy(ltpaSecret,0, workingBuffer, preUserDataLength

60+ usernameArray.length, ltpaSecret.length);

61// 創(chuàng)建Hash字符串

62byte[] hash = createHash(workingBuffer);

63

64// ltpaToken版本+開始時(shí)間(16進(jìn)制)+到期時(shí)間(16進(jìn)制)+用戶全名+SHA-1(ltpaToken版本+開始時(shí)間(16進(jìn)制)+到期時(shí)間(16進(jìn)制)+用戶全名)

65byte[] outputBuffer =new byte[preUserDataLength + usernameArray.length

66+ hashLength];

67System.arraycopy(workingBuffer,0, outputBuffer,0, preUserDataLength

68+ usernameArray.length);

69System.arraycopy(hash,0, outputBuffer, preUserDataLength

70+ usernameArray.length, hashLength);

71// 返回已Base64編碼的outputBuffer

72return new String(Base64.encodeBase64(outputBuffer));

73}

74…...

4.?通過F5 BIG-IP創(chuàng)建Domino LTPAToken

F5 iRule代碼如下:

when RULE_INIT {

01set cookie_name"LtpaToken"?????????? # 不更改

02set ltpa_version"\x00\x01\x02\x03"?? # 不更改

03set ltpa_secret"b64encodedsecretkey" # 從Domino SSO文檔獲得ltpa密鑰

04set ltpa_timeout"1800"?????????????? # 從Domino SSO文檔中獲得過期時(shí)間,單位:秒

05}

06

07when HTTP_REQUEST {

08#

09# Do your usual F5 HTTP authentication here

10#

11# Initial values

12set creation_time_temp [clock seconds]

13set creation_time [format %X $creation_time_temp]

14set expr_time_temp [expr { $creation_time_temp+ $::ltpa_timeout}]

15set expr_time [format %X $expr_time_temp]

16set username [HTTP::username]

17set ltpa_secret_decode [b64decode $::ltpa_secret]

18# First part of token

19set cookie_data_raw {}

20append cookie_data_raw $::ltpa_version

21append cookie_data_raw $creation_time

22append cookie_data_raw $expr_time

23append cookie_data_raw $username

24append cookie_data_raw $ltpa_secret_decode

25# SHA1 of first part of token

26set sha_cookie_raw [sha1 $cookie_data_raw]

27# Final not yet encoded token

28set ltpa_token_raw {}

29append ltpa_token_raw $::ltpa_version

30append ltpa_token_raw $creation_time

31append ltpa_token_raw $expr_time

32append ltpa_token_raw $username

33append ltpa_token_raw $sha_cookie_raw

34# Final Base64 encoded token

35set ltpa_token_final [b64encode $ltpa_token_raw]

36# Insert the cookie

37HTTP::cookie insert name $::cookie_name value $ltpa_token_final

38}

39# Remove Authorization HTTP header to avoid using basic authentication

40if { [HTTP::header exists"Authorization"] } {

41HTTP::header remove"Authorization"

42}

43}

相關(guān)鏈接:

總結(jié)

以上是生活随笔為你收集整理的java ltpa_LTPA Cookie原理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。