Oauth2-0 實現單點登錄的原理流程,這次總該懂了!

大家好,我是不才陳某~

單點登錄是多域名企業站點流行的登錄方式。本文以現實生活場景輔助理解,力爭徹底理清 OAuth2.0 實現單點登錄的原理流程。同時總結了權限控制的實現方案,及其在微服務架構中的應用。

1 什麼是單點登錄

1.1 多點登錄

傳統的多點登錄系統中,每個站點都實現了本站專用的帳號數據庫和登錄模塊。各站點的登錄狀態相互不認可,各站點需要逐一手工登錄。如下圖,有兩個術語含義如下:

1.2 單點登錄

單點登錄,英文是 Single Sign On,縮寫爲 SSO。多個站點 (192.168.1.20X) 共用一臺認證授權服務器 (192.168.1.110,用戶數據庫和認證授權模塊共用)。用戶經由其中任何一個站點(比如 192.168.1.201) 登錄後,可以免登錄訪問其他所有站點。而且,各站點間可以通過該登錄狀態直接交互。

2 OAuth2 認證授權的原理流程

2.1 生活實例【★★重點★★】

爲了直觀的理解 OAuth2.0 原理流程,我們假設這樣一個生活場景:

(1) 檔案局 A(客戶端 / Client):以 “檔案局 ID / 密碼” 標識,是掌握檔案資源的機構。並列還有很多檔案局 B/C/…,每個檔案局存儲的檔案內容(資源 / Resource) 不一樣,比如政治、經濟、軍事、文化等;

(2) 公民張三 (資源所有者 / Resource Owner):以 “用戶名 / 密碼” 標識,需要到各個檔案局查檔案;

(3) 派出所 (授權服務器 / Authentication Server):可以是單個巨大的派出所,也可以是數據共享的派出所集羣,掌管的信息、提供的對外接口功能有:

2.1.1 張三首次訪問檔案局 A

張三之前從未到訪檔案局,第一次來檔案局。對照下圖序號理解:

(1)張三來到 “檔案局 A” 的“檔案處”,該處要求實名登記後才能查詢,被指示到 “用戶登記處” 辦理(HTTP 重定向);

(2)張三來到 “檔案局 A” 的“用戶登記處”,既不能證明身份(認證),又不能證明自己有查檔案 A 的權限 (授權)。張三攜帶檔案局 A 的標識 (client-id),被重定向至 “授權信開具處”;

(3)張三來到 “派出所” 的“授權信開具處”,出示檔案局 A 的標識,希望開具授權信(授權)。該處要求首先證明身份 (認證),被重定向至 “用戶身份驗證處”;

(4)張三來到 “派出所” 的“用戶身份驗證處”,領取了用戶身份表(網頁登錄表單 Form);

(5) 張三填上自己的用戶名和密碼,交給 (提交 / Submit)“用戶身份驗證處”,該處從私用數據庫中查得用戶名密碼匹配,確定此人是張三,開具身份證明信,完成 認證。張三帶上身份證明信和檔案局 A 的標識,被重定向至 “授權信開具處”;

(6)張三再次來到 “授權信開具處”,出示身份證明信和檔案局 A 的標識,該處從私用數據庫中查得,張三的官職是市長級別(角色),該官職具有檔案局 A 的查詢權限,就開具“允許張三查詢檔案局 A” 的授權信(授權碼 / code),張三帶上授權信被重定向至 “檔案局” 的“用戶登錄處”;

(7)張三到了 “檔案局” 的“用戶登錄處”,該處私下拿出檔案局 A 的標識(client-id) 和密碼,再附上張三出示的授權信 (code),向 “派出所” 的“腰牌發放處”爲張三申請的“腰牌”(token),將來張三可以帶着這個腰牌表明身份和權限。又被重定向到 “檔案處”;

(8)張三的會話 (Session) 已經關聯上了腰牌 (token),可以直接通過“檔案處” 查檔案。

2.1.2 張三首次訪問檔案局 B

張三已經成功訪問了檔案局 A,現在他要訪問檔案局 B。對照下圖序號理解:

(1)/(2) 同上;

(3)張三已經有 “身份證明信”,直接在“派出所” 的“授權信開具處”成功開具 “訪問檔案局 B” 的授權信;

(4)/(5)/(6) 免了;

(7)“檔案局 B”的 “用戶登記處” 完成登記;

(8)“檔案局 B”的 “檔案處” 查得檔案。

