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

Spring Authorization Server入門 (十六) Spring Cloud Gateway對接認(rèn)證服務(wù)

這篇具有很好參考價值的文章主要介紹了Spring Authorization Server入門 (十六) Spring Cloud Gateway對接認(rèn)證服務(wù)。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報違法"按鈕提交疑問。

前言

????????之前雖然單獨(dú)講過Security Client和Resource Server的對接,但是都是基于Spring webmvc的,Gateway這種非阻塞式的網(wǎng)關(guān)是基于webflux的,對于集成Security相關(guān)內(nèi)容略有不同,且涉及到代理其它微服務(wù),所以會稍微比較麻煩些,今天就帶大家來實(shí)現(xiàn)Gateway網(wǎng)關(guān)對接OAuth2認(rèn)證服務(wù)。

Gateway對接說明

身份問題

????????在本次示例中網(wǎng)關(guān)既是客戶端(OAuth2 Client Server)又是資源服務(wù)(OAuth2 Resource Server),Client服務(wù)負(fù)責(zé)認(rèn)證,Resource負(fù)責(zé)鑒權(quán),這樣如果有在瀏覽器直接訪問網(wǎng)關(guān)的需要可以直接在瀏覽器由框架引導(dǎo)完成OAuth2認(rèn)證過程。

框架版本與架構(gòu)說明

架構(gòu)圖

spring cloud 微服務(wù).jpg

Spring Cloud依賴版本

框架 版本號
Spring Boot 3.1.0
Nacos Server 2.2.1
Spring Cloud 2022.0.4
Spring Cloud Alibaba 2022.0.0.0
Spring Security 6.1.0
Spring OAuth2 Client 6.1.0
Spring OAuth2 Resource Server 6.1.0

讀者可以自選版本使用,作為對接方版本問題不大;不確定Spring Cloud Alibaba 在部署時會不會有Spring Boot的版本限制,如果3.1.x無法使用請降級至3.0.10版本,開發(fā)時測試都是沒問題的。

網(wǎng)關(guān)集成認(rèn)證服務(wù)請求流程圖說明

Spring Cloud Gateway對接OAuth2認(rèn)證服務(wù).jpg

  1. 用戶請求受限資源
  2. 網(wǎng)關(guān)檢測沒有認(rèn)證信息,通過RedirectServerAuthenticationEntryPoint處理并發(fā)起OAuth2登錄授權(quán)申請
  3. 授權(quán)申請到達(dá)認(rèn)證服務(wù),認(rèn)證服務(wù)檢測到未登錄重定向至登錄頁面并展示給用戶
  4. 用戶登錄成功后請求重定向至授權(quán)申請接口,通過校驗(yàn)后攜帶Token重定向至回調(diào)地址(redirect_uri),注意:這里回調(diào)地址要設(shè)置為網(wǎng)關(guān)的地址,htttp://{網(wǎng)關(guān)ip}:{網(wǎng)關(guān)port}/login/oauth2/code/{registrationId},后邊的/login/oauth2/code/{registrationId}路徑是固定的,這是框架(Security OAuth2 Client)自帶的端點(diǎn)
  5. 請求到達(dá)網(wǎng)關(guān),由OAuth2LoginAuthenticationWebFilter攔截并調(diào)用父類AuthenticationWebFilterfilter方法進(jìn)行處理
  6. AuthenticationWebFilter調(diào)用OidcAuthorizationCodeReactiveAuthenticationManagerOAuth2LoginReactiveAuthenticationManager類處理(由授權(quán)申請的scope決定,包含openid就走OidcAuthorizationCodeReactiveAuthenticationManager,否則走另一個)
  7. 在獲取AccessToken成功以后調(diào)用ReactiveOAuth2UserService獲取用戶信息
  8. 獲取到用戶信息后會解析并將認(rèn)證信息保存至ReactiveSecurityContextHolder
  9. 完成這一系列的認(rèn)證之后會重定向至最一開始請求的受限資源,這時候就能獲取到認(rèn)證信息了
  10. 如果訪問的是被網(wǎng)關(guān)代理的服務(wù)則會通過令牌中繼(TokenRelay)攜帶token訪問

這就是網(wǎng)關(guān)通過認(rèn)證服務(wù)獲取認(rèn)證信息的一個流程,基本上只需要添加配置文件即可由框架引導(dǎo)進(jìn)行OAuth2認(rèn)證流程。

