欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

分析xxljob登入功能集成OIDC的統(tǒng)一認(rèn)證

 更新時(shí)間:2022年02月21日 09:20:18   作者:kl  
這篇文章主要為大家介紹分析xxljob登入功能集成OIDC的統(tǒng)一認(rèn)證的詳解說(shuō)明,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步

前言

xxl-job 是一款 java 開發(fā)的、開源的分布式任務(wù)調(diào)度系統(tǒng),自帶了登錄認(rèn)證功能,不支持對(duì)接、擴(kuò)展 LDAP 、OIDC 等標(biāo)準(zhǔn)認(rèn)證系統(tǒng),考慮到單獨(dú)維護(hù) xxl-job 自有的用戶系統(tǒng)不方便,以及存在人員離職、調(diào)崗、權(quán)限變動(dòng)等需要及時(shí)調(diào)整用戶權(quán)限的情況,需要接入公司統(tǒng)一的 OIDC 認(rèn)證系統(tǒng)

相關(guān)鏈接

XXL-JOB 自身認(rèn)證功能分析

xxl-job 自帶的登錄認(rèn)證用戶信息維護(hù)在 mysql 的 user 表中,用戶從登錄頁(yè)提交用戶名和密碼,后端查詢用戶信息、校驗(yàn)密碼,驗(yàn)證成功后設(shè)置登錄信息到 cookie 中,采用 cookie 保持登錄狀態(tài),大致的流程如下:

OIDC 的認(rèn)證流程

OIDC(OpenID Connect) 是一種融合了 OpenID 、Oauth2 的身份認(rèn)證協(xié)議。認(rèn)證流程上和 Oauth2 基本一致,但是,OIDC 在 Oauth2 的 access\_token 基礎(chǔ)上新增了一個(gè)使用 jwt 生成的 idToken,idToken 中攜帶了用戶基本信息,使用私鑰驗(yàn)簽成功后,可直接使用,省略了通過(guò) access\_token 獲取用戶信息的步驟。所以 OIDC 的認(rèn)證流程既和 Oauth2 類似又有區(qū)別,基本流程如下:

  • 客戶端準(zhǔn)備包含所需請(qǐng)求參數(shù)的身份驗(yàn)證請(qǐng)求。
  • 客戶端將請(qǐng)求發(fā)送到授權(quán)服務(wù)器。
  • 授權(quán)服務(wù)器對(duì)終端用戶進(jìn)行身份驗(yàn)證。
  • 授權(quán)服務(wù)器獲得終端用戶同意/授權(quán)。
  • 授權(quán)服務(wù)器將 code 發(fā)送回客戶端 。
  • 客戶端將 code 發(fā)送到令牌端點(diǎn)獲取 access_token 和 idToken。
  • 客戶端使用私鑰驗(yàn)證 idToken 拿到用戶標(biāo)識(shí) or 將 access_token 發(fā)送到授權(quán)服務(wù)器獲取用戶標(biāo)識(shí)。

這里注意最后第 6、7 點(diǎn)操作,這里開始 OIDC 和 Oauth2 不一樣了

XXL-JOB 集成 OIDC 后的認(rèn)證流程

從 OIDC 的認(rèn)證流程得知,終端用戶通過(guò)授權(quán)服務(wù)器授權(quán)認(rèn)證后,授權(quán)服務(wù)器會(huì)攜帶 code 重定向到客戶端服務(wù),客戶端通過(guò) code 可以拿到用戶唯一標(biāo)識(shí),通過(guò)這個(gè)唯一標(biāo)識(shí),可以繼續(xù)完成客戶端原本的認(rèn)證流程。集成 OIDC 后,xxl-job 登錄的大致流程如下:

集成 OIDC 后,系統(tǒng)認(rèn)證保持用戶登錄狀態(tài)的機(jī)制沒(méi)有變化,依然使用  Cookie ,需要特殊處理以及關(guān)注地方有:

  • 用戶首次登錄系統(tǒng),由于不存在系統(tǒng)中,需要先創(chuàng)建用戶
  • 如果系統(tǒng)首次投產(chǎn)使用,記得設(shè)計(jì)一個(gè)可以從配置指定管理賬戶的功能,不然你得手動(dòng)改數(shù)據(jù)庫(kù)了
  • 如果系統(tǒng)運(yùn)行很久了,需要考慮好原系統(tǒng)用戶和 OIDC 授權(quán)用戶的映射關(guān)系
  • 退出操作時(shí),除了清除自身的用戶登錄狀態(tài),是否退出 OIDC 服務(wù)(實(shí)現(xiàn) sso)的登錄狀態(tài)也需要考慮

