向SAML响应中添加自定义声明–(如何为WSO2 Identity Server编写自定义声明处理程序)...

总览

最新版本的WSO2 Identity Server(版本5.0.0)配备了“应用程序身份验证框架”,该框架提供了很大的灵活性,可以对来自使用异构协议的各种服务提供商的用户进行身份验证。 它具有多个扩展点,可用于满足企业系统中常见的几个自定义要求。 在这篇文章中,我将分享使用这样一个扩展点的细节。


功能扩展

在企业系统中使用SAML单一登录时,依赖方通过SAML响应来了解用户是否已通过身份验证。 在这一点上,依赖方尚不知道其为业务和授权目的可能需要的已认证用户的其他属性。 为了向依赖方提供这些属性详细信息,SAML规范允许在SAML响应中也发送属性。 WSO2 Identity Server通过为管理员提供的GUI开箱即用地支持此功能。 有关此功能和配置的详细信息,请参阅[1]。

当我们需要向SAML响应中添加除下划线用户存储中可用的属性之外的其他属性时,此特定扩展提供的灵活性会派上用场。 为了提供依赖方请求的所有属性,可能需要寻找外部数据源。

在这里我要描述的样本中,我们将研究一个场景,该系统需要提供一些存储在用户存储中的用户本地属性,以及一些我希望从外部数据源中检索到的其他属性。
遵循SAML响应是我们需要从WSO2 IS发送给依赖方的内容。

<saml2p:Response Destination="https://localhost:9444/acs" ID="faibaccbcepemkackalbbjkihlegenhhigcdjbjk"
                 InResponseTo="kbedjkocfjdaaadgmjeipbegnclbelfffbpbophe" IssueInstant="2014-07-17T13:15:05.032Z"
                 Version="2.0" xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol"
                 xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <saml2:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity"
                  xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">localhost
    </saml2:Issuer>
    <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
        ..........
    </ds:Signature>
    <saml2p:Status>
        <saml2p:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
    </saml2p:Status>
    <saml2:Assertion ID="phmbbieedpcfdhcignelnepkemobepgaaipbjjdk" IssueInstant="2014-07-17T13:15:05.032Z" Version="2.0"
                     xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:xs="http://www.w3.org/2001/XMLSchema">
        <saml2:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">localhost</saml2:Issuer>
        <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
            .........
        </ds:Signature>
        <saml2:Subject>
          <saml2:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">Administrator</saml2:NameID>
            <saml2:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
                <saml2:SubjectConfirmationData InResponseTo="kbedjkocfjdaaadgmjeipbegnclbelfffbpbophe"
                                               NotOnOrAfter="2014-07-17T13:20:05.032Z"
                                               Recipient="https://localhost:9444/acs"/>
            </saml2:SubjectConfirmation>
        </saml2:Subject>
        <saml2:Conditions NotBefore="2014-07-17T13:15:05.032Z" NotOnOrAfter="2014-07-17T13:20:05.032Z">
            <saml2:AudienceRestriction>
                <saml2:Audience>carbonServer2</saml2:Audience>
            </saml2:AudienceRestriction>
        </saml2:Conditions>
        <saml2:AuthnStatement AuthnInstant="2014-07-17T13:15:05.033Z">
            <saml2:AuthnContext>
                <saml2:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml2:AuthnContextClassRef>
            </saml2:AuthnContext>
        </saml2:AuthnStatement>
        <saml2:AttributeStatement>
            <saml2:Attribute Name="http://wso2.org/claims/role"
                             NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
                <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">
                    Internal/carbonServer2,Internal/everyone
                </saml2:AttributeValue>
            </saml2:Attribute>
            <saml2:AttributeStatement>
                <saml2:Attribute Name="http://pushpalanka.org/claims/keplerNumber"
                                 NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
                    <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">
                        E90836W19881010
                    </saml2:AttributeValue>
                </saml2:Attribute>
                <saml2:Attribute Name="http://pushpalanka.org/claims/status"
                                 NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
                    <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">
                        active
                    </saml2:AttributeValue>
                </saml2:Attribute>
            </saml2:AttributeStatement>
        </saml2:AttributeStatement>
    </saml2:Assertion>
</saml2p:Response>

在此响应中,我们具有一个本地属性(即角色)和另外两个属性http://pushpalanka.org/claims/keplerNumber和http://pushpalanka.org/claims/status,这些属性已从其他方法中检索出在我们的扩展名中定义。

