使用场景
RequiredActionProvider,它是在认证过程中,需要当前登录的用户实行个性化的动作;当用户符合条件,就被实行RequiredActionProvider对作,当RequiredActionProvider没有正常提交(context.success())之前,当前用户仍旧是未登录状态,这在keycloak框架中,也有一些默认的个性化动作,它与整个登录流程是解耦的,事实上,keycloak的设计理念也是微架构设计,插件化设计。
keycloak默认提供的RequiredActionProvider
- VERIFY_EMAIL 验证邮箱
- UPDATE_PROFILE 更新用户信息
- CONFIGURE_TOTP 设置totp多因子认证
- UPDATE_PASSWORD 强制更新密码,用在临时建立的密码场景(CredentialRepresentation中的isTemporary为true时实行)
- TERMS_AND_CONDITIONS 用户在初次登录时会被要求查看并接受特定的服务条款和条件
- VERIFY_PROFILE 验证个人信息
keycloak后台设置RequiredActionProvider
在侧-验证菜单,选择Required Action标签,可以管理它们,开启大概设置成默认,同时也可以添加自定义的RequiredActionProvider
1 设置列表
2 添加新的Required Action
自定义的RequiredActionProvider
下面我们添加一个自定义的RequiredActionProvider,业务场景是,当登任命户名前缀是test时,就让这个用户去验证手机号
1 添加一个UpdatePhoneNumberRequiredAction文件,让它实现RequiredActionProvider接口- public class UpdatePhoneNumberRequiredAction implements RequiredActionProvider {
- public static final String PROVIDER_ID = "UPDATE_PHONE_NUMBER";
- @Override
- public void evaluateTriggers(RequiredActionContext context) {
- }
- @Override
- public void requiredActionChallenge(RequiredActionContext context) {
- Response challenge = context.form()
- .createForm("login-update-phone-number.ftl");
- context.challenge(challenge);
- }
- @Override
- public void processAction(RequiredActionContext context) {
- TokenCodeServiceProvider tokenCodeServiceProvider = context.getSession().getProvider(TokenCodeServiceProvider.class);
- String phoneNumber = context.getHttpRequest().getDecodedFormParameters().getFirst("phoneNumber");
- String code = context.getHttpRequest().getDecodedFormParameters().getFirst("code");
- try {
- tokenCodeServiceProvider.validateCode(context.getUser(), phoneNumber, code);
- context.success();
- } catch (BadRequestException e) {
- Response challenge = context.form()
- .setError("noOngoingVerificationProcess")
- .createForm("login-update-phone-number.ftl");
- context.challenge(challenge);
- } catch (ForbiddenException e) {
- Response challenge = context.form()
- .setAttribute("phoneNumber", phoneNumber)
- .setError("verificationCodeDoesNotMatch")
- .createForm("login-update-phone-number.ftl");
- context.challenge(challenge);
- }
- }
- @Override
- public void close() {
- }
- }
复制代码 2 添加UpdatePhoneNumberRequiredActionFactory文件,让它去构建上面的UpdatePhoneNumberRequiredAction实例- public class UpdatePhoneNumberRequiredActionFactory implements RequiredActionFactory {
- private static final UpdatePhoneNumberRequiredAction instance = new UpdatePhoneNumberRequiredAction();
- @Override
- public String getDisplayText() {
- return "";
- }
- @Override
- public RequiredActionProvider create(KeycloakSession session) {
- return instance;
- }
- @Override
- public void init(Scope scope) {
- }
- @Override
- public void postInit(KeycloakSessionFactory sessionFactory) {
- }
- @Override
- public void close() {
- }
- @Override
- public String getId() {
- return UpdatePhoneNumberRequiredAction.PROVIDER_ID;
- }
- }
复制代码 3 在resources/META-INF/services/文件夹下,添加org.keycloak.authentication.RequiredActionFactory文件,通过SPI的方式,注册咱们的UpdatePhoneNumberRequiredActionFactory工厂- org.keycloak.phone.authentication.requiredactions.UpdatePhoneNumberRequiredActionFactory
复制代码
4 添加咱们这个UpdatePhoneNumberRequiredActionFactory,它在keycloak后台RequiredActionProvider中,显示的名称是“Update Phone Number”,我们去添加并开启它
5 在brower的认证流程中,你需要在context.success()之前去判断用户名的前缀,并为它指定RequiredAction,如果是对全部用户有效的,那不需要添加以下代码,可以把它在keycloak后台,设置为“默认”行为即可。
- 要想使RequiredAction见效,需要先在keycloak后台启用它
- 要想对新建用户启用它,需要先在keycloak后台启用它,并开启“默认”选项【默认是对新用户来说的,老用户不受这个值的控制,就是说你新建一个requiredAction,没有任何规则,如果你开启+默认,那它只对全部新建用户有效】
- 要想对某些规则的用户启用它,需要在form表单认证时,添加对应的业务逻辑,可以添加自定义的"Authenticator"来实现这个逻辑,尽量不修改之前的核心代码。
- 当前用户实行的RequiredAction步调,会在数据表user_required_action中存储,用户每次登录都会检查这个表的状态,如果用户存在这表里,你的对应的RequiredAction关闭了,事实上,当前这个老用户在登录时依然会走这个RequiredAction逻辑。
- 注意,这个user_required_action表产生的数据会有缓存,只删除数据表记载是不起作用的,需要重启keycloak
- 这个user_required_action表里对应的用户数据,当用户成功验证后,这条数据会被删除,下次用户再登录,就不会出现required_action了
- if(context.getUser().getUsername().startsWith("test")){
- context.getUser().addRequiredAction(UpdatePhoneNumberRequiredAction.PROVIDER_ID);
- }
- context.success();
复制代码 好了,到目前来说,咱们用户名登录时,前缀为test的用户,都会走这个手机验证的界面了,在验证成功前,用户是不能直接登录的。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |