高级账户字段表达式

本文详细介绍了如何在IDaaS的内置表达式引擎中使用高级账户字段表达式,以及详细的模型字段说明、函数说明及相应的参考示例。

基础说明

IDaaS内置了表达式引擎,在SAMLOIDC应用中,支持使用高级表达式,向返回用户信息中添加新的参数。当目标应用需接受额外参数,且参数需要进行某种转化、拼接、判断时,可使用表达式实现。

与此类似,可以使用同样方法,在配置与身份提供方间同步的字段映射时,也可使用表达式实现字段值自定义赋值。

本篇文档下方列有参考示例,帮助快速理解表达式使用场景和方法。​

OIDC为例,在SSO配置中,支持扩展返回的id_token信息。在扩展值中,可填写高级表达式full_phone,以达成特定处理目标。

image.png

更多使用方式请参考:SAML Attribute Statements值填写规范OIDC id_token扩展值填写规范字段管理

表达式分为两部分:

  • 模型,包含User(对应IDaaS账户)和AppUser(对应应用账户)两种。

  • 函数,代表执行逻辑关系。

模型说明

1. User

下列字段在IDaaSUser模型中,可使用类似user.usernameuser.lockExpireTime 的引用方式。

字段显示名称

字段标识

数据类型

是否必填

是否唯一

用户侧权限

说明

账户 ID

userId

字符串

可见

用户ID。

账户名

username

字符串

可见

用户名。

显示名称

displayName

字符串

可编辑

用户显示名。

邮箱

email

字符串

可编辑

邮箱。

手机

phoneNumber

数字

可编辑

手机号。

手机区号

phoneRegion

数字

可编辑

手机地区编号,示例:中国区号为 "86",不带 "00" 或 "+"。

外部 ID

userExternalId

字符串

可见

用户外部ID。

来源类型

userSourceType

字符串

可见

来源类型,取值为:

  • build_in:自建。

  • ding_talk:钉钉。

  • ad:AD。

  • ldap:LDAP。

  • we_com:企业微信。

  • lark:飞书。

  • idp_auto_build:IDP自动创建。

来源 ID

userSourceId

字符串

可见

来源ID。

账户状态

status

字符串

可见

用户状态,取值为:

  • enabled:启用。

  • disabled:禁用。

描述

description

字符串

可见

描述。

账户过期时间

accountExpireTime

数字

可见

用户过期时间,UNIX时间戳,单位毫秒。

账户注册时间

registerTime

数字

可见

用户注册时间,UNIX时间戳,单位毫秒。

密码过期时间

passwordExpireTime

数字

可见

密码过期时间,UNIX时间戳,单位毫秒。

锁定过期时间

lockExpireTime

数字

可见

锁定过期时间,UNIX时间戳,单位毫秒。

创建时间

createTime

数字

可见

创建时间,UNIX时间戳,单位毫秒。

更新时间

updateTime

数字

可见

最近一次更新用户信息的时间,UNIX时间戳,单位毫秒。

2. App User

下列字段在IDaaSAppUser模型中,可使用类似appUser.username引用方式。

属性

说明

username

应用账号用户名。

3. IdP User

IdP User模型应用于与身份提供方进行同步时,举例:钉钉的办公地点字段:idpUser.work_place

具体字段请查看对应身份提供方文档,例如钉钉的钉钉帮助文档-用户详情

重要

对于OIDC身份提供方(参考绑定OIDC身份提供方),在自动绑定能力中使用表达式时,仅id_token中的sub、phoneNumber、email字段的前缀使用idpUser.,例如idpUser.sub;其余字段的前缀需使用idpUser.rawUserInfo.,例如idpUser.rawUserInfo.aud

函数说明

以下为我们开放的对应的函数及示例:

函数名

函数定义

说明

举例

Append

Append(str1, str2, ..., strn)

拼接输入参数为新的字符串,等于str1+str2+...

  • 输入:Append("str1", "@example.com")

  • 输出: str1@example.com

Join

Join(source1, source2, ..., sourceN, separator)

将多个源值拼接为一个字符串,源值间用分隔符分隔。

  • 输入:Join("str1", "str2", 123,"-")

  • 输出:"str1-str2-123"

Coalesce

Coalesce(source1, source2, ..., sourceN, defaultValue)

返回输入参数中第一个非空参数,若参数都为空,则返回null,其中非空指非null且参数长度大于0。

  • 输入:Coalesce("", user.phoneRegion, "86")

  • 输出:当手机号区号为空即缺失时,输出为 86

IIF

IIF(condition, whenTrue, whenFalse)

三目运算。根据condition的结果返回不同的值,为true时返回whenTrue,为false时返回whenFalse。

示例1:

  • 输入:IIF(true, 1, 2)

  • 输出:1

示例2:

  • 输入:IIF(false, 1, 2)

  • 输出:2

IsNull

IsNull(value)

valuenull即缺失时,输出为true。

示例1:

  • 输入:IsNull(null)

  • 输出:输出为true

示例2:

  • 输入:IsNull("")

  • 输出:输出为false