怎么样?

  1. 实施定制逻辑以获取外部声明。 我们仅需注意两个事实。
    • 定制实现应实现接口“ org.wso2.carbon.identity.application.authentication.framework.handler.claims.ClaimHandler”,或扩展接口“ org.wso2.carbon.identity.application.authentication”的默认实现。 framework.handler.claims.impl.DefaultClaimHandler”。
    • 在方法“ public Map <String,String> handleClaimMappings”处返回的映射应包含我们要添加到SAML响应中的所有属性。

    以下是我按照上面编写的示例代码。 外部声明可能已从数据库中查询,从文件中读取或根据需要使用任何其他机制。

    public class CustomClaimHandler implements ClaimHandler {
    
        private static Log log = LogFactory.getLog(CustomClaimHandler.class);
        private static volatile CustomClaimHandler instance;
        private String connectionURL = null;
        private String userName = null;
        private String password = null;
        private String jdbcDriver = null;
        private String sql = null;
    
    
        public static CustomClaimHandler getInstance() {
            if (instance == null) {
                synchronized (CustomClaimHandler.class) {
                    if (instance == null) {
                        instance = new CustomClaimHandler();
                    }
                }
            }
            return instance;
        }
    
        public Map<String, String> handleClaimMappings(StepConfig stepConfig,
                                                       AuthenticationContext context, Map<String, String> remoteAttributes,
                                                       boolean isFederatedClaims) throws FrameworkException {
    
            String authenticatedUser = null;
    
            if (stepConfig != null) {
                //calling from StepBasedSequenceHandler
                authenticatedUser = stepConfig.getAuthenticatedUser();
            } else {
                //calling from RequestPathBasedSequenceHandler
                authenticatedUser = context.getSequenceConfig().getAuthenticatedUser();
            }
    
            Map<String, String> claims = handleLocalClaims(authenticatedUser, context);
            claims.putAll(handleExternalClaims(authenticatedUser));
    
            return claims;
        }
    
    
        /**
         * @param context
         * @return
         * @throws FrameworkException
         */
        protected Map<String, String> handleLocalClaims(String authenticatedUser,
                                                        AuthenticationContext context) throws FrameworkException {
    	....
        }
    
        private Map<String, String> getFilteredAttributes(Map<String, String> allAttributes,
                                                          Map<String, String> requestedClaimMappings, boolean isStandardDialect) {
    	....
        }
    
        protected String getDialectUri(String clientType, boolean claimMappingDefined) {
    	....
        }
    
        /**
         * Added method to retrieve claims from external sources. This results will be merged to the local claims when
         * returning final claim list, to be added to the SAML response, that is sent back to the SP.
         *
         * @param authenticatedUser : The user for whom we require claim values
         * @return
         */
        private Map<String, String> handleExternalClaims(String authenticatedUser) throws FrameworkException {
            Map<String, String> externalClaims = new HashMap<String, String>();
            externalClaims.put("http://pushpalanka.org/claims/keplerNumber","E90836W19881010");
            externalClaims.put("http://pushpalanka.org/claims/status","active");
            return externalClaims;
        }
    }
  2. 将已编译的OSGI软件包放在IS_HOME / repository / components / dropins中。 (我们将其开发为OSGI捆绑软件,因为我们还需要使用RealmService获得本地声明。 您可以在此处找到完整的捆绑软件和源代码
  3. 使WSO2 Identity Server使用我们拥有的新的自定义实现。

在IS_HOME / repository / conf / security / applicationauthentication.xml中,配置新的处理程序名称。 (在“ ApplicationAuthentication.Extensions.ClaimHandler”元素中。)

   <ClaimHandler>com.wso2.sample.claim.handler.CustomClaimHandler</ClaimHandler>

现在,如果查看生成的SAML响应,我们将看到添加的外部属性。

干杯!

[1] – https://docs.wso2.com/display/IS500/Adding+a+Service+Provider

翻译自: https://www.javacodegeeks.com/2014/08/adding-custom-claims-to-the-saml-response-how-to-write-a-custom-claim-handler-for-wso2-identity-server.html

在PHP使用cURL库实现与Microsoft Azure AD的SAML 2.0登录过程,通常涉及以下几个步骤: 1. 初始化cURL会话。 2. 设置cURL选项,包括URL、请求方法、头部信息、POST字段等。 3. 发送请求并获取响应。 4. 关闭cURL会话。 以下是一个简化的示例,展示如何使用PHP的cURL功能向Microsoft Azure AD发送登录请求: ```php <?php // 初始化cURL会话 $ch = curl_init(); // 设置请求的URL curl_setopt($ch, CURLOPT_URL, "https://login.microsoftonline.com/common/saml2"); // 设置请求方法为POST curl_setopt($ch, CURLOPT_POST, true); // 设置POST字段(例如用户名和密码) // 注意:实际应用SAML认证不需要直接在URL提交用户名和密码,而是需要构建一个SAML请求 // 这里仅为示例,具体情况需要根据实际认证协议处理 $postData = http_build_query(array( 'username' => 'your_username', 'password' => 'your_password' )); curl_setopt($ch, CURLOPT_POSTFIELDS, $postData); // 设置请求头部信息,需要包括内容类型和接受类型等 curl_setopt($ch, CURLOPT_HTTPHEADER, array( 'Content-Type: application/x-www-form-urlencoded', 'Accept: */*' )); // 执行cURL请求并获取响应 $response = curl_exec($ch); // 检查是否有错误发生 if (curl_errno($ch)) { echo 'cURL error: ' . curl_error($ch); } else { // 打印服务器响应 echo $response; } // 关闭cURL会话 curl_close($ch); ?> ``` 请注意,上面的代码仅用于说明如何使用cURL来发送HTTP请求,并不适用于实际的SAML 2.0登录流程,因为SAML认证流程涉及到构建和解析SAML请求响应,这些通常需要使用专门的库来处理,而不是简单的POST请求。 对于实际的SAML认证,你需要根据SAML协议构造认证请求,处理SAML响应,并从解析出所需的令牌信息,通常需要使用如`OneLogin_Saml2\Auth`等专门的库。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值