最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

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

前言

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

相關(guān)鏈接

XXL-JOB 自身認證功能分析

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

OIDC 的認證流程

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

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

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

XXL-JOB 集成 OIDC 后的認證流程

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

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

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

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

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

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

onlyLocal 模式登錄界面:

mix 模式登錄界面:

olnyOidc 模式登錄界面:

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

保留登錄按鈕的界面(實際這個頁面取消了)

編碼環(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
    }
}

對應(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ù)類,使用這個類里的方法和 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;
    }
    /**
     * 請求 OIDC 授權(quán)服務(wù)器,獲取 idToken
     * idToken 中包含的信息 (非標準)
     * {
     * "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;
}

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

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

跳轉(zhuǎ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)登錄頁時,直接 302 到 OIDC 授權(quán)頁,否則,將登錄模式,和 OIDC 授權(quán)頁傳遞給前端,由前端控制展示的 UI

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

相關(guān)文章

最新評論

潞西市| 九龙城区| 陆丰市| 海盐县| 田东县| 河北区| 昂仁县| 五河县| 东至县| 成安县| 神池县| 富源县| 沁水县| 和平区| 开化县| 新邵县| 南京市| 长丰县| 阳高县| 金门县| 青田县| 康保县| 丹阳市| 长宁区| 长丰县| 雅江县| 腾冲县| 聂拉木县| 舟曲县| 应城市| 林周县| 盐城市| 瓦房店市| 缙云县| 无棣县| 奇台县| 醴陵市| 新疆| 汤原县| 浠水县| 阿城市|