XXL-JOB 登錄模塊重新設(shè)計(jì)

考慮開發(fā)環(huán)境使用 OIDC 服務(wù)不方便以及解耦對(duì)第三方認(rèn)證授權(quán)服務(wù)的依賴,決定在集成 OIDC 時(shí),兼容本地登錄功能,登錄流程由登錄模式來(lái)控制區(qū)分,登錄模式使用配置驅(qū)動(dòng),設(shè)計(jì)集成 OIDC 后 ,xxl-job 支持的登錄模式如下:

  • onlyLocal :只支持 xxl-job 自身用戶系統(tǒng)登錄認(rèn)證
  • onlyOidc : 只支持 Oidc 授權(quán)服務(wù)器授權(quán)登錄認(rèn)證
  • mix :混合模式,同時(shí)支持自身用戶系統(tǒng)登錄認(rèn)證、Oidc 授權(quán)服務(wù)器授權(quán)登錄認(rèn)證

onlyLocal 模式登錄界面:

mix 模式登錄界面:

olnyOidc 模式登錄界面:

olnyOidc 模式特殊,從設(shè)計(jì)上來(lái)說(shuō),如果需要保留用戶使用習(xí)慣,可以保留一個(gè)跳轉(zhuǎn)到 OIDC 授權(quán)服務(wù)器的鏈接按鈕給用戶點(diǎn)擊。如果做的干凈利落,在 olnyOidc 模式下,訪問(wèn)登錄頁(yè)可以直接 302 到 OIDC 授權(quán)服務(wù)器。

保留登錄按鈕的界面(實(shí)際這個(gè)頁(yè)面取消了)

編碼環(huán)節(jié)

配置屬性類,省略了get、set

/**
 * @author kl (http://kailing.pub)
 * @since 2021/6/21
 */
@ConfigurationProperties(prefix = "oidc")
@Configuration
public class OidcProperties {
    private static final LoginMod DEFAULT_LOGIN_MOD = LoginMod.onlyLocal;
    private LoginMod loginMod = DEFAULT_LOGIN_MOD;
    private String clientId;
    private String clientSecret;
    private String accessTokenUrl;
    private String profileUrl;
    private String redirectUri;
    private String logoutUrl;
    private String loginUrl;
    private ListadminLists = new ArrayList<>();
    public enum LoginMod {
        mix,
        onlyOidc,
        onlyLocal
    }
}

對(duì)應(yīng)了如下的配置, 除了 login-mod  、redirect-uri 、admin-Lists 是 xxl-job 自身登錄功能需要,其他的配置均由 OIDC 授權(quán)服務(wù)器提供

oidc.login-mod=onlyOidc
oidc.client-id = xxl-job-dev
oidc.client-secret = xx
oidc.base-url =?https://sso.security.oidc.com oidc.access-token-url = ${oidc.base-url}/cas/oidc/accessToken
oidc.login-url = ${oidc.base-url}/cas/oidc/authorize?response_type=code&client_id=${oidc.client-id}&redirect_uri=${oidc.redirect-uri}&scope=openid
oidc.redirect-uri =?http://172.26.203.103:8071/oidc/tokenLogin oidc.logout-url =${oidc.base-url}/cas/logout?service=${oidc.redirect-uri}
oidc.admin-Lists = chenkailing

Oidc 服務(wù)類,使用這個(gè)類里的方法和 OIDC 授權(quán)服務(wù)器交互

/**
 * @author kl (http://kailing.pub)
 * @since 2021/6/21
 */
