Citrix ADC

nFactor 可扩展性

nFactor 身份验证框架提供了添加自定义设置的灵活性,使登录界面更直观,实现了丰富的用户体验。可以添加自定义登录标签、自定义登录凭据、自定义 UI 显示等。

使用 nFactor,每个因素都可以有自己的登录屏幕。在每个登录屏幕中,您都可以显示以前任何因素中的任何信息或其他因素中不可见的更多信息。例如,您的最后一个因素可能是一个信息性页面,用户可以在其中阅读说明并单击继续。

在 nFactor 之前,自定义登录页面受到限制,需要自定义设置和支持。可以替换 tmindex.html 或应用重写规则来更改其某些行为。但是,无法实现基础功能。

本主题将详细捕获下列与 nFactor 相关的自定义设置。

  • 自定义登录标签
  • 自定义 UI 以显示图像
  • 自定义 Citrix ADC nFactor 登录表单

假设

您熟悉 nFactor、Shell 命令、XML 和文本编辑器。

必备条件

  • 只有在 Citrix ADC 上配置了 RfWeb UI 主题(或基于主题)时,才可能实现本主题中描述的自定义设置。
  • 身份验证策略必须绑定到身份验证、授权和审核虚拟服务器,否则流将无法按预期工作。有关详细信息,请参阅 CTX224241。
  • 您有以下项目与 nFactor 相关
    • XML 架构
    • JavaScript
    • 身份验证操作
    • 身份验证虚拟服务器
    • Citrix ADC 版本 11.1 及更高版本

自定义登录标签

要自定义登录标签,您需要以下对象:

  • 描述登录页面外观的 XML 架构。
  • 包含用于更改呈现过程的 JavaScript 的 script.js 文件。

工作原理

JavaScript 解析 XML 文件,将每个项目呈现在 <Requirements> 标签中。每个元素对应 HTML 表单中的一行。例如,登录字段占一行,密码字段占另一行,登录按钮也占一行。要引入新行,则必须使用 StoreFront SDK 在 XML 架构文件中指定新行。StoreFront SDK 允许具有 XML 架构的登录页面使用 <Requirement> 标记并在其上定义元素。这些元素允许使用 JavaScript 在该空间中引入任何所需的 HTML 元素。在这种情况下,将使用 HTML 格式的文本创建一行。

可以使用的 XML 如下:

<Requirement>
<Credential>
<Type>nsg-custom-cred</Type>
<ID>passwd</ID>
</Credential>
<Label>
<Type>nsg-custom-label</Type>
</Label>
</Requirement>
<!--NeedCopy-->

<Requirement>:登录页面中提供的空间。凭据将填充该空间,其他部分则将引擎路由到正确的信息。在这种情况下,请键入 nsg-custom-cred。这定义为纯文本,标签是为其正文定义的。 要求 XML 与 JavaScript 代码配对以实现所需的结果。

// Custom Label Handler for Self Service Links
CTXS.ExtensionAPI.addCustomAuthLabelHandler({
getLabelTypeName: function () { return "nsg-custom-label"; },
getLabelTypeMarkup: function (requirements) {
return $("< Your HTML Code Here>");
},
// Instruction to parse the label as if it was a standard type
parseAsType: function () {
return "plain";
}
});
//Custom Credential Handler for Self Service Links
CTXS.ExtensionAPI.addCustomCredentialHandler({
getCredentialTypeName: function () { return "nsg-custom-cred"; },
getCredentialTypeMarkup: function (requirements) {
return $("<div/>");
},
});
<!--NeedCopy-->

