OAM 和 SP 中的定制验证后模块

本文介绍如何实施将在联邦 SSO 完成后调用的定制验证插件,该插件将:

有关如何设计定制验证插件的更多信息,请参阅《 OAM Developer’s Guide 》第 3 章,其中介绍了如何开发此类模块:http://docs.oracle.com/cd/E40329_01/dev.1112/e27134/authnapi.htm。重点介绍如何:

联盟验证模块

重要说明:使用联合测试 SP 应用程序时,将绕过验证模块,因此不会执行此类模块中定义的插件。

OAM 验证模块为:

OOTB 联盟验证模块(称为 FederationPlugin)由两个插件组成:

可通过以下方式查看该编排:

  1. 转到 OAM 管理控制台:http(s)://oam-adminhost:oam-admin-port/oamconsole
  2. 导航到 Access Manager(访问管理器)Authentication Modules(验证模块)
  3. 打开 FederationScheme
  4. 单击步骤选项卡以查看插件。
  5. 单击步骤业务流程选项卡以查看不同插件与用于启动操作的插件之间的业务流程。

插图 Federation_Plugin_Screen.png 的说明

AssertionProcessing 插件

AssertionProcessing 插件负责验证和使用传入的 SSO 断言,将断言映射到本地 LDAP 用户记录,并返回用户的身份以及断言到 OAM 的内容。验证插件之间共享的 AuthenticationContext 实例包含 CredentialParam 对象,这些对象允许各种插件在运行时进行通信以及验证操作的结果。

验证上下文数据

验证成功后,OAM 验证插件将返回 AuthenticationContext 中的以下数据:

AuthenticationContext 的 Credential 对象中包含以下 CredentialParam 实例

AuthenticationContext 中包含以下 PluginResponse 实例:

用户记录所在的身份存储库的名称

如果在联盟 SP 处理过程中覆盖了验证级别(有关更多信息,请参见本文):Art 27 Mapping Fed Authn Method to Authn Levels in OAM SP)

断言数据,每个元素都是独立的 PluginResponse 实例:

OAM 使用 AuthenticationContext 中包含的数据进一步进行处理。

断言数据由以下元素组成:

示例

让我们使用以下示例检查 AssertionProcessing 插件在流末尾返回的数据:

OAM/SP 中的 IdP 合作伙伴绑定到仅包含一个条目的 IdP 属性概要文件,该条目将 SAML 属性名称 uid 映射到 OAM 会话属性名称用户 ID。在示例中,测试用户将是 alice:

SAML 2.0 断言的一个示例为:

<samlp:Response ..>
     <saml:Issuer ...>hLp://acme.com/idp</saml:Issuer>
     <samlp:Status>
         <samlp:StatusCode
 Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
     </samlp:Status>
     <saml:Assertion ...>
         <saml:Issuer ...>hLp://acme.com/idp</saml:Issuer>
         <dsig:Signature ...>
         ...
         </dsig:Signature>
         <saml:Subject>
 <saml:NameID ...>alice@oracle.com</saml:NameID>
             ...
         </saml:Subject>         <saml:Conditions ...>
          ...
         </saml:Conditions>         <saml:AuthnStatement ...>
         ...
         </saml:AuthnStatement>
         <saml:AttributeStatement ...>
             <saml:Attribute Name="userid" ...>
                 <saml:AttributeValue ...>alice</saml:AttributeValue>
             </saml:Attribute>
             <saml:Attribute Name="lastname" ...>
                 <saml:AttributeValue ...>Appleton</saml:AttributeValue>             </saml:Attribute>
             <saml:Attribute Name="firstname" ...>
                 <saml:AttributeValue ...>Alice</saml:AttributeValue>
             </saml:Attribute>
         </saml:AttributeStatement>
     </saml:Assertion>
 </samlp:Response>

After a successful processing of the SAML 2.0 Assertion and the mapping of the incoming SSO response to a local user record, the AssertionProcessing plugin returns to OAM the AuthenticationContext with the following data: The Subject containing:

AuthenticationContext 的 Credential 对象中包含以下 CredentialParam 实例

AuthenticationContext 中包含以下 PluginResponse 实例:

定制验证插件

概述

在本文中,假设 OAM/SP 部署需要支持:

使用即时用户配置模块,为 #1 提供支持。为了满足 #2 的要求,需要使用定制验证插件来执行以下操作:

对于此示例,环境由以下各项组成:

定制验证插件由以下项组成:

这三个元素捆绑在一个 JAR 文件中,然后通过 OAM 管理控制台上载到 OAM 服务器。上载并激活后,修改联盟验证模块。

Java 类

实施定制验证插件的类必须符合以下条件:

以下代码是定制插件的一个示例。

