首页 > 其他分享 >keycloak~RequiredActionProvider的使用

keycloak~RequiredActionProvider的使用

时间:2024-04-11 09:35:52浏览次数:23  
标签:RequiredActionProvider challenge context 使用 Override public keycloak

使用场景

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后台启用它,并开启“默认”选项
  • 要想对某些规则的用户启用它,需要在form表单认证时,添加对应的业务逻辑,可以添加自定义的"Authenticator"来实现这个逻辑,尽量不修改之前的核心代码。
  if(context.getUser().getUsername().startsWith("test")){
    context.getUser().addRequiredAction(UpdatePhoneNumberRequiredAction.PROVIDER_ID);
  }
  context.success();

好了,到目前来说,咱们用户名登录时,前缀为test的用户,都会走这个手机验证的界面了,在验证成功前,用户是不能直接登录的。

标签:RequiredActionProvider,challenge,context,使用,Override,public,keycloak
From: https://www.cnblogs.com/lori/p/18128023

相关文章

  • VB中DirectCast和CType的区别及使用
    DirectCast:主要用于执行明确的类型转换,只能在编译时确定类型关系时使用。如果转换不是有效的,则会引发异常。如果你要把一个Object变量用DirectCast转换成String,必须确定这个变量确实包含一个String(或者为Nothing).如果它包含一个Integer之类的东西,会抛出一个异常......
  • 使用docker部署基于selenium和chrome-headless的爬虫
    使用docker部署基于selenium和chrome-headless的爬虫无论是测试还是爬虫的一些工作,有时候都会用到selenium去对chrome执行自动化操作,这里介绍一下如何使用docker快捷方便的部署相关应用。1.selenium+chrome镜像通过dockersearchselenium我们发现,有一个docker镜像叫做sele......
  • Windows环境下scoop使用
    #安装(powershell管理员)iex(new-objectnet.webclient).downloadstring('https://get.scoop.sh')#卸载scoopuninstallscoop#安装必备软件(必装后面方便折腾)scoopinstallaria2scoopinstall7zipscoopintallgit#对aria2进行设置scoopconfigaria2-split3scoop......
  • linux 修复ntfs磁盘,安装和使用NTFSfix(安装Ntfs-3g),以在Linux上修复Windows硬盘驱动
    本文介绍在Linux系统中安装和使用NTFSfix(安装Ntfs-3g)的方法,支持Ubuntu、Debian、ArchLinux、Fedora、OpenSUSE,使用它可以在Linux上修复不工作的Windows硬盘驱动器。你是否有运行NTFS文件系统的dirtyWindows硬盘驱动器,遇到问题并且不想重新启动到Windows?如果是这样,别担心,使用......
  • 一个使用HOOK/WH_GETMESSAGE解决软件交互问题的案例
    一、问题背景:1、某设计软件AD,可以打开/编辑二维电路设计界面,其交互方式如下:(1)鼠标右键按下拖动(2)鼠标滚轮上下移动(3)鼠标滚轮按下+鼠标移动缩放(4)ctrl+鼠标滚轮缩放   该软件的交互方式可以通过软件设置修改,但是基本的使用习惯就是如此,用户的一个场景是通过每台机器msts......
  • 前端使用 Konva 实现可视化设计器(3)
    github/giteeStar终于有几个了!从这章开始,难度算是(或者说细节较多)升级,是不是值得更多的Star呢?!继续求Star,希望大家多多一键三连,十分感谢大家的支持~创作不易,Star50个,创作加速!github源码gitee源码示例地址选择框准备工作想要拖动一个元素,可以考虑使用节点的drag......
  • 【讲解下Fiddler的安装和使用】
    ......
  • 使用dd命令创建swap交换分区
    [root@k-DevOps-10-13~]#ddif=/dev/zeroof=/data/swapfilebs=1Mcount=3072030720+0recordsin30720+0recordsout32212254720bytes(32GB)copied,148.272s,217MB/s[root@k-DevOps-10-13~]#chmod666/data/swapfile[root@k-DevOps-10-13~]#mkswap/......
  • 使用 `omit` 函数移除敏感信息
    exportdefaultfunctionomit<Textendsobject,KextendskeyofT>(obj:T,fields:K[]|readonlyK[],):Omit<T,K>{constclone={...obj};if(Array.isArray(fields)){fields.forEach(key=>{deleteclone[key];......
  • Python中关于finally的使用场景
    finally关键字在Python中用于定义一个代码块,该代码块在try-except结构中无论是否发生异常,或者在try块中执行了return、break、continue等控制流语句,都会被执行。finally子句提供了确保某些清理操作(如释放资源、关闭文件、断开连接等)始终执行的一种机制,即使程序在处理过程中遭遇异......