Active Directory 联合身份验证服务(AD FS)声明规则语言充当传入和传出声明行为的管理构建基块,而声明引擎充当定义自定义规则的声明规则语言中逻辑的处理引擎。 有关声明引擎如何处理所有规则的详细信息,请参阅 声明引擎的角色。
使用声明规则语言创建自定义声明规则
AD FS 为管理员提供了定义自定义规则的选项,这些规则可用于通过声明规则语言确定标识声明的行为。 可以使用本主题中的声明规则语言语法示例创建自定义规则,该规则枚举、添加、删除和修改声明以满足组织的需求。 可以通过使用自定义声明规则模板在 “发送声明 ”中键入声明语言语法来生成自定义规则。
规则用分号相互分隔。
有关何时使用自定义规则的详细信息,请参阅 何时使用自定义声明规则。
使用声明规则模板了解声明规则语言语法
AD FS 还提供一组预定义的声明颁发和声明接受规则模板,可用于实现常见声明规则。 在给定信任的 “编辑声明规则 ”对话框中,可以通过单击该规则的 “查看规则语言 ”选项卡来创建预定义规则,并查看构成该规则的声明规则语言语法。 使用本节中的信息和 视图规则语言 技术可以深入了解如何构造自己的自定义规则。
有关声明规则和声明规则模板的更多详细信息,请参阅 声明规则的角色。
了解声明规则语言的组件
声明规则语言包括以下组件(由“ =>”运算符分隔):
条件
发出语句
条件
可以在规则中使用条件来检查输入声明并确定是否应执行规则的发出语句。 条件表示必须求值为 true 才能执行规则主体的逻辑表达式。 如果缺少此部分,则会采用逻辑 true;也就是说,始终执行规则主体。 条件部分包含一个条件列表,这些条件与联合逻辑运算符(“&&”)组合在一起。 列表中的所有条件都必须计算为 true,以便整个条件部分的计算结果为 true。 条件可以是声明选择运算符或聚合函数调用。 这两者是互斥的,这意味着声明选择器和聚合函数不能在单个规则条件部件中组合。
条件在规则中是可选的。 例如,以下规则没有条件:
=> issue(type = "http://test/role", value = "employee");
有三种类型的条件:
单个条件 - 这是条件的最简单形式。 只对一个表达式进行检查;例如,Windows 帐户名称 = 域用户。
多条件 - 此条件需要进行额外检查以处理规则主体中的多个表达式;例如,windows account name = ___domain user 和 group = contosopurchasers。
注释
存在另一个条件,但它是单个条件或多个条件的子集。 它被称为正则表达式(Regex)条件。 它用于获取输入表达式,并将表达式与给定模式匹配。 下面显示了如何使用它的示例。
以下示例演示了一些语法构造,这些构造基于条件类型,可用于创建自定义规则。
单条件示例
下表描述了单个 -expression 条件。 构造它们是为了仅检查具有指定声明类型的声明,或者检查具有指定声明类型和声明值的声明。
条件说明 | 条件语法示例 |
---|---|
此规则有一个条件,用于检查具有指定声明类型的输入声明(“<http://test/name >” )。 如果匹配声明位于输入声明中,规则会将匹配声明或声明复制到输出声明集。 |
c: [type == "http://test/name"] => issue(claim = c ); |
此规则有一个条件,用于检查具有指定声明类型(“”“<http://test/name >)和声明值(”Terry“)的输入声明。 如果匹配声明位于输入声明中,规则会将匹配声明或声明复制到输出声明集。 |
c: [type == "http://test/name", value == "Terry"] => issue(claim = c); |
下一节中显示了更多 -complex 条件,包括检查多个声明的条件、检查声明颁发者的条件,以及检查与正则表达式模式匹配的值的条件。
多条件示例
下表提供了多个 -expression 条件的示例。
条件说明 | 条件语法示例 |
---|---|
此规则有一个条件来检查两个输入声明,每个声明类型为指定的声明类型(“”<http://test/name >和“<http://test/email >”)。 如果两个匹配声明位于输入声明中,规则会将名称声明复制到输出声明集。 |
c1: [type == "http://test/name"] && c2: [type == "http://test/email"] => issue (claim = c1 ); |
正则表达式条件示例
下表提供了正则表达式 -based 条件的示例。
条件说明 | 条件语法示例 |
---|---|
此规则具有一个条件,它使用正则表达式检查以“@fabrikam.com”结尾的电子邮件声明。 如果在输入声明中找到匹配声明,规则会将匹配声明复制到输出声明集。 | c: [type == "http://test/email", value =~ "^. +@fabrikam.com$" ] => issue (claim = c ); |
发出语句
自定义规则基于你在声明规则中编写的发出语句(issue 或 add)进行处理。 根据所需的结果,可以将问题语句或 add 语句写入规则以填充输入声明集或输出声明集。 使用 add 语句的自定义规则仅向输入声明集填充声明值,而使用问题语句的自定义声明规则在输入声明集和输出声明集中填充声明值。 当声明值仅供声明规则集中的未来规则使用时,这非常有用。
例如,在下图中,传入声明将被加到声明颁发引擎的输入声明集合中。 当第一个自定义声明规则执行并满足域用户的条件时,声明颁发引擎将使用 add 语句处理规则中的逻辑,并将 编辑器 的值添加到输入声明集。 由于编辑器的值存在于输入声明集中,规则 2 可以在其逻辑中成功处理问题语句,并生成一个新的 Hello 值,该值将添加到输出声明集和输入声明集以供规则集中的下一个规则使用。 规则 3 现在可以使用输入声明集中存在的所有值作为处理其逻辑的输入。
声明发出操作
规则主体表示声明发出操作。 语言可识别两种声明发出操作:
问题语句: 问题语句将创建一个声明,该声明同时转到输入和输出声明集。 例如,下面的语句基于其输入声明集发出新声明:
c:[type == "Name"] => issue(type = "Greeting", value = "Hello " + c.value);
添加语句: add 语句将创建一个新声明,该声明仅添加到输入声明集集合中。 例如,以下语句向输入声明集添加新声明:
c:[type == "Name", value == "___domain user"] => add(type = "Role", value = "Editor");
规则的发出语句定义在匹配条件时由规则发出的声明。 在参数和语句行为方面有两种形式的发出语句:
正常 — 正常发出语句可以通过使用规则中的文本值或来自与条件匹配的声明的值来发出声明。 正常发出语句可以包含一个或两个以下格式:
声明副本:声明副本在输出声明集中创建现有声明的副本。 仅当与“issue”发出语句结合使用时,此发出形式才有意义。 当与“add”发出语句结合使用时,它没有任何效果。
新声明:此格式创建一个新声明,给定各种声明属性的值。 必须指定 Claim.Type;所有其他声明属性都是可选的。 忽略此格式的参数顺序。
属性存储 - 此窗体创建声明,其中包含从属性存储中检索的值。 可以使用单个发出语句创建多种声明类型,这对于在属性检索过程中生成网络或磁盘输入/输出 (I/O) 操作的属性存储十分重要。 因此,需要限制策略引擎和属性存储之间的往返次数。 为给定声明类型创建多个声明也是合法的。 当属性存储返回给定声明类型的多个值时,颁发语句会自动为每个返回的声明值创建声明。 属性存储实现使用 param 参数将 query 参数中的占位符替换为 param 参数中提供的值。 占位符使用与 .NET String.Format (例如,{1}{2}等)函数相同的语法。 这种发出形式的参数顺序十分重要,必须是采用以下语法规定的顺序。
下表描述了声明规则中两类颁发语句的一些常见语法结构。
发行声明类型 | 发出语句说明 | 发布声明语法示例 |
---|---|---|
正常 | 每当用户具有指定的声明类型和值时,以下规则始终发出相同的声明: | c: [type == "http://test/employee", value == "true"] => issue (type = "http://test/role", value = "employee"); |
正常 | 以下规则将一个声明类型转换为另一种声明类型。 请注意,与条件“c”相匹配的声明的值在发出语句中使用。 | c: [type == "http://test/group" ] => issue (type = "http://test/role", value = c.Value ); |
属性存储 | 以下规则使用传入声明的值来查询 Active Directory 属性存储: | c: [Type == "http://test/name" ] => issue (store = "Enterprise AD Attribute Store", types = ("http://test/email" ), query = ";mail;{0}", param = c.Value ) |
属性存储 | 以下规则使用传入声明的值来查询以前配置的结构化查询语言 (SQL) 属性存储: | c: [type == "http://test/name"] => issue (store = "Custom SQL store", types = ("http://test/email","http://test/displayname" ), query = "SELECT mail, displayname FROM users WHERE name ={0}", param = c.value ); |
表达式
表达式在右侧用于声明选择器约束和发出语句参数。 语言支持的各种表达式。 语言中的所有表达式都是基于字符串的,这意味着它们采用字符串作为输入并生成字符串。 表达式中不支持数字或其他数据类型,例如日期/时间。 以下是语言支持的表达式类型:
字符串文字:字符串值,两端使用引号 (") 字符分隔。
表达式的字符串串联:结果是由左右值串联生成的字符串。
函数调用:该函数由标识符标识,参数以逗号 -delimited 括在方括号(“()”中的表达式列表传递。
采用“变量名.属性名”形式的声明属性访问:对于给定的变量赋值,所标识的声明属性的值结果。 必须先将变量绑定到声明选择器,然后才能以这种方式使用。 在同一声明选择器的约束中使用绑定到该声明选择器的变量是违法的。
以下是可用于访问的声明属性:
索赔类型
Claim.Value
Claim.Issuer
Claim.OriginalIssuer
Claim.ValueType
Claim.Properties[property_name] (如果在声明的属性集合中找不到属性_name,此属性将返回一个空字符串。
可以使用 RegexReplace 函数在表达式中调用。 此函数采用输入表达式,并将其与给定模式匹配。 如果模式匹配,匹配项的输出会被替换为替换值。
Exists 函数
Exists 函数可用于条件,以评估输入声明集中是否存在与该条件匹配的声明。 如果存在任何匹配声明,则发出语句只调用一次。 在下面的示例中,“origin”声明恰好发出一次 — 如果输入声明集集合中至少有一个声明的发出者设置为“MSFT”(无论有多少声明的发出者设置为“MSFT”)。 使用此函数可防止发出重复声明。
exists([issuer == "MSFT"])
=> issue(type = "origin", value = "Microsoft");
规则主体
规则主体只能包含单个发出语句。 如果在不使用 Exists 函数的情况下使用条件,则每次匹配条件部分时,都会执行规则正文一次。