没有明确定义生成 SAML ID 的确切方法——它必须仅符合 XML ID 的标准。 XML ID 是一个 xsd:NCName,它是从 xsd:Name 派生的,它不能以数字开头或包含空格,并且应该具有 160 位的“随机性”。
满足该标准的 Java 中最简单的 ID 生成器是:
String id() {
return "a" + UUID.randomUUID();
}
此外,OpenSAML 还附带 SecureRandomIdentifierGenerator:
// You will need to catch the NoSuchAlgorithmException during construction.
IdentifierGenerator idGenerator = new SecureRandomIdentifierGenerator();
String id() {
return idGenerator.generateIdentifier();
}
实际的生成代码如下所示:
SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
String generateIdentifier() {
return generateIdentifier(16);
}
String generateIdentifier(int size) {
byte[] buf = new byte[size];
random.nextBytes(buf);
return "_".concat(new String(Hex.encode(buf)));
}
从SAMLSSOUtil 中提取的另一个替代方案:
char[] charMapping = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p' };
Random random = new Random();
String createID() {
byte[] bytes = new byte[20]; // 160 bits
random.nextBytes(bytes);
char[] chars = new char[40];
for (int i = 0; i < bytes.length; i++) {
int left = (bytes[i] >> 4) & 0x0f;
int right = bytes[i] & 0x0f;
chars[i * 2] = charMapping[left];
chars[i * 2 + 1] = charMapping[right];
}
return String.valueOf(chars);
}
来自Oasis 文档:
xs:ID 简单类型用于声明断言、请求和响应的 SAML 标识符。在本规范中声明为 xs:ID 类型的值除了 xs:ID 类型本身的定义强加的属性外,还必须满足以下属性:
• 分配标识符的任何一方必须确保该方或任何其他方意外地将相同标识符分配给不同数据对象的可能性可以忽略不计。
• 如果数据对象声明它具有特定标识符,则必须有一个这样的声明。
SAML 系统实体确保标识符唯一的机制留给实现。在采用随机或伪随机技术的情况下,两个随机选择的标识符相同的概率必须小于或等于 2^-128 并且应该小于或等于 2^-160。可以通过对长度在 128 到 160 位之间的随机选择的值进行编码来满足此要求。编码必须符合定义 xs:ID 数据类型的规则。必须为伪随机生成器播种独特的材料,以确保不同系统之间具有所需的唯一性。
xs:NCName 简单类型在 SAML 中用于引用 xs:ID 类型的标识符,因为 xs:IDREF 不能用于此目的。在 SAML 中,SAML 标识符引用所引用的元素实际上可能在与使用标识符引用的文档不同的文档中定义。使用 xs:IDREF 将违反其值与同一 XML 文档中某些元素的 ID 属性值匹配的要求。