開始編碼

前置條件

  1. 搭建好標(biāo)準(zhǔn)OAuth2認(rèn)證服務(wù)
  2. 搭建nacos服務(wù)

項(xiàng)目結(jié)構(gòu)

項(xiàng)目結(jié)構(gòu)

gateway-example # 父模塊
 │  
 ├─gateway-client-example # 網(wǎng)關(guān)
 │  
 ├─normal-resource-example # webmvc資源服務(wù)
 │  
 ├─webflux-resource-example # webflux資源服務(wù)
 │  
 └─pom.xml # 公共依賴,依賴管理
 

創(chuàng)建一個空的maven項(xiàng)目

引入Spring Boot、Spring Cloud、Spring Cloud Alibaba,如下

<?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 https://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>3.1.0</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>gateway-example</artifactId>
    <version>0.0.1</version>
    <packaging>pom</packaging>
    <name>gateway-example</name>
    <description>gateway-example</description>
    <modules>
        <module>gateway-client-example</module>
        <module>normal-resource-example</module>
        <module>webflux-resource-example</module>
    </modules>

    <properties>
        <java.version>17</java.version>
        <!-- 修復(fù)漏洞 -->
        <snakeyaml.version>2.0</snakeyaml.version>
        <!-- Spring Cloud版本號 -->
        <spring-cloud.version>2022.0.4</spring-cloud.version>
        <!-- Spring Cloud Alibaba版本號 -->
        <spring-cloud-alibaba.version>2022.0.0.0</spring-cloud-alibaba.version>
    </properties>

    <dependencies>
        <!-- Lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <!-- Spring Boot 測試依賴 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!-- 服務(wù)注冊與發(fā)現(xiàn) -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!-- 配置中心 -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>

        <!-- 資源服務(wù)器starter -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${spring-cloud-alibaba.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

</project>

里邊的modules標(biāo)簽是在新建module時自動添加的

創(chuàng)建網(wǎng)關(guān)gateway-client-example模塊

創(chuàng)建gateway-client-example模塊

Spring Cloud 相關(guān)依賴已經(jīng)在parent模塊中引入,所以該模塊只需要引入Gateway、Client依賴,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>
    <parent>
        <groupId>com.example</groupId>
        <artifactId>gateway-example</artifactId>
        <version>0.0.1</version>
    </parent>

    <artifactId>gateway-client-example</artifactId>
    <name>gateway-client-example</name>
    <description>gateway-client-example</description>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-oauth2-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webflux</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <dependency>
            <groupId>io.projectreactor</groupId>
            <artifactId>reactor-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!-- 負(fù)載均衡依賴 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-loadbalancer</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

編寫客戶端配置

package com.example.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
import org.springframework.security.oauth2.core.user.OAuth2UserAuthority;

import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

/**
 * 客戶端配置
 *
 * @author vains
 */
@Configuration
public class ClientServerConfig {

    /**
     * 解析用戶權(quán)限信息(當(dāng)在瀏覽器中直接訪問接口,框架自動調(diào)用OIDC流程登錄時會用到該配置)
     *
     * @return GrantedAuthoritiesMapper
     */
    @Bean
    public GrantedAuthoritiesMapper userAuthoritiesMapper() {
        return (authorities) -> {
            Set<GrantedAuthority> mappedAuthorities = new HashSet<>();

            authorities.forEach(authority -> {
                if (authority instanceof OAuth2UserAuthority oAuth2UserAuthority) {
                    // 從認(rèn)證服務(wù)獲取的用戶信息中提取權(quán)限信息
                    Object userAuthorities = oAuth2UserAuthority.getAttributes().get("authorities");
                    if (userAuthorities instanceof Collection<?> collection) {
                        // 轉(zhuǎn)為SimpleGrantedAuthority的實(shí)例并插入mappedAuthorities中
                        collection.stream().filter(a -> a instanceof String)
                                .map(String::valueOf)
                                .map(SimpleGrantedAuthority::new)
                                .forEach(mappedAuthorities::add);
                    }
                }
            });

            return mappedAuthorities;
        };
    }


}

該配置會在獲取到用戶信息后解析用戶的權(quán)限信息,詳見文檔

編寫網(wǎng)關(guān)資源服務(wù)配置

package com.example.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.converter.Converter;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.method.configuration.EnableReactiveMethodSecurity;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter;
import org.springframework.security.oauth2.server.resource.authentication.JwtGrantedAuthoritiesConverter;
import org.springframework.security.oauth2.server.resource.authentication.ReactiveJwtAuthenticationConverterAdapter;
import org.springframework.security.web.server.SecurityWebFilterChain;
import reactor.core.publisher.Mono;

/**
 * 資源服務(wù)器配置
 *
 * @author vains
 */
@Configuration
@EnableWebFluxSecurity
@EnableReactiveMethodSecurity
public class ResourceServerConfig {

    /**
     * 配置認(rèn)證相關(guān)的過濾器鏈
     *
     * @param http Spring Security的核心配置類
     * @return 過濾器鏈
     */
    @Bean
    public SecurityWebFilterChain defaultSecurityFilterChain(ServerHttpSecurity http) {
        // 禁用csrf與cors
        http.csrf(ServerHttpSecurity.CsrfSpec::disable);
        http.cors(ServerHttpSecurity.CorsSpec::disable);

        // 開啟全局驗(yàn)證
        http.authorizeExchange((authorize) -> authorize
                //全部需要認(rèn)證
                .anyExchange().authenticated()
        );

        // 開啟OAuth2登錄
        http.oauth2Login(Customizer.withDefaults());

        // 設(shè)置當(dāng)前服務(wù)為資源服務(wù),解析請求頭中的token
        http.oauth2ResourceServer((resourceServer) -> resourceServer
                        // 使用jwt
                        .jwt(jwt -> jwt
                                // 請求中攜帶token訪問時會觸發(fā)該解析器適配器
                                .jwtAuthenticationConverter(grantedAuthoritiesExtractor())
                        )
                /*
                // xhr請求未攜帶Token處理
                .authenticationEntryPoint(this::authenticationEntryPoint)
                // 權(quán)限不足處理
                .accessDeniedHandler(this::accessDeniedHandler)
                // Token解析失敗處理
                .authenticationFailureHandler(this::failureHandler)
                */
        );

        return http.build();
    }

    /**
     * 自定義jwt解析器,設(shè)置解析出來的權(quán)限信息的前綴與在jwt中的key
     *
     * @return jwt解析器適配器 ReactiveJwtAuthenticationConverterAdapter
     */
    public Converter<Jwt, Mono<AbstractAuthenticationToken>> grantedAuthoritiesExtractor() {
        JwtGrantedAuthoritiesConverter grantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
        // 設(shè)置解析權(quán)限信息的前綴,設(shè)置為空是去掉前綴
        grantedAuthoritiesConverter.setAuthorityPrefix("");
        // 設(shè)置權(quán)限信息在jwt claims中的key
        grantedAuthoritiesConverter.setAuthoritiesClaimName("authorities");

        JwtAuthenticationConverter jwtAuthenticationConverter = new JwtAuthenticationConverter();
        jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(grantedAuthoritiesConverter);
        return new ReactiveJwtAuthenticationConverterAdapter(jwtAuthenticationConverter);
    }

}

需要注意的是開啟方法級別鑒權(quán)的注解變了,webflux的注解和webmvc的注解不一樣,并且過濾器鏈也換成SecurityWebFilterChain了;jwt自定義解析器的方式也不一致,實(shí)現(xiàn)方式見上方代碼

說明文檔如下

EnableReactiveMethodSecurity注解文檔

Jwt解析器適配器詳見文檔

編寫application.yml,添加nacos配置

spring:
  cloud:
    nacos:
      serverAddr: 127.0.0.1:8848
  config:
    import:
      - nacos:gateway.yml?refresh=true
  application:
    name: gateway

在nacos中創(chuàng)建gateway.yml配置文件

添加客戶端與資源服務(wù)配置,并添加其它資源服務(wù)的代理配置

server:
  port: 7000
spring:
  security:
    oauth2:
      # 資源服務(wù)器配置
      resourceserver:
        jwt:
          # Jwt中claims的iss屬性,也就是jwt的簽發(fā)地址,即認(rèn)證服務(wù)器的根路徑
          # 資源服務(wù)器會進(jìn)一步的配置,通過該地址獲取公鑰以解析jwt
          issuer-uri: http://192.168.119.1:8080
      client:
        provider:
          # 認(rèn)證提供者,自定義名稱
          custom-issuer:
            # Token簽發(fā)地址(認(rèn)證服務(wù)地址)
            issuer-uri: http://192.168.119.1:8080
            # 獲取用戶信息的地址,默認(rèn)的/userinfo端點(diǎn)需要IdToken獲取,為避免麻煩自定一個用戶信息接口
            user-info-uri: ${spring.security.oauth2.client.provider.custom-issuer.issuer-uri}/user
            user-name-attribute: name
        registration:
          messaging-client-oidc:
            # oauth認(rèn)證提供者配置,和上邊配置的認(rèn)證提供者關(guān)聯(lián)起來
            provider: custom-issuer
            # 客戶端名稱,自定義
            client-name: gateway
            # 客戶端id,從認(rèn)證服務(wù)申請的客戶端id
            client-id: messaging-client
            # 客戶端秘鑰
            client-secret: 123456
            # 客戶端認(rèn)證方式
            client-authentication-method: client_secret_basic
            # 獲取Token使用的授權(quán)流程
            authorization-grant-type: authorization_code
            # 回調(diào)地址,這里設(shè)置為Spring Security Client默認(rèn)實(shí)現(xiàn)使用code換取token的接口,當(dāng)前服務(wù)(gateway網(wǎng)關(guān))的地址
            redirect-uri: http://127.0.0.1:7000/login/oauth2/code/messaging-client-oidc
            scope:
              - message.read
              - message.write
              - openid
              - profile

  cloud:
    gateway:
      default-filters:
        # 令牌中繼
        - TokenRelay=
        # 代理路徑,代理至服務(wù)后會去除第一個路徑的內(nèi)容
        - StripPrefix=1
      routes:
        # 資源服務(wù)代理配置
        - id: resource
          uri: lb://resource
          predicates:
            - Path=/resource/**
        # 資源服務(wù)代理配置
        - id: webflux
          uri: lb://webflux-resource
          predicates:
            - Path=/webflux/**

注意:配置文件中令牌中繼(TokenRelay)的配置就是添加一個filterTokenRelay=; 當(dāng)網(wǎng)關(guān)引入spring-boot-starter-oauth2-client依賴并設(shè)置spring.security.oauth2.client.*屬性時,會自動創(chuàng)建一個TokenRelayGatewayFilterFactory過濾器,它會從認(rèn)證信息中獲取access token,并放入下游請求的請求頭中。 詳見Gateway關(guān)于TokenRelay的文檔

項(xiàng)目結(jié)構(gòu)

網(wǎng)關(guān)項(xiàng)目結(jié)構(gòu)

創(chuàng)建webmvc資源服務(wù)模塊normal-resource-example

在pom.xml中添加web依賴,如下

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.example</groupId>
        <artifactId>gateway-example</artifactId>
        <version>0.0.1</version>
    </parent>

    <artifactId>normal-resource-example</artifactId>
    <name>normal-resource-example</name>
    <description>normal-resource-example</description>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

創(chuàng)建資源服務(wù)器配置,添加自定義jwt解析器

package com.example.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter;
import org.springframework.security.oauth2.server.resource.authentication.JwtGrantedAuthoritiesConverter;

/**
 * 資源服務(wù)器配置
 *
 * @author vains
 */
@Configuration
@EnableWebSecurity
@EnableMethodSecurity(jsr250Enabled = true, securedEnabled = true)
public class ResourceServerConfig {

    /**
     * 自定義jwt解析器,設(shè)置解析出來的權(quán)限信息的前綴與在jwt中的key
     *
     * @return jwt解析器 JwtAuthenticationConverter
     */
    @Bean
    public JwtAuthenticationConverter jwtAuthenticationConverter() {
        JwtGrantedAuthoritiesConverter grantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
        // 設(shè)置解析權(quán)限信息的前綴,設(shè)置為空是去掉前綴
        grantedAuthoritiesConverter.setAuthorityPrefix("");
        // 設(shè)置權(quán)限信息在jwt claims中的key
        grantedAuthoritiesConverter.setAuthoritiesClaimName("authorities");

        JwtAuthenticationConverter jwtAuthenticationConverter = new JwtAuthenticationConverter();
        jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(grantedAuthoritiesConverter);
        return jwtAuthenticationConverter;
    }

}

編寫application.yml添加nacos配置

spring:
  cloud:
    nacos:
      serverAddr: 127.0.0.1:8848
  config:
    import:
      - nacos:resource.yml?refresh=true
  application:
    name: resource

在nacos中創(chuàng)建resource.yml配置文件,添加資源服務(wù)配置

server:
  port: 7100

spring:
  security:
    oauth2:
      # 資源服務(wù)器配置
      resourceserver:
        jwt:
          # Jwt中claims的iss屬性,也就是jwt的簽發(fā)地址,即認(rèn)證服務(wù)器的根路徑
          # 資源服務(wù)器會進(jìn)一步的配置,通過該地址獲取公鑰以解析jwt
          issuer-uri: http://192.168.119.1:8080

注意端口,不能與網(wǎng)關(guān)和認(rèn)證服務(wù)重復(fù)

模塊結(jié)構(gòu)

normal-resource-example結(jié)構(gòu)

創(chuàng)建webflux資源服務(wù)模塊

pom.xml添加webflux依賴,如下

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.example</groupId>
        <artifactId>gateway-example</artifactId>
        <version>0.0.1</version>
    </parent>

    <artifactId>webflux-resource-example</artifactId>
    <name>webflux-resource-example</name>
    <description>webflux-resource-example</description>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webflux</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

創(chuàng)建資源服務(wù)配置并且添加jwt解析器適配器

跟網(wǎng)關(guān)的資源服務(wù)配置差不多,如下

package com.example.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.converter.Converter;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.config.annotation.method.configuration.EnableReactiveMethodSecurity;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter;
import org.springframework.security.oauth2.server.resource.authentication.JwtGrantedAuthoritiesConverter;
import org.springframework.security.oauth2.server.resource.authentication.ReactiveJwtAuthenticationConverterAdapter;
import org.springframework.security.web.server.SecurityWebFilterChain;
import reactor.core.publisher.Mono;

/**
 * 資源服務(wù)器配置
 *
 * @author vains
 */
@Configuration
@EnableWebFluxSecurity
@EnableReactiveMethodSecurity
public class ResourceServerConfig {

    /**
     * 配置認(rèn)證相關(guān)的過濾器鏈
     *
     * @param http Spring Security的核心配置類
     * @return 過濾器鏈
     */
    @Bean
    public SecurityWebFilterChain defaultSecurityFilterChain(ServerHttpSecurity http) {
        // 禁用csrf與cors
        http.csrf(ServerHttpSecurity.CsrfSpec::disable);
        http.cors(ServerHttpSecurity.CorsSpec::disable);

        // 開啟全局驗(yàn)證
        http.authorizeExchange((authorize) -> authorize
                //全部需要認(rèn)證
                .anyExchange().authenticated()
        );

        // 設(shè)置當(dāng)前服務(wù)為資源服務(wù),解析請求頭中的token
        http.oauth2ResourceServer((resourceServer) -> resourceServer
                // 使用jwt
                .jwt(jwtSpec -> jwtSpec
                        // 設(shè)置jwt解析器適配器
                        .jwtAuthenticationConverter(grantedAuthoritiesExtractor())
                )
        );
        return http.build();
    }

    /**
     * 自定義jwt解析器,設(shè)置解析出來的權(quán)限信息的前綴與在jwt中的key
     *
     * @return jwt解析器適配器 ReactiveJwtAuthenticationConverterAdapter
     */
    public Converter<Jwt, Mono<AbstractAuthenticationToken>> grantedAuthoritiesExtractor() {
        JwtGrantedAuthoritiesConverter grantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
        // 設(shè)置解析權(quán)限信息的前綴,設(shè)置為空是去掉前綴
        grantedAuthoritiesConverter.setAuthorityPrefix("");
        // 設(shè)置權(quán)限信息在jwt claims中的key
        grantedAuthoritiesConverter.setAuthoritiesClaimName("authorities");

        JwtAuthenticationConverter jwtAuthenticationConverter = new JwtAuthenticationConverter();
        jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(grantedAuthoritiesConverter);
        return new ReactiveJwtAuthenticationConverterAdapter(jwtAuthenticationConverter);
    }

}

編寫application.yml添加nacos配置

spring:
  cloud:
    nacos:
      serverAddr: 127.0.0.1:8848
  config:
    import:
      - nacos:webflux.yml?refresh=true
  application:
    name: webflux-resource

nacos中添加webflux.yml配置文件并添加資源服務(wù)配置

server:
  port: 7200

spring:
  security:
    oauth2:
      # 資源服務(wù)器配置
      resourceserver:
        jwt:
          # Jwt中claims的iss屬性,也就是jwt的簽發(fā)地址,即認(rèn)證服務(wù)器的根路徑
          # 資源服務(wù)器會進(jìn)一步的配置,通過該地址獲取公鑰以解析jwt
          issuer-uri: http://192.168.119.1:8080

與webmvc的資源服務(wù)的配置是一樣的,注意端口不能與其它服務(wù)端口沖突

模塊結(jié)構(gòu)

webflux-resource-example模塊結(jié)構(gòu)

在三個模塊中添加測試類,一式三份

webmvc測試接口

package com.example.controller;

import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * 測試接口
 *
 * @author vains
 */
@RestController
public class TestController {

    @GetMapping("/test01")
    @PreAuthorize("hasAnyAuthority('message.write')")
    public String test01() {
        return "test01";
    }

    @GetMapping("/test02")
    @PreAuthorize("hasAnyAuthority('test02')")
    public String test02() {
        return "test02";
    }

    @GetMapping("/app")
    @PreAuthorize("hasAnyAuthority('app')")
    public String app() {
        return "app";
    }

}

webflux測試接口

package com.example.controller;

import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;

/**
 * 測試接口
 *
 * @author vains
 */
@RestController
public class TestController {

    @GetMapping("/test01")
    @PreAuthorize("hasAnyAuthority('message.write')")
    public Mono<String> test01() {
        return Mono.just("test01");
    }

    @GetMapping("/test02")
    @PreAuthorize("hasAnyAuthority('test02')")
    public Mono<String> test02() {
        return Mono.just("test02");
    }

    @GetMapping("/app")
    @PreAuthorize("hasAnyAuthority('app')")
    public Mono<String> app() {
        return Mono.just("app");
    }

}

測試

前置條件

  1. 啟動認(rèn)證服務(wù)
  2. 啟動nacos
  3. nacos中都有相關(guān)配置

啟動項(xiàng)目

依次啟動三個服務(wù),順序無所謂

在postman中直接訪問網(wǎng)關(guān)接口或代理的服務(wù)接口

在postman中直接訪問網(wǎng)關(guān)
被重定向至登錄了,攜帶X-Requested-With請求頭訪問,代表當(dāng)前是xhr請求

攜帶請求頭訪問
響應(yīng)401,框架有區(qū)分是瀏覽器請求還是xhr請求,對于瀏覽器請求會重定向到頁面,對于xhr請求默認(rèn)會響應(yīng)401狀態(tài)碼,可自己實(shí)現(xiàn)異常處理,這里錯誤信息在請求頭中是因?yàn)闆]有重寫異常處理,網(wǎng)關(guān)資源服務(wù)配置代碼中有注釋。

在瀏覽器中訪問網(wǎng)關(guān)接口或代理的服務(wù)接口

訪問

瀏覽器打開地址:http://127.0.0.1:7000/resource/app

引導(dǎo)請求至認(rèn)證服務(wù)發(fā)起授權(quán)申請
請求到達(dá)網(wǎng)關(guān)后檢測到未登錄會引導(dǎo)用戶進(jìn)行OAuth2認(rèn)證流程

登錄后提交

登錄后提交
登錄提交后認(rèn)證服務(wù)重定向授權(quán)申請接口,校驗(yàn)通過后會生成code并攜帶code重定向至回調(diào)地址,注意,這里的回調(diào)地址是網(wǎng)關(guān)的服務(wù)地址,由網(wǎng)關(guān)中的OAuth2 Client處理,如圖

網(wǎng)關(guān)根據(jù)code換取token
網(wǎng)關(guān)會根據(jù)code換取token,獲取token后根據(jù)token獲取用戶信息,并調(diào)用網(wǎng)關(guān)客戶端配置中自定義的userAuthoritiesMapper解析權(quán)限信息。

訪問權(quán)限不足的接口

權(quán)限不足
響應(yīng)403,并將錯誤信息放入響應(yīng)頭中

使用token訪問網(wǎng)關(guān)

