基于Spring cloud搭建oauth2

news2024/11/18 5:52:36

1,OAuth2.0简介

OAuth(开发授权)是一个开放标准,允许用户授权第三方应用访问他们存储在另外的服务提供者上的信息,而不需要将用户名和密码提供给第三方应用或分享他们数据的所有内容。
OAuth2.0是OAuth的延续,但他并不兼容OAuth1.0,即它完全废除OAuth1.0。很多大公司如Google,Yahoo,Microsoft等都提供了OAuth认证服 务,这些都足以说明OAUTH标准逐渐成为开放资源授权的标准。
微信小程序授权登录同样也是提供OAuth认证服务。详情请看

2,业务场景

某一天你想登录网站CSDN,之前没有在CSDN网站注册过,此时在人家的登陆页面提供了其他登录方式,如下图
在这里插入图片描述

假设我们自己做的网站叫网站B,也在上图中红框部分,如下图
在这里插入图片描述

你恰好之前在我们的B网站上注册过账号,那么现在就可以使用B网站上的账号登录在CSDN上。那么我们在B网站上做这样的一个功能就是使用OAuth2做的。

OAuth2.0包含一下几种角色

  • 1,客户端:本身不存储资源,需要通过资源拥有者的授权去请求资源服务器的资源。
  • 2,资源拥有者:通常为用户,也可以是应用程序,即该资源的拥有者。
  • 3,授权服务器(认证服务器):用于服务提供商对资源拥有者的身份认证,对访问资源进行授权,认证成功后会给客户端发放令牌(access_token),作为客户端访问资源服务器的凭据。
  • 4,资源服务器:存储资源的服务器
  • 5,客户端标识:client_id
  • 6,客户端密钥:client_secret
    为什么要有client_id和client_secret呢?
    因为服务提供商不能允许随便一个客户端就接入到它的授权服务器,服务提供商会 给准入的接入方一个身份,用于接入时的凭据。

3,环境搭建

在这里插入图片描述

authServer-service 认证服务(颁发Token)

gateway-service 网关(认证用户的请求 也即认证Token)

member-service 会员服务(资源服务)

在这里插入图片描述

5,环境搭建

父工程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>shop.awz</groupId>
  <artifactId>rwShop</artifactId>
  <version>1.0-SNAPSHOT</version>
  <modules>
    <module>authServer-service</module>
    <module>gateway-service</module>
    <module>order-service</module>
    <module>authServer-service</module>
    <module>admin-service</module>
      <module>product-service</module>
      <module>common-service</module>
  </modules>
  <packaging>pom</packaging>

  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-parent</artifactId>
    <version>2.3.2.RELEASE</version>
  </parent>

  <properties>
    <project.build.sourceEncoding>UTF‐8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF‐8</project.reporting.outputEncoding>
    <java.version>1.8</java.version>
    <maven.compiler.source>1.7</maven.compiler.source>
    <maven.compiler.target>1.7</maven.compiler.target>
    <spring.cloud-version>Hoxton.SR9</spring.cloud-version>
  </properties>


  <dependencies>

    <!--服务注册发现-->
    <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-sentinel</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-actuator</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>
      <!--spring-cloud-alibaba 版本控制-->
      <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-alibaba-dependencies</artifactId>
        <version>2.2.6.RELEASE</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>

    </dependencies>
  </dependencyManagement>

  <build>
    <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
      <plugins>
        <!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
        <plugin>
          <artifactId>maven-clean-plugin</artifactId>
          <version>3.1.0</version>
        </plugin>
        <!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
        <plugin>
          <artifactId>maven-resources-plugin</artifactId>
          <version>3.0.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>3.8.0</version>
        </plugin>
        <plugin>
          <artifactId>maven-surefire-plugin</artifactId>
          <version>2.22.1</version>
        </plugin>
        <plugin>
          <artifactId>maven-jar-plugin</artifactId>
          <version>3.0.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-install-plugin</artifactId>
          <version>2.5.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-deploy-plugin</artifactId>
          <version>2.8.2</version>
        </plugin>
        <!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
        <plugin>
          <artifactId>maven-site-plugin</artifactId>
          <version>3.7.1</version>
        </plugin>
        <plugin>
          <artifactId>maven-project-info-reports-plugin</artifactId>
          <version>3.0.0</version>
        </plugin>
      </plugins>
    </pluginManagement>
  </build>
</project>

authServer-service 工程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">
    <parent>
        <artifactId>rwShop</artifactId>
        <groupId>shop.awz</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>authServer-service</artifactId>

    <name>authServer-service</name>
    <!-- FIXME change it to the project's website -->
    <url>http://www.example.com</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.7</maven.compiler.source>
        <maven.compiler.target>1.7</maven.compiler.target>
    </properties>

    <dependencies>
        <!--Lombok引入-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <!-- Spring Boot JPA 依赖 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.0</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-oauth2</artifactId>
        </dependency>
        <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>
                <executions>
                    <execution>
                        <goals>
                            <!--可以把依赖的包都打包到生成的Jar包中-->
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

网关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">
    <parent>
        <artifactId>rwShop</artifactId>
        <groupId>shop.awz</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>gateway-service</artifactId>

    <name>gateway-service</name>
    <!-- FIXME change it to the project's website -->
    <url>http://www.example.com</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.7</maven.compiler.source>
        <maven.compiler.target>1.7</maven.compiler.target>
        <spring.cloud-version>Hoxton.SR9</spring.cloud-version>
    </properties>

    <dependencies>

        <!--安全认证框架-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <!--security-oauth2整合-->
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-oauth2-resource-server</artifactId>
        </dependency>
        <!--oauth2-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-oauth2</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.30</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <!--网关-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <!--https://github.com/alibaba/spring-cloud-alibaba/wiki/%E7%89%88%E6%9C%AC%E8%AF%B4%E6%98%8E-->
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring.cloud-version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>


    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <goals>
                            <!--可以把依赖的包都打包到生成的Jar包中-->
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

4,authServer-service

