如何使用LTPA令牌中的信息

时间:2009-10-22 14:29:58

标签: java websphere single-sign-on webseal ltpa

考虑以下设置:

  • 部署在Websphere Application Server上的Web应用程序(如果重要,则为6.1)
  • 将通过webseal反向代理
  • 访问该应用
  • webseal负责身份验证并传递LTPA令牌作为有效身份验证的标志

如果我做对了,LTPA令牌包含用户名,角色等信息。

问题:如何从我的Java Web应用程序中的LTPA令牌访问此信息?

2 个答案:

答案 0 :(得分:10)

查看LTPA令牌非常适合调试,我们使用这个很多。您需要使用ltpa-key和密码才能使用

/* Copyright notice
# Copyright (C) 2007, Cosmin Stejerean (http://www.offbytwo.com)
#
# You are free to use this code under the terms of the Creative Commons Attribution license
# available at http://creativecommons.org/licenses/by/3.0/
# so long as you include the following notice 'includes code from Cosmin Stejerean (http://www.offbytwo.com)'
*/

import java.security.Key;
import java.security.MessageDigest;
import java.security.spec.KeySpec;
import java.sql.Date;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.StringTokenizer;

import javax.crypto.Cipher;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;

import sun.misc.BASE64Decoder;


//The shared 3DES key is itself encrypted using the SHA hash value of the LTPA password (padded with 0x0 upto 24 bytes).

public class LtpaDecoder
{
    private String ltpa3DESKey = "JvJRzwdhKk6o40FuATa9acKD2uaXswVHlUsn2c2+MKQ=";
    private String ltpaPassword = "secretpassword";

    private String sUserInfo = "";
    private Date dExpiry;
    private String sFullToken = ""; 
    private String sSignature = "";

    public static void main(String[] args)
    {
          String tokenCipher = "vsof5exb990sb2r5hRJ+bneCnmBTuLQ3XF+......";

          try {
            LtpaDecoder t = new LtpaDecoder(tokenCipher);
            System.out.println("UserInfo: " + t.getUserInfo());
            System.out.println("Expiry: " + t.getExpiryDate());
            System.out.println("Full token: " + t.getFullToken());
        }
        catch(Exception e) {
            e.printStackTrace();
        }
    }

    public LtpaDecoder(String fulltoken) throws Exception {
        byte[] secretKey = getSecretKey(this.ltpa3DESKey, this.ltpaPassword);
        String ltpaPlaintext = new String(decryptLtpaToken(fulltoken, secretKey));

        extractTokenData(ltpaPlaintext);
    }

    private void extractTokenData(String token)
    {
        System.out.println("\n");
        StringTokenizer st = new StringTokenizer(token, "%");

        sUserInfo = st.nextToken();
        String sExpires = st.nextToken();
        sSignature = st.nextToken();
        dExpiry = new Date(Long.parseLong(sExpires));
        sFullToken = token;
    }

    public String getSignature() {
        return sSignature;
    }

    public String getFullToken() {
        return sFullToken;
    }

    public String getUserInfo() {
        return sUserInfo;
    }

    public String getExpiryDate() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z");
        return sdf.format(dExpiry);
    }

    private byte[] getSecretKey(String shared3DES, String password) throws Exception
    {
        MessageDigest md = MessageDigest.getInstance("SHA");
        md.update(password.getBytes());
        byte[] hash3DES = new byte[24];
        System.arraycopy(md.digest(), 0, hash3DES, 0, 20);
        Arrays.fill(hash3DES, 20, 24, (byte) 0);
        // decrypt the real key and return it
        BASE64Decoder base64decoder = new BASE64Decoder();
        return decrypt(base64decoder.decodeBuffer(shared3DES), hash3DES);
    }

    public byte[] decryptLtpaToken(String encryptedLtpaToken, byte[] key) throws Exception 
    {
        BASE64Decoder base64decoder = new BASE64Decoder();
        final byte[] ltpaByteArray = base64decoder.decodeBuffer(encryptedLtpaToken);
        return decrypt(ltpaByteArray, key);
    }

    public byte[] decrypt(byte[] ciphertext, byte[] key) throws Exception {
        final Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");
        final KeySpec keySpec = new DESedeKeySpec(key);
        final Key secretKey = SecretKeyFactory.getInstance("TripleDES").generateSecret(keySpec);

        cipher.init(Cipher.DECRYPT_MODE, secretKey);
        return cipher.doFinal(ciphertext);
    }
}

答案 1 :(得分:9)

您不直接访问LTPA令牌,而是假设WebSphere已根据其身份验证过程为您建立了安全上下文。

然后您可以使用

getUserPrincipal()

在您的HttpServletRequest对象上访问用户的身份。

角色特定于当前资源(serlvet,ejb ...),因此您使用HttpServletRequest方法

isUserInRole()

确定用户是否在角色中。

您也可以使用方法

 public static javax.security.auth.Subject getCallerSubject()

获取更多安全信息,包括组成员身份。