国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

18.Oauth2-微服務(wù)認證

這篇具有很好參考價值的文章主要介紹了18.Oauth2-微服務(wù)認證。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

18.Oauth2-微服務(wù)認證,skill,微服務(wù),面試,架構(gòu)

18.Oauth2-微服務(wù)認證,skill,微服務(wù),面試,架構(gòu)

1.Oauth2

OAuth 2.0授權(quán)框架支持第三方支持訪問有限的HTTP服務(wù),通過在資源所有者和HTTP服務(wù)之間進行一個批準交互來代表資源者去訪問這些資源,或者通過允許第三方應(yīng)用程序以自己的名義獲取訪問權(quán)限。

18.Oauth2-微服務(wù)認證,skill,微服務(wù),面試,架構(gòu)

為了方便理解,可以想象OAuth2.0就是在用戶資源和第三方應(yīng)用之間的一個中間層,它把資源和第三方應(yīng)用隔開,使得第三方應(yīng)用無法直接訪問資源,從而起到保護資源的作用。

為了訪問這種受保護的資源,第三方應(yīng)用(客戶端)在訪問的時候需要提供憑證。即,需要告訴OAuth2.0你是誰你要做什么。

用戶可以將用戶名和密碼告訴第三方應(yīng)用,讓第三方應(yīng)用直接以你的名義去訪問,也可以授權(quán)第三方應(yīng)用去訪問。

例如,微信公眾平臺開發(fā),在微信公眾平臺開發(fā)過程中當我們訪問某個頁面,頁面可能彈出一個提示框應(yīng)用需要獲取我們的個人信息問是否允許,點確認其實就是授權(quán)第三方應(yīng)用獲取我們在微信公眾平臺的個人信息,這里微信網(wǎng)頁授權(quán)就是使用的OAuth2.0。

  • 第三方應(yīng)用程序(Third-party application): 又稱之為客戶端(client),我們自己開發(fā)的各種客戶端,對我們自己的項目來說,QQ、微信、支付寶等是第三方應(yīng)用程序。

  • HTTP 服務(wù)提供商(HTTP service): 我們開發(fā)的項目以及 QQ、微信、支付寶、釘釘?shù)榷伎梢苑Q之為“服務(wù)提供商”。

  • 資源所有者(Resource Owner): 又稱之為用戶(user),擁有賬號密碼的人。

  • 用戶代理(User Agent): 用來訪問資源,比如瀏覽器,代替用戶去訪問這些資源。

  • 認證服務(wù)器(Authorization server): 即服務(wù)提供商專門用來處理認證的服務(wù)器,主要就是實現(xiàn)登錄、授權(quán)功能。

  • 資源服務(wù)器(Resource server): 即服務(wù)提供商存放用戶生成的資源的服務(wù)器,比如電商中的商品模塊、訂單模塊等,是用來處理具體業(yè)務(wù)的服務(wù)器。

????????OAuth2.0協(xié)議流程描述了四種角色之間的交互過程,如下圖所示。

18.Oauth2-微服務(wù)認證,skill,微服務(wù),面試,架構(gòu)

????????簡單說,OAuth 就是一種授權(quán)機制。數(shù)據(jù)的所有者告訴系統(tǒng),同意授權(quán)第三方應(yīng)用進入系統(tǒng),獲取這些數(shù)據(jù)。系統(tǒng)從而產(chǎn)生一個短期的進入令牌(token),用來代替密碼,供第三方應(yīng)用使用。

令牌(token)與密碼(password)的作用是一樣的,都可以進入系統(tǒng),但是有三點差異。

  • 令牌是短期的,到期會自動失效,用戶自己無法修改。密碼一般長期有效,用戶不修改,就不會發(fā)生變化。

  • 令牌可以被數(shù)據(jù)所有者撤銷,會立即失效。

  • 令牌有權(quán)限范圍(scope),對于網(wǎng)絡(luò)服務(wù)來說,只讀令牌就比讀寫令牌更安全。密碼一般是完整權(quán)限。

上面這些設(shè)計,保證了令牌既可以讓第三方應(yīng)用獲得權(quán)限,同時又隨時可控,不會危及系統(tǒng)安全。這就是 OAuth 2.0 的優(yōu)點。

注意,只要知道了令牌,就能進入系統(tǒng)。系統(tǒng)一般不會再次確認身份,所以令牌必須保密,泄漏令牌與泄漏密碼的后果是一樣的。 這也是為什么令牌的有效期,一般都設(shè)置得很短的原因。

1.1 開放平臺

????????開放平臺(Open Platform)在軟件行業(yè)和網(wǎng)絡(luò)中,開放平臺是指軟件系統(tǒng)通過公開其應(yīng)用程序編程接口(API)或函數(shù)(function)來使外部的程序可以增加該軟件系統(tǒng)的功能或使用該軟件系統(tǒng)的資源,而不需要更改該軟件系統(tǒng)的源代碼。

????????在互聯(lián)網(wǎng)時代,把網(wǎng)站的服務(wù)封裝成一系列計算機易識別的數(shù)據(jù)接口開放出去,供第三方開發(fā)者使用,這種行為就叫做Open API,提供開放API的平臺本身就被稱為開放平臺。

????????第一種是技術(shù)性的開放,例如百度、騰訊、阿里巴巴等,例如阿里可以提供標準化的應(yīng)用軟件,但是數(shù)百萬形形色色的賣家對于個性化要求的軟件,并不是一個公司的力量可以滿足的,所以就把這些需求開放給眾多的第三方開發(fā)者的方式。再例如google的基于Linux平臺的開源手機操作系統(tǒng)就被認為會很快打敗Nokia塞班系統(tǒng)。這一種技術(shù)性開放平臺雖然目前來看跟B2C企業(yè)的開放平臺關(guān)系不大,但是也能從一定程度上說明開放平臺是互聯(lián)網(wǎng)企業(yè)的趨勢。

????????第二種開放平臺是指軟件系統(tǒng)通過公開其應(yīng)用程序編程接口(API)或函數(shù)(function)來使外部的程序可以增加該軟件系統(tǒng)的功能或使用該軟件系統(tǒng)的資源,而不需要更改該軟件系統(tǒng)的源代碼。B2C企業(yè)開放平臺又包含兩種形式,A:淘寶商城、日本樂天這種純平臺的模式,即自己不碰商品的進銷存,全部由入駐商家來做;B:美國亞馬遜、當當網(wǎng)、京東商城這種“自營+聯(lián)營”的模式。

1.2 開放平臺交互模型

三個角色:

  • 資源擁有者:用戶

  • 客戶端:各種app、瀏覽器

  • 服務(wù)提供方:包含兩個角色

    認證服務(wù)器

    資源服務(wù)器

1.2.1 認證服務(wù)器

認證服務(wù)器負責(zé)對用戶進行認證,并授權(quán)給客戶端權(quán)限。一般的認證都是通過對賬號密碼進行驗證實現(xiàn),而難點在于怎么進行授權(quán)。比如我們使用第三方登錄 "嗶哩嗶哩",可以看到如使用 QQ 登錄的授權(quán)頁面上有 "嗶哩嗶哩將獲取以下權(quán)限" 的字樣以及權(quán)限信息

18.Oauth2-微服務(wù)認證,skill,微服務(wù),面試,架構(gòu)

認證服務(wù)器需要知道請求授權(quán)的客戶端的身份以及該客戶端請求的權(quán)限。常見的做法是為每一個客戶端預(yù)先分配一個 id,并給每個 id 對應(yīng)一個名稱以及權(quán)限信息。這些信息可以寫在認證服務(wù)器上的配置文件里,今后客戶端每次打開授權(quán)頁面的時候,客戶端需要將該id發(fā)送到認證服務(wù)器,0Auth2.0就可以用來自動給客戶端分配id,同時完成配置文件的自動更新。

1.3 OAuth2 開放平臺

開放平臺是由 OAuth2.0 協(xié)議發(fā)展而來的一個產(chǎn)品,它的作用是讓客戶端自己去這上面進行注冊、申請,通過之后系統(tǒng)自動分配 客戶端id ,并完成配置的自動更新。

客戶端要完成申請,通常需要申請人填寫客戶端程序的類型(Web、App、微信小程序、支付寶小程序等等)、企業(yè)信息、營業(yè)執(zhí)照、法人信息以及想要獲取權(quán)限等信息,申請需要得到得到服務(wù)提供上的審核通過之后,開發(fā)平臺才會自動分配一個客戶端id給客戶端。

在通過審核之后,第三方應(yīng)用在進行認證時,就會想需要獲取到的權(quán)限信息展示到頁面上,例如嗶哩嗶哩獲取QQ權(quán)限。授權(quán)成功之后認證服務(wù)器需要把產(chǎn)生的 access_token 發(fā)送給客戶端,客戶端才能訪問具體的資源(頭像、性別之類的),大致過程如下:

  • 讓客戶端在開放平臺提交申請時候,填寫一個 網(wǎng)址,例如:www.baidu.com,此網(wǎng)址主要用來獲取認證碼。

  • 當有用戶授權(quán)成功之后,認證服務(wù)器將頁面重定向到這個網(wǎng)址,并將生成的 access_token拼接到該網(wǎng)址后面,例如:www.baidu.com?access_token=123?

  • 客戶端接收到access_token,之后客戶端就可以拿著這個token去獲取需要的數(shù)據(jù)了

1.3.1 令牌

傳統(tǒng)項目向服務(wù)端請求數(shù)據(jù),服務(wù)端需要頻繁的去數(shù)據(jù)庫查詢用戶名和密碼并進行對比,判斷用戶名和密碼正確與否,并作出相應(yīng)提示,這樣效率非常低下,怎么提高效率呢?Token便應(yīng)運而生。

Token是服務(wù)端生成的一串字符串,以作客戶端進行請求的一個令牌,當?shù)谝淮蔚卿浐螅?wù)器生成一個Token便將此Token返回給客戶端,以后客戶端只需帶上這個Token前來請求數(shù)據(jù)即可,無需再次帶上用戶名和密碼。減輕服務(wù)器的壓力,減少頻繁的查詢數(shù)據(jù)庫,使服務(wù)器更加健壯。

1.3.2 Access Token

Access Token 是客戶端訪問資源服務(wù)器的令牌。擁有這個令牌代表著得到用戶的授權(quán),即具備了訪問資源的權(quán)限。同時這個授權(quán)應(yīng)該是臨時的,只能在一定期限內(nèi)使用。主要原因是因為Access Token 在使用的過程中很有可能會泄露,被不法分子利用獲取我們的數(shù)據(jù)。所以Access Token應(yīng)該只能在某個期限內(nèi)使用,這樣可以降低因 Access Token 泄露而帶來的風(fēng)險。

1.4?認證模式

OAuth2.0中定義了四種授權(quán)模式:

  • authorization code 授權(quán)碼模式

  • implicit 簡化模式

  • resource owner password credentials 密碼模式

  • client credentials 客戶端模式

常見模式:授權(quán)碼、密碼模式

1.4.1 授權(quán)碼模式

授權(quán)碼模式(authorization code)是功能最完整、流程最嚴密的授權(quán)模式,code保證了token的安全性,即使code被攔截,由于沒有secret,也是無法通過code獲得token的。

角色行為與功能
  • 資源所有者

    只需要允許或拒絕第三方應(yīng)用獲得授權(quán)

  • 第三方應(yīng)用

    申請成為資源服務(wù)器的第三方應(yīng)用

    獲取資源服務(wù)器提供的資源

  • 授權(quán)服務(wù)器

    提供授權(quán)許可code、令牌token等

  • 資源服務(wù)器

    提供給第三方應(yīng)用開放資源的接口

18.Oauth2-微服務(wù)認證,skill,微服務(wù),面試,架構(gòu)

時序圖

18.Oauth2-微服務(wù)認證,skill,微服務(wù),面試,架構(gòu)

環(huán)境搭建

創(chuàng)建父項目

18.Oauth2-微服務(wù)認證,skill,微服務(wù),面試,架構(gòu)

18.Oauth2-微服務(wù)認證,skill,微服務(wù),面試,架構(gòu)

指定打包方式為pom

<?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>

    <groupId>com.woniuxy</groupId>
    <artifactId>oauth2</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>
</project>

創(chuàng)建auth-server認證服務(wù)器模塊

18.Oauth2-微服務(wù)認證,skill,微服務(wù),面試,架構(gòu)

18.Oauth2-微服務(wù)認證,skill,微服務(wù),面試,架構(gòu)

導(dǎo)入依賴

18.Oauth2-微服務(wù)認證,skill,微服務(wù),面試,架構(gòu)

導(dǎo)入依賴版本如下

<properties>
    <java.version>1.8</java.version>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <spring-boot.version>2.3.7.RELEASE</spring-boot.version>
    <spring-cloud-alibaba.version>2.2.2.RELEASE</spring-cloud-alibaba.version>
