第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

首頁 慕課教程 Spring Security Spring Security OAuth2 集成構(gòu)造認(rèn)證授權(quán)服務(wù)器

OAuth2 集成 - 構(gòu)造認(rèn)證授權(quán)服務(wù)器

1. 前言

上一節(jié)中,我們使用了 Spring Security 提供的社交化組件,實(shí)現(xiàn)了利用第三方認(rèn)證平臺(tái)完成用戶身份識(shí)別的過程。

雖然使用第三方平臺(tái)作為認(rèn)證中心十分的方便,但是如果我們的系統(tǒng)是在內(nèi)部環(huán)境下使用,或者我們的用戶沒有注冊(cè)過 Github、微信這類平臺(tái),又或者我們希望自己的平臺(tái)為其他應(yīng)用提供認(rèn)證服務(wù)時(shí),就需要考慮創(chuàng)建自己的認(rèn)證中心了。

本節(jié)將重點(diǎn)討論如何創(chuàng)建自己的 OAuth2 認(rèn)證中心。

本小節(jié)實(shí)例開發(fā)環(huán)境

本小節(jié)所使用的實(shí)例代碼是基于 Spring 官網(wǎng)中提供的最小化 HelloWorld 模板創(chuàng)建,請(qǐng)點(diǎn)此下載完整的 HelloWorld 模板壓縮包。

2. OAuth2 授權(quán)原理介紹

OAuth 的全稱為 Open Authorization 即「開放授權(quán)」。它被設(shè)計(jì)成為一個(gè)通用安全協(xié)議,用于實(shí)現(xiàn)桌面應(yīng)用(包括手機(jī)應(yīng)用)及 B / S 應(yīng)用的統(tǒng)一 API 鑒權(quán)服務(wù)。它通過頒發(fā)令牌的方式,允許第三方網(wǎng)站在特定時(shí)間、操作范圍內(nèi)訪問資源而避免了重新輸入密碼。

OAuth 授權(quán)有三個(gè)主要特點(diǎn):

  1. 簡單:易于理解和實(shí)現(xiàn);
  2. 安全:過程中不暴露敏感信息(如:用戶名、密碼等);
  3. 開放:誰都可以用。

OAuth 標(biāo)準(zhǔn)一共出現(xiàn)了兩代,1.0 在 2007 年底提出,只適用于瀏覽器 B / S 應(yīng)用,后來在 2011 年,OAuth 發(fā)布了協(xié)議 2.0,并開始支持終端應(yīng)用的認(rèn)證?,F(xiàn)在 OAuth 2.0 協(xié)議基本完全替代了 OAuth 1.0 協(xié)議。

OAuth 2.0 有四種授權(quán)方式,也就是四種獲得令牌的方式,分別是:授權(quán)碼式、隱蔽式、密碼式、客戶端憑證式。

2.1 授權(quán)碼式

這種方式下,APP(或網(wǎng)站)首先申請(qǐng)授權(quán)碼并保存在客戶端(或?yàn)g覽器)中,再用授權(quán)碼去換取令牌,并將令牌保存在服務(wù)器上。這樣就實(shí)現(xiàn)了即認(rèn)證客戶端,又認(rèn)證了服務(wù)器。

圖片描述

授權(quán)碼式

2.2 隱蔽式

有時(shí)會(huì)遇到應(yīng)用只有前端,沒有后端,上述方式就無法實(shí)現(xiàn)了,此時(shí)我們需要將令牌保存在前端,于是出現(xiàn)了第二種方式:隱蔽式。

這種方式下應(yīng)用客戶端直接向認(rèn)證服務(wù)器請(qǐng)求令牌。

圖片描述

隱蔽式

注意:這種方式下,令牌被存儲(chǔ)在客戶端,容易被攻擊者攔截,所以用完后應(yīng)及時(shí)銷毀。

2.3 密碼式

加入客戶端應(yīng)用實(shí)可信的,既用戶允許客戶端知道自己的用戶名密碼,此時(shí)就可以使用密碼式換取令牌。