@Service
public class OidcService {
    private final OidcProperties oidcProperties;
    private final RestTemplate restTemplate;
    public OidcService(OidcProperties oidcProperties, RestTemplate restTemplate) {
        this.oidcProperties = oidcProperties;
        this.restTemplate = restTemplate;
    }
    /**
     * 請(qǐng)求 OIDC 授權(quán)服務(wù)器,獲取 idToken
     * idToken 中包含的信息 (非標(biāo)準(zhǔn))
     * {
     * "sub": "248289761001",
     * "name": "Jane Doe",
     * "given_name": "Jane",
     * "family_name": "Doe",
     * "preferred_username": "j.doe",
     * "email": "janedoe@example.com",
     * "picture": "http://example.com/janedoe/me.jpg"
     * }
     */
    public String getUsernameByCode(String code) {
        URI uri = UriComponentsBuilder.fromUriString(oidcProperties.getAccessTokenUrl())
                .queryParam("client_id", oidcProperties.getClientId())
                .queryParam("client_secret", oidcProperties.getClientSecret())
                .queryParam("redirect_uri", oidcProperties.getRedirectUri())
                .queryParam("code", code)
                .queryParam("grant_type", "authorization_code")
                .build()
                .toUri();
        AuthorizationEntity auth = restTemplate.getForObject(uri, AuthorizationEntity.class);
        Assert.notNull(auth, "AccessToken is null");
        String idToken = auth.getIdToken();
        int i = idToken.lastIndexOf('.');
        String withoutSignatureToken = idToken.substring(0, i+1);
        return Jwts.parserBuilder()
                .build()
                .parseClaimsJwt(withoutSignatureToken)
                .getBody()
                .get("sub", String.class);
    }
    /**
     * @return 1 : 管理員 、0 : 普通用戶
     */
    public int getUserRole(XxlJobUser user) {
        ListadminLists = oidcProperties.getAdminLists();
        if (adminLists.contains(user.getUsername())) {
            return 1;
        }
        return 0;
    }
    public String getOidcLoginUrl() {
        return oidcProperties.getLoginUrl();
    }
    public OidcProperties.LoginMod getLoginMod() {
        return oidcProperties.getLoginMod();
    }
    public boolean isRedirectOidcLoginUrl() {
        return oidcProperties.getLoginMod().equals(OidcProperties.LoginMod.onlyOidc);
    }
    public String getLogoutUrl() {
        return oidcProperties.getLogoutUrl();
    }
    static class AuthorizationEntity {
        @JsonProperty("access_token")
        private String accessToken;
        @JsonProperty("id_token")
        private String idToken;
        @JsonProperty("refresh_token")
        private String refreshToken;
        @JsonProperty("expires_in")
        private String expiresIn;
        @JsonProperty("token_type")
        private String tokenType;
        private String scope;
    }
}

OIDC 登錄接口,也就是提供給 OIDC 授權(quán)服務(wù)器回調(diào)的接口

/**
 * OIDC登錄
 */
@RequestMapping(value = "/oidc/tokenLogin", method = {RequestMethod.POST, RequestMethod.GET})
@PermissionLimit(limit = false)
public ModelAndView loginByOidc(HttpServletRequest request, HttpServletResponse response, ModelAndView modelAndView) {
    if (loginService.ifLogin(request, response) != null) {
        modelAndView.setView(new RedirectView("/", true, false));
        return modelAndView;
    }
    String code = request.getParameter("code");
    if (Objects.isNull(code)) {
        return this.loginPageView();
    }
    String username = oidcService.getUsernameByCode(code);
    loginService.oidcLogin(username, response);
    modelAndView.setView(new RedirectView("/", true, false));
    return modelAndView;
}

這個(gè)接口對(duì)應(yīng)了 xxl-job 集成 OIDC 后的認(rèn)證流程:

  • 判斷是否登錄,已經(jīng)登錄則跳轉(zhuǎn)到登錄成功的頁(yè)面
  • 獲取 code ,不存在則調(diào)整到登錄頁(yè)面
  • 通過(guò) code 請(qǐng)求 OIDC 授權(quán)服務(wù)器獲取 UserInfo
  • 處理內(nèi)部登錄邏輯(用戶是否存在,存在則設(shè)置 Cookie,不存在則先創(chuàng)建用戶在設(shè)置 Cookie)
  • 跳轉(zhuǎn)到登錄成功的頁(yè)面

跳轉(zhuǎn)登錄頁(yè)邏輯做了封裝,因?yàn)?,根?jù)登錄模式的不同,有不同的處理邏輯:

private ModelAndView loginPageView() {
    ModelAndView modelAndView = new ModelAndView(LOGIN_PAGE);
    if (oidcService.isRedirectOidcLoginUrl()) {
        modelAndView.setView(new RedirectView(oidcService.getOidcLoginUrl(), true, false));
    } else {
        modelAndView.addObject("loginMod", oidcService.getLoginMod().name());
        modelAndView.addObject("oidcLoginUrl", oidcService.getOidcLoginUrl());
    }
    return modelAndView;
}