</properties>

oauth2依賴

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

創(chuàng)建用戶信息配置類

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

@Configuration
@EnableWebSecurity
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter{
	
	//密碼編碼器
	@Bean
	public BCryptPasswordEncoder passwordEncoder() {
		return new BCryptPasswordEncoder();
	}
	
    // 基于內(nèi)存的用戶信息
	@Override
	protected void configure(AuthenticationManagerBuilder auth) throws Exception {
		auth
			.inMemoryAuthentication()	//內(nèi)存認證
			.withUser("zhangsan")		//用戶名
			.password(passwordEncoder().encode("123"))	//密碼
			.authorities("ROLE_ADMIN");	//角色
	}
}

創(chuàng)建客戶端配置類,配置客戶端信息

import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
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 javax.annotation.Resource;

@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter{
	
	@Resource
	private BCryptPasswordEncoder passwordEncoder;
	
	@Override
	public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
		//配置客戶端
		clients
			.inMemory()		//內(nèi)存方式
			.withClient("client")	//客戶端名字
			.secret(passwordEncoder.encode("secret"))	//客戶端秘鑰
			.authorizedGrantTypes("authorization_code")//授權(quán)類型
			.scopes("all")	//授權(quán)范圍
			.redirectUris("http://www.baidu.com");	//回調(diào)網(wǎng)址,攜帶授權(quán)碼
	}
}

在application.yml文件中配置以下信息

server:
  port: 8000
spring:
  application:
    name: oauth

啟動項目進行登錄

localhost:8000/login

進入登錄頁面,輸入賬號:zhangsan,密碼:123進行登錄

18.Oauth2-微服務(wù)認證,skill,微服務(wù),面試,架構(gòu)

登錄成功之后向服務(wù)器發(fā)送請求獲取授權(quán)碼,在地址欄上輸入以下內(nèi)容回車

http://localhost:8080/oauth/authorize?client_id=client&response_type=code

可以看到一個授權(quán)頁面,詢問用戶是否進行授權(quán)

18.Oauth2-微服務(wù)認證,skill,微服務(wù),面試,架構(gòu)

授權(quán)成功之后會重定向到AuthorizationServerConfiguration配置類中指定的地址,并以參數(shù)的方式攜帶授權(quán)碼

通過postman發(fā)送請求向服務(wù)器獲取token

地址欄填寫:http://client:secret@localhost:8000/oauth/token

填寫客戶端賬號密碼

18.Oauth2-微服務(wù)認證,skill,微服務(wù),面試,架構(gòu)

填寫授權(quán)類型、授權(quán)碼,發(fā)送請求

18.Oauth2-微服務(wù)認證,skill,微服務(wù),面試,架構(gòu)

成功之后在postman上可以看到以下信息

18.Oauth2-微服務(wù)認證,skill,微服務(wù),面試,架構(gòu)

表示成功

注意:每個授權(quán)碼只能使用一次

1.4.2 密碼模式

密碼模式(Resource Owner Password Credentials Grant)中,用戶向客戶端提供自己的用戶名和密碼??蛻舳耸褂眠@些信息,向"服務(wù)商提供商"索要授權(quán)。

在這種模式中,用戶必須把自己的密碼給客戶端,但是客戶端不得儲存密碼。這通常用在用戶對客戶端高度信任的情況下,比如客戶端是操作系統(tǒng)的一部分,或者由一個著名公司出品。而認證服務(wù)器只有在其他授權(quán)模式無法執(zhí)行的情況下,才能考慮使用這種模式。

修改AuthorizationServerConfiguration配置類,添加密碼模式

@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
    //配置客戶端
    clients
        .inMemory()		
        .withClient("client")
        .secret(passwordEncoder.encode("secret"))
        .authorizedGrantTypes("authorization_code","password") //添加密碼授權(quán)模式
        .scopes("all")	//授權(quán)范圍
        .redirectUris("http://www.woniuxy.com");
}

在postman中新開一個請求,地址欄中填寫:http://localhost:8080/oauth/token

密碼授權(quán)模式要求以請求頭的方式提交客戶端賬號密碼,并且需要對賬號密碼進行base64加密,因此選擇Authorization選項卡,設(shè)置TYPE為"Basic Auth",并填寫客戶端賬號密碼

18.Oauth2-微服務(wù)認證,skill,微服務(wù),面試,架構(gòu)

在請求體中設(shè)置授權(quán)類型、用戶賬號密碼參數(shù)

18.Oauth2-微服務(wù)認證,skill,微服務(wù),面試,架構(gòu)

發(fā)送請求測試

18.Oauth2-微服務(wù)認證,skill,微服務(wù),面試,架構(gòu)

可以發(fā)現(xiàn)此時并不支持密碼模式,即使在AuthorizationServerConfiguration配置類中指定了密碼模式。

原因是此時代碼中缺少對密碼模式的支持,在oauth2中需要添加AuthenticationManager對象對密碼模式進行支持。

在WebSecurityConfiguration配置類中配置 AuthenticationManager

// 配置 AuthenticationManager(密碼模式需要該對象進行賬號密碼校驗)
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
    return super.authenticationManagerBean();
}

在AuthorizationServerConfiguration類中注入AuthenticationManager,并重寫以下方法

// 認證管理器
@Autowired
private AuthenticationManager authenticationManager;

//配置使用的 AuthenticationManager 實現(xiàn)用戶認證的功能
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
    endpoints.authenticationManager(authenticationManager);
}

重啟項目再次發(fā)送請求獲取token

18.Oauth2-微服務(wù)認證,skill,微服務(wù),面試,架構(gòu)

整合JWT

導(dǎo)入了oauth2依賴就自動導(dǎo)入的JWT相關(guān)依賴,因此不用單獨導(dǎo)入JWT,只需要進行設(shè)置就行

創(chuàng)建TokenConfiguration配置類

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;

@Configuration
public class TokenConfiguration {
    // 密碼
    private static String SIGNING_KEY="www.woniuxy.com";

    // token轉(zhuǎn)換器
    @Bean
    public JwtAccessTokenConverter accessTokenConverter() {
        JwtAccessTokenConverter jwtAccessTokenConverter = 
            new JwtAccessTokenConverter();
        jwtAccessTokenConverter.setSigningKey(SIGNING_KEY);
        return jwtAccessTokenConverter;
    }

    // 令牌存儲策略:jwt方式
    @Bean
    public TokenStore tokenStore(){
        return new JwtTokenStore(accessTokenConverter());
    }
}

在AuthorizationServerConfiguration配置類中注入相關(guān)對象