XML 部分指示登录页面要显示的内容,JavaScript 代码提供实际的文本。凭据处理程序会打开空间,标签将填充该空间。由于所有身份验证流量现在对重写和响应程序都不可见,因此您可以更改页面的外观。 用于自定义登录标签的配置

  1. 基于 RfWeb 创建和绑定主题。

    add vpn portaltheme RfWebUI_MOD -basetheme RfWebUI
    
    bind vpn vserver TESTAAA –portaltheme RfWebUI_MOD
    <!--NeedCopy-->
    

    基于主题的文件的路径可在目录 /var/netscaler/logon/themes/RfWebUI_MOD 中找到

  2. 将以下代码段添加到 script.js 文件的末尾:

    注意:如果无法在正确的文件中包含前面的行或错过包含任何 JavaScript 函数,则会导致 XML 无法加载。该错误只能在浏览器的开发人员控制台中显示,其中包含以下文本:“Undefined Type nsg-custom-cred”(未定义的类型 nsg-custom-cred)。

    // Custom Label Handler for Self Service Links
    CTXS.ExtensionAPI.addCustomAuthLabelHandler({
    getLabelTypeName: function () { return "nsg-custom-label"; },
    getLabelTypeMarkup: function (requirements) {
    return $("<a href="https://identity.test.com/identity/faces/register" style="font-size: 16px;" style="text-align: center;">Self Registration</a><br><a href="https://identity.test.com/identity/faces/forgotpassword" style="font-size: 16px;" style="text-align: center;">Forgot Password</a><br><a href="https://identity.test.com/identity/faces/forgotuserlogin" style="font-size: 16px;" style="text-align: center;">Forgot User Login</a>");
    },
    // Instruction to parse the label as if it was a standard type
    parseAsType: function () {
    return "plain";
    }
    });
    //Custom Credential Handler for Self Service Links
    CTXS.ExtensionAPI.addCustomCredentialHandler({
    getCredentialTypeName: function () { return "nsg-custom-cred"; },
    getCredentialTypeMarkup: function (requirements) {
    return $("<div/>");
    },
    });
    <!--NeedCopy-->
    

本示例中使用的 Loginschema

<?xml version="1.0" encoding="utf-8"?>
<AuthenticateResponse xmlns="http://citrix.com/authentication/response/1">
<Status>success</Status>
<Result>more-info</Result>
<StateContext/>
<AuthenticationRequirements>
<PostBack>/nf/auth/doAuthentication.do</PostBack>
<CancelPostBack>/Citrix/Authentication/ExplicitForms/CancelAuthenticate</CancelPostBack>
<CancelButtonText>Cancel</CancelButtonText>
<Requirements>
<Requirement>
<Credential>
<ID>login</ID>
<SaveID>Username</SaveID>
<Type>username</Type>
</Credential>
<Label>
<Text>User name</Text>
<Type>plain</Type>
</Label>
<Input>
<AssistiveText>Please supply either domain\username or user@fully.qualified.domain</AssistiveText>
<Text>
<Secret>false</Secret>
<ReadOnly>false</ReadOnly>
<InitialValue></InitialValue>
<Constraint>.+</Constraint>
</Text>
</Input>
</Requirement>
<Requirement>
<Credential>
<ID>passwd</ID>
<SaveID>Password</SaveID>
<Type>password</Type>
</Credential>
<Label>
<Text>Password:</Text>
<Type>plain</Type>
</Label>
<Input>
<Text>
<Secret>true</Secret>
<ReadOnly>false</ReadOnly>
<InitialValue/>
<Constraint>.+</Constraint>
</Text>
</Input>
</Requirement>
<Requirement>
<Credential>
<Type>nsg-custom-cred</Type>
<ID>passwd</ID>
</Credential>
<Label>
<Type>nsg-custom-label</Type>
</Label>
</Requirement>
<Requirement>
<Credential>
<ID>loginBtn</ID>
<Type>none</Type>
</Credential>
<Label>
<Type>none</Type>
</Label>
<Input>
<Button>Please Log On</Button>
</Input>
</Requirement>
</Requirements>
</AuthenticationRequirements>
</AuthenticateResponse>
<!--NeedCopy-->

执行以下命令将自定义架构加载到配置中。

add authentication loginSchema custom -authenticationSchema custom.xml

add authentication loginSchemaPolicy custom -rule true -action custom

bind authentication vserver AAATEST -policy custom -priority 100 -gotoPriorityExpression END
<!--NeedCopy-->

下图显示了使用此配置呈现的登录页面。

本地化后的图片

自定义 UI 以显示图像

nFactor 允许使用 loginschema 文件进行自定义显示。除了内置的 loginschema 文件提供的自定义设置外,可能还需要进一步的自定义。例如,在 UI 中显示超链接或编写自定义逻辑。这些可以使用由 loginschema 扩展和相应的 javascript 文件组成的“自定义凭据”来实现。

对于 UI 自定义以显示图像,将使用“Citrix ADC-Swivel”集成中的部署流作为示例。

此流中有两个因素。

  • 第一个因素:检查用户的 AD 凭据。
  • 第二个因素:根据组成员身份提示用户登录。

本地化后的图片

在此流中,所有用户都经历了第一个因素。在第二个因素之前,有一个伪因素可以检查是否能够从“旋转”因素中省略某些用户。如果用户需要“旋转”因素,则会显示图像和文本框以输入代码。

解决方案

自定义 UI 以显示图像的解决方案包含两个部分;

  • loginschema 扩展。
  • 用于处理 loginschema 扩展的自定义脚本。

loginschema 扩展

为了控制表单呈现,将自定义的“id’/’credential”注入 loginschema 中。这可以通过重复使用现有架构并根据要求进行修改来完成。

在此示例中,假设只有一个文本字段(例如 /nsconfig/loginschema/LoginSchema/OnlyPassword.xml)的 loginschema。 以下代码段将添加到 loginschema 中。

<Requirement><Credential><ID>swivel_cred</ID><Type>swivel_cred</Type><Input><Text><Hidden>true</Hidden><InitialValue>${http.req.user.name}</InitialValue></Text></Input></Credential></Requirement>
<!--NeedCopy-->

在该代码段中,“swivel_cred”被指定为凭据的“Type”。由于这不会被识别为内置“凭据”,因此 UI 会查找此类型的处理程序,如果存在,则进行调用。 将为此凭据发送初始值,此凭据是 Citrix ADC 动态填充的表达式。在此示例中,它是用于通知旋转服务器用户名的用户名。可能不是任何时候都需要,也可以用其他一些数据对其进行增强。必须根据需要添加这些详细信息。

用于处理自定义凭据的 JavaScript

当 UI 找到自定义凭据时,则会查找处理程序。所有自定义处理程序都写入默认门户主题的 /var/netscaler/logon/LogonPoint/custom/script.js 中。 对于自定义门户主题,可以在目录 /var/netscaler/logon/themes/<custom_theme>/ 中找到 script.js。

添加了以下脚本来呈现自定义凭据的标记。

CTXS.ExtensionAPI.addCustomCredentialHandler({
    // The name of the credential, must match the type returned by the server
    getCredentialTypeName: function () { return "swivel_cred"; },
    // Generate HTML for the custom credential
    getCredentialTypeMarkup: function (requirements) {
        var div = $("<div></div>");
        var image = $("<img/>");
        var username = requirements.input.text.initialValue; //Get the secret from the response
        image.attr({
            "style" : "width:200px;height:200px;",
            "id" : "qrcodeimg",
            "src" : "https://myswivelserver.citrix.com:8443/pinsafe/SCImage?username=" + username
        });
        div.append(image);
        return div;
    }
});
<!--NeedCopy-->

此代码段用于处理“swivel_cre”的标记。突出显示的凭据名称必须与之前在 loginschema 扩展中指定的“type”匹配。 要生成标记,需要添加源指向旋转服务器的图像。完成此操作后,UI 将从指定位置加载图像。因为此 loginschema 也有一个文本框,因此 UI 会呈现该文本框。

注意: 管理员可以修改图像元素的“style”来调整图像的大小。当前图像配置为 200x200 像素。

用于自定义 UI 以显示图像的配置

nFactor 配置最好自下而上进行构建,即最后一个因素有限,因为当您尝试为以前的因素指定“nextFactor”时,需要后续因素的名称。

旋转因素配置:

add loginschema swivel_image –authenticationSchema /nsconfig/loginschema/SwivelImage.xml

add authentication policylabel SwivelFactor –loginSchema swivel_image

bind authentication policylabel SwivelFactor –policy <policy-to-check-swivel-image> -priority 10
<!--NeedCopy-->

注意:从示例中使用的 loginschema 下载 SwivelImage.xml。

组检查配置的伪因素:

add authentication policylabel GroupCheckFactor

add authentication policy contractors_auth_policy –rule ‘http.req.user.is_member_of(“contractors”)’ –action NO_AUTHN

add authentication policy not_contractors _auth_policy–rule true –action NO_AUTHN

bind authentication policylabel GroupCheckFactor –policy contractors_auth_policy –pri 10 –nextFactor SwivelFactor

bind authentication policylabel GroupCheckFactor –policy not_contractors_auth_policy –pri 20
<!--NeedCopy-->

Active Directory 登录的第一个因素:

add ldapAction <>

add authentication policy user_login_auth_policy –rule true –action <>

bind authentication vserver <> -policy user_login_auth_policy –pri 10 –nextFactor GroupCheckFactor
<!--NeedCopy-->

在此配置中,指定了三个因素,其中一个是隐式因素/伪因素。

本示例中使用的 Loginschema

下面是带旋转凭据和文本框的示例架构。

注意:复制 Web 浏览器的数据时,引号可能会以不同的方式显示。请先在记事本等编辑器中复制数据,然后再将其保存到文件。

<?xml version="1.0" encoding="UTF-8"?>
<AuthenticateResponse xmlns="http://citrix.com/authentication/response/1">
<Status>success</Status>
<Result>more-info</Result>
<StateContext></StateContext>
<AuthenticationRequirements>
<PostBack>/nf/auth/doAuthentication.do</PostBack>
<CancelPostBack>/nf/auth/doLogoff.do</CancelPostBack>
<CancelButtonText>Cancel</CancelButtonText>
<Requirements>
<Requirement><Credential><ID>swivel_cred</ID><Type>swivel_cred</Type><Input><Text><Hidden>true</Hidden><InitialValue>${http.req.user.name}</InitialValue></Text></Input></Credential></Requirement>
<Requirement><Credential><ID>passwd</ID><SaveID>ExplicitForms-Password</SaveID><Type>password</Type></Credential><Label><Text>Password:</Text><Type>plain</Type></Label><Input><Text><Secret>true</Secret><ReadOnly>false</ReadOnly><InitialValue></InitialValue><Constraint>.+</Constraint></Text></Input></Requirement>
<Requirement><Credential><Type>none</Type></Credential><Label><Text>Hello ${http.req.user.name}, Please enter passcode from above image.</Text><Type>confirmation</Type></Label><Input /></Requirement>
<Requirement><Credential><ID>saveCredentials</ID><Type>savecredentials</Type></Credential><Label><Text>Remember my password</Text><Type>plain</Type></Label><Input><CheckBox><InitialValue>false</InitialValue></CheckBox></Input></Requirement>
<Requirement><Credential><ID>loginBtn</ID><Type>none</Type></Credential><Label><Type>none</Type></Label><Input><Button>Log On</Button></Input></Requirement>
</Requirements>
</AuthenticationRequirements>
</AuthenticateResponse>
<!--NeedCopy-->

输出

执行配置后,将显示以下图像。

本地化后的图片

注意: 可以在 JavaScript 中更改图像高度和放置位置。

自定义 Citrix ADC nFactor 登录表单以显示或隐藏字段

Citrix Gateway 的 RfWeb UI 允许进行各种自定义。与 nFactor 身份验证框架结合使用时,客户可以在不影响现有工作流的情况下配置复杂流。

在此示例中,“Logon Type”(登录类型)列表中有两个身份验证选项 OAuth 和 LDAP。首次加载表单时,将显示用户名和密码字段(首先显示 LDAP)。如果选择了 OAuth,则所有字段都将隐藏,因为 OAuth 意味着将身份验证卸载到第三方服务器。这样,管理员可以根据用户是否方便来配置直观的工作流。

注意

  • 只需简单修改脚本文件即可修改“Logon Type”(登录类型)列表中的值。
  • 本部分仅介绍流的 UI 部分。身份验证的运行时处理不在本文的讨论范围之内。建议用户参阅 nFactor 文档了解身份验证配置。

如何自定义 nFactor 登录表单

自定义 nFactor 登录表单可分为两个部分

  • 将正确的 loginschema 发送到 UI
  • 编写处理程序以解释 loginschema 和用户选择对象

将正确的 loginschema 发送到 UI

在此示例中,在 loginschema 中发送了一个简单的声明/要求。

为此,修改了 SingleAuth.xml 文件。SingleAuth.xml 随 Citrix ADC 固件一起提供,可在 //nsconfig/loginschema/LoginSchema目录中找到。

发送 loginschema 的步骤:

  1. 通过 SSH 登录并放置到 shell(键入 shell)。

  2. 将 SingleAuth.xml 复制到另一个文件进行修改。

    注意:目标文件夹与默认的 Citrix ADC loginschemas 文件夹不同。

    cp /nsconfig/loginschema/LoginSchema/SingleAuth.xml /nsconfig/loginschema/SingleAuthDynamic.xml

  3. 将以下声明添加到 SingleAuthDynamic.xml。

    <Requirement><Credential><ID>nsg_dropdown</ID><Type>nsg_dropdown</Type></Credential><Label><Text>Logon Type:</Text><Type>plain</Type></Label></Requirement>
    <!--NeedCopy-->
    
  4. 将 Citrix ADC 配置为发送此 loginschema 以加载第一个表单。

    add loginschema single_auth_dynamic –authenticationSchema SingleAuthDynamic.xml
    
    add loginschemaPolicy single_auth_dynamic –rule true –action single_auth_dynamic
    
    bind authentication vserver aaa_nfactor –policy single_auth_dynamic –pri 10
    <!--NeedCopy-->
    

脚本发生变化以加载表单和处理用户事件

您可以修改 JavaScript,使管理员能够自定义登录表单的显示。在此示例中,如果选择了 LDAP,则会显示用户名和密码字段,如果选择了 OAuth,则将隐藏用户名和密码字段。管理员也可以只隐藏密码。 管理员必须将以下代码段附加到“/var/netscaler/logon/LogonPoint/custom”目录下的“script.js”中。

注意:由于此目录是全局目录,因此,请创建一个门户主题并在该文件夹中编辑“script.js”文件,位置为 "/var/netscaler/logon/themes/<THEME_NAME>"

CTXS.ExtensionAPI.addCustomCredentialHandler({
    // The name of the credential, must match the type returned by the server
    getCredentialTypeName: function () { return "nsg_dropdown"; },
    // Generate HTML for the custom credential
    getCredentialTypeMarkup: function (requirements) {
        var div = $("<div></div>");
        var select = $("<select name='nsg_dropdown'></select>").attr("id", "nsg_dropdown");

        var rsa = $("<option></option>").attr("selected", "selected").text("LDAP").val("LDAP");
        var OAuthID = $("<option></option>").text("OAuth").val("OAuth");
        select.append(rsa, OAuthID);

        select.change(function(e) {
            var value = $(this).val();
            var ldapPwd = $($(".credentialform").find(".CredentialTypepassword")[0]);
            var ldapUname = $($(".credentialform").find(".CredentialTypeusername"));
            if(value == "OAuth") {
                if (ldapPwd.length)
                        ldapPwd.hide();
                if (ldapUname.length)
                        ldapUname.hide();
            } else if(value == "LDAP") {
                if (ldapPwd.length)
                        ldapPwd.show();
                if (ldapUname.length)
                        ldapUname.show();
            }
        });
       div.append(select);
        return div;
    }
});
<!--NeedCopy-->

最终用户体验

最终用户首次加载登录页面时,将显示以下屏幕。

本地化后的图片

如果在 Logon Type(登录类型)中选择 OAuth,用户名和密码字段将隐藏。

本地化后的图片

如果选择 LDAP,则将显示用户名和密码。这样,可以根据用户选择动态加载登录页面。

本示例中使用的 Loginschema

<?xml version="1.0" encoding="UTF-8"?>
<AuthenticateResponse xmlns="http://citrix.com/authentication/response/1">
<Status>success</Status>
<Result>more-info</Result>
<StateContext></StateContext>
<AuthenticationRequirements>
<PostBack>/nf/auth/doAuthentication.do</PostBack>
<CancelPostBack>/nf/auth/doLogoff.do</CancelPostBack>
<CancelButtonText>Cancel</CancelButtonText>
<Requirements>
<Requirement><Credential><ID>login</ID><SaveID>ExplicitForms-Username</SaveID><Type>username</Type></Credential><Label><Text>User name</Text><Type>plain</Type></Label><Input><AssistiveText>Please supply either domain\username or user@fully.qualified.domain</AssistiveText><Text><Secret>false</Secret><ReadOnly>false</ReadOnly><InitialValue></InitialValue><Constraint>.+</Constraint></Text></Input></Requirement>
<Requirement><Credential><ID>passwd</ID><SaveID>ExplicitForms-Password</SaveID><Type>password</Type></Credential><Label><Text>Password:</Text><Type>plain</Type></Label><Input><Text><Secret>true</Secret><ReadOnly>false</ReadOnly><InitialValue></InitialValue><Constraint>.+</Constraint></Text></Input></Requirement>
<Requirement><Credential><ID>nsg_dropdown</ID><Type>nsg_dropdown</Type></Credential><Label><Text>Logon Type:</Text><Type>plain</Type></Label></Requirement>
<Requirement><Credential><Type>none</Type></Credential><Label><Text>First factor</Text><Type>confirmation</Type></Label><Input /></Requirement>
<Requirement><Credential><ID>saveCredentials</ID><Type>savecredentials</Type></Credential><Label><Text>Remember my password</Text><Type>plain</Type></Label><Input><CheckBox><InitialValue>false</InitialValue></CheckBox></Input></Requirement>
<Requirement><Credential><ID>loginBtn</ID><Type>none</Type></Credential><Label><Type>none</Type></Label><Input><Button>Log On</Button></Input></Requirement>
</Requirements>
</AuthenticationRequirements>
</AuthenticateResponse>
<!--NeedCopy-->

重要提示: 有关各种 nFactor 相关主题的更多详细信息,请参阅 nFactor

nFactor 可扩展性