目前的策略,如果配置了登錄模式為 onlyOidc ,則跳轉(zhuǎn)登錄頁(yè)時(shí),直接 302 到 OIDC 授權(quán)頁(yè),否則,將登錄模式,和 OIDC 授權(quán)頁(yè)傳遞給前端,由前端控制展示的 UI

以上就是分析xxljob登入功能集成OIDC的統(tǒng)一認(rèn)證的詳細(xì)內(nèi)容,更多關(guān)于xxljob登入集成OIDC統(tǒng)一認(rèn)證的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 理解JDK動(dòng)態(tài)代理為什么必須要基于接口

    理解JDK動(dòng)態(tài)代理為什么必須要基于接口

    這篇文章主要介紹了理解JDK動(dòng)態(tài)代理為什么必須要基于接口,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-10-10
  • java中單例模式講解

    java中單例模式講解

    這篇文章主要介紹了java中單例模式,本文通過(guò)簡(jiǎn)單的案例,講解了該模式在java中的使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • Mybatis一對(duì)多和多對(duì)一處理的深入講解

    Mybatis一對(duì)多和多對(duì)一處理的深入講解

    Mybatis可以通過(guò)關(guān)聯(lián)查詢實(shí)現(xiàn),關(guān)聯(lián)查詢是幾個(gè)表聯(lián)合查詢,只查詢一次,通過(guò)在resultMap里面的association,collection節(jié)點(diǎn)配置一對(duì)一,一對(duì)多的類就可以完成,這篇文章主要給大家介紹了關(guān)于Mybatis一對(duì)多和多對(duì)一處理的相關(guān)資料,需要的朋友可以參考下
    2021-09-09
  • 詳解Java中自定義注解的使用

    詳解Java中自定義注解的使用

    Annontation是Java5開始引入的新特征,中文名稱叫注解,它提供了一種安全的類似注釋的機(jī)制,用來(lái)將任何的信息或元數(shù)據(jù)(metadata)與程序元素(類、方法、成員變量等)進(jìn)行關(guān)聯(lián)。本文主要介紹了自定義注解的使用,希望對(duì)大家有所幫助
    2023-03-03
  • Java實(shí)現(xiàn)定時(shí)備份文件

    Java實(shí)現(xiàn)定時(shí)備份文件

    這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)定時(shí)備份文件,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-08-08
  • 詳解Java如何利用數(shù)字描述更多的信息

    詳解Java如何利用數(shù)字描述更多的信息

    在數(shù)據(jù)庫(kù)里面?,通常我們會(huì)用數(shù)字的遞進(jìn)來(lái)描述狀態(tài)等信息?,?但是如果想進(jìn)行更復(fù)雜的操作?,?就有必要對(duì)二進(jìn)制有一定理解了。本文就來(lái)趣味性的探討一下?,?如何通過(guò)更少的空間描述更多的信息
    2022-09-09
  • @RequestParam使用defaultValue屬性設(shè)置默認(rèn)值的操作

    @RequestParam使用defaultValue屬性設(shè)置默認(rèn)值的操作

    這篇文章主要介紹了@RequestParam使用defaultValue屬性設(shè)置默認(rèn)值的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-02-02
  • SpringCloud集成Sleuth和Zipkin的思路講解

    SpringCloud集成Sleuth和Zipkin的思路講解

    Zipkin 是 Twitter 的一個(gè)開源項(xiàng)目,它基于 Google Dapper 實(shí)現(xiàn),它致力于收集服務(wù)的定時(shí)數(shù)據(jù),以及解決微服務(wù)架構(gòu)中的延遲問(wèn)題,包括數(shù)據(jù)的收集、存儲(chǔ)、查找和展現(xiàn),這篇文章主要介紹了SpringCloud集成Sleuth和Zipkin,需要的朋友可以參考下
    2022-11-11
  • 通Java接口上傳實(shí)現(xiàn)SMMS圖床

    通Java接口上傳實(shí)現(xiàn)SMMS圖床

    這篇文章主要介紹了通Java接口上傳實(shí)現(xiàn)SMMS圖床,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-07-07
  • Idea 解決 Could not autowire. No beans of ''xxxx'' type found 的錯(cuò)誤提示

    Idea 解決 Could not autowire. No beans of ''xxxx'' type found

    這篇文章主要介紹了Idea 解決 Could not autowire. No beans of 'xxxx' type found 的錯(cuò)誤提示,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2019-01-01

最新評(píng)論