這種方式下,由客戶端認(rèn)證用戶,并攜帶用戶的認(rèn)證信息一并發(fā)送到認(rèn)證服務(wù)器換取令牌。

圖片描述

密碼式

2.4 客戶端憑證式

有的應(yīng)用并沒有明確的前端應(yīng)用,比如控制臺(tái)程序或者是服務(wù)接口,這種情況下就需要用到客戶端憑證式獲得憑證了。

這種方式下,沒有「人」的參與,只有認(rèn)證服務(wù)對(duì)后臺(tái)服務(wù)的認(rèn)證。

圖片描述

客戶端憑證式

3. 過程實(shí)現(xiàn)

在前面章節(jié),我們討論了如何快速建立一個(gè) Spring Security 的認(rèn)證服務(wù)器,此處我們將在前述實(shí)例上擴(kuò)展 OAuth2.0 認(rèn)證支持。

3.1 創(chuàng)建 Spring Boot web 服務(wù)端應(yīng)用

工程目錄結(jié)構(gòu)如下:

? OAuth2AuthorizationServer/
  ? src/
    ? main/
      ? java/imooc/springsecurity/oauth2/server/
        ? config/
            OAuth2ServerConfiguration.java          # OAuth2 相關(guān)配置類
            UserConfiguration.java                  # 基礎(chǔ)認(rèn)證配置類,用于配置用戶信息
          OAuth2AuthorizationServerApplication.java # 程序入口
      ? resources/
          application.properties                    # 配置文件,本例中無特殊配置
    ? test/java/
    pom.xml

在 pom.xml 文件中增加依賴項(xiàng),相比「用戶名密碼認(rèn)證實(shí)例」,此處注意添加了 OAuth2 自動(dòng)配置的相關(guān)依賴。spring-security-oauth2-autoconfigure。完整 pom.xml 文件如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.1.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <groupId>imooc.springsecurity</groupId>
    <artifactId>OAuth2AuthorizationServerSample</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.security.oauth.boot</groupId>
            <artifactId>spring-security-oauth2-autoconfigure</artifactId>
            <version>2.3.1.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

創(chuàng)建 SpringSecurity OAuth2 配置類: OAuth2ServerConfiguration.java。

src/
  main/
    java/
      imooc/
        springsecurity/
          oauth2/
            server/
              OAuth2ServerConfiguration.java
  1. 使其繼承 org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter 類,并其增加 @EnableAuthorizationServer 標(biāo)簽,以聲明此類作為 OAuth2 認(rèn)證服務(wù)器的配置依據(jù);
  2. configure(AuthorizationServerEndpointsConfigurer endpoints) 方法中配置其 TokenStore,為了便于演示,此例中 TokenStore 采用內(nèi)存形式,賬戶信息寫死在代碼中;
  3. configure(ClientDetailsServiceConfigurer clients) 方法中為 OAuth2 認(rèn)證服務(wù)器設(shè)置可用于認(rèn)證的客戶端信息。

完整代碼如下:

package imooc.springsecurity.oauth2.server.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore;

@EnableAuthorizationServer
@Configuration
public class OAuth2ServerConfiguration extends AuthorizationServerConfigurerAdapter {

    private AuthenticationManager authenticationManager;

    public OAuth2ServerConfiguration(
            AuthenticationConfiguration authenticationConfiguration) throws Exception {
        this.authenticationManager = authenticationConfiguration.getAuthenticationManager();
    }

