中文字幕精品亚洲无线码二区,国产黄a三级三级三级看三级,亚洲七七久久桃花影院,丰满少妇被猛烈进入,国产小视频在线观看网站

keycloak~登錄時將請求頭(tou)里某(mou)個屬性放入UserSessionModel

UserSessionModel做為用(yong)(yong)戶登錄過程中的(de)(de)一個會(hui)話,可以(yi)(yi)用(yong)(yong)來跨(kua)flow使用(yong)(yong)數(shu)據,這(zhe)些數(shu)據被保存(cun)到內(nei)存(cun)里,在認證(zheng)過程中可以(yi)(yi)被使用(yong)(yong),今天的(de)(de)一個需求(qiu)(qiu)要求(qiu)(qiu)在登錄時從(cong)請(qing)求(qiu)(qiu)頭獲取(qu)IP所(suo)在地并(bing)寫到kafka里,要想實(shi)現(xian)這(zhe)個需求(qiu)(qiu),你可以(yi)(yi)在現(xian)有認證(zheng)流程中修改代碼,但不建議(yi)這(zhe)樣做,因為這(zhe)種修改對原始邏輯會(hui)有破壞,keycloak提(ti)供了自定義認證(zheng)流,并(bing)在后臺(tai)可以(yi)(yi)靈活的(de)(de)配(pei)置(zhi)。

圖片

相關keycloak中的知識

認證流程的執行動作

從上(shang)面(mian)圖中可以(yi)看到,這個(ge)登錄的(de)(de)過程(cheng)會經歷多個(ge)認(ren)(ren)證(zheng)流(liu)(liu),在所有被開(kai)啟(qi)的(de)(de)認(ren)(ren)證(zheng)流(liu)(liu)執行完成(cheng)后才算登錄成(cheng)功,而這些流(liu)(liu)程(cheng)我們是可以(yi)進行按需開(kai)發并配置的(de)(de),下面(mian)說一(yi)下keycloak認(ren)(ren)證(zheng)過程(cheng)的(de)(de)幾大事(shi)件,以(yi)表(biao)單登錄為例(社區三方認(ren)(ren)證(zheng)流(liu)(liu)程(cheng)更(geng)復(fu)雜一(yi)些:

  • 表單提交
  • 標準用戶密碼認證流執行
  • 擴展認證流執行
    • 會話限制 User Session Count Limiter
    • 請求頭到session的轉換 Header-session-authenticator
    • 黑名單控制 BlackListFilterAuthenticator
    • 用戶有效性控制 User Validate
    • 弱密碼提醒 Config Simple Password Alert Form
    • MFA多因子認證 OTP Form
  • 執行jwt token構建流程,包含自定義的AbstractOIDCProtocolMapper
  • 發布Login登錄成功事件
  • 訂閱了Login事件的監聽器可以寫入kafka消息

keycloak認證流程相關元素

  1. 瀏覽器認證流Browser Flow 繼承AbstractUsernameFormAuthenticator類
  2. 直接認證流Direct Grant Flow 繼承BaseDirectGrantAuthenticator類
  3. 用戶所需要動作Require Action 實現RequiredActionProvider接口
  4. 表單頁面Form Action,實現了FormAction接口

關于登錄事件Login擴展的分析

  1. 在AbstractUsernameFormAuthenticator實現類中,添加登錄擴展參數
  2. 定義一個認證流,專業處理這塊請求頭參數,并把它放入登錄事件
  3. 定義一個Login事件監聽器,在收到后信息后,可進行中間件轉發
  4. 如果需要擴展token中的屬性,也可以通過擴展認證流來實現,將數據存入userSession,并且在AbstractOIDCProtocolMapper階段讀取userSession的內容寫入到jwtToken中

實現步驟

下(xia)面自定義一個(ge)從請求(qiu)頭獲取屬性寫入userSessionModel的(de)例子

  @JBossLog
public class RequestHeaderToSessionNoteAuthenticator implements Authenticator {

    private final KeycloakSession session;

    public RequestHeaderToSessionNoteAuthenticator(KeycloakSession session) {
        this.session = session;
    }


    @Override
    public void authenticate(AuthenticationFlowContext context) {
        HttpHeaders httpHeaders = context.getHttpRequest().getHttpHeaders();
        if (httpHeaders.getRequestHeaders().containsKey(UserUtils.EO_CLIENT_REGIONNAME)) {
            context.getAuthenticationSession().setUserSessionNote("lastLoginProvince",
                    URLDecoder.decode(httpHeaders.getHeaderString(UserUtils.EO_CLIENT_REGIONNAME)));
            context.getEvent().detail("lastLoginProvince",
                    URLDecoder.decode(httpHeaders.getHeaderString(UserUtils.EO_CLIENT_REGIONNAME)));
        }
        if (httpHeaders.getRequestHeaders().containsKey(UserUtils.EO_CLIENT_CITYNAME)) {
            context.getAuthenticationSession().setUserSessionNote("lastLoginCity",
                    URLDecoder.decode(httpHeaders.getHeaderString(UserUtils.EO_CLIENT_CITYNAME)));
            context.getEvent().detail("lastLoginCity",
                    URLDecoder.decode(httpHeaders.getHeaderString(UserUtils.EO_CLIENT_CITYNAME)));
        }
        context.success();
    }

    private EntityManager getEntityManager() {
        return this.session.getProvider(JpaConnectionProvider.class).getEntityManager();
    }

    @Override
    public void action(AuthenticationFlowContext context) {
    }

    @Override
    public boolean requiresUser() {
        return false;
    }

    @Override
    public boolean configuredFor(KeycloakSession session, RealmModel realm, UserModel user) {
        return false;
    }

    @Override
    public void setRequiredActions(KeycloakSession session, RealmModel realm, UserModel user) {

    }
}

public class RequestHeaderToSessionNoteAuthenticatorFactory implements AuthenticatorFactory, ConfigurableAuthenticatorFactory {

    public final static String PROVIDER_ID = "header-session-authenticator";


    @Override
    public String getDisplayType() {
        return "header-session-authenticator";
    }

    @Override
    public String getReferenceCategory() {
        return null;
    }

    @Override
    public boolean isConfigurable() {
        return false;
    }

    @Override
    public AuthenticationExecutionModel.Requirement[] getRequirementChoices() {
        return REQUIREMENT_CHOICES;
    }

    // 是否針對用戶有require action動作,如果沒有,requiresUser()返回也為false
    @Override
    public boolean isUserSetupAllowed() {
        return false;
    }

    @Override
    public String getHelpText() {
        return "header-session-authenticator";
    }

    @Override
    public List<ProviderConfigProperty> getConfigProperties() {
        return null;
    }

    @Override
    public Authenticator create(KeycloakSession keycloakSession) {
        return new RequestHeaderToSessionNoteAuthenticator(keycloakSession);
    }

    @Override
    public void init(Scope scope) {
    }

    @Override
    public void postInit(KeycloakSessionFactory keycloakSessionFactory) {
    }

    @Override
    public void close() {
    }

    @Override
    public String getId() {
        return PROVIDER_ID;
    }
}

最后在resources/META-INF/services/org.keycloak.authentication.AuthenticatorFactory中添加你的(de)這個(ge)Factory即可(ke)。

posted @ 2025-11-05 14:01  張占嶺  閱讀(19)  評論(0)    收藏  舉報