sql脚本
DROP TABLE IF EXISTS `oauth_refresh_token`;
CREATE TABLE `oauth_refresh_token`  (
  `token_id` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `token` blob NULL,
  `authentication` blob NULL
) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of oauth_refresh_token
-- ----------------------------
INSERT INTO `oauth_refresh_token` VALUES ('bbd20d647aae14322d441c3bfee18d03', 0xACED00057372004C6F72672E737072696E676672616D65776F726B2E73656375726974792E6F61757468322E636F6D6D6F6E2E44656661756C744578706972696E674F417574683252656672657368546F6B656E2FDF47639DD0C9B70200014C000A65787069726174696F6E7400104C6A6176612F7574696C2F446174653B787200446F72672E737072696E676672616D65776F726B2E73656375726974792E6F61757468322E636F6D6D6F6E2E44656661756C744F417574683252656672657368546F6B656E73E10E0A6354D45E0200014C000576616C75657400124C6A6176612F6C616E672F537472696E673B787074002438396463643534612D626663392D343964352D613332372D3834653637643030656630637372000E6A6176612E7574696C2E44617465686A81014B5974190300007870770800000186CF2F197E78, 0xACED0005737200416F72672E737072696E676672616D65776F726B2E73656375726974792E6F61757468322E70726F76696465722E4F417574683241757468656E7469636174696F6EBD400B02166252130200024C000D73746F7265645265717565737474003C4C6F72672F737072696E676672616D65776F726B2F73656375726974792F6F61757468322F70726F76696465722F4F4175746832526571756573743B4C00127573657241757468656E7469636174696F6E7400324C6F72672F737072696E676672616D65776F726B2F73656375726974792F636F72652F41757468656E7469636174696F6E3B787200476F72672E737072696E676672616D65776F726B2E73656375726974792E61757468656E7469636174696F6E2E416273747261637441757468656E7469636174696F6E546F6B656ED3AA287E6E47640E0200035A000D61757468656E746963617465644C000B617574686F7269746965737400164C6A6176612F7574696C2F436F6C6C656374696F6E3B4C000764657461696C737400124C6A6176612F6C616E672F4F626A6563743B787000737200266A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C654C697374FC0F2531B5EC8E100200014C00046C6973747400104C6A6176612F7574696C2F4C6973743B7872002C6A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C65436F6C6C656374696F6E19420080CB5EF71E0200014C00016371007E00047870737200136A6176612E7574696C2E41727261794C6973747881D21D99C7619D03000149000473697A65787000000001770400000001737200426F72672E737072696E676672616D65776F726B2E73656375726974792E636F72652E617574686F726974792E53696D706C654772616E746564417574686F7269747900000000000002120200014C0004726F6C657400124C6A6176612F6C616E672F537472696E673B787074003C24326124313024397A6D7A72516F485065324C76552F6369594F6837656830767054686C47306A66566E643935742F4D634C794C623974354E337A477871007E000C707372003A6F72672E737072696E676672616D65776F726B2E73656375726974792E6F61757468322E70726F76696465722E4F41757468325265717565737400000000000000010200075A0008617070726F7665644C000B617574686F72697469657371007E00044C000A657874656E73696F6E7374000F4C6A6176612F7574696C2F4D61703B4C000B726564697265637455726971007E000E4C00077265667265736874003B4C6F72672F737072696E676672616D65776F726B2F73656375726974792F6F61757468322F70726F76696465722F546F6B656E526571756573743B4C000B7265736F7572636549647374000F4C6A6176612F7574696C2F5365743B4C000D726573706F6E7365547970657371007E0014787200386F72672E737072696E676672616D65776F726B2E73656375726974792E6F61757468322E70726F76696465722E426173655265717565737436287A3EA37169BD0200034C0008636C69656E74496471007E000E4C001172657175657374506172616D657465727371007E00124C000573636F706571007E00147870740003617070737200256A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C654D6170F1A5A8FE74F507420200014C00016D71007E00127870737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F400000000000067708000000080000000374000A6772616E745F7479706574000870617373776F7264740009636C69656E745F6964740003617070740008757365726E616D657400047A69796178737200256A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C65536574801D92D18F9B80550200007871007E0009737200176A6176612E7574696C2E4C696E6B656448617368536574D86CD75A95DD2A1E020000787200116A6176612E7574696C2E48617368536574BA44859596B8B7340300007870770C000000103F4000000000000174000377656278017371007E0025770C000000103F400000000000017371007E000D740009524F4C455F55534552787371007E001A3F40000000000000770800000010000000007870707371007E0025770C000000103F40000000000001740003617070787371007E0025770C000000103F40000000000000787372004F6F72672E737072696E676672616D65776F726B2E73656375726974792E61757468656E7469636174696F6E2E557365726E616D6550617373776F726441757468656E7469636174696F6E546F6B656E00000000000002120200024C000B63726564656E7469616C7371007E00054C00097072696E636970616C71007E00057871007E0003017371007E00077371007E000B0000000177040000000171007E000F7871007E0032737200176A6176612E7574696C2E4C696E6B6564486173684D617034C04E5C106CC0FB0200015A000B6163636573734F726465727871007E001A3F400000000000067708000000080000000474000D636C69656E745F73656372657474000361707071007E001C71007E001D71007E001E71007E001F71007E002071007E0021780070737200326F72672E737072696E676672616D65776F726B2E73656375726974792E636F72652E7573657264657461696C732E5573657200000000000002120200075A00116163636F756E744E6F6E457870697265645A00106163636F756E744E6F6E4C6F636B65645A001563726564656E7469616C734E6F6E457870697265645A0007656E61626C65644C000B617574686F72697469657371007E00144C000870617373776F726471007E000E4C0008757365726E616D6571007E000E7870010101017371007E0022737200116A6176612E7574696C2E54726565536574DD98509395ED875B0300007870737200466F72672E737072696E676672616D65776F726B2E73656375726974792E636F72652E7573657264657461696C732E5573657224417574686F72697479436F6D70617261746F720000000000000212020000787077040000000171007E000F78707400047A697961);