package postsp;
 import java.util.Hashtable;
 import java.util.Map;
 import java.util.Set;
 import javax.naming.Context;
 import javax.naming.NamingException;
 import javax.naming.directory.Attributes;
 import javax.naming.directory.BasicAttribute;
 import javax.naming.directory.BasicAttributes;
 import javax.naming.directory.DirContext;
 import javax.naming.directory.InitialDirContext;
 import javax.security.auth.Subject;
 import oracle.security.am.common.utilities.principal.OAMUserDNPrincipal;
 import oracle.security.am.common.utilities.principal.OAMUserPrincipal;
 import oracle.security.am.plugin.ExecutionStatus;
 import oracle.security.am.plugin.MonitoringData;
 import oracle.security.am.plugin.PluginAttributeContextType;
 import oracle.security.am.plugin.PluginResponse;
 import oracle.security.am.plugin.authn.AbstractAuthenticationPlugIn;
 import oracle.security.am.plugin.authn.AuthenticationContext;
 import oracle.security.am.plugin.authn.AuthenticationException;
 public class CustomAttributesUpdatePlugin extends
 AbstractAuthenticationPlugIn
 {
   public ExecutionStatus process(AuthenticationContext context)
               throws AuthenticationException {
     // user's ID and DN. Note: we are not making necessary checks for size/null to
     // keep the sample code minimal.
     Subject subject = context.getSubject();
     Set<OAMUserPrincipal> principalsUserID =
               subject.getPrincipals(OAMUserPrincipal.class);
     Set<OAMUserDNPrincipal> principalsDN =
               subject.getPrincipals(OAMUserDNPrincipal.class);
     String localUserID =
 (String)principalsUserID.iterator().next().getName();
     String localUserDN = (String)principalsDN.iterator().next().getName();
     // get the assertion data. Note: We are not making necessary checks for size/null to
     // keep the sample code minimal.
     PluginResponse partnerResponse = context.getResponse(               PluginAttributeContextType.SESSION, "fed.partner");
     String partnerName = (String)partnerResponse.getValue();     PluginResponse nameIDResponse = context.getResponse(
               PluginAttributeContextType.SESSION, "fed.nameidvalue");
     String nameID = (String)nameIDResponse.getValue();
     PluginResponse uidResponse = context.getResponse(
               PluginAttributeContextType.SESSION, "fed.aLr.uid");
     String uid = (String)uidResponse.getValue();
     PluginResponse firstnameResponse = context.getResponse(
               PluginAttributeContextType.SESSION, "fed.aLr.firstname");
     String firstname = (String)firstnameResponse.getValue();     PluginResponse lastnameResponse = context.getResponse(
               PluginAttributeContextType.SESSION, "fed.aLr.lastname");
     String lastname = (String)lastnameResponse.getValue();
     try {
       // open ldap connection
       Hashtable env = new Hashtable();
       env.put(Context.INITIAL_CONTEXT_FACTORY,
 "com.sun.jndi.ldap.LdapCtxFactory");
       env.put(Context.PROVIDER_URL, "ldap://host:port");
       env.put(Context.SECURITY_PRINCIPAL, "admin");
       env.put(Context.SECURITY_CREDENTIALS, "password");       DirContext ldapContext = new InitialDirContext(env);
       // modify user ldap record. Note: We are not making the necessary checks to
       // keep the sample code minimal.
       Attributes attributes = new BasicAttributes();
       attributes.put(new BasicAttribute("givenname", firstname));
       attributes.put(new BasicAttribute("sn", lastname));
       attributes.put(new BasicAttribute("mail", nameID));
       attributes.put(new BasicAttribute("uid", uid));
       ldapContext.modifyAttributes(localUserDN,
                          DirContext.REPLACE_ATTRIBUTE, attributes);
     }
     catch (NamingException ex) {
       throw new AuthenticationException(ex);
     }
     // return success, so that OAM can resume the flow
     return ExecutionStatus.SUCCESS;
   }
   public String getPluginName() {
     return "CustomAttributesUpdatePlugin";
   }
   public String getDescription() {
     return "Custom Attributes Update Plugin";
   }
   public Map<String, MonitoringData> getMonitoringData() {
     return null;
   }
   public boolean getMonitoringStatus() {
     return false;
   }
   public int getRevision() {
     return 10;
   }
   public void setMonitoringStatus(boolean arg0) {
   } }

插件注册文件

自定义验证插件必须在插件 XML 文件中定义,例如:

<Plugin type="Authentication">
<author>uid=admin</author>
<email>admin@example</email>
<creationDate>08:00:00,2014-01-15</creationDate>
<description>Custom Attributes Update Plugin</description>
<conhguration>
</conhguration>
</Plugin>