@Resource
private TokenStore tokenStore;

@Resource
private JwtAccessTokenConverter jwtAccessTokenConverter;

@Resource
private ClientDetailsService clientDetailsService;

在AuthorizationServerConfiguration配置類中編寫token服務(wù)方法,該方法主要用來設(shè)置

private AuthorizationServerTokenServices tokenServices(){
    // 創(chuàng)建服務(wù)對象
    DefaultTokenServices services = new DefaultTokenServices();
    // 設(shè)置客戶端詳情服務(wù)
    services.setClientDetailsService(clientDetailsService);
    // 支持刷新令牌
    services.setSupportRefreshToken(true);
    // 不重復(fù)使用refreshtoken,每次刷新之后只能用新的refreshtoken才能繼續(xù)刷新
	services.setReuseRefreshToken(false);
    // 設(shè)置令牌存儲策略
    services.setTokenStore(tokenStore);

    // 設(shè)置令牌增強
    TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
    tokenEnhancerChain.setTokenEnhancers(Arrays.asList(jwtAccessTokenConverter));
    services.setTokenEnhancer(tokenEnhancerChain);

    // 設(shè)置令牌過期時間
    services.setAccessTokenValiditySeconds(600);
    services.setRefreshTokenValiditySeconds(6000);

    return services;
}

修改configure(AuthorizationServerEndpointsConfigurer endpoints)方法,添加token服務(wù)

//配置使用的 AuthenticationManager 實現(xiàn)用戶認證的功能
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
    endpoints
        .authenticationManager(authenticationManager) // 認證管理器
        .tokenServices(tokenServices());	// 配置token服務(wù)
}

重啟項目發(fā)送請求獲取token

18.Oauth2-微服務(wù)認證,skill,微服務(wù),面試,架構(gòu)

如果想要獲取到refreshtoken,可以修改AuthorizationServerConfiguration配置類,添加refresh_token授權(quán)方式

@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
    //配置客戶端
    clients
        .inMemory()		
        .withClient("client")
        .secret(passwordEncoder.encode("secret"))	
        .authorizedGrantTypes("authorization_code","password","refresh_token") 
        .scopes("all")
        .redirectUris("http://www.woniuxy.com");
}

重啟項目測試

18.Oauth2-微服務(wù)認證,skill,微服務(wù),面試,架構(gòu)

18.Oauth2-微服務(wù)認證,skill,微服務(wù),面試,架構(gòu)

整合數(shù)據(jù)庫(user)

建表SQL

create database sc default character set=utf8;