過期token

過期token
響應(yīng)401并在響應(yīng)頭中提示token已過期

錯誤token

錯誤token
響應(yīng)401并在響應(yīng)頭中提示token無法解析

權(quán)限不足token

權(quán)限不足

響應(yīng)403并提示權(quán)限不足

正常請求

正常請求
響應(yīng)200并正確響應(yīng)接口信息

寫在最后

本文帶大家簡單實(shí)現(xiàn)了Spring Cloud Gateway對接認(rèn)證服務(wù),Gateway中添加客戶端主要是為了如果代理服務(wù)有靜態(tài)資源(html、css、image)時可以直接發(fā)起OAuth2授權(quán)流程,在瀏覽器登錄后直接訪問,同時也是開啟令牌中繼的必要依賴;引入Resource Server依賴是當(dāng)需要對網(wǎng)關(guān)的接口鑒權(quán)時可以直接使用,如果網(wǎng)關(guān)只負(fù)責(zé)轉(zhuǎn)發(fā)應(yīng)該是可以去掉資源服務(wù)相關(guān)依賴和配置的,由各個被代理的微服務(wù)對自己的接口進(jìn)行鑒權(quán)。這些東西在之前基本都是講過的內(nèi)容,所以本文很多地方都是一筆帶過的,如果某些地方不清楚可以針對性的翻翻之前的文章,也可以在評論區(qū)中提出。
如果有什么問題或者需要補(bǔ)充的請在評論區(qū)指出,謝謝。

