5

考虑以下设置:

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

如果我没记错的话,LTPA 令牌包含用户名、角色等信息。

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

4

2 回答 2

10

查看 LTPA 令牌内部非常适合调试,我们经常使用它。您需要 ltpa-key 和密码才能正常工作

/* 版权声明
# 版权所有 (C) 2007,Cosmin Stejerean (http://www.offbytwo.com)
#
# 您可以根据知识共享署名许可的条款自由使用此代码
# 可在 http://creativecommons.org/licenses/by/3.0/ 获得
# 只要您包含以下通知“包括来自 Cosmin Stejerean (http://www.offbytwo.com) 的代码”
*/

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

导入 javax.crypto.Cipher;
导入 javax.crypto.SecretKeyFactory;
导入 javax.crypto.spec.DESedeKeySpec;

导入 sun.misc.BASE64Decoder;


//共享的 3DES 密钥本身是使用 LTPA 密码的 SHA 哈希值加密的(用 0x0 填充,最多 24 个字节)。

公共类 LtpaDecoder
{
    私有字符串 ltpa3DESKey = "JvJRzwdhKk6o40FuATa9acKD2uaXswVHlUsn2c2+MKQ=";
    私人字符串 ltpaPassword = "秘密密码";

    私人字符串 sUserInfo = "";
    私人日期到期;
    私有字符串 sFullToken = "";
    私人字符串 sSignature = "";

    公共静态无效主要(字符串 [] 参数)
    {
          字符串 tokenCipher = "vsof5exb990sb2r5hRJ+bneCnmBTuLQ3XF+......";

          尝试 {
            LtpaDecoder t = new LtpaDecoder(tokenCipher);
            System.out.println("用户信息:" + t.getUserInfo());
            System.out.println("有效期:" + t.getExpiryDate());
            System.out.println("完整令牌:" + t.getFullToken());
        }
        捕获(异常 e){
            e.printStackTrace();
        }
    }

    公共 LtpaDecoder(String fulltoken) 抛出异常 {
        byte[] secretKey = getSecretKey(this.ltpa3DESKey, this.ltpaPassword);
        String ltpaPlaintext = new String(decryptLtpaToken(fulltoken, secretKey));

        extractTokenData(ltpaPlaintext);
    }

    私人无效extractTokenData(字符串令牌)
    {
        System.out.println("\n");
        StringTokenizer st = new StringTokenizer(token, "%");

        sUserInfo = st.nextToken();
        字符串 sExpires = st.nextToken();
        sSignature = st.nextToken();
        dExpiry = new Date(Long.parseLong(sExpires));
        sFullToken = 令牌;
    }

    公共字符串 getSignature() {
        返回签名;
    }

    公共字符串 getFullToken() {
        返回 sFullToken;
    }

    公共字符串 getUserInfo() {
        返回 sUserInfo;
    }

    公共字符串 getExpiryDate() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z");
        返回 sdf.format(dExpiry);
    }

    private byte[] getSecretKey(String shared3DES, String password) 抛出异常
    {
        MessageDigest md = MessageDigest.getInstance("SHA");
        md.update(password.getBytes());
        字节[] hash3DES = 新字节[24];
        System.arraycopy(md.digest(), 0, hash3DES, 0, 20);
        Arrays.fill(hash3DES, 20, 24, (byte) 0);
        // 解密真正的密钥并返回
        BASE64Decoder base64decoder = new BASE64Decoder();
        返回解密(base64decoder.decodeBuffer(shared3DES),hash3DES);
    }

    public byte[] decryptLtpaToken(String encryptedLtpaToken, byte[] key) 抛出异常
    {
        BASE64Decoder base64decoder = new BASE64Decoder();
        最终字节[] ltpaByteArray = base64decoder.decodeBuffer(encryptedLtpaToken);
        返回解密(ltpaByteArray,密钥);
    }

    公共字节 [] 解密(字节 [] 密文,字节 [] 密钥)抛出异常 {
        final Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");
        final KeySpec keySpec = new DESedeKeySpec(key);
        最终密钥 secretKey = SecretKeyFactory.getInstance("TripleDES").generateSecret(keySpec);

        cipher.init(Cipher.DECRYPT_MODE,secretKey);
        返回 cipher.doFinal(密文);
    }
}
于 2009-10-22T15:25:31.577 回答
9

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

然后你可以使用

getUserPrincipal()

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

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

isUserInRole()

确定用户是否在角色中。

你也可以使用方法

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

获取进一步的安全信息,包括组成员身份。

于 2009-10-22T14:59:25.970 回答