2.1.3 張三再次訪問檔案局 A

張三已經成功訪問了檔案局 A,現在他要訪問檔案局 A。對照下圖序號理解:

(1) 直接成功查到了檔案;

(2~8) 都免了。

2.2 HTTP 重定向原理

HTTP 協議中,瀏覽器的 REQUEST 發給服務器之後,服務器如果發現該業務不屬於自己管轄,會把你支派到自身服務器或其他服務器 (host) 的某個接口 (uri)。正如我們去政府部門辦事,每到一個窗口,工作人員會說“你帶上材料 A,到本所的 X 窗口,或者其他 Y 所的 Z 窗口” 進行下一個手續。

2.3 SSO 工作流程

至此,就不難理解 OAuth 2.0 的認證 / 授權流程,此處不再贅述。請拿下圖對照 “2.1 生活實例” 一節來理解。

2.4 OAuth2.0 進階

根據官方標準,OAuth 2.0 共用四種授權模式:

3 基於 SpringBoot 實現認證 / 授權

3.1 授權服務器 (Authorization Server)

(1) pom.xml

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency>

(2) application.properties

server.port=8110 ## 監聽端口

(3) AuthorizationServerApplication.java

@EnableResourceServer // 啓用資源服務器
public class AuthorizationServerApplication {
    // ...
}

(4) 配置授權服務的參數

@Configuration
@EnableAuthorizationServer
public class Oauth2AuthorizationServerConfigurer extends AuthorizationServerConfigurerAdapter {
    @Override
    public void configure(final ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()
                .withClient("webapp").secret("secret") //客戶端 id/secret
                .authorizedGrantTypes("authorization code") //授權媽模式
                .scopes("user_info")
                .autoApprove(true) //自動審批
                .accessTokenValiditySeconds(3600); //有效期1hour
    }
}

@Configuration
public class Oauth2WebSecurityConfigurer extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.requestMatchers()
                .antMatchers("/login""/oauth/authorize/oauth/logout")
                .and().authorizeRequests().anyRequest().authenticated()
                .and().formLogin().permitAll();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication().withUser("admin").password("admin123").roles("ADMIN");
    }
}

3.2 客戶端 (Client, 業務網站)

(1) pom.xml

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency>

(2) application.properties

server port=8080
security.oauth2.client.client-id=webapp
security.oauth2.client.client-secret=secret
security.oauth2.client.access-token-uri=http://localhost:8110/oauth/token
security.oauth2.client.user-authorization-uri=http://localhost:8110/oauth/authorize
security.oauth2.resource.user-info-uri=http://localhost:8110/oauth/user

(3) 配置 WEB 安全

@Configuration
@EnableOAuth2Sso
public class Oauth2WebsecurityConfigurer extends WebSecurityConfigurerAdapter {
    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.antMatcher("/**").authorizeRequests()
                .antMatchers("/""/login").permitAll()
                .anyRequest().authenticated();
    }
}

@RestController
public class Oauth2ClientController {
    @GetMapping("/")
    public ModelAndView index() {
        return new ModelAndView("index");
    }

    @GetMapping("/welcome")
    public ModelAndView welcome() {
        return new ModelAndView("welcome");
    }
}

3.3 用戶權限控制 (基於角色)

@RestController
public class Oauth2ClientController {
    @GetMapping("/welcome")
    public ModelAndView welcome() {
        return new ModelAndView("welcome");
    }

    @GetMapping("/api/user")
    @PreAuthorize("hasAuthority('USER')")
    public Map<String, Object> apiUser() {
    }

    @GetMapping("/api/admin")
    @PreAuthorize("hasAuthority('ADMIN')")
    public Map<String, Object> apiAdmin() {
    }

    @GetMapping("/api/root")
    @PreAuthorize("hasAuthority('ROOT')")
    public Map<String, Object> apiRoot() {
    }
}

4 綜合運用

4.1 權限控制方案

下圖是基本的認證 / 授權控制方案,主要設計了認證授權服務器上相關數據表的基本定義。可對照本文 “2.1 生活實例” 一節來理解。

4.2 在微服務架構中的應用

與常規服務架構不同,在微服務架構中,Authorization Server/Resource Server 是作爲微服務存在的,用戶的登錄可以通過 API 網關一次性完成,無需與無法跳轉至內網的 Authorization Server 來完成。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/XOaE6ETncA6JkBiBGOXylg