Keycloak自定义条件执行器开发经验
介绍 Keycloak中的自定义SPI种类有很多,在设计认证流时,可添加三种类型: 执行器(Execution) 在主流程中标签为execution;在子流程中标签为step 条件(Condition) 标签为condition 子流程(Sub-flow) 标签为flow 执行器用于直接执行某项认证,例如要求用户输入账户名密码、要求用户进行TOTP认证等,通常包括一个或多个用于认证的前端页面以与用户交互 条件用于根据某项信息进行决策判断,决定是否执行所在的流程或子流程,一般不包括前端页面(因为只需要与系统内信息交互,不会参与用户操作过程) 子流程用于划分更精细的认证流程,通常与条件共同构成认证流的某一个条件分支 接下来开发一个最简单的自定义条件类型SPI,作用是负责判断当前上下文中的属性registeringDevice的值是否为true,如果为true,则条件成立,否则不成立 开发 不同于开发自定义认证器SPI需要继承、实现多个类或接口,自定义条件SPI只需要一个实现了ConditionalAuthenticator接口的类以及相应地实现了ConditionalAuthenticatorFactory接口的工厂类即可 编写RegisterDeviceConditionAuthenticator类,实现ConditionalAuthenticator接口: public class RegisterDeviceConditionAuthenticator implements ConditionalAuthenticator { @Override public boolean matchCondition(AuthenticationFlowContext authenticationFlowContext) { String registeringDevice = authenticationFlowContext.getAuthenticationSession().getClientNote("registeringDevice"); return "true".equals(registeringDevice); } @Override public void action(AuthenticationFlowContext authenticationFlowContext) {} @Override public boolean requiresUser() { return false; } @Override public void setRequiredActions(KeycloakSession keycloakSession, RealmModel realmModel, UserModel userModel) {} @Override public void close() {} } 这个类唯一需要关注的就是matchCondition()方法,这个方法定义了【何种条件下条件成立】,在这里表现为读取registeringDevice属性并返回是否为"true" 接下来编写RegisterDeviceConditionAuthenticatorFactory类,实现ConditionalAuthenticatorFactory接口: public class RegisterDeviceConditionAuthenticatorFactory implements ConditionalAuthenticatorFactory { public static final String PROVIDER_ID = "register-device-condition"; private static final ConditionalAuthenticator SINGLETON = new RegisterDeviceConditionAuthenticator(); private static AuthenticationExecutionModel.Requirement[] REQUIREMENT_CHOICES = { AuthenticationExecutionModel.Requirement.REQUIRED, AuthenticationExecutionModel.Requirement.DISABLED }; @Override public String getDisplayType() { return "Condition - 注册设备时触发"; } @Override public boolean isConfigurable() { return false; } @Override public AuthenticationExecutionModel.Requirement[] getRequirementChoices() { return REQUIREMENT_CHOICES; } @Override public boolean isUserSetupAllowed() { return false; } @Override public String getHelpText() { return "只有在注册设备流程中才会执行子认证器"; } @Override public List<ProviderConfigProperty> getConfigProperties() { return null; } @Override public void init(Config.Scope scope) {} @Override public void postInit(KeycloakSessionFactory keycloakSessionFactory) {} @Override public void close() {} @Override public String getId() { return PROVIDER_ID; } // create()实际上是执行了getSingleton(),因此重写create()与重写getSingleton()是等价的 @Override public ConditionalAuthenticator getSingleton() { return SINGLETON; } } 这个工厂类定义了该条件SPI将如何展示于Keycloak系统中,并设置了“必需”、“禁用”两种可选选项,用于开关功能 ...