DROP TABLE IF EXISTS `perms`;
CREATE TABLE `perms` (
  `id` int(11) DEFAULT NULL,
  `name` varchar(20) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO `perms` VALUES (3001,'user:add'),(3002,'user:del'),(3003,'user:find'),(3004,'user:update'),(3005,'goods:add'),(3006,'goods:find'),(3007,'goods:del'),(3008,'goods:update');

DROP TABLE IF EXISTS `role`;
CREATE TABLE `role` (
  `id` int(11) DEFAULT NULL,
  `name` varchar(20) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO `role` VALUES (2001,'ROLE_ADMIN'),(2002,'ROLE_USER');


DROP TABLE IF EXISTS `role_perms`;
CREATE TABLE `role_perms` (
  `rid` int(11) DEFAULT NULL,
  `pid` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO `role_perms` VALUES (2001,3001),(2001,3003),(2001,3004),(2002,3005),(2002,3006),(2002,3007),(2002,3008);

DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
  `id` int(11) DEFAULT NULL,
  `username` varchar(20) DEFAULT NULL,
  `password` varchar(64) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO `user` VALUES (1001,'zhangsan','$2a$10$pINVnd8.cXScFXCxI2x4cem4fOexA2J5TNY/Mx2CjN6mJuYGBNG0m'),(1002,'wangwu','wangwu');

DROP TABLE IF EXISTS `user_role`;
CREATE TABLE `user_role` (
  `uid` int(11) DEFAULT NULL,
  `rid` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO `user_role` VALUES (1001,2001),(1002,2002),(1003,2002);

auth-server的pom.xml中引入mybatis

<!--mybatis-->
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.1.4</version>
</dependency>

在application.yml中配置mybatis參數(shù)

mybatis:
  type-aliases-package: com.woniuxy.authserver.entity
  mapper-locations: classpath:/mapper/*.xml

創(chuàng)建Perms、Role、User實體類,注意:實體類必須實現(xiàn)序列化接口,不然運行過程中可能會報Failed to find access token for token錯誤

import lombok.Data;

@Data
public class Perms implements Serializable {
    private static final long serialVersionUID = 1L;
    private int id;
    private String name;
}
import lombok.Data;
import java.util.List;

@Data
public class Role implements Serializable {
    private static final long serialVersionUID = 1L;
    private int id;
    private String name;
    private List<Perms> perms;
}
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

@Slf4j
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User implements UserDetails, Serializable {

    private static final long serialVersionUID = 1L;

    private int id;
    private String username;
    private String password;
    private List<Role> roles;

    // 返回當前用戶的所有角色、權(quán)限信息
    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        log.debug("獲取用戶角色權(quán)限信息");
        // 新建集合
        List<GrantedAuthority> grantedAuthorities = new ArrayList<>();
        // 遍歷role
        for(Role role : this.roles){
            // 放入角色信息
            grantedAuthorities.add(new SimpleGrantedAuthority(role.getName()));
            // 遍歷當前角色的所有權(quán)限信息
            for(Perms perms : role.getPerms()){
                grantedAuthorities.add(new SimpleGrantedAuthority(perms.getName()));
            }
        }
        log.debug(grantedAuthorities.toString());
        return grantedAuthorities;
    }

    // 獲取用戶名
    @Override
    public String getUsername() {
        return this.username;
    }

    // 賬號是否過期    true表示未過期   false表示過期
    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    // 賬號是否被鎖定  true表示未鎖定   false表示鎖定
    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    // 憑證是否過期  true表示未過期   false表示過期
    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    // 用戶是否被禁用  true表示未禁用   false表示禁用
    @Override
    public boolean isEnabled() {
        return true;
    }
}

創(chuàng)建UerMapper接口

import com.woniuxy.springsecurity.entity.User;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface UserMapper {
    public User findByName(String username);
}

在resources目錄下創(chuàng)建mapper文件夾,并在該文件夾下創(chuàng)建Mapper文件

18.Oauth2-微服務(wù)認證,skill,微服務(wù),面試,架構(gòu)

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.woniuxy.authserver.mapper.UserMapper" >
    <select id="findByName" resultMap="user_map">
        select * from user where username = #{username}
    </select>

    <resultMap id="user_map" type="User">
        <id column="id" property="id"></id>
        <result column="username" property="username"></result>
        <result column="password" property="password"></result>

        <collection property="roles" ofType="Role" column="id" select="findRolesByUid"></collection>
    </resultMap>

    <select id="findRolesByUid" resultMap="role_map">
        select r.id,r.name from user_role ur,role r where ur.rid = r.id and ur.uid = #{id}
    </select>
    <resultMap id="role_map" type="Role">
        <id column="id" property="id"></id>
        <result column="name" property="name"></result>

        <collection property="perms" ofType="Perms" column="id" select="findPermsByRid"></collection>
    </resultMap>

    <select id="findPermsByRid" resultType="Perms">
        select p.id,p.name from role_perms rp,perms p where rp.pid = p.id and rp.rid = #{rid}
    </select>
</mapper>

創(chuàng)建CustomUserDetailsServiceImpl類實現(xiàn)UserDetailsService接口

import com.woniuxy.authserver.entity.User;
import com.woniuxy.authserver.mapper.UserMapper;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

@Service
public class CustomUserDetailsServiceImpl implements UserDetailsService {
    @Resource
    private UserMapper userMapper;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        //1.查詢用戶
        User user = userMapper.findByName(username);

        //2.判斷
        if (user == null) throw new UsernameNotFoundException("用戶不存在");

        //3.返回用戶信息
        return user;
    }
}

在配置類WebSecurityConfiguration中注入UserDetailsService對象,并修改configure(AuthenticationManagerBuilder auth)反方指定用戶信息從數(shù)據(jù)庫中獲取

@Resource
private UserDetailsService userDetailsService;

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    //auth
        //.inMemoryAuthentication()	//內(nèi)存認證
        //.withUser("zhangsan")		//用戶名
        //.password(passwordEncoder().encode("123"))	//密碼
        //.authorities("ROLE_ADMIN");	//角色
    auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}

重啟auth-server服務(wù),進行認證

封裝用戶id

在生成token時可以將用戶id封裝到token中,以便后期使用

修改TokenConfiguration類中的accessTokenConverter()方法,在創(chuàng)建轉(zhuǎn)換器時重寫enhance方法

// token轉(zhuǎn)換器
@Bean
public JwtAccessTokenConverter accessTokenConverter() {
    JwtAccessTokenConverter jwtAccessTokenConverter = 
        new JwtAccessTokenConverter(){
        @Override
        public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
            final Map<String,Object> map = new HashMap<>();
            // 從認證對象中得到用戶信息
            User user = (User) authentication.getUserAuthentication().getPrincipal();
            // 將用戶id放到token中
            map.put("uid", user.getId());
            ((DefaultOAuth2AccessToken)accessToken).setAdditionalInformation(map);
            // 返回
            return super.enhance(accessToken, authentication);
        }
    };
    jwtAccessTokenConverter.setSigningKey(SIGNING_KEY);
    return jwtAccessTokenConverter;
}

利用postman進行測試

18.Oauth2-微服務(wù)認證,skill,微服務(wù),面試,架構(gòu)

返回的結(jié)果中可以看到用戶id,token中也包含了用戶id

檢驗token是否過期

在org.springframework.security.oauth2.provider.endpoint.CheckTokenEndpoint類中定義了校驗token的接口/oauth/check_token,該接口可以用來校驗token是否合法、是否過期、是否是偽造的

@RequestMapping(value = "/oauth/check_token")
@ResponseBody
public Map<String, ?> checkToken(@RequestParam("token") String value) {

    OAuth2AccessToken token = resourceServerTokenServices.readAccessToken(value);
    if (token == null) {
        throw new InvalidTokenException("Token was not recognised");
    }

    if (token.isExpired()) {
        throw new InvalidTokenException("Token has expired");
    }

    OAuth2Authentication authentication = resourceServerTokenServices.loadAuthentication(token.getValue());

    Map<String, Object> response = (Map<String, Object>)accessTokenConverter.convertAccessToken(token, authentication);

    // gh-1070
    response.put("active", true);	// Always true if token exists and not expired

    return response;
}

只是該接口oauth2默認情況下是不對外公開的,如果要使用該接口那就必須手動配置開啟,在AuthorizationServerConfiguration配置類中重寫以下方法

//設(shè)置 /oauth/check_token 端點,通過認證后可訪問。
//該端點對應(yīng) CheckTokenEndpoint類,用于校驗訪問令牌的有效性。
//在客戶端訪問資源服務(wù)器時,會在請求中帶上訪問令牌。
//在資源服務(wù)器收到客戶端的請求時,會使用請求中的訪問令牌,找授權(quán)服務(wù)器確認該訪問令牌的有效性。
@Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
    // 默認是denyAll():拒絕所有
    oauthServer.checkTokenAccess("permitAll()");
}

checkTokenAccess常用值有三種:

  • denyAll():拒絕所有請求,不開放該接口

  • isAuthenticated():只對完成認證之后的請求開放

  • permitAll():對所有請求開放

測試:登錄成功之后在Postman中發(fā)送請求進行測試

接口url:http://localhost:8080/oauth/check_token

18.Oauth2-微服務(wù)認證,skill,微服務(wù),面試,架構(gòu)

返回的結(jié)果中包含了用戶的用戶名、權(quán)限等信息,還包括了token是否可用的信息

如果返回以下信息表示token已經(jīng)過期

18.Oauth2-微服務(wù)認證,skill,微服務(wù),面試,架構(gòu)

而如果返回以下信息表示token非法

18.Oauth2-微服務(wù)認證,skill,微服務(wù),面試,架構(gòu)

通過refresh_token獲取新token

獲取token和刷新token使用的是同一個接口,所以地址欄url還是

http://local:8080/oauth/token

只是grant_type需要換成refresh_token,然后將之前的refresh token作為參數(shù)傳遞給后臺

18.Oauth2-微服務(wù)認證,skill,微服務(wù),面試,架構(gòu)

還是需要將客戶端id、密碼以base64編碼放到請求頭中

18.Oauth2-微服務(wù)認證,skill,微服務(wù),面試,架構(gòu)

發(fā)送請求得到結(jié)果

18.Oauth2-微服務(wù)認證,skill,微服務(wù),面試,架構(gòu)

根據(jù)結(jié)果可以知道,token和refresh_token都會自動刷新,這樣做的好處是當token過期時通過程序調(diào)用刷新接口,獲取到新的token和refresh_token,實現(xiàn)自動續(xù)期。

refresh_token如果過期會得到以下結(jié)果

18.Oauth2-微服務(wù)認證,skill,微服務(wù),面試,架構(gòu)

refresh_token過期就需要重新登錄

1.5 資源服務(wù)器

創(chuàng)建resource子模塊,導(dǎo)入相關(guān)依賴

18.Oauth2-微服務(wù)認證,skill,微服務(wù),面試,架構(gòu)

設(shè)置父子關(guān)系

創(chuàng)建OAuth2ResourceServerConfig配置類

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;

@Configuration
@EnableResourceServer
public class OAuth2ResourceServerConfig extends ResourceServerConfigurerAdapter {
 
    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
            // 設(shè)置請求,需要認證后訪問
            .anyRequest().authenticated();
    }
}

創(chuàng)建controller

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/resource")
public class ResourceController {

    @RequestMapping("/info")
    public String info(){

        return "success";
    }
}

配置application.yml

server:
  port: 8001
spring:
  application:
    name: resource
security:
  oauth2:
    # OAuth2 Client 配置,對應(yīng) OAuth2ClientProperties 類
    client:
      client-id: client
      client-secret: secret
    # OAuth2 Resource 配置,對應(yīng) ResourceServerProperties 類
    resource:
      token-info-uri: http://127.0.0.1:8000/oauth/check_token # 獲得 Token 信息的 URL
    # 訪問令牌獲取 URL,自定義的
    access-token-uri: http://127.0.0.1:8000/oauth/token
management:
  endpoints:
    web:
      exposure:
        include: '*'

啟動resource資源服務(wù)器

先進行認證,得到token和refresh_token

localhost:8000/oauth/token

18.Oauth2-微服務(wù)認證,skill,微服務(wù),面試,架構(gòu)

然后將得到的token放到請求資源服務(wù)器的請求頭中

18.Oauth2-微服務(wù)認證,skill,微服務(wù),面試,架構(gòu)

發(fā)送請求后可以發(fā)現(xiàn)報500錯誤,查看resource控制臺可以發(fā)現(xiàn)以下信息

org.springframework.web.client.HttpClientErrorException$Forbidden: 403 : [{"timestamp":"2022-05-07T03:40:14.063+00:00","status":403,"error":"Forbidden","message":"","path":"/oauth/check_token"}]

根據(jù)信息提示:沒有權(quán)限訪問 /oauth/check_token,該URL是認證服務(wù)器用來校驗token是否合法的接口。資源服務(wù)器在接收到請求時會獲取到token,然后調(diào)用認證服務(wù)器的/oauth/check_token接口去檢驗token,但是此時認證服務(wù)器還沒有開放該端口(默認關(guān)閉),所以造成了403無法訪問。

到認證服務(wù)器的AuthorizationServerConfiguration配置類中開啟/oauth/check_token

//設(shè)置 /oauth/check_token 端點,通過認證后可訪問。
//該端點對應(yīng) CheckTokenEndpoint類,用于校驗訪問令牌的有效性。
//在客戶端訪問資源服務(wù)器時,會在請求中帶上訪問令牌。
//在資源服務(wù)器收到客戶端的請求時,會使用請求中的訪問令牌,找授權(quán)服務(wù)器確認該訪問令牌的有效性。
@Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
    // 默認是denyAll():拒絕所有
    oauthServer.checkTokenAccess("isAuthenticated()");
}

重啟認證服務(wù)器

重新進行認證得到token,然后用新的token再訪問資源服務(wù)器

18.Oauth2-微服務(wù)認證,skill,微服務(wù),面試,架構(gòu)

看到success表明成功

角色權(quán)限管理

在資源服務(wù)器主啟動類上添加@EnableGlobalMethodSecurity注解,開啟spring security權(quán)限注解的支持

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;

@SpringBootApplication
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class ResourceApplication {
    public static void main(String[] args) {
        SpringApplication.run(ResourceApplication.class, args);
    }
}

在resource/info接口方法上添加注解@PreAuthorize并指定角色或權(quán)限

@RequestMapping("/info")
@PreAuthorize("hasRole('USER')")
public String info(){

    return "success";
}

利用postman再次訪問該接口

18.Oauth2-微服務(wù)認證,skill,微服務(wù),面試,架構(gòu)

得到不允許訪問的結(jié)果,表明角色權(quán)限管理生效

1.6 整合數(shù)據(jù)庫(client)

建表SQL

CREATE TABLE `clientdetails` (
  `appId` VARCHAR(128) NOT NULL,
  `resourceIds` VARCHAR(256) DEFAULT NULL,
  `appSecret` VARCHAR(256) DEFAULT NULL,
  `scope` VARCHAR(256) DEFAULT NULL,
  `grantTypes` VARCHAR(256) DEFAULT NULL,
  `redirectUrl` VARCHAR(256) DEFAULT NULL,
  `authorities` VARCHAR(256) DEFAULT NULL,
  `access_token_validity` INT(11) DEFAULT NULL,
  `refresh_token_validity` INT(11) DEFAULT NULL,
  `additionalInformation` VARCHAR(4096) DEFAULT NULL,
  `autoApproveScopes` VARCHAR(256) DEFAULT NULL,
  PRIMARY KEY (`appId`)
) ENGINE=INNODB DEFAULT CHARSET=utf8;

CREATE TABLE `oauth_access_token` (
  `token_id` VARCHAR(256) DEFAULT NULL,
  `token` BLOB,
  `authentication_id` VARCHAR(128) NOT NULL,
  `user_name` VARCHAR(256) DEFAULT NULL,
  `client_id` VARCHAR(256) DEFAULT NULL,
  `authentication` BLOB,
  `refresh_token` VARCHAR(256) DEFAULT NULL,
  PRIMARY KEY (`authentication_id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8;

CREATE TABLE `oauth_approvals` (
  `userId` VARCHAR(256) DEFAULT NULL,
  `clientId` VARCHAR(256) DEFAULT NULL,
  `scope` VARCHAR(256) DEFAULT NULL,
  `status` VARCHAR(10) DEFAULT NULL,
  `expiresAt` TIMESTAMP NULL DEFAULT NULL,
  `lastModifiedAt` TIMESTAMP NULL DEFAULT NULL
) ENGINE=INNODB DEFAULT CHARSET=utf8;

CREATE TABLE `oauth_client_details` (
  `client_id` VARCHAR(128) NOT NULL,
  `resource_ids` VARCHAR(256) DEFAULT NULL,
  `client_secret` VARCHAR(256) DEFAULT NULL,
  `scope` VARCHAR(256) DEFAULT NULL,
  `authorized_grant_types` VARCHAR(256) DEFAULT NULL,
  `web_server_redirect_uri` VARCHAR(256) DEFAULT NULL,
  `authorities` VARCHAR(256) DEFAULT NULL,
  `access_token_validity` INT(11) DEFAULT NULL,
  `refresh_token_validity` INT(11) DEFAULT NULL,
  `additional_information` VARCHAR(4096) DEFAULT NULL,
  `autoapprove` VARCHAR(256) DEFAULT NULL,
  PRIMARY KEY (`client_id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8;

CREATE TABLE `oauth_client_token` (
  `token_id` VARCHAR(256) DEFAULT NULL,
  `token` BLOB,
  `authentication_id` VARCHAR(128) NOT NULL,
  `user_name` VARCHAR(256) DEFAULT NULL,
  `client_id` VARCHAR(256) DEFAULT NULL,
  PRIMARY KEY (`authentication_id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8;

CREATE TABLE `oauth_code` (
  `code` VARCHAR(256) DEFAULT NULL,
  `authentication` BLOB
) ENGINE=INNODB DEFAULT CHARSET=utf8;

CREATE TABLE `oauth_refresh_token` (
  `token_id` VARCHAR(256) DEFAULT NULL,
  `token` BLOB,
  `authentication` BLOB
) ENGINE=INNODB DEFAULT CHARSET=utf8;

在表 oauth_client_details 中增加一條客戶端配置記錄,在填入時可以按照AuthorizationServerConfiguration配置類中的客戶端配置進行配置

配置的效果如下:

18.Oauth2-微服務(wù)認證,skill,微服務(wù),面試,架構(gòu)

注:各字段解釋說明

  • client_id:客戶端標識

  • client_secret:客戶端安全碼。注意安全碼不能是明文需要加密,此處可以寫一段程序,然后使用BCryptPasswordEncoder為客戶端安全碼加密,得到加密之后的安全碼,再寫入到數(shù)據(jù)庫中,例如:

  • System.out.println(new BCryptPasswordEncoder().encode("secret"));

  • scope:客戶端授權(quán)范圍

  • authorized_grant_types:客戶端授權(quán)類型,支持多種類型,多種類型之間用逗號隔開

  • web_server_redirect_uri:服務(wù)器回調(diào)地址

創(chuàng)建實體類User、Role、Perms

在auth-server模塊的pom.xml中引入mybatis相關(guān)依賴

<!-- spring-boot-starter-jdbc 內(nèi)置了HikariCP 連接池,所以使用該連接池連接數(shù)據(jù)庫 -->
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!-- mysql -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- 獲取application.yml文件中的配置 -->
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-configuration-processor</artifactId>
	<optional>true</optional>
</dependency>

application.yml文件中添加數(shù)據(jù)庫相關(guān)配置

server:
  port: 8000
spring:
  application:
    name: oauth
  datasource:
    type: com.zaxxer.hikari.HikariDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    jdbc-url: jdbc:mysql://localhost:3306/sc?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC
    username: root
    password: root
    hikari:
      minimum-idle: 5
      maximum-pool-size: 10
      auto-commit: true #自動提交
      pool-name: MYHIKARICP
      connection-test-query: SELECT 1 #測試是否能連接上數(shù)據(jù)庫的SQL語句
  main:
    #true,后定義的bean會覆蓋之前定義的相同名稱的bean,生成dataSource替換掉原生的dataSource
    allow-bean-definition-overriding: true

創(chuàng)建數(shù)據(jù)庫配置類DataSourceConfiguration,主要配置用到的數(shù)據(jù)源,用HikariCP連接池的數(shù)據(jù)源替換到spring內(nèi)置的數(shù)據(jù)源。

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

import javax.sql.DataSource;

@Configuration
public class DataSourceConfiguration {
    @Bean   
    @Primary    
    //根據(jù)application.yml中的配置信息創(chuàng)建dataSource
    @ConfigurationProperties(prefix = "spring.datasource")
    //import javax.sql.DataSource;
    public DataSource dataSource() {
        //創(chuàng)建dataSource
        return DataSourceBuilder.create().build();
    }
}

在TokenConfiguration配置類中把token存儲策略改成JDBC方式,將jwt存放到數(shù)據(jù)庫中DataSource

@Resource
private DataSource dataSource;

// 令牌存儲策略:jwt方式
@Bean
public TokenStore tokenStore(DataSource dataSource){
    //return new JwtTokenStore(accessTokenConverter());
    return new JdbcTokenStore(dataSource);
}

修改AuthorizationServerConfiguration配置類,添加ClientDetailsService clientDetailsService(DataSource dataSource)方法,讓程序通過DataSource從數(shù)據(jù)庫中獲取到客戶端信息

@Bean
public ClientDetailsService clientDetailsService(DataSource dataSource) {
    //在數(shù)據(jù)庫中去獲取客戶端信息(oauth_client_details表)
    return new JdbcClientDetailsService(dataSource);
}

修改configure(ClientDetailsServiceConfigurer clients)方法指定到數(shù)據(jù)庫獲取客戶端信息

@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
    //配置客戶端
    //clients
    //.inMemory()		//內(nèi)存方式
    //.withClient("client")	//客戶端名字
    //.secret(passwordEncoder.encode("secret"))	//客戶端秘鑰
    //.authorizedGrantTypes("authorization_code","password","refresh_token")
    //.scopes("all")	//授權(quán)范圍
    //.redirectUris("http://www.woniuxy.com");	//回調(diào)網(wǎng)址

    clients.withClientDetails(clientDetailsService);
}

完成之后重啟項目,再次進行認證測試

正常情況下,測試完畢之后會在數(shù)據(jù)庫的oauth_access_token 表中會增加一個記錄,這個記錄就是瀏覽器獲取到的token和refresh token

18.Oauth2-微服務(wù)認證,skill,微服務(wù),面試,架構(gòu)

角色、權(quán)限管理測試

在resource服務(wù)的controller中添加以下方法

@RequestMapping("/message")
@PreAuthorize("hasRole('ADMIN')")
public String message(){

    return "message";
}

@RequestMapping("/data")
@PreAuthorize("hasAuthority('user:add')")
public String data(){

    return "data";
}
@RequestMapping("/test")
@PreAuthorize("hasAuthority('user:del')")
public String test(){

    return "test";
}

啟動resource服務(wù),通過postman分別測試info、message、data、test接口,如果只有message、data接口可以訪問,那么說明角色、權(quán)限管理成功。文章來源地址http://www.zghlxwxcb.cn/news/detail-687298.html

到了這里,關(guān)于18.Oauth2-微服務(wù)認證的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • SpringSecurity+OAuth2.0 搭建認證中心和資源服務(wù)中心

    SpringSecurity+OAuth2.0 搭建認證中心和資源服務(wù)中心

    目錄 ? 1. OAuth2.0 簡介 2. 代碼搭建? 2.1 認證中心(8080端口) 2.2 資源服務(wù)中心(8081端口) 3. 測試結(jié)果 ? OAuth 2.0(開放授權(quán) 2.0)是一個開放標準,用于授權(quán)第三方應(yīng)用程序訪問用戶在資源所有者(用戶)的帳戶上存儲的受保護資源,而無需共享用戶憑據(jù)。OAuth 2.0 主要用于在

    2024年01月22日
    瀏覽(21)
  • 認證服務(wù)---OAuth2.0基本介紹,微博登錄整合到實際項目中【下篇】

    認證服務(wù)---OAuth2.0基本介紹,微博登錄整合到實際項目中【下篇】

    上一篇簡單介紹了它的基本使用,這一篇就粗略說明一下如何在項目中實際應(yīng)用 當你進行了授權(quán)之后,跳轉(zhuǎn)到一個新的地址。這個地址應(yīng)該是你訪問接口的地址。在這個接口中完成相應(yīng)的access_token獲取,以及調(diào)用遠程服務(wù)接口實現(xiàn)新用戶注冊 具體業(yè)務(wù)實現(xiàn) 1、選擇登錄方式,

    2023年04月12日
    瀏覽(20)
  • 34、商城系統(tǒng)(十五):認證服務(wù),短信驗證碼,密碼加鹽,OAuth2.0社交登錄,SpringSession認證功能,單點登錄

    目錄 一、新建認證服務(wù) 1.后端項目啟動 2.前端頁面復(fù)制 3.配置域名 4.配置gateway

    2024年02月19日
    瀏覽(17)
  • Spring Authorization Server入門 (八) Spring Boot引入Security OAuth2 Client對接認證服務(wù)

    Spring Authorization Server入門 (八) Spring Boot引入Security OAuth2 Client對接認證服務(wù)

    在之前的文章中實現(xiàn)了一個認證服務(wù),并且添加了一些自定義的內(nèi)容,現(xiàn)在暫時沒想到認證服務(wù)的新內(nèi)容,本篇文章就先寫一下客戶端對接的吧,水一篇。 當用戶通過客戶端去訪問一個受限的資源時,客戶端會檢測是否有登錄信息,沒有登錄信息會重定向至認證服務(wù)器去請求

    2024年02月21日
    瀏覽(28)
  • OAuth2認證流程

    OAuth2認證流程

    目錄 什么是OAuth2 1. OAuth2認證流程 1、用戶點擊微信掃碼 2、用戶授權(quán)黑馬網(wǎng)站訪問用戶信息 3、黑馬程序員的網(wǎng)站獲取到授權(quán)碼 4、攜帶授權(quán)碼請求微信認證服務(wù)器申請令牌 5、微信認證服務(wù)器向黑馬程序員的網(wǎng)站響應(yīng)令牌 6、黑馬程序員網(wǎng)站請求微信資源服務(wù)器獲取資源即用

    2024年02月16日
    瀏覽(20)
  • 如何支持微軟郵箱OAuth2.0認證

    如何支持微軟郵箱OAuth2.0認證

    近期收到部分使用微軟郵箱的客戶反映,在EDI系統(tǒng)中無法連接到他們的企業(yè)郵箱中,連接過程中報錯: IMAP protocol error. 1 NO LOGIN failed…,經(jīng)確認是微軟停用了郵箱的基本驗證功能,客戶端必須使用OAuth2.0認證,才可以進行連接。那么在知行EDI系統(tǒng)中該如何解決這一問題呢? 知

    2024年02月07日
    瀏覽(28)
  • Spring Oauth2.0 自定義認證模式

    在特定場景下,可能Oauth2自帶的4種認證模式可能滿足不了我們?nèi)粘5氖褂?那么今天就為大家?guī)鞳auth2自定義認證模式。 知道你們肯定沒耐心讀完(總結(jié)一句話就是授權(quán)用的),有耐心的可以讀完下面的內(nèi)容介紹: 首先呢在這之前我們要搞清楚什么是Oauth , OAuth 是一個開放標準,該

    2024年02月16日
    瀏覽(20)
  • 【Oauth2.0 單點登錄 + 第三方授權(quán)認證】用戶認證、授權(quán)模式

    【Oauth2.0 單點登錄 + 第三方授權(quán)認證】用戶認證、授權(quán)模式

    本文主要對 SpringSecurity Oauth 2.0 用戶認證,授權(quán)碼授權(quán)模式、密碼授權(quán)模式,以及授權(quán)流程進行講解 開發(fā)中,有些功能只有管理員才有,普通用戶是沒有的。即需要對用戶的身份進行認證,是管理員還是普通用戶。認證方式有兩種: 身份認證: 用戶在訪問相應(yīng)資源時對用戶

    2023年04月08日
    瀏覽(25)
  • SpringBoot 如何使用 OAuth2 進行認證和授權(quán)

    OAuth2 是一種授權(quán)框架,可以用于實現(xiàn)第三方應(yīng)用程序訪問用戶資源的安全性。在 SpringBoot 中,我們可以使用 Spring Security 和 Spring OAuth2 來實現(xiàn) OAuth2 的認證和授權(quán)功能。本文將介紹如何在 SpringBoot 中使用 OAuth2 進行認證和授權(quán)。 在開始介紹如何使用 OAuth2 進行認證和授權(quán)之前,

    2024年02月13日
    瀏覽(24)
  • Springdoc Swagger UI集成OAuth2認證

    Springdoc Swagger UI集成OAuth2認證

    之前的文章講過OAuth2體系,以 授權(quán)碼 流程為例(參見下圖), 其中資源服務(wù)器(Resource Server)作為服務(wù)的提供者, 用戶在客戶端應(yīng)用完成授權(quán)流程后,客戶端應(yīng)用需要 攜帶AccessToken請求資源服務(wù)器 , 也即是要想訪問資源服務(wù)器就需要提供正確的 Authorization: Bearer AccessToke

    2024年02月02日
    瀏覽(28)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包