附錄

Gitee倉庫地址

Gateway令牌中繼文檔

OAuth2登錄后用戶權(quán)限解析文檔

webflux開啟方法鑒權(quán)EnableReactiveMethodSecurity注解說明文檔

webflux的Jwt解析器適配器說明文檔

webflux對接OAuth2 Client文檔

webflux對接OAuth2 Resource Server文檔
文章來源地址http://www.zghlxwxcb.cn/news/detail-683272.html

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

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

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

相關(guān)文章

  • 【spring authorization server系列教程】(一)入門系列,spring authorization server簡介??焖贅?gòu)建一個授權(quán)服務(wù)器(基于最新版本0.3.0)

    【spring authorization server系列教程】(一)入門系列,spring authorization server簡介??焖贅?gòu)建一個授權(quán)服務(wù)器(基于最新版本0.3.0)

    【spring authorization server系列教程】(一)入門系列,快速構(gòu)建一個授權(quán)服務(wù)器 spring authorization server是spring團(tuán)隊最新的認(rèn)證授權(quán)服務(wù)器,之前的oauth2后面會逐步棄用。不過到現(xiàn)在發(fā)文的時候,我看到官網(wǎng)已經(jīng)把之前oauth2倉庫廢棄了。 現(xiàn)在spring authorization server已經(jīng)到生產(chǎn)就緒階段了

    2024年02月05日
    瀏覽(26)
  • spring cloud gateway 網(wǎng)關(guān) server Web Exchange方法

    1.String getHeader (String name)?該方法用于獲取一個指定頭字段的值,如果請求消息中沒有包含指定的頭字段,則 getHeader() 方法返回 null;如果請求消息中包含多個指定名稱的頭字段,則 getHeader() 方法返回其中第一個頭字段的 2.getQueryParams()獲取 請求參數(shù)中的信息

    2024年02月12日
    瀏覽(14)
  • Spring Authorization Server入門 (二十) 實(shí)現(xiàn)二維碼掃碼登錄

    Spring Authorization Server入門 (二十) 實(shí)現(xiàn)二維碼掃碼登錄

    打開網(wǎng)頁,發(fā)起授權(quán)申請/未登錄被重定向到登錄頁面 選擇二維碼登錄,頁面從后端請求二維碼 頁面渲染二維碼圖片,并輪詢請求,獲取二維碼的狀態(tài) 事先登錄過APP的手機(jī)掃描二維碼,然后APP請求服務(wù)器端的API接口,把用戶認(rèn)證信息傳遞到服務(wù)器中 后端收到APP的請求后更改

    2024年02月21日
    瀏覽(23)
  • Spring Authorization Server入門 (十五) 分離授權(quán)確認(rèn)與設(shè)備碼校驗(yàn)頁面

    2023-12-01修改:在session-data-redis(Github)分支中添加了基于 spring-session-data-redis 的實(shí)現(xiàn),無需借助 nonceId 來保持認(rèn)證狀態(tài),該分支已去除所有 nonceId 相關(guān)內(nèi)容,需要注意的是 axios 在初始化時需要添加配置 withCredentials: true ,讓請求攜帶cookie。當(dāng)然一些響應(yīng)json的處理還是使用下方的

    2024年02月14日
    瀏覽(18)
  • 【Spring Authorization Server 系列】(一)入門篇,快速搭建一個授權(quán)服務(wù)器

    【Spring Authorization Server 系列】(一)入門篇,快速搭建一個授權(quán)服務(wù)器

    官方主頁:https://spring.io/projects/spring-authorization-server Spring Authorization Server 是一個框架,提供了 OAuth 2.1 和 OpenID Connect 1.0 規(guī)范以及其他相關(guān)規(guī)范的實(shí)現(xiàn)。 它建立在 Spring Security 之上,為構(gòu)建 OpenID Connect 1.0 Identity Providers 和 OAuth2 Authorization Server 產(chǎn)品提供安全、輕量級和可定制

    2024年02月16日
    瀏覽(26)
  • Spring Authorization Server入門 (一) 初識SpringAuthorizationServer和OAuth2.1協(xié)議

    Spring Authorization Server入門 (一) 初識SpringAuthorizationServer和OAuth2.1協(xié)議

    經(jīng)過近些年網(wǎng)絡(luò)和設(shè)備的不斷發(fā)展,之前的oauth2.0發(fā)布的授權(quán)協(xié)議標(biāo)準(zhǔn)已經(jīng)遠(yuǎn)遠(yuǎn)不能滿足現(xiàn)在的場景和需求,根據(jù)其安全最佳實(shí)踐,在oauth2.0的基礎(chǔ)上移除了一些不安全的授權(quán)方式,并且對擴(kuò)展協(xié)議進(jìn)行整合。該協(xié)議定義了一系列關(guān)于授權(quán)的開放網(wǎng)絡(luò)標(biāo)準(zhǔn),允許用戶授權(quán)第三方

    2024年02月11日
    瀏覽(24)
  • Spring Authorization Server入門 (十二) 實(shí)現(xiàn)授權(quán)碼模式使用前后端分離的登錄頁面

    Spring Authorization Server入門 (十二) 實(shí)現(xiàn)授權(quán)碼模式使用前后端分離的登錄頁面

    2023-12-01修改:在session-data-redis(Github)分支中添加了基于 spring-session-data-redis 的實(shí)現(xiàn),無需借助 nonceId 來保持認(rèn)證狀態(tài),該分支已去除所有 nonceId 相關(guān)內(nèi)容,需要注意的是 axios 在初始化時需要添加配置 withCredentials: true ,讓請求攜帶cookie。當(dāng)然一些響應(yīng)json的處理還是使用下方的

    2024年02月13日
    瀏覽(26)
  • Spring Authorization Server入門 (三) 集成流程說明、細(xì)節(jié)補(bǔ)充和各種方式獲取token測試

    Spring Authorization Server入門 (三) 集成流程說明、細(xì)節(jié)補(bǔ)充和各種方式獲取token測試

    在上一篇文章中的AuthorizationConfig.java配置類中,類上有三個注解,分別是@Configuration、@EnableWebSecurity和@EnableMethodSecurity注解,雖然在類中有注釋,但是這里在細(xì)講一下,同時放一下官網(wǎng)的說明 @EnableWebSecurity 加載了WebSecurityConfiguration配置類, 配置安全認(rèn)證策略。 加載了Authenti

    2024年02月11日
    瀏覽(21)
  • Spring Security 6.x 系列【28】授權(quán)服務(wù)器篇之Spring Authorization Server 1.0 入門案例

    Spring Security 6.x 系列【28】授權(quán)服務(wù)器篇之Spring Authorization Server 1.0 入門案例

    有道無術(shù),術(shù)尚可求,有術(shù)無道,止于術(shù)。 本系列Spring Boot 版本 3.0.4 本系列Spring Security 版本 6.0.2 本系列Spring Authorization Server 版本 1.0.2 源碼地址:https://gitee.com/pearl-organization/study-spring-security-demo 在前幾篇文檔中,我們學(xué)習(xí)了 OAuth 2.0 協(xié)議,并使用 spring-security-oauth2-client 完成

    2024年02月12日
    瀏覽(24)
  • Spring Cloud Gateway快速入門(二)——斷言工廠

    Spring Cloud Gateway快速入門(二)——斷言工廠

    Spring Cloud Gateway包含許多內(nèi)置的Route Predicate工廠。所有這些斷言都匹配HTTP請求的不同屬性。多路由斷言工廠通過and組合。 官方提供的路由工廠: 這些斷言工廠的配置方式,參照官方文檔:https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.1.0.RELEASE/single/spring-cloud-gateway.html

    2024年02月07日
    瀏覽(26)

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

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

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

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

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包