IsNullOrEmpty

IsNullOrEmpty(value)

valuenull或空字符串时,输出为true。

示例1:

  • 输入:IsNullOrEmpty(user.email)

  • 输出:当邮箱为null即缺失时,输出为true

示例2:

  • 输入:IsNullOrEmpty("")

  • 输出:输出为true

Now

Now()

返回表示当前UTC DateTime的字符串,格式为 yyyy-MM-dd'T'HH:mm:ssXXX。

  • 输出:2021-11 01T09:52:11Z

StringReplace

StringReplace("hello $VariableName", "$VariableName", ReplaceString)

普通字符串替换。

  • 输入:StringReplace("hello $str", "$str", "world")

  • 输出:hello world

Trim

Trim(source)

去除源值字符串前后的空白字符。

  • 输入:Trim(" 123 ")

  • 输出:123

TrimLeft

TrimLeft(source)

去除源值字符串左侧的空白字符。

  • 输入:TrimLeft(" 123 ")

  • 输出:123

TrimRight

TrimRight(source)

去除源值字符串右侧的空白字符。

  • 输入:TrimRight(" 123 ")

  • 输出: 123

ToLower

ToLower(source)

字符串变为全大写或全小写。

  • 输入:ToLower(" Abc ")

  • 输出:abc

ToUpper

ToUpper(source)

字符串变为全大写。

  • 输入:ToUpper(" Abc ")

  • 输出:ABC

Substring

Substring(source, fromIndex, endIndex)

返回字符串的子字符串,即子字符串下标地址为 [fromIndex, endIndex]。

  • source:必须,源字符串,可为语法支持的任意类型。

  • fromIndex:必须,整数类型。非整型时返回null。

  • endIndex:必须,整数类型。非整型时返回null。

示例1:

  • 输入:Substring("0123456", 1, 5)

  • 输出:1234

示例2:

  • 输入:Substring("0123456", -1, 7)

  • 输出:0123456

示例3:

  • 输入:Substring("0123456", "1", 5)

  • 输出:null

SubstringBefore

SubstringBefore(source, subString)

返回源字符串中从左到右匹配到的第一个目标字符串后的字串。若目标字符串不存在,则返回null。

参数:

  • source:必须,源字符串,可为语法支持的任意类型。

  • target:必须,目标字符串,可为语法支持的任意类型。

返回值:string

示例1:

  • 输入:SubstringBefore("test@example@com", "@")

  • 输出:"test"

Array

Array(source1, source2,...)

将多个值组合成为数组。值可为Object类型。

  • 输入:Array(1, 2, 3)

  • 输出:[1, 2, 3]

ArrayAdd

ArrayAdd(Array(), "test")

在数组对象中添加一个数组。

  • 输入:ArrayAdd(Array(), "test")

  • 输出:["test"]

ArrayMap

ArrayMap($ArrayObject, __item.ObjectProperty)

取数组对象中的某个属性的值形成新的数组。

取用户中所属组的ID列表:

  • 输入:ArrayMap(user.groups, __item.groupId)

  • 输出:["groupId1","groupId2","groupId3"]

ArrayIndex

ArrayIndex(Array(), n)

Array第几个元素,从0开始。

  • 输入:ArrayIndex(Array(1,2,3), 0)

  • 输出:1

ArrayJoin

ArrayJoin(Array(), str)

数组以某个字符串拼接。

  • 输入:ArrayJoin(Array(1,2,3), "-")

  • 输出:"1-2-3"

Object

Object(key1, value1, key2, value2, ...)

通过制定键值对组合成为Object对象。

支持零个或偶数个参数。

  • 输入 Object("key1", "value1", "key2", "value2")

  • 输出对应对象:

{"key1": "value1", "key2": "value2"}

ObjectIndex

ObjectIndex(user, "username")

指定对象的某个属性的值

代码 ObjectIndex(user, "username") 等价于 user.username

ObjectToJsonString

ObjectToJsonString(user.groups)

对象转JSON字符串。

-

Contains

Contains(str1,str2)

判断是否包含,返回true,false。

示例1:

  • 输入:Contains("test", "t")

  • 输出:true

示例2:

  • 输入:Contains("test", "a")

  • 输出:false

Or

Or(true,false,...,true)

或的方式判断多个条件,有一个条件为true,则为true。

示例1:

  • 输入:Or(true,false)

  • 输出:true

示例2:

  • 输入:Or(true,true,false)

  • 输出:true

示例3:

  • 输入:Or(false,false)

  • 输出:false

And

And(true,false,...,true)

且的方式判断多个条件,有一个条件为false,则为false。

示例1:

  • 输入:And(true,false)

  • 输出:false

示例2:

  • 输入:And(true,true,false)

  • 输出:false

示例3:

  • 输入:And(true,true,true)

  • 输出:true

xOr

xOr(true,false,...,true)

有且只能有2个条件。

如果都为true或者都为false,则返回false。

如果同时存在true,false的条件,则返回true。

示例1:

  • 输入:xOr(true,false)

  • 输出:true

