You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WSO2 IS 5.10自定义自适应函数无法设置Claim问题求助

问题:WSO2 IS 5.10自定义自适应函数添加Claim无效

使用WSO2 IS 5.10开发自定义自适应函数setForceAuth,意图添加自定义Claim,但在自适应认证脚本中调用该函数时无法生效,不过该函数在自定义认证器中可正常工作。


SetForceAuthFunctionImpl实现类代码

package org.wso2.custom.auth.functions;

import java.util.HashMap;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.identity.application.authentication.framework.config.model.graph.js.JsAuthenticatedUser;
import org.wso2.carbon.identity.application.authentication.framework.config.model.graph.js.JsAuthenticationContext;
import org.wso2.carbon.identity.application.authentication.framework.model.AuthenticatedUser;
import org.wso2.carbon.utils.multitenancy.MultitenantUtils;
import org.wso2.custom.auth.functions.internal.CustomAuthFuncComponent;
import org.wso2.carbon.identity.application.authentication.framework.config.model.graph.js.*;

public class SetForceAuthFunctionImpl implements SetForceAuthFunction {

    private static final Log LOGGER = LogFactory.getLog(SetForceAuthFunctionImpl.class);
    
    
    @Override
    public JsAuthenticatedUser setForceAuth(JsAuthenticationContext context, boolean forceAuth) {

        AuthenticatedUser lastAuthenticatedUser = context.getContext().getLastAuthenticatedUser();
        
        LOGGER.info("lastAuthenticatedUser****:::::::::::"+lastAuthenticatedUser);
        String userName = lastAuthenticatedUser.getUserName();
        LOGGER.info("userName2****:::::::::::"+userName);
        
        
        String tenantDomain = MultitenantUtils.getTenantDomain(userName);
        String fullyQualifiedUserName=("USERS"+"/"+userName+"@"+tenantDomain);
        Map<org.wso2.carbon.identity.application.common.model.ClaimMapping, String> claims = new HashMap<org.wso2.carbon.identity.application.common.model.ClaimMapping, String>();
        claims.put(org.wso2.carbon.identity.application.common.model.ClaimMapping.build("test123", "test123", null, true), org.apache.commons.lang3.StringUtils.join("*******************",",,,"));
        
        AuthenticatedUser authenticatedUserObj = AuthenticatedUser.createLocalAuthenticatedUserFromSubjectIdentifier(MultitenantUtils.getTenantAwareUsername
                (fullyQualifiedUserName));
        authenticatedUserObj.setAuthenticatedSubjectIdentifier(MultitenantUtils.getTenantAwareUsername
                (fullyQualifiedUserName));
        authenticatedUserObj.setUserAttributes(claims);
        authenticatedUserObj.setUserName(MultitenantUtils.getTenantAwareUsername
                (fullyQualifiedUserName));
        
        
        return new JsAuthenticatedUser(authenticatedUserObj);
    }
}

CustomAuthFuncComponent组件代码

package org.wso2.custom.auth.functions.internal;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.osgi.service.component.ComponentContext;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.osgi.service.component.annotations.ReferencePolicy;
import org.wso2.carbon.identity.application.authentication.framework.JsFunctionRegistry;
import org.wso2.carbon.registry.core.service.RegistryService;
import org.wso2.carbon.user.core.service.RealmService;
import org.wso2.custom.auth.functions.GenerateHashFunction;
import org.wso2.custom.auth.functions.GenerateHashFunctionImpl;
import org.wso2.custom.auth.functions.GetClaimsForUsernameFunction;
import org.wso2.custom.auth.functions.GetClaimsForUsernameFunctionImpl;
import org.wso2.custom.auth.functions.GetUsernameFromContextFunction;
import org.wso2.custom.auth.functions.GetUsernameFromContextFunctionImpl;
import org.wso2.custom.auth.functions.SetForceAuthFunction;
import org.wso2.custom.auth.functions.SetForceAuthFunctionImpl;

@Component(
        name = "custom.auth.functions.component",
        immediate = true
)
public class CustomAuthFuncComponent {

    private static final Log LOG = LogFactory.getLog(CustomAuthFuncComponent.class);
    private static JsFunctionRegistry jsFunctionRegistry;

    @Activate
    protected void activate(ComponentContext ctxt) {

        SetForceAuthFunction setForceAuthFunctionImpl = new SetForceAuthFunctionImpl();
        jsFunctionRegistry.register(JsFunctionRegistry.Subsystem.SEQUENCE_HANDLER, "setForceAuth",
                setForceAuthFunctionImpl);

        GetUsernameFromContextFunction getUsernameFromContextFunctionImpl = new GetUsernameFromContextFunctionImpl();
        jsFunctionRegistry.register(JsFunctionRegistry.Subsystem.SEQUENCE_HANDLER, "getUsernameFromContext",
                getUsernameFromContextFunctionImpl);

        GetClaimsForUsernameFunction getClaimsForUsernameFunctionImpl = new GetClaimsForUsernameFunctionImpl();
        jsFunctionRegistry.register(JsFunctionRegistry.Subsystem.SEQUENCE_HANDLER, "getClaimsForUsername",
                getClaimsForUsernameFunctionImpl);

        GenerateHashFunction generateHashFunctionImpl = new GenerateHashFunctionImpl();
        jsFunctionRegistry.register(JsFunctionRegistry.Subsystem.SEQUENCE_HANDLER, "generateHash",
                generateHashFunctionImpl);
    }