SET FOREIGN_KEY_CHECKS = 1;

DROP TABLE IF EXISTS `oauth_access_token`;
CREATE TABLE `oauth_access_token`  (
  `token_id` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `token` blob NULL,
  `authentication_id` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `user_name` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `client_id` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `authentication` blob NULL,
  `refresh_token` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  PRIMARY KEY (`authentication_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of oauth_access_token
-- ----------------------------
INSERT INTO `oauth_access_token` VALUES ('5e45bb16fc49de6fbdbbc5272cf199f7', 0xACED0005737200436F72672E737072696E676672616D65776F726B2E73656375726974792E6F61757468322E636F6D6D6F6E2E44656661756C744F4175746832416363657373546F6B656E0CB29E361B24FACE0200064C00156164646974696F6E616C496E666F726D6174696F6E74000F4C6A6176612F7574696C2F4D61703B4C000A65787069726174696F6E7400104C6A6176612F7574696C2F446174653B4C000C72656672657368546F6B656E74003F4C6F72672F737072696E676672616D65776F726B2F73656375726974792F6F61757468322F636F6D6D6F6E2F4F417574683252656672657368546F6B656E3B4C000573636F706574000F4C6A6176612F7574696C2F5365743B4C0009746F6B656E547970657400124C6A6176612F6C616E672F537472696E673B4C000576616C756571007E000578707372001E6A6176612E7574696C2E436F6C6C656374696F6E7324456D7074794D6170593614855ADCE7D002000078707372000E6A6176612E7574696C2E44617465686A81014B597419030000787077080000018637437F9E787372004C6F72672E737072696E676672616D65776F726B2E73656375726974792E6F61757468322E636F6D6D6F6E2E44656661756C744578706972696E674F417574683252656672657368546F6B656E2FDF47639DD0C9B70200014C000A65787069726174696F6E71007E0002787200446F72672E737072696E676672616D65776F726B2E73656375726974792E6F61757468322E636F6D6D6F6E2E44656661756C744F417574683252656672657368546F6B656E73E10E0A6354D45E0200014C000576616C756571007E0005787074002438396463643534612D626663392D343964352D613332372D3834653637643030656630637371007E0009770800000186CF2F197E78737200256A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C65536574801D92D18F9B80550200007872002C6A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C65436F6C6C656374696F6E19420080CB5EF71E0200014C0001637400164C6A6176612F7574696C2F436F6C6C656374696F6E3B7870737200176A6176612E7574696C2E4C696E6B656448617368536574D86CD75A95DD2A1E020000787200116A6176612E7574696C2E48617368536574BA44859596B8B7340300007870770C000000103F400000000000017400037765627874000662656172657274002433633033643735392D376665362D346164322D383034332D303066303564366466353066, '743b6d0443f74879a092610739f759b6', 'ziya', 'app', 0xACED0005737200416F72672E737072696E676672616D65776F726B2E73656375726974792E6F61757468322E70726F76696465722E4F417574683241757468656E7469636174696F6EBD400B02166252130200024C000D73746F7265645265717565737474003C4C6F72672F737072696E676672616D65776F726B2F73656375726974792F6F61757468322F70726F76696465722F4F4175746832526571756573743B4C00127573657241757468656E7469636174696F6E7400324C6F72672F737072696E676672616D65776F726B2F73656375726974792F636F72652F41757468656E7469636174696F6E3B787200476F72672E737072696E676672616D65776F726B2E73656375726974792E61757468656E7469636174696F6E2E416273747261637441757468656E7469636174696F6E546F6B656ED3AA287E6E47640E0200035A000D61757468656E746963617465644C000B617574686F7269746965737400164C6A6176612F7574696C2F436F6C6C656374696F6E3B4C000764657461696C737400124C6A6176612F6C616E672F4F626A6563743B787000737200266A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C654C697374FC0F2531B5EC8E100200014C00046C6973747400104C6A6176612F7574696C2F4C6973743B7872002C6A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C65436F6C6C656374696F6E19420080CB5EF71E0200014C00016371007E00047870737200136A6176612E7574696C2E41727261794C6973747881D21D99C7619D03000149000473697A65787000000001770400000001737200426F72672E737072696E676672616D65776F726B2E73656375726974792E636F72652E617574686F726974792E53696D706C654772616E746564417574686F7269747900000000000002120200014C0004726F6C657400124C6A6176612F6C616E672F537472696E673B787074003C24326124313024397A6D7A72516F485065324C76552F6369594F6837656830767054686C47306A66566E643935742F4D634C794C623974354E337A477871007E000C707372003A6F72672E737072696E676672616D65776F726B2E73656375726974792E6F61757468322E70726F76696465722E4F41757468325265717565737400000000000000010200075A0008617070726F7665644C000B617574686F72697469657371007E00044C000A657874656E73696F6E7374000F4C6A6176612F7574696C2F4D61703B4C000B726564697265637455726971007E000E4C00077265667265736874003B4C6F72672F737072696E676672616D65776F726B2F73656375726974792F6F61757468322F70726F76696465722F546F6B656E526571756573743B4C000B7265736F7572636549647374000F4C6A6176612F7574696C2F5365743B4C000D726573706F6E7365547970657371007E0014787200386F72672E737072696E676672616D65776F726B2E73656375726974792E6F61757468322E70726F76696465722E426173655265717565737436287A3EA37169BD0200034C0008636C69656E74496471007E000E4C001172657175657374506172616D657465727371007E00124C000573636F706571007E00147870740003617070737200256A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C654D6170F1A5A8FE74F507420200014C00016D71007E00127870737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F400000000000067708000000080000000374000A6772616E745F7479706574000870617373776F7264740009636C69656E745F6964740003617070740008757365726E616D657400047A69796178737200256A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C65536574801D92D18F9B80550200007871007E0009737200176A6176612E7574696C2E4C696E6B656448617368536574D86CD75A95DD2A1E020000787200116A6176612E7574696C2E48617368536574BA44859596B8B7340300007870770C000000103F4000000000000174000377656278017371007E0025770C000000103F400000000000017371007E000D740009524F4C455F55534552787371007E001A3F40000000000000770800000010000000007870707371007E0025770C000000103F40000000000001740003617070787371007E0025770C000000103F40000000000000787372004F6F72672E737072696E676672616D65776F726B2E73656375726974792E61757468656E7469636174696F6E2E557365726E616D6550617373776F726441757468656E7469636174696F6E546F6B656E00000000000002120200024C000B63726564656E7469616C7371007E00054C00097072696E636970616C71007E00057871007E0003017371007E00077371007E000B0000000177040000000171007E000F7871007E0032737200176A6176612E7574696C2E4C696E6B6564486173684D617034C04E5C106CC0FB0200015A000B6163636573734F726465727871007E001A3F400000000000067708000000080000000474000D636C69656E745F73656372657474000361707071007E001C71007E001D71007E001E71007E001F71007E002071007E0021780070737200326F72672E737072696E676672616D65776F726B2E73656375726974792E636F72652E7573657264657461696C732E5573657200000000000002120200075A00116163636F756E744E6F6E457870697265645A00106163636F756E744E6F6E4C6F636B65645A001563726564656E7469616C734E6F6E457870697265645A0007656E61626C65644C000B617574686F72697469657371007E00144C000870617373776F726471007E000E4C0008757365726E616D6571007E000E7870010101017371007E0022737200116A6176612E7574696C2E54726565536574DD98509395ED875B0300007870737200466F72672E737072696E676672616D65776F726B2E73656375726974792E636F72652E7573657264657461696C732E5573657224417574686F72697479436F6D70617261746F720000000000000212020000787077040000000171007E000F78707400047A697961, 'bbd20d647aae14322d441c3bfee18d03');

SET FOREIGN_KEY_CHECKS = 1;
DROP TABLE IF EXISTS `oauth_client_details`;
CREATE TABLE `oauth_client_details`  (
  `client_id` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `resource_ids` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `client_secret` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `scope` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `authorized_grant_types` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `web_server_redirect_uri` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `authorities` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `access_token_validity` int NULL DEFAULT NULL,
  `refresh_token_validity` int NULL DEFAULT NULL,
  `additional_information` varchar(4096) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `autoapprove` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  PRIMARY KEY (`client_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of oauth_client_details
-- ----------------------------
INSERT INTO `oauth_client_details` VALUES ('app', 'app', '$2a$10$by3F74LZAxBQLXCbESOS/eew8/7skdxvx5QdcJAMddfLISizAOXAe', 'web', 'implicit,client_credentials,authorization_code,refresh_token,password', 'http://www.baidu.com', 'ROLE_USER', NULL, NULL, NULL, NULL);

SET FOREIGN_KEY_CHECKS = 1;
DROP TABLE IF EXISTS `oauth_client_token`;
CREATE TABLE `oauth_client_token`  (
  `token_id` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `token` blob NULL,
  `authentication_id` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `user_name` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `client_id` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  PRIMARY KEY (`authentication_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of oauth_client_token
-- ----------------------------

SET FOREIGN_KEY_CHECKS = 1;
DROP TABLE IF EXISTS `oauth_code`;
CREATE TABLE `oauth_code`  (
  `code` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `authentication` blob NULL
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of oauth_code
-- ----------------------------

SET FOREIGN_KEY_CHECKS = 1;
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user`  (
  `id` int NOT NULL AUTO_INCREMENT,
  `passwd` varchar(265) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `user_name` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `user_role` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES (1, '$2a$10$9zmzrQoHPe2LvU/ciYOh7eh0vpThlG0jfVnd95t/McLyLb9t5N3zG', 'ziya', 'ADMIN');

SET FOREIGN_KEY_CHECKS = 1;

配置文件application.yml

server:
  port: 9000


spring:
  main:
    allow-bean-definition-overriding: true
  application:
    name: auth-service
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/awz_admins?serverTimezone=GMT%2B8&useSSL=false&characterEncoding=utf8
    username: root
    password: 123456
  jackson:
    date-format: yyyy-MM-dd HH:mm:ss
    time-zone: GMT+8
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
logging:
  level:
    shop.awz.uaa.dao: debug
#  file:
#    name: log/blog.log
  pattern:
    level:

mybatis-plus:
  type-aliases-package: shop.awz.uaa.entity
  mapper-locations: classpath:mapper/*.xml
  #配置驼峰命名映射
  configuration:
    map-underscore-to-camel-case: true

AuthorizationServerConfig配置类


```java
package shop.awz.uaa.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
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.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.TokenEnhancerChain;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;

import javax.sql.DataSource;
import java.util.Arrays;

/**
 * @ClassName AuthorizationServerConfig
 * @Author 杨杰
 * @Date 2023/2/9 12:15
 * @Version 1.0
 */


@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
    @Autowired
    private UserDetailsService userDetailService;

    // 认证管理器
    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private DataSource dataSource;

    @Autowired
    private JwtAccessTokenConverter accessTokenConverter;

    @Autowired
    private TokenStore tokenStore;

    @Autowired
    private ClientDetailsService clientDetailsService;


    //令牌管理服务
    @Bean
    public AuthorizationServerTokenServices tokenService() {
        DefaultTokenServices service = new DefaultTokenServices();
        // 客户端详情服务
        service.setClientDetailsService(clientDetailsService);
        service.setSupportRefreshToken(true);//支持刷新令牌
        service.setTokenStore(tokenStore);//令牌存储策略
        //令牌增强
        TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
        tokenEnhancerChain.setTokenEnhancers(Arrays.asList(accessTokenConverter));
        service.setTokenEnhancer(tokenEnhancerChain);

        service.setAccessTokenValiditySeconds(7200); // 令牌默认有效期2小时
        service.setRefreshTokenValiditySeconds(259200); // 刷新令牌默认有效期3天
        return service;
    }

//    /**
//     * access_token存储器
//     * 这里存储在数据库,大家可以结合自己的业务场景考虑将access_token存入数据库还是redis
//     */
//    @Bean
//    public TokenStore tokenStore() {
//        return new JdbcTokenStore(dataSource);
//    }

    /**
     * 从数据库读取clientDetails相关配置
     * 有InMemoryClientDetailsService 和 JdbcClientDetailsService 两种方式选择
     */
    @Bean
    public ClientDetailsService clientDetails() {
        return new JdbcClientDetailsService(dataSource);
    }

    /**
     * 注入密码加密实现器
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    /**
     * 认证服务器Endpoints配置
     */
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        //如果需要使用refresh_token模式则需要注入userDetailService
        endpoints.userDetailsService(userDetailService);
        endpoints.authenticationManager(this.authenticationManager);
        endpoints.tokenServices(tokenService());
        endpoints.tokenStore(tokenStore);
    }

    /**
     * 认证服务器相关接口权限管理
     */
    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security.allowFormAuthenticationForClients() //如果使用表单认证则需要加上
                .tokenKeyAccess("permitAll()")
                .checkTokenAccess("isAuthenticated()");
    }

    /**
     * client存储方式,此处使用jdbc存储
     */
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.withClientDetails(clientDetails());
    }
}

ClientDetailsServiceConfigurer:用来配置客户端详情服务(ClientDetailsService),客户端详情信息在 这里进行初始化,你能够把客户端详情信息写死在这里或者是通过数据库来存储调取详情信息。

AuthorizationServerEndpointsConfigurer:用来配置令牌(token)的访问端点和令牌服务(token services)。

AuthorizationServerSecurityConfigurer:用来配置令牌端点的安全约束
TokenConfig配置类

```java
package shop.awz.uaa.config;

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;

/**
 * @ClassName TokenConfig
 * @Author 杨杰
 * @Date 2023/2/9 22:14
 * @Version 1.0
 */
@Configuration
public class TokenConfig {

    private String SIGNING_KEY = "uaa123";

    @Bean
    public TokenStore tokenStore() {
        //JWT令牌存储方案
        return new JwtTokenStore(accessTokenConverter());
    }

    @Bean
    public JwtAccessTokenConverter accessTokenConverter() {
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        converter.setSigningKey(SIGNING_KEY); //对称秘钥,资源服务器使用该秘钥来验证
        return converter;
    }

   /* @Bean
    public TokenStore tokenStore() {
        //使用内存存储令牌(普通令牌)
        return new InMemoryTokenStore();
    }*/
}

这里使用的是JWT
WebSecurityConfig配置类

package shop.awz.uaa.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.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import shop.awz.uaa.service.UserDetailServiceImpl;
/**
 * @ClassName WebSecurityConfig
 * @Author 杨杰
 * @Date 2023/2/9 12:25
 * @Version 1.0
 */


@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    @Bean("UserDetailServiceImpl")
    public UserDetailsService userDetailsService(){
        return new UserDetailServiceImpl();
    }

    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }


    /**
     * 认证管理
     * @return 认证管理对象
     * @throws Exception 认证异常信息
     */
    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService()).passwordEncoder(new PasswordEncoder() {
            //密码加密
            @Override
            public String encode(CharSequence charSequence) {
                BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
                return passwordEncoder.encode(charSequence);
            }

            @Override
            public boolean matches(CharSequence charSequence, String s) {
                BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
                boolean res = passwordEncoder.matches(charSequence, s);
                return res;
            }
        });
    }

    /**
     * http安全配置
     * @param http http安全对象
     * @throws Exception http安全异常信息
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .anyRequest().authenticated()
                .and().httpBasic()
                .and().cors()
                .and().csrf().disable();
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers(
                "/error",
                "/static/**",
                "/v2/api-docs/**",
                "/swagger-resources/**",
                "/webjars/**",
                "/favicon.ico"
        );
    }
}

UserDetailServiceImpl实现类

package shop.awz.uaa.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.AuthorityUtils;
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 shop.awz.uaa.dao.UserMapper;
import shop.awz.uaa.entity.User;

/**
 * @ClassName UserDetailServiceImpl
 * @Author 杨杰
 * @Date 2023/2/9 12:11
 * @Version 1.0
 */
@Service("UserDetailServiceImpl")
public class UserDetailServiceImpl implements UserDetailsService {

    @Autowired
    private UserMapper userMapper;

    @Override
    public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
        //获取本地用户
//        User user = userName.queryByUserName(userName);
        User user = userMapper.selectOne(new QueryWrapper<User>().eq("user_name",userName));
        if (user != null) {
            //返回oauth2的用户
            return new org.springframework.security.core.userdetails.User(
                    user.getUserName(),
                    user.getPasswd(),
                    AuthorityUtils.createAuthorityList(user.getPasswd()));
        } else {
            throw new UsernameNotFoundException("用户[" + userName + "]不存在");
        }
    }
}

user实体类

package shop.awz.uaa.entity;

/**
 * @ClassName User
 * @Author 杨杰
 * @Date 2023/2/9 11:59
 * @Version 1.0
 */

import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;

@Data
@TableName("user")
public class User {

    @TableId
    private Integer id;
    private String passwd;

    private String userName;

    private String userRole;

}

usermapper

@Mapper
public interface UserMapper extends BaseMapper<User> {
}

启动类

@SpringBootApplication
@EnableResourceServer
@EnableDiscoveryClient
public class AuthServiceMain9000
{
    public static void main( String[] args )
    {
        SpringApplication.run(AuthServiceMain9000.class,args);
    }
}

6,网关

application.yml

server:
  port: 80

spring:
  application:
    name: gateway-service
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/awz_admins?serverTimezone=GMT%2B8&useSSL=false&characterEncoding=utf8
    username: root
    password: 123456
  jackson:
    date-format: yyyy-MM-dd HH:mm:ss
    time-zone: GMT+8
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
    gateway:
      routes:
        - id: auth-route
          uri: lb://auth-service
          predicates:
            - Path=/oauth/**

        - id: order-route
          uri: lb://order-service
          predicates:
            - Path=/order/**
        - id: admin-route
          uri: lb://admin-service
          predicates:
            - Path=/admin-service/**
      globalcors:
        cors-configurations:
          '[/**]':
            allow-credentials: true
            allowed-methods: "*"
            allowed-origins: "*"
            allowed-headers: "*"

TokenConfig配置类

@Configuration
public class TokenConfig {

    private String SIGNING_KEY = "uaa123";

    @Bean
    public TokenStore tokenStore() {
        //JWT令牌存储方案
        return new JwtTokenStore(accessTokenConverter());
    }

    @Bean
    public JwtAccessTokenConverter accessTokenConverter() {
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        converter.setSigningKey(SIGNING_KEY); //对称秘钥,资源服务器使用该秘钥来验证
        return converter;
    }

   /* @Bean
    public TokenStore tokenStore() {
        //使用内存存储令牌(普通令牌)
        return new InMemoryTokenStore();
    }*/
}

securityConfig配置类

package shop.awz.gateway.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.ReactiveAuthenticationManager;
import org.springframework.security.config.web.server.SecurityWebFiltersOrder;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.server.resource.web.server.ServerBearerTokenAuthenticationConverter;
import org.springframework.security.web.server.SecurityWebFilterChain;
import org.springframework.security.web.server.authentication.AuthenticationWebFilter;
import shop.awz.gateway.Manager.AccessManager;
import shop.awz.gateway.Manager.ReactiveJdbcAuthenticationManager;

import javax.sql.DataSource;

/**
 * @ClassName SecurityConfig
 * @Author 杨杰
 * @Date 2023/2/9 12:38
 * @Version 1.0
 */
@Configuration
public class SecurityConfig {
    private static final String MAX_AGE = "18000L";
    @Autowired
    private DataSource dataSource;
    @Autowired
    private AccessManager accessManager;

    @Autowired
    private TokenStore tokenStore;


    @Bean
    SecurityWebFilterChain webFluxSecurityFilterChain(ServerHttpSecurity http) throws Exception{
        //token管理器
        ReactiveAuthenticationManager tokenAuthenticationManager = new ReactiveJdbcAuthenticationManager(tokenStore);
        //认证过滤器
        AuthenticationWebFilter authenticationWebFilter = new AuthenticationWebFilter(tokenAuthenticationManager);
        authenticationWebFilter.setServerAuthenticationConverter(new ServerBearerTokenAuthenticationConverter());

        http
                .httpBasic().disable()
                .csrf().disable()
                .authorizeExchange()
                .pathMatchers(HttpMethod.OPTIONS).permitAll()
                .pathMatchers(HttpMethod.GET).permitAll()
                .pathMatchers(HttpMethod.POST).permitAll()
                .anyExchange().access(accessManager)
                .and()
                //oauth2认证过滤器
                .addFilterAt(authenticationWebFilter, SecurityWebFiltersOrder.AUTHENTICATION);
        return http.build();
    }
}

AccessManager配置类

package shop.awz.gateway.Manager;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authorization.AuthorizationDecision;
import org.springframework.security.authorization.ReactiveAuthorizationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.web.server.authorization.AuthorizationContext;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.Set;
import java.util.concurrent.ConcurrentSkipListSet;

/**
 * @ClassName AccessManager
 * @Author 杨杰
 * @Date 2023/2/9 12:37
 * @Version 1.0
 */

@Slf4j
@Component
public class AccessManager implements ReactiveAuthorizationManager<AuthorizationContext> {
    private Set<String> permitAll = new ConcurrentSkipListSet<>();
    private static final AntPathMatcher antPathMatcher = new AntPathMatcher();


    public AccessManager() {
        permitAll.add("/");
        permitAll.add("/error");
        permitAll.add("/favicon.ico");
        permitAll.add("/**/v2/api-docs/**");
        permitAll.add("/**/swagger-resources/**");
        permitAll.add("/webjars/**");
        permitAll.add("/doc.html");
        permitAll.add("/swagger-ui.html");
        permitAll.add("/**/oauth/**");
        permitAll.add("/**/current/get");
        permitAll.add("/admin-service/**");
    }

    /**
     * 实现权限验证判断
     */
    @Override
    public Mono<AuthorizationDecision> check(Mono<Authentication> authenticationMono, AuthorizationContext authorizationContext) {
        ServerWebExchange exchange = authorizationContext.getExchange();
        //请求资源
        String requestPath = exchange.getRequest().getURI().getPath();
        // 是否直接放行
        if (permitAll(requestPath)) {
            return Mono.just(new AuthorizationDecision(true));
        }

        return authenticationMono.map(auth -> {
            return new AuthorizationDecision(checkAuthorities(exchange, auth, requestPath));
        }).defaultIfEmpty(new AuthorizationDecision(false));

    }

    /**
     * 校验是否属于静态资源
     *
     * @param requestPath 请求路径
     * @return
     */
    private boolean permitAll(String requestPath) {
        return permitAll.stream()
                .filter(r -> antPathMatcher.match(r, requestPath)).findFirst().isPresent();
    }

    //权限校验
    private boolean checkAuthorities(ServerWebExchange exchange, Authentication auth, String requestPath) {
        if (auth instanceof OAuth2Authentication) {
            OAuth2Authentication athentication = (OAuth2Authentication) auth;
            String clientId = athentication.getOAuth2Request().getClientId();
            log.info("clientId is {}", clientId);
        }

        Object principal = auth.getPrincipal();
        log.info("用户信息:{}", principal.toString());
        return true;
    }
}

拦截器配置类

package shop.awz.gateway.Manager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.ReactiveAuthenticationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.exceptions.InvalidTokenException;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.server.resource.BearerTokenAuthenticationToken;
import reactor.core.publisher.Mono;


/**
 * @ClassName ReactiveJdbcAuthenticationManager
 * @Author 杨杰
 * @Date 2023/2/9 12:37
 * @Version 1.0
 */

public class ReactiveJdbcAuthenticationManager implements ReactiveAuthenticationManager {

    Logger logger= LoggerFactory.getLogger(ReactiveJdbcAuthenticationManager.class);
    private TokenStore tokenStore;

    public ReactiveJdbcAuthenticationManager(TokenStore tokenStore){
        this.tokenStore = tokenStore;
    }

    @Override
    public Mono<Authentication> authenticate(Authentication authentication) {
        return Mono.justOrEmpty(authentication)
                .filter(a -> a instanceof BearerTokenAuthenticationToken)
                .cast(BearerTokenAuthenticationToken.class)
                .map(BearerTokenAuthenticationToken::getToken)
                .flatMap((accessToken ->{
                    logger.info("accessToken is :{}",accessToken);
                    OAuth2AccessToken oAuth2AccessToken = this.tokenStore.readAccessToken(accessToken);
                    //根据access_token从数据库获取不到OAuth2AccessToken
                    if(oAuth2AccessToken == null){
                        return Mono.error(new InvalidTokenException("invalid access token,please check"));
                    }else if(oAuth2AccessToken.isExpired()){
                        return Mono.error(new InvalidTokenException("access token has expired,please reacquire token"));
                    }

                    OAuth2Authentication oAuth2Authentication =this.tokenStore.readAuthentication(accessToken);
                    if(oAuth2Authentication == null){
                        return Mono.error(new InvalidTokenException("Access Token 无效!"));
                    }else {
                        return Mono.just(oAuth2Authentication);
                    }
                })).cast(Authentication.class);
    }
}

启动类

@SpringBootApplication
@EnableDiscoveryClient
public class GateWayServiceMain80
{
    public static void main( String[] args )
    {
        SpringApplication.run(GateWayServiceMain80.class,args);
    }
}
               6,member-service
@GetMapping("/product/{productId}")
public String getProductName(@PathVariable Integer productId) {
    return "用户基本信息";
}
                          6,测试

在测试之前我们再来梳理一下流程

在这里插入图片描述

1,用户想要登录CSDN,

2,用户在CSDN上选择我们的网站B进行快捷登录(此时我们的网站B已经和CSDN有合作,并且给我们网站B给CSND密钥。和客户端ID)

3,当用户选择后跳转到我们的网站B的第三方授权登录页面,

4,用户输入用户名或密码进行授权登录

5,用户请求携带用户名和密码以及CSDN客户端的ID密钥等信息在我们的网站B上进行登录

6,网关断言后将请求分到授权服务

7,授权服务认证通过后响应授权码到网关

8,网关响应授权码并重定向到CSDN

9,CSDN获取授权码,并携带授权码,再次请求我们的网站B以获取access_token

这里我们为什么要获取access_token?

这是因为你要获取的用户信息接口,需要校验这个请求中是否包含access_token,来判断是否是合法请求,这也是Oauth2协议的一个关键部分。之前的是授权码,仅仅代表用户已经同意CSDN网站从我们的网站B上获取他的一些基本信息。而要获取到用户的信息,还必须要有access_token。

10,网关断言后将请求分到授权服务,

11,授权服务通过后,响应access_token给网关

12,网关将access_token响应给CSDN

13,CSDN携带access_token再次请求我们的网站B

14,网关认证(认证access_token是否合法,是否过期等)后,将请求分发到资源服务器

15,资源服务器将用户信息响应给网关

16,网关将用户信息响应给CSDN,

17,CSDN就可以使用这些基本信息来登录

其中1-4部分用户是可以感知的,其余的用户无法感知。

测试:因为我们的网站还无法提供给CSDN做快捷登录

所以我们的模拟只能从9步开始,使用密码登录模式,使用postman进行测试

图片

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/353248.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

预告| 亮点抢先看!第四届OpenI/O启智开发者大会主论坛24日启幕!

2023年2月24日至25日&#xff0c;第四届OpenI/O启智开发者大会将在深圳隆重举行。“算网筑基、开源启智、AI赋能”作为今年大会的主题&#xff0c;吸引了全球业界关注的目光。大会集结中国算力网资源基座、开源社区治理及AI开源生态建设、国家级开放创新应用平台、NLP大模型等前…

2023年云计算的发展趋势如何?还值得学习就业吗?

一、2023年云计算的发展将迎来新篇章 随着政策的正式放开&#xff0c;2023年的经济开始慢慢复苏&#xff0c;云计算在疫情期间支撑了复工复产&#xff0c;那么在今年对于云计算发展的限制将进一步的放开。Gartner的数据显示&#xff0c;到2023年&#xff0c;全球公共云支出将达…

MybatisPlus------条件构造器Wrapper以及QueryWrapper用法(七)

MybatisPlus------条件构造器Wapper&#xff08;七&#xff09; Wrapper:条件构造器抽象类&#xff0c;最顶端父类 AbstarctWrapper&#xff1a;用于查询条件封装&#xff0c;生成sql的where条件。 QueryWrapper&#xff1a;查询条件封装&#xff08;可以用于查询、删除&#x…

Java必备小知识点1

Java程序类型: Applications和AppletApplications:是指在计算机操作系统中运行的程序。是完整的程序&#xff0c;能独立运行。被编译后&#xff0c;用普通的Java解释器就可以使其边解释边执行。必定含有一个main方法&#xff0c;程序执行时&#xff0c;首先寻找main方法&#x…

IDEA中如何配置SpringBoot项目多实例不同端口运行

1 问题场景 我们在进行新项目开发的时候&#xff0c; 可能做完一个新的模块功能并自测通过之后&#xff0c; 我们希望测试人员能帮我跑一些单元测试用例来进行测试验证&#xff0c; 但是我们又需要在此基础上技术开发新的功能&#xff0c; 这是我们就需要在我们的开发PC上同时…

Prometheus监控案例-kube-state-metrics

kube-state-metrics组件介绍 kube-stste-metrics项目地址&#xff1a;https://github.com/kubernetes/kube-state-metrics kube-stste-metrics是一个简单的组件&#xff0c;通过监听API Server生成有关资源对象的状态指标&#xff08;例如Deployment、Pod、Node等&#xff09…

HiEV洞察 | 卖一台亏半台,激光雷达第一股禾赛隐忧仍在

作者 | 感知君Alex 编辑 | 王博2月9日晚&#xff0c;禾赛在万众瞩目下登陆纳斯达克&#xff0c;发行价19美元每股&#xff0c;首日涨超11%&#xff0c;市值超过Luminar&#xff0c;登顶全球市值最高的激光雷达公司。 随后两个交易日&#xff0c;其股价均有不同程度的涨幅&#…

08- 汽车产品聚类分析综合项目 (机器学习聚类算法) (项目八)

项目难点 主要通过聚类算法 kmeans 进行调整 . 需要找出分为几类时模型参数最佳 . (n_clusters)找出性价比较高的车 获取训练数据: train_X data.drop([car_ID,CarName],axis 1)计算模型的得分和误差: kmeans.inertia_ # inertia簇内误差平方和 from sklearn.cluster i…

【深度学习/机器学习】为什么要归一化?归一化方法详解

【深度学习/机器学习】为什么要归一化&#xff1f;归一化方法详解 文章目录1. 介绍1.1 什么是归一化1.2 归一化的好处2. 归一化方法2.1 最大最小标准化&#xff08;Min-Max Normalization&#xff09;2.2 Z-score标准化方法2.3 非线性归一化2.4 L范数归一化方法&#xff08;最典…

宝塔搭建实战人才求职管理系统admin前端vue源码(二)

大家好啊&#xff0c;我是测评君&#xff0c;欢迎来到web测评。 上一期给大家分享骑士cms后台端在宝塔的搭建部署方式&#xff0c;这套系统是前后端分离的架构&#xff0c;前端是用vue2开发的&#xff0c;还需要在本地打包手动发布上宝塔&#xff0c;所以本期给大家分享&#x…

智能笔式万用表简单体验加拆解 - VC6012C - 智能电笔

简而言之&#xff0c;能用&#xff0c;甚至还挺好用的&#xff0c;机身大小参考上面的示意图&#xff0c;跟比较粗的记号笔差不多。单纯想买个万用表的话&#xff0c;如果不追求这种精简的外形&#xff0c;同价位有其他功能更强的选项。其实就是个能自动切换档位的智能万用表加…

山东大学软件学院面向对象简答题整理【个人向】

面向对象简答题整理【个人向】 0.试用面向对象语言简述改写和重定义的异同&#xff0c;以及方法绑定时的差别 改写是子类的方法和父类的方法具有相同的方法名和类型签名重定义是子类的方法和父类的方法方法名相同但类型签名不同在方法绑定时&#xff0c;改写是动态绑定&#…

kettle开发-Day38-其实chatGPT一直在身边

前言&#xff1a;最近chatGPT火出圈&#xff0c;其实不是chatGPT多智能&#xff0c;只是它用了一种新的交互方式来组织我们现有的知识&#xff0c;然后通过“高智商”的表达来使我们惊艳。但是目前或者未来的人工智能缺少创造力&#xff0c;他们只会整合信息目的是提高我们的效…

力扣sql简单篇练习(十八)

力扣sql简单篇练习(十八) 1 报告的记录 1.1 题目内容 1.1.1 基本题目信息 1.1.2 示例输入输出 1.2 示例sql语句 SELECT extra report_reason,count(distinct post_id) report_count FROM Actions WHERE action_dateDATE_SUB(2019-07-05,interval 1 day) AND extra IS NOT N…

突破监管“困局”,ScanV为您提供重保安全监测保障!

三月重保即将开始&#xff0c;重保期间是重要时间区间、重要基础设施和重要业务系统安全保障的“三重”考验期。 作为基于实战的网络安全提供商&#xff0c;知道创宇ScanV为您提供三月重保期间免费安全监测保障&#xff0c;并专门针对监管客户重保时期需求提供实战化监测保障方…

GGX发布全新路线图,揭示具备 Layer0 特性且可编程的跨链基建生态

据彭博社报道&#xff0c;具备跨链通信且可编程的 Layer0 基础设施协议 Golden Gate (GGX) 已进行了 两年的线下开发&#xff0c;于近日公开发布了最新的路线图&#xff0c;该路线图不仅显示了该生态在过去两年的发展历程&#xff0c;也披露了 2023 年即将实现的重要里程碑。 G…

IDEA上配置并运行Scala

这里使用 java17 和 Scala3.2.2作为演示 其中&#xff0c; IDEA 版本为2022.3.2 首先&#xff0c;要安装scala插件 Of course, you can also install third one above to format you scala program! 个人认为 Build system 选择 Intellij 比较方便&#xff01; 然后&#xf…

jvm中指定时区信息user.timezone

问题 同一份程序使用时间LocalDateTime类型&#xff0c;在国内和国外部署后&#xff0c;返回的时间信息前端使用出问题。 因为LocalDateTime不带时区信息&#xff0c;国内调用后&#xff0c;前端页面默认使用的浏览器所在os的时区&#xff08;我们的系统中没有给用户设置时区&…

Apache Beanutils为什么被禁止使用?

收录于热门专栏Java基础教程系列&#xff08;进阶篇&#xff09; 在实际的项目开发中&#xff0c;对象间赋值普遍存在&#xff0c;随着双十一、秒杀等电商过程愈加复杂&#xff0c;数据量也在不断攀升&#xff0c;效率问题&#xff0c;浮出水面。 问&#xff1a;如果是你来写…

09 OpenCV图形检测

1 轮廓描边 cv2.findContours() 函数是OpenCV中用于寻找轮廓的函数之一。它可以用于在二值图像中查找并检测出所有的物体轮廓&#xff0c;以及计算出这些轮廓的各种属性&#xff0c;例如面积、周长、质心等。 cv2.findContours() 函数的语法如下&#xff1a; contours, hiera…