    @Override
    public void configure(ClientDetailsServiceConfigurer clients)
            throws Exception {
        // 配置授信客戶端信息
        clients.inMemory() // 內(nèi)存模式
                .withClient("reader") // 第一個(gè)客戶端用戶,其名稱為「reader」
                .authorizedGrantTypes("password") // 授權(quán)模式為「password」
                .secret("{noop}secret") // 認(rèn)證密碼為「secret」,加密方式為「NoOp」
                .scopes("message:read") // 權(quán)限的使用范圍
                .accessTokenValiditySeconds(600_000_000) // 票據(jù)有效期
                .and()  // 增加第二個(gè)授權(quán)客戶端,設(shè)置方法一致,但擁有不同的范圍權(quán)限
                .withClient("writer")
                .authorizedGrantTypes("password")
                .secret("{noop}secret")
                .scopes("message:write")
                .accessTokenValiditySeconds(600_000_000);
    }
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
        endpoints
                .authenticationManager(this.authenticationManager)
                .tokenStore(tokenStore()); // 使用虛機(jī)內(nèi)存存儲(chǔ)票據(jù)信息,也可替換成 Mysql、Redis 等。
    }

    @Bean
    public TokenStore tokenStore() {
        return new InMemoryTokenStore();
    }
}

除了設(shè)置授權(quán)客戶端之外,還要增加客戶端中被授權(quán)的用戶。

創(chuàng)建類 UserConfiguration.java

src/
  main/
    java/
      imooc/
        springsecurity/
          oauth2/
            server/
              UserConfiguration.java

并在其中配置用戶信息。

package imooc.springsecurity.oauth2.server.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;

@Configuration
public class UserConfiguration extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                .anyRequest().authenticated() // 任何地址都受到保護(hù),需要首先認(rèn)證
                .and()
                .httpBasic() // 支持基本認(rèn)證,因?yàn)?OAuth2 認(rèn)證往往用于不同種類客戶端,所以基本認(rèn)證支持是必要的。
                .and()
                .csrf().disable();
    }

    @Bean
    @Override
    public UserDetailsService userDetailsService() {
        InMemoryUserDetailsManager inMemoryUserDetailsManager = new InMemoryUserDetailsManager();
        inMemoryUserDetailsManager.createUser(User.withUsername("admin").password("$2a$10$sR.KWdKOWYseh0KVHHnzMOveh/S7wvOkd.JrTyP2AzHhEcCSZfAmK").roles("USER").build()); // 用戶名: admin; 密碼: 123456
        return inMemoryUserDetailsManager;
    }
}

3.2 運(yùn)行及測(cè)試

我們用 curl 工具測(cè)試 OAuth2.0 認(rèn)證服務(wù)器。

在 OAuth2.0 框架中,實(shí)現(xiàn) Password 認(rèn)證需要提供四個(gè)參數(shù):

  1. 客戶端標(biāo)識(shí):clientID;
  2. 客戶端認(rèn)證密碼:clientSecret;
  3. 授權(quán)類型:grant_type,該值固定為「password」;
  4. 認(rèn)證用戶的用戶名:username;
  5. 認(rèn)證用戶的密碼:password。

完整的請(qǐng)求表達(dá)式為:

curl [clientID]:[clientSecret]@ip:port/oauth/token -d grant_type=password -d username=[username] -d password=[password]

在本實(shí)例中,測(cè)試指令可定義為:

curl reader:secret@localhost:8080/oauth/token -d grant_type=password -d username=admin -d password=123456

如果認(rèn)證成功,服務(wù)端將返回以下內(nèi)容:

{
	"access_token": "OOwNfgjvJKHItYnk4buWC8BMGtU=",
	"token_type": "bearer",
	"expires_in": 599995027,
	"scope": "message:read"
}

其中,access_token 值在 OAuth2 體系中作為統(tǒng)一票據(jù),用于各個(gè)資源服務(wù)的認(rèn)證。

至此,OAuth2 認(rèn)證服務(wù)器的 Password 模式授權(quán)模式就已完成。Spring Security 對(duì) OAuth2.0 的其他幾種授權(quán)模式已有成熟支持,在使用時(shí)需要配置對(duì)應(yīng)的客戶端授權(quán)模式權(quán)限。

3.3 使用數(shù)據(jù)庫作為認(rèn)證源