示例2:

  • 输入:xOr(true,true)

  • 输出:false

示例3:

  • 输入:And(false,false)

  • 输出:false

StartsWith

StartsWith(str1, str2)

判断字符串以...开头,只能包含2个参数。

示例1:

  • 输入:StartsWith("test", "t")

  • 输出:true

示例2:

  • 输入:StartsWith("test", "e")

  • 输出:false

Split

Split("str1,str2,str3")

字符串分割后,返回一个数组。

示例1:

  • 输入:Split("str1,str2,str3",",")

  • 输出:Array(str1,str2,str3)

Equals

Equals(str1,str2)

比较2个字符串是否一致。

Equals(str1,str2)。

Equals(str1,str2,false) 不忽略大小写比较。

Equals(str1,str2,true) 忽略大小写比较。

示例1:

  • 输入:Equals("test","Test")

  • 输出:false

示例2:

  • 输入:Equals("test","Test",true)

  • 输出:true

示例3:

  • 输入:Equals("test","Test",false)

  • 输出:false

CurrentTimeMillis

CurrentTimeMillis()

当前时间UNIX时间戳,单位毫秒。

-

SamlArray

SamlArray(Array())

SAML SSO可用。

输入:

SamlArray(Array("group1","group2"))

  • SAML Response输出:

<saml2:Attribute Name="grouIdArray"

NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified">

<saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:type="xsd:string">

group1

</saml2:AttributeValue>

<saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xsd:string">

group2

</saml2:AttributeValue>

  • 输入:SamlArray(Array("group1","group2"))

  • SAML Response输出:

</saml2:Attribute>

参考示例

效果

表达式示例

取用户名,拼接固定 "@example.com"。

Append(user.username, "@example.com")

当邮箱不为空,返回邮箱。

当邮箱为空时,取手机号。

Coalesce(user.email, user.phoneNumber)

当手机号为空时,默认填写固定手机号。

IIF(IsNullOrEmpty(user.phoneNumber), "1888888****", user.phoneNumber)

将手机号地区和手机号以 - 拼接。

Join(user.phoneRegion, user.phoneNumber, "-")

返回包含显示名的自定义欢迎信息。

StringReplace("hello $DisplayName", "$DisplayName", user.displayName)

将手机号中间四位用 * 脱敏返回。

Append(

SubString(user.phoneNumber, 0, 4),

"****",

SubString(user.phoneNumber, 8, 10)

)

提取邮箱中的用户名。

SubstringBefore(user.email, "@")

组装SCIM规范中数组格式的email字段。

Array(Object("email", user.email, "type", "work", "primary", true))

User模型JSON示例:

{
  "customFieldMap": {
        "place": {
            "fieldName": "place",
            "fieldValue": "beijing"
        },
        "age": {
            "fieldName": "age",
            "fieldValue": "18"
        }
    },
    "identityProviderUserMap": {
        "idp_m2gngriuenktdkxxxxxx": {
            "identityProviderId": "idp_m2gngriuenktdkxxxxxx",
            "identityProviderType": "ding_talk",
            "identityProviderExternalId": "corp_1234xxxxxxx",
            "identityProviderUserId": "b2ed5fc0xxxxx"
        }
    },
    "organizationalUnits": [
        {
            "organizationalUnitId": "ou_sdfadtaaxxxxxx",
            "organizationalUnitName": "name_001",
            "primary": false
        },
        {
            "organizationalUnitId": "ou_werttxxxxxx",
            "organizationalUnitName": "name_002",
            "primary": true
        }
    ],
    "primaryOrganizationalUnitId": "ou_werttxxxxxx",
    "customFields": [
        {
            "fieldName": "place",
            "fieldValue": "beijing"
        },
        {
            "fieldName": "age",
            "fieldValue": "18"
        }
    ],
    "groups": [
        {
            "groupId": "group_jp6al4sn4n4wjgjxxxxxx",
            "groupName": "group1",
            "groupExternalId": "group_jp6al4sn4n4wjgjxxxxxx"
        },
        {
            "groupId": "group_vavikcxewkf5h3oxxxxxx",
            "groupName": "group2",
            "groupExternalId": "group_vavikcxewkf5h3oxxxxxx"
        }
    ],
  "userId": "user_x3zyd6cxxxxxxxxxxxxx",
  "username": "name_001",
  "displayName": "displayname_001",
  "passwordSet": true,
  "phoneRegion": "86",
  "phoneNumber": "333xxxx3333",
  "phoneNumberVerified": true,
  "email": "xxxxx@example.com",
  "emailVerified": true,
  "userExternalId": "b2ed5fc0xxxxxxxxxx",
  "userSourceType": "ding_talk",
  "userSourceId": "corp_1234xxxxxxx",
  "status": "enabled",
  "accountExpireTime": "-1",
  "passwordExpireTime": "-1",
  "registerTime": "1730454581598",
  "lockExpireTime": "-1",
  "createTime": "1730454582379",
  "updateTime": "1733479455307"
}