    @Deactivate
    protected void deactivate(ComponentContext ctxt) {

        if (jsFunctionRegistry != null) {
            jsFunctionRegistry.deRegister(JsFunctionRegistry.Subsystem.SEQUENCE_HANDLER, "setForceAuth");
            jsFunctionRegistry.deRegister(JsFunctionRegistry.Subsystem.SEQUENCE_HANDLER, "getUsernameFromContext");
            jsFunctionRegistry.deRegister(JsFunctionRegistry.Subsystem.SEQUENCE_HANDLER, "getClaimsForUsername");
            jsFunctionRegistry.deRegister(JsFunctionRegistry.Subsystem.SEQUENCE_HANDLER, "generateHash");
        }
    }

    @Reference(
            name = "user.realmservice.default",
            service = RealmService.class,
            cardinality = ReferenceCardinality.MANDATORY,
            policy = ReferencePolicy.DYNAMIC,
            unbind = "unsetRealmService"
    )
    protected void setRealmService(RealmService realmService) {

        if (LOG.isDebugEnabled()) {
            LOG.debug("RealmService is set in the custom conditional authentication user functions bundle");
        }
        CustomAuthFuncHolder.getInstance().setRealmService(realmService);
    }

    protected void unsetRealmService(RealmService realmService) {

        if (LOG.isDebugEnabled()) {
            LOG.debug("RealmService is unset in the custom conditional authentication user functions bundle");
        }
        CustomAuthFuncHolder.getInstance().setRealmService(null);
    }

    @Reference(
            name = "registry.service",
            service = RegistryService.class,
            cardinality = ReferenceCardinality.MANDATORY,
            policy = ReferencePolicy.DYNAMIC,
            unbind = "unsetRegistryService"
    )
    protected void setRegistryService(RegistryService registryService) {

        if (LOG.isDebugEnabled()) {
            LOG.debug("RegistryService is set in the custom conditional authentication user functions bundle");
        }
        CustomAuthFuncHolder.getInstance().setRegistryService(registryService);
    }

    protected void unsetRegistryService(RegistryService registryService) {

        if (LOG.isDebugEnabled()) {
            LOG.debug("RegistryService is unset in the custom conditional authentication user functions bundle");
        }
        CustomAuthFuncHolder.getInstance().setRegistryService(null);
    }

    @Reference(
            service = JsFunctionRegistry.class,
            cardinality = ReferenceCardinality.MANDATORY,
            policy = ReferencePolicy.DYNAMIC,
            unbind = "unsetJsFunctionRegistry"
    )
    public void setJsFunctionRegistry(JsFunctionRegistry jsFunctionRegistry) {

        this.jsFunctionRegistry = jsFunctionRegistry;
    }

    public void unsetJsFunctionRegistry(JsFunctionRegistry jsFunctionRegistry) {

        this.jsFunctionRegistry = null;
    }
}

自适应认证脚本代码

function onLoginRequest(context) {
    doLogin(context);
}

function doLogin(context) {
  executeStep(1,{
        onSuccess: function (context) {
        },
        onFail: function(context){
           executeStep(4,{
                onSuccess: function (context) {
                    var subject = context.currentKnownSubject;
                    setForceAuth(context, true);
                    
            },
                onFail: function(context){
                }
            });
             
        }
    });
}

排查要点及解决方案

  1. 上下文未更新
    函数创建了新的AuthenticatedUser对象,但未将其设置回认证上下文。修改脚本调用逻辑:

    var updatedUser = setForceAuth(context, true);
    context.currentKnownSubject = updatedUser;
    
  2. Claim URI配置错误
    代码中ClaimMapping.build的第一个参数应为合法的Claim URI(需提前在WSO2 IS控制台配置),而非自定义名称。修改示例:

    claims.put(ClaimMapping.build("http://wso2.org/claims/test123", "test123", null, true), "目标Claim值");
    
  3. 用户标识符格式错误
    fullyQualifiedUserName拼接格式不符合WSO2规范,本地用户标识符应为username@tenantdomain,无需前缀USERS/,修改代码:

    String fullyQualifiedUserName = userName + "@" + tenantDomain;
    AuthenticatedUser authenticatedUserObj = AuthenticatedUser.createLocalAuthenticatedUserFromSubjectIdentifier(
        MultitenantUtils.getTenantAwareUsername(userName)
    );
    
  4. 函数注册子系统错误
    自适应认证函数需注册到AUTHENTICATION子系统,而非SEQUENCE_HANDLER,修改组件激活方法中的注册代码:

    jsFunctionRegistry.register(JsFunctionRegistry.Subsystem.AUTHENTICATION, "setForceAuth", setForceAuthFunctionImpl);
    

内容的提问来源于stack exchange,提问作者rahul

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 17:15:43