如果使用數(shù)據(jù)庫(例如:mysql)作為數(shù)據(jù)源時(shí),需要?jiǎng)?chuàng)建 JdbcClientDetailsService 對(duì)象,并配置到 ClientDetailsServiceConfigurer 之中。具體代碼為

    @Bean
    public ClientDetailsService clientDetailsService() {
        // 新增部分,用于從數(shù)據(jù)庫獲取客戶端信息
        return new JdbcClientDetailsService(dataSource);
    }

    @Override
    public void configure(ClientDetailsServiceConfigurer clients)
            throws Exception {
        // 此處去掉內(nèi)存配置項(xiàng),改為 jdbc 數(shù)據(jù)源
        clients.withClientDetails(clientDetailsService);
    }

除此之外,還需要在書庫中插入相關(guān)數(shù)據(jù)表,表結(jié)構(gòu)定義如下,也可以從 spring 項(xiàng)目主頁 中獲取。

-- used in tests that use HSQL
create table oauth_client_details (
  client_id VARCHAR(256) PRIMARY KEY,
  resource_ids VARCHAR(256),
  client_secret VARCHAR(256),
  scope VARCHAR(256),
  authorized_grant_types VARCHAR(256),
  web_server_redirect_uri VARCHAR(256),
  authorities VARCHAR(256),
  access_token_validity INTEGER,
  refresh_token_validity INTEGER,
  additional_information VARCHAR(4096),
  autoapprove VARCHAR(256)
);

create table oauth_client_token (
  token_id VARCHAR(256),
  token LONGVARBINARY,
  authentication_id VARCHAR(256) PRIMARY KEY,
  user_name VARCHAR(256),
  client_id VARCHAR(256)
);

create table oauth_access_token (
  token_id VARCHAR(256),
  token LONGVARBINARY,
  authentication_id VARCHAR(256) PRIMARY KEY,
  user_name VARCHAR(256),
  client_id VARCHAR(256),
  authentication LONGVARBINARY,
  refresh_token VARCHAR(256)
);

create table oauth_refresh_token (
  token_id VARCHAR(256),
  token LONGVARBINARY,
  authentication LONGVARBINARY
);

create table oauth_code (
  code VARCHAR(256), authentication LONGVARBINARY
);

create table oauth_approvals (
	userId VARCHAR(256),
	clientId VARCHAR(256),
	scope VARCHAR(256),
	status VARCHAR(10),
	expiresAt TIMESTAMP,
	lastModifiedAt TIMESTAMP
);


-- customized oauth_client_details table
create table ClientDetails (
  appId VARCHAR(256) PRIMARY KEY,
  resourceIds VARCHAR(256),
  appSecret VARCHAR(256),
  scope VARCHAR(256),
  grantTypes VARCHAR(256),
  redirectUrl VARCHAR(256),
  authorities VARCHAR(256),
  access_token_validity INTEGER,
  refresh_token_validity INTEGER,
  additionalInformation VARCHAR(4096),
  autoApproveScopes VARCHAR(256)
);

4. 小結(jié)

本節(jié)我們討論了如何構(gòu)建自己的 OAuth2.0 認(rèn)證中心,主要知識(shí)點(diǎn)有:

圖片描述

OAuth 2.0 認(rèn)證服務(wù)器
  • Spring Security 對(duì) OAuth2.0 認(rèn)證標(biāo)準(zhǔn)已經(jīng)有成熟的支持,僅需幾個(gè)注解就可以構(gòu)造出 OAuth2.0 認(rèn)證服務(wù)器;
  • Spring Security 對(duì) OAuth2.0 認(rèn)證同樣提供了多種認(rèn)證支持,比如內(nèi)存認(rèn)證、數(shù)據(jù)庫認(rèn)證及 Redis 認(rèn)證等,可以根據(jù)需要進(jìn)行配置或調(diào)整。

下節(jié)我們繼續(xù) OAuth2.0 話題,討論如何在 OAuth2.0 協(xié)議下,如何保護(hù)私密資源被合理訪問。