重要说明:XML 文件必须与实现插件的类具有相同的名称,在本例中为 CustomAttributesUpdatePlugin.xml

有关详细信息,请参阅 OAM 开发人员指南

清单文件

Before packaging the custom Authentication plugin in a JAR file, a MANIFEST.MF must be defined such as: Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: CustomAttributesUpdatePlugin Bundle-SymbolicName: CustomAttributesUpdatePlugin Bundle-Version: 10 Bundle-Activator: postsp.CustomAttributesUpdatePlugin Import-Package: org.osgi.framework;version=”1.3.0”,oracle.security.am.plugin,oracle.security.am.plugin.authn,oracle.security.am.common.utilities.principal,javax.naming,javax.naming.directory,javax.security.auth Bundle-RequiredExecutionEnvironment: JavaSE-1.6

有关详细信息,请参阅 OAM 开发人员指南

:清单文件必须包括 "Import-Package" 属性,该属性列出插件中使用的所有软件包

构建插件

编译

需要使用 OAM 部署中的以下 JAR 文件进行编译:

这些文件位于以下位置:

在此示例中,将 CustomAttributesUpdatePlugin.java 文件放置在 src/postsp 文件夹中:

bash-4.1$ ls -l src/postsp/ total 4
-rw-r--r-- 1 root root 4377 Oct 1 09:54 CustomAttributesUpdatePlugin.java

要进行编译,请执行以下命令:

$JDK_HOME/bin/javac -cp $IAM_HOME/oam/server/lib/plugin /felix.jar:$IAM_HOME/oam/server/lib/plugin/oam-
plugin.jar:$IAM_HOME/oam/server/lib/plugin/utilities.jar src/postsp /\*.java

打包定制插件

我们根据上一节中列出的内容在当前目录中创建了 MANIFEST.MF,在 src 目录中创建了 CustomAttributesUpdatePlugin.xml,该目录包含上一节中列出的插件定义。

find
.
./MANIFEST.MF
./src
./src/userauthn
./src/userauthn/CustomAttributesUpdatePlugin.class
./src/userauthn/CustomAttributesUpdatePlugin.java
./src/CustomAttributesUpdatePlugin.xml

要创建包含插件和所需文件的 CustomAttributesUpdatePlugin.jar JAR 文件,请执行以下命令:

jar cfvm CustomAttributesUpdatePlugin.jar MANIFEST.MF -C src/ . added manifest adding: CustomAttributesUpdatePlugin.xml(in = 238) (out= 158)(deflated 33%) adding: postsp/(in = 0) (out= 0)(stored 0%) adding: postsp/CustomAttributesUpdatePlugin.java(in = 4377) (out= 1206)(deflated 72%) adding: postsp/CustomAttributesUpdatePlugin.class(in = 3726) (out= 1667)(deflated 55%)

这将创建 CustomAttributesUpdatePlugin.jar。查看文件内容:

unzip -l CustomAttributesUpdatePlugin.jar Archive: CustomAttributesUpdatePlugin.jar
长度 日期 时间 名称
0 10-01-2014 10:04 元信息/
542 10-01-2014 10:04 元信息/MANIFEST.MF
238 10-01-2014 09:11 CustomAttributesUpdatePlugin.xml
0 10-01-2014 09:59 邮政编码
4377 10-01-2014 09:54 Postsp/CustomAttributesUpdatePlugin.java
3726 10-01-2014 09:54 Postsp/CustomAttributesUpdatePlugin.class
8883   6  

重要说明:JAR 文件必须与实现插件的类具有相同的名称,在本例中为 CustomAttributesUpdatePlugin.jar

部署定制验证插件

执行以下步骤以在 OAM 中部署定制验证插件:

  1. 转到 OAM 管理控制台:http(s)://oam-adminhost:oam-admin-port/oamconsole
  2. 导航到访问管理器插件
  3. 单击导入插件
  4. 选择插件 JAR 文件(在此示例中为 CustomAttributesUpdatePlugin.jar

插图 Specifying_Plug-in_JAR_file.png 的说明

该插件将处于已上载状态:

插图 Plug-in_loaded_Screen.png 的说明

您需要将插件分发到运行时 OAM 服务器并激活它:

  1. 选择插件
  2. 单击“分发所选项”插件的“激活状态”选项卡显示插件的状态

插图 Plug-in_Screen_with_Status.png 的说明

您需要激活插件:

  1. 选择插件
  2. 单击“激活所选项”插件的“激活状态”选项卡显示插件的状态

插图 Plug-in_Screen_with_Status_Activated.png 的说明

创建验证模块

根据现有 FederationPlugin 验证模块创建新的联盟验证模块,该模块与现有模块不同:

要创建新的验证模块,请执行以下操作:

  1. 转到 OAM 管理控制台:http(s)://oam-adminhost: oam-admin-port/oamconsole
  2. 导航到 Access ManagerAuthentication Modules
  3. 单击创建验证模块
  4. 选择创建定制验证模块
  5. 输入名称(例如 CustomFedModule

插图 Creating_Authentication_Module.png 的说明

执行以下步骤向新验证模块添加步骤:

  1. 单击“步骤”选项卡
  2. 单击添加以添加 FedAuthnRequestPlugin 步骤:
  3. 单击确定
  4. 插图 Add_Authentication_Module.png 的说明

  5. 单击添加以添加 AssertionProcessing 步骤:
  6. 单击确定
  7. 插图 Add_Assertion_Processing_Screen.png 的说明

  8. 单击添加以添加 AttributesUpdate 步骤:
  9. 单击确定

插图 Attributes_Update_Screen.png 的说明

“步骤”选项卡显示:

插图 Steps_Screen.png 的说明

执行以下步骤可定义新验证模块的步骤编排:

  1. 单击“步骤业务流程”选项卡,选择 FedAuthnRequestPlugin 作为 FedAuthnRequestPlugin 的初始步骤:
  2. 选择成功时成功
  3. 为失败时选择 AssertionProcessing 为出错时选择失败
  4. 单击应用

插图 Define_Orchestration_Screen.png 的说明

验证方案

在使用新的验证模块的验证策略保护资源之前,需要创建一个新的验证方案,引用该新的定制模块。这是必需的,因为验证策略绑定到验证方案,而不是验证模块。要为该定制模块创建新的验证方案,请执行以下步骤:

  1. 转到 OAM 管理控制台:http(s)://oam-adminhost:oam-admin-port/oamconsole
  2. 导航到 Access Manager(访问管理器)Authentication Schemes(验证方案)
  3. 单击“Create Authentication Scheme(创建验证方案)”
  4. 输入名称(例如 CustomFedScheme)和说明 将验证级别设置为可接受的值(在此示例中为 2)
  5. 选择 FORM 作为质询方法
  6. 设置质询重定向 URL (在此示例中,将其设置为 /oam/server/
  7. 选择新创建的定制验证模块(示例中的 CustomFedModule
  8. 设置质询 URL (在此示例中为 /pages/servererror.jsp
  9. 设置上下文类型(例如 customWar
  10. 设置上下文值(在此处为 /oam,因为我们不使用任何页)
  11. 至少为质询参数输入以下内容:
  12. 单击应用

插图 Authentication_Schemes_Screen.png 的说明

测试

使用新创建的验证方案通过验证策略保护资源。这将调用定制验证模块。在联盟 SSO 之前,OAM/SP 中的 alice 的 LDAP 用户记录为:

dn: cn=alice,ou=users,dc=us,dc=oracle,dc=com
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
objectClass: top
givenName: al
title: manager
uid: alice
cn: alice
sn: APPLETON
userPassword:: e1NTSEE1MTJ9TXp0R2d0Si9GT1NzYUxvRXJqZW0rM1Q2eU5QMW9ZZmZ2Y3FkVWpaS1o1OFNGMy95ZDBueUxUbnllRi83SFRtS2JmOTJ0anY4TFd6di9UanliOGw4WFNQV1BxSnF3N mail: alice@oracle.com

验证后,IdP 将为 SAML 2.0 断言中的用户别名发送以下信息:

在联盟 SSO 之后,CustomAttributesUpdatePlugin 必须更新 alice 的 LDAP 记录,以便将 sn、assname、uid 和 mail 设置为来自 SAML 断言的值。在 OAM/SP 中执行联合 SSO 操作后的别名 LDAP 用户记录现在为:

dn: cn=alice,ou=users,dc=us,dc=oracle,dc=com
objectClass: person
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: top
givenName: Alice
title: manager
uid: alice
cn: alice
sn: Appleton
userPassword:: e1NTSEE1MTJ9TXp0R2d0Si9GT1NzYUxvRXJqZW0rM1Q2eU5QMW9ZZmZ2Y3FkVWpaS1o1OFNGMy95ZDBueUxUbnllRi83SFRtS2JmOTJ0anY4TFd6di9UanliOGw4WFNQV1BxSnF3N
mail: alice@oracle.com

更多学习资源

浏览 docs.oracle.com/learn 上的其他实验室,或在 Oracle Learning YouTube 频道上访问更多免费学习内容。此外,请访问 education.oracle.com/learning-explorer 以成为 Oracle Learning Explorer。

有关产品文档,请访问 Oracle 帮助中心