From 0 to 1, build spring cloud alibaba micro service large application framework (Mini cloud) and build authentication service (authentication / resource separation version) oauth2 0

Immediately above Build spring cloud alibaba microservice large application framework (II) (Mini cloud) creation project from 0 to 1 and build source code startup version nacos registry Today, let's talk in detail about how to build a certification center, that is, auth2 in the figure below 0 authentication service

There are many aspects involved today. I will also talk about some internal principles and codes, so it is divided into upper, middle and lower parts

The whole film is mainly based on the following process. It is also a process from scratch and from coarse to fine. It is close to everyone's development process as much as possible. What this paper introduces is not the final version. There will be some articles on refactoring code later. In the early stage, it will not be done step by step. It will directly paste the perfect code and become perfect step by step. I think the latter is more helpful to you, The source code will be exposed to github later

OK, let's introduce the overall article process first

##1. Create authentication center service
##2. Integrate the authentication center service into the spring cloud nacos registry
##3. Select oauth2 authentication mode, separate authentication server and resource server, and design sinking resource side authentication mode
##4. Build oauth2 client authentication according to the official memory authentication demo of spring
##5. Add the test service module and integrate it into spring cloud nacos
##6. The test service performs authentication test as a resource server
##7. Bring the configuration file parameters into the nacos configuration center for management
##8. Change the in memory authentication to the actual redis and clientdetail, and the userdetail is obtained from the database
##9. Change demo permission authentication to dynamically verify permissions according to the current login user role
##10. Extract the common part between the authentication server and the resource server and change it to common module
##11. Apply the common module to reconstruct the code and verify the authentication again

 

1. Create authentication center service

We will create a new module in the mini cloud directory, named authentication center, that is, the authentication center, which is specially used to authenticate and obtain access_ token ,reflush_ token ,check_ After creating the module, we integrate the service into the spring cloud nacos system

2. Integrate the authentication center service into the spring cloud nacos registry

Where relevant changes are required, there are the following documents, and the code is given

MiniCloudAuthApplication.java
package com.minicloud.authentication;

import org.springframework.boot.SpringApplication;
import org.springframework.cloud.client.SpringCloudApplication;

/**
 * @Author alan.wang
 * @date: 2022-01-17 10:18
 */
@SpringCloudApplication
public class MiniCloudAuthApplication {

    public static void main(String[] args) {
        SpringApplication.run(MiniCloudAuthApplication.class, args);
    }
}

bootstrap.yml

server:
  port: 8800

spring:
  application:
    name: @artifactId@
  cloud:
    nacos:
      discovery:
        server-addr: ${NACOS_HOST:127.0.0.1}:${NACOS_PORT:8848}
      config:
        server-addr: ${spring.cloud.nacos.discovery.server-addr}
        file-extension: yml
        shared-configs:
          - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
  profiles:
    active: @profiles.active@

pom.xml

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

    <artifactId>authentication-center</artifactId>


    <dependencies>
        <!--Registry client-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!--Configuration center client-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>
        <!--Security module -->
        <dependency>
            <groupId>org.springframework.security.oauth</groupId>
            <artifactId>spring-security-oauth2</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.security.oauth.boot</groupId>
            <artifactId>spring-security-oauth2-autoconfigure</artifactId>
        </dependency>
        <!--web modular-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-jwt</artifactId>
        </dependency>
        <dependency>
            <groupId>com.nimbusds</groupId>
            <artifactId>nimbus-jose-jwt</artifactId>
        </dependency>
    </dependencies>
</project>

In fact, spring cloud integration only needs

In addition, the previous Mini cloud root POM There are some changes in XML, some dependency management is added, and all of them are posted directly

 

<?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>org.mini-cloud</groupId>
    <artifactId>mini-cloud</artifactId>
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>
    <modules>
        <module>register-center</module>
        <module>authentication-center</module>
        <module>mini-cloud-tester</module>
    </modules>

    <properties>
        <nacos-version>1.4.1</nacos-version>
        <nacos-name>com.alibaba.nacos</nacos-name>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <!-- Compiler settings properties -->
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <!-- Maven properties -->
        <maven.test.skip>false</maven.test.skip>
        <maven.javadoc.skip>true</maven.javadoc.skip>
        <sonar.java.coveragePlugin>jacoco</sonar.java.coveragePlugin>
        <!-- Exclude all generated code -->
        <sonar.jacoco.itReportPath>${project.basedir}/../test/target/jacoco-it.exec</sonar.jacoco.itReportPath>
        <sonar.exclusions>file:**/generated-sources/**,**/test/**</sonar.exclusions>
        <security.oauth.version>2.3.6.RELEASE</security.oauth.version>

        <!-- plugin version -->
        <versions-maven-plugin.version>2.2</versions-maven-plugin.version>
        <dependency-mediator-maven-plugin.version>1.0.2</dependency-mediator-maven-plugin.version>
        <clirr-maven-plugin.version>2.7</clirr-maven-plugin.version>
        <maven-enforcer-plugin.version>1.4.1</maven-enforcer-plugin.version>
        <maven-compiler-plugin.version>3.5.1</maven-compiler-plugin.version>
        <maven-javadoc-plugin.version>2.10.4</maven-javadoc-plugin.version>
        <maven-source-plugin.version>3.0.1</maven-source-plugin.version>
        <maven-pmd-plugin.version>3.8</maven-pmd-plugin.version>
        <apache-rat-plugin.version>0.12</apache-rat-plugin.version>
        <maven-resources-plugin.version>3.0.2</maven-resources-plugin.version>
        <coveralls-maven-plugin.version>4.3.0</coveralls-maven-plugin.version>
        <jacoco-maven-plugin.version>0.7.8</jacoco-maven-plugin.version>
        <maven-surefire-plugin.version>2.20</maven-surefire-plugin.version>
        <findbugs-maven-plugin.version>3.0.4</findbugs-maven-plugin.version>
        <sonar-maven-plugin.version>3.0.2</sonar-maven-plugin.version>
        <maven-gpg-plugin.version>1.6</maven-gpg-plugin.version>
        <maven-failsafe-plugin.version>2.19.1</maven-failsafe-plugin.version>
        <maven-assembly-plugin.version>3.0.0</maven-assembly-plugin.version>
        <maven-checkstyle-plugin.version>3.1.1</maven-checkstyle-plugin.version>
        <!-- dependency version related to plugin -->
        <extra-enforcer-rules.version>1.0-beta-4</extra-enforcer-rules.version>
        <p3c-pmd.version>1.3.0</p3c-pmd.version>

        <!-- dependency version -->
        <spring-cloud-starter-netflix-hystrix.version>2.2.5.RELEASE</spring-cloud-starter-netflix-hystrix.version>
        <spring-cloud-alibaba.version>2.2.3.RELEASE</spring-cloud-alibaba.version>
        <spring-boot-dependencies.version>2.2.6.RELEASE</spring-boot-dependencies.version>
        <servlet-api.version>3.0</servlet-api.version>
        <commons-lang3.version>3.4</commons-lang3.version>
        <commons-io.version>2.2</commons-io.version>
        <commons-collections.version>3.2.2</commons-collections.version>
        <commons-logging.version>1.2</commons-logging.version>
        <commons-dbcp.version>1.4</commons-dbcp.version>
        <commons-cli.version>1.2</commons-cli.version>
        <slf4j-api.version>1.7.7</slf4j-api.version>
        <logback.version>1.2.3</logback.version>
        <log4j.version>2.13.3</log4j.version>
        <httpcore.version>4.4.1</httpcore.version>
        <httpclient.version>4.5</httpclient.version>
        <httpasyncclient.version>4.1.3</httpasyncclient.version>
        <mysql-connector-java.version>8.0.16</mysql-connector-java.version>
        <derby.version>10.14.2.0</derby.version>
        <cglib-nodep.version>2.1</cglib-nodep.version>
        <jcip-annotations.version>1.0</jcip-annotations.version>
        <jackson-core.version>2.10.4</jackson-core.version>
        <jackson-databind.version>2.10.4</jackson-databind.version>
        <jackson-core-asl.version>1.9.13</jackson-core-asl.version>
        <jjwt.version>0.11.2</jjwt.version>
        <netty-all.version>4.1.42.Final</netty-all.version>
        <netty-common.version>4.1.31.Final</netty-common.version>
        <mina-core.version>2.0.0-RC1</mina-core.version>
        <guava.version>24.1.1-jre</guava.version>
        <javatuples.version>1.2</javatuples.version>
        <commonOkHttp.version>0.4.1</commonOkHttp.version>
        <grpc-java.version>1.24.0</grpc-java.version>
        <proto-google-common-protos.version>1.17.0</proto-google-common-protos.version>
        <protobuf-java.version>3.8.0</protobuf-java.version>
        <protoc-gen-grpc-java.version>1.24.0</protoc-gen-grpc-java.version>
        <hessian.version>4.0.63</hessian.version>
        <reflections.version>0.9.11</reflections.version>
        <mockito-all.version>1.10.19</mockito-all.version>
        <hamcrest-all.version>1.3</hamcrest-all.version>
        <prometheus-simpleclient.version>0.5.0</prometheus-simpleclient.version>
        <tomcat-embed-jasper.version>9.0.37</tomcat-embed-jasper.version>
        <truth.version>0.30</truth.version>
        <HikariCP.version>3.4.2</HikariCP.version>
        <jraft-core.version>1.3.5</jraft-core.version>
        <rpc-grpc-impl.version>1.3.5</rpc-grpc-impl.version>

    </properties>
    <!-- Management dependent version number,Subprojects are not dependent by default -->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <!-- Import dependency management from Spring Boot -->
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot-dependencies.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <!-- Internal libs -->
            <dependency>
                <groupId>${nacos-name}</groupId>
                <artifactId>nacos-config</artifactId>
                <version>${nacos-version}</version>
            </dependency>
            <dependency>
                <groupId>${nacos-name}</groupId>
                <artifactId>nacos-core</artifactId>
                <version>${nacos-version}</version>
            </dependency>
            <dependency>
                <groupId>${nacos-name}</groupId>
                <artifactId>nacos-naming</artifactId>
                <version>${nacos-version}</version>
            </dependency>
            <dependency>
                <groupId>${nacos-name}</groupId>
                <artifactId>nacos-api</artifactId>
                <version>${nacos-version}</version>
            </dependency>
            <dependency>
                <groupId>${project.groupId}</groupId>
                <artifactId>nacos-client</artifactId>
                <version>${nacos-version}</version>
            </dependency>

            <dependency>
                <groupId>${project.groupId}</groupId>
                <artifactId>nacos-common</artifactId>
                <version>${nacos-version}</version>
            </dependency>
            <dependency>
                <groupId>${project.groupId}</groupId>
                <artifactId>nacos-cmdb</artifactId>
                <version>${nacos-version}</version>
            </dependency>
            <dependency>
                <groupId>${project.groupId}</groupId>
                <artifactId>nacos-console</artifactId>
                <version>${nacos-version}</version>
            </dependency>
            <dependency>
                <groupId>${project.groupId}</groupId>
                <artifactId>nacos-distribution</artifactId>
                <version>${nacos-version}</version>
            </dependency>

            <dependency>
                <groupId>${nacos-name}</groupId>
                <artifactId>nacos-address</artifactId>
                <version>${nacos-version}</version>
            </dependency>

            <dependency>
                <groupId>${nacos-name}</groupId>
                <artifactId>nacos-istio</artifactId>
                <version>${nacos-version}</version>
            </dependency>
            <dependency>
                <groupId>${project.groupId}</groupId>
                <artifactId>nacos-consistency</artifactId>
                <version>${nacos-version}</version>
            </dependency>
            <dependency>
                <groupId>${nacos-name}</groupId>
                <artifactId>nacos-auth</artifactId>
                <version>${nacos-version}</version>
            </dependency>
            <dependency>
                <groupId>${nacos-name}</groupId>
                <artifactId>nacos-sys</artifactId>
                <version>${nacos-version}</version>
            </dependency>

            <dependency>
                <groupId>javax.servlet</groupId>
                <artifactId>servlet-api</artifactId>
                <version>${servlet-api.version}</version>
                <scope>provided</scope>
            </dependency>

            <!-- HikariCP -->
            <dependency>
                <groupId>com.zaxxer</groupId>
                <artifactId>HikariCP</artifactId>
                <version>${HikariCP.version}</version>
            </dependency>

            <!-- hessian -->

            <dependency>
                <groupId>com.caucho</groupId>
                <artifactId>hessian</artifactId>
                <version>${hessian.version}</version>
            </dependency>

            <!-- Apache commons -->
            <dependency>
                <groupId>org.apache.commons</groupId>
                <artifactId>commons-lang3</artifactId>
                <version>${commons-lang3.version}</version>
            </dependency>

            <dependency>
                <groupId>commons-io</groupId>
                <artifactId>commons-io</artifactId>
                <version>${commons-io.version}</version>
            </dependency>

            <dependency>
                <groupId>commons-collections</groupId>
                <artifactId>commons-collections</artifactId>
                <version>${commons-collections.version}</version>
            </dependency>

            <dependency>
                <groupId>commons-logging</groupId>
                <artifactId>commons-logging</artifactId>
                <version>${commons-logging.version}</version>
            </dependency>

            <dependency>
                <groupId>commons-dbcp</groupId>
                <artifactId>commons-dbcp</artifactId>
                <version>${commons-dbcp.version}</version>
            </dependency>

            <dependency>
                <groupId>commons-cli</groupId>
                <artifactId>commons-cli</artifactId>
                <version>${commons-cli.version}</version>
            </dependency>

            <!-- Logging libs -->
            <dependency>
                <groupId>org.slf4j</groupId>
                <artifactId>slf4j-api</artifactId>
                <version>${slf4j-api.version}</version>
            </dependency>

            <dependency>
                <groupId>ch.qos.logback</groupId>
                <artifactId>logback-classic</artifactId>
                <version>${logback.version}</version>
            </dependency>

            <dependency>
                <groupId>ch.qos.logback</groupId>
                <artifactId>logback-core</artifactId>
                <version>${logback.version}</version>
            </dependency>

            <dependency>
                <groupId>org.apache.logging.log4j</groupId>
                <artifactId>log4j-core</artifactId>
                <version>${log4j.version}</version>
            </dependency>

            <dependency>
                <groupId>org.apache.logging.log4j</groupId>
                <artifactId>log4j-api</artifactId>
                <version>${log4j.version}</version>
            </dependency>

            <dependency>
                <groupId>org.apache.logging.log4j</groupId>
                <artifactId>log4j-slf4j-impl</artifactId>
                <version>${log4j.version}</version>
            </dependency>

            <!-- HTTP client libs -->
            <dependency>
                <groupId>org.apache.httpcomponents</groupId>
                <artifactId>httpcore</artifactId>
                <version>${httpcore.version}</version>
            </dependency>

            <dependency>
                <groupId>org.apache.httpcomponents</groupId>
                <artifactId>httpclient</artifactId>
                <version>${httpclient.version}</version>
                <exclusions>
                    <exclusion>
                        <artifactId>commons-logging</artifactId>
                        <groupId>commons-logging</groupId>
                    </exclusion>
                </exclusions>
            </dependency>

            <dependency>
                <groupId>org.apache.httpcomponents</groupId>
                <artifactId>httpasyncclient</artifactId>
                <version>${httpasyncclient.version}</version>
            </dependency>

            <!-- JDBC libs -->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>${mysql-connector-java.version}</version>
            </dependency>

            <dependency>
                <groupId>org.apache.derby</groupId>
                <artifactId>derby</artifactId>
                <version>${derby.version}</version>
            </dependency>

            <!-- JRaft -->
            <dependency>
                <groupId>com.alipay.sofa</groupId>
                <artifactId>jraft-core</artifactId>
                <version>${jraft-core.version}</version>
                <exclusions>
                    <exclusion>
                        <groupId>com.alipay.sofa</groupId>
                        <artifactId>bolt</artifactId>
                    </exclusion>
                    <exclusion>
                        <groupId>org.apache.logging.log4j</groupId>
                        <artifactId>log4j-api</artifactId>
                    </exclusion>
                    <exclusion>
                        <groupId>org.apache.logging.log4j</groupId>
                        <artifactId>log4j-core</artifactId>
                    </exclusion>
                    <exclusion>
                        <groupId>org.apache.logging.log4j</groupId>
                        <artifactId>log4j-slf4j-impl</artifactId>
                    </exclusion>
                    <exclusion>
                        <groupId>org.apache.logging.log4j</groupId>
                        <artifactId>log4j-jcl</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>

            <dependency>
                <groupId>com.alipay.sofa</groupId>
                <artifactId>rpc-grpc-impl</artifactId>
                <version>${rpc-grpc-impl.version}</version>
            </dependency>

            <!-- Third-party libs -->
            <dependency>
                <groupId>cglib</groupId>
                <artifactId>cglib-nodep</artifactId>
                <version>${cglib-nodep.version}</version>
            </dependency>

            <dependency>
                <groupId>net.jcip</groupId>
                <artifactId>jcip-annotations</artifactId>
                <version>${jcip-annotations.version}</version>
            </dependency>

            <dependency>
                <groupId>com.fasterxml.jackson.core</groupId>
                <artifactId>jackson-core</artifactId>
                <version>${jackson-core.version}</version>
            </dependency>

            <dependency>
                <groupId>com.fasterxml.jackson.core</groupId>
                <artifactId>jackson-databind</artifactId>
                <version>${jackson-databind.version}</version>
            </dependency>
            <dependency>
                <groupId>org.codehaus.jackson</groupId>
                <artifactId>jackson-core-asl</artifactId>
                <version>${jackson-core-asl.version}</version>
            </dependency>

            <dependency>
                <groupId>io.jsonwebtoken</groupId>
                <artifactId>jjwt-api</artifactId>
                <version>${jjwt.version}</version>
            </dependency>
            <dependency>
                <groupId>io.jsonwebtoken</groupId>
                <artifactId>jjwt-impl</artifactId>
                <version>${jjwt.version}</version>
                <scope>runtime</scope>
            </dependency>
            <dependency>
                <groupId>io.jsonwebtoken</groupId>
                <artifactId>jjwt-jackson</artifactId>
                <version>${jjwt.version}</version>
                <scope>runtime</scope>
            </dependency>

            <dependency>
                <groupId>io.netty</groupId>
                <artifactId>netty-all</artifactId>
                <version>${netty-all.version}</version>
            </dependency>

            <dependency>
                <groupId>io.netty</groupId>
                <artifactId>netty-common</artifactId>
                <version>${netty-common.version}</version>
            </dependency>

            <dependency>
                <groupId>org.apache.mina</groupId>
                <artifactId>mina-core</artifactId>
                <version>${mina-core.version}</version>
            </dependency>

            <dependency>
                <groupId>com.google.guava</groupId>
                <artifactId>guava</artifactId>
                <version>${guava.version}</version>
            </dependency>

            <dependency>
                <groupId>org.javatuples</groupId>
                <artifactId>javatuples</artifactId>
                <version>${javatuples.version}</version>
            </dependency>

            <dependency>
                <groupId>com.github.keran213539</groupId>
                <artifactId>commonOkHttp</artifactId>
                <version>${commonOkHttp.version}</version>
                <scope>test</scope>
            </dependency>

            <!-- gRPC dependency start -->

            <dependency>
                <groupId>io.grpc</groupId>
                <artifactId>grpc-netty-shaded</artifactId>
                <version>${grpc-java.version}</version>
            </dependency>
            <dependency>
                <groupId>io.grpc</groupId>
                <artifactId>grpc-protobuf</artifactId>
                <version>${grpc-java.version}</version>
            </dependency>
            <dependency>
                <groupId>io.grpc</groupId>
                <artifactId>grpc-stub</artifactId>
                <version>${grpc-java.version}</version>
            </dependency>
            <dependency>
                <groupId>io.grpc</groupId>
                <artifactId>protoc-gen-grpc-java</artifactId>
                <version>${grpc-java.version}</version>
                <type>pom</type>
            </dependency>
            <dependency>
                <groupId>com.google.api.grpc</groupId>
                <artifactId>proto-google-common-protos</artifactId>
                <version>${proto-google-common-protos.version}</version>
            </dependency>

            <!-- gRPC dependency end -->

            <dependency>
                <groupId>com.google.protobuf</groupId>
                <artifactId>protobuf-java</artifactId>
                <version>${protobuf-java.version}</version>
            </dependency>

            <dependency>
                <groupId>org.reflections</groupId>
                <artifactId>reflections</artifactId>
                <version>${reflections.version}</version>
            </dependency>

            <dependency>
                <groupId>org.mockito</groupId>
                <artifactId>mockito-all</artifactId>
                <version>${mockito-all.version}</version>
            </dependency>

            <dependency>
                <groupId>org.hamcrest</groupId>
                <artifactId>hamcrest-all</artifactId>
                <version>${hamcrest-all.version}</version>
            </dependency>

            <dependency>
                <groupId>io.prometheus</groupId>
                <artifactId>simpleclient</artifactId>
                <version>${prometheus-simpleclient.version}</version>
            </dependency>

            <dependency>
                <groupId>org.apache.tomcat.embed</groupId>
                <artifactId>tomcat-embed-jasper</artifactId>
                <version>${tomcat-embed-jasper.version}</version>
            </dependency>

            <dependency>
                <groupId>com.google.truth</groupId>
                <artifactId>truth</artifactId>
                <version>${truth.version}</version>
            </dependency>

            <!--spring cloud alibaba-->
            <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>
            <dependency>
                <groupId>org.springframework.security</groupId>
                <artifactId>spring-security-jwt</artifactId>
                <version>1.1.0.RELEASE</version>
            </dependency>
            <dependency>
                <groupId>com.nimbusds</groupId>
                <artifactId>nimbus-jose-jwt</artifactId>
                <version>8.2.1</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.security.oauth.boot</groupId>
                <artifactId>spring-security-oauth2-autoconfigure</artifactId>
                <version>2.2.1.RELEASE</version>
            </dependency>
            <!--Stable version, replace spring security bom built-in-->
            <dependency>
                <groupId>org.springframework.security.oauth</groupId>
                <artifactId>spring-security-oauth2</artifactId>
                <version>${security.oauth.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
                <version>${spring-cloud-starter-netflix-hystrix.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <distributionManagement>
        <snapshotRepository>
            <!-- there ID Be sure to maven setting File exists in server Lower ID -->
            <id>sona</id>
            <url>https://oss.sonatype.org/content/repositories/snapshots/</url>
        </snapshotRepository>
        <repository>
            <id>sona</id>
            <url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
        </repository>
    </distributionManagement>

    <profiles>
        <profile>
            <id>dev</id>
            <properties>
                <!-- Environment ID, corresponding to the name of the configuration file -->
                <profiles.active>dev</profiles.active>
            </properties>
            <activation>
                <!-- Default environment -->
                <activeByDefault>true</activeByDefault>
            </activation>
        </profile>
        <profile>
            <id>test</id>
            <properties>
                <profiles.active>test</profiles.active>
            </properties>
        </profile>
        <profile>
            <id>prod</id>
            <properties>
                <profiles.active>prod</profiles.active>
            </properties>
        </profile>
    </profiles>
    <build>
        <finalName>${project.name}</finalName>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <filtering>true</filtering>
            </resource>
        </resources>
        <pluginManagement>

            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                    <executions>
                        <execution>
                            <goals>
                                <goal>repackage</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>

            </plugins>
        </pluginManagement>

    </build>
</project>

The application name of the registration center has been changed and unified, from nacos to MiniCloudRegisterApplication

OK, test whether spring cloud nacos is integrated. Start the nacos registry first, and then the authentication center

Then visit http://localhost:8848/nacos/ Console

It is found that the authentication service just built and integrated into nacos

 3. Select oauth2 authentication mode, separate authentication server and resource server, and design sinking resource side authentication mode

This involves some theoretical content. I drew two diagrams to describe what is authentication service, what is resource service, and what is their relationship. It is easier to understand

Certification services and resource services

     

The authentication service is associated with the resource service

 

To sum up in Vernacular:

Authentication service: mainly our authentication center. When all clients access the resource service, the resource service will internally access the authentication service to verify whether they have the right

Resource service: it is the accessed interface. If chivalry goes to the web, it can be said to be the url of our controller

For more information, visit spring auth2 0 official website and the demo provided by the official website can be run directly

auth2.0 official website introduction: https://projects.spring.io/spring-security-oauth/docs/oauth2.html

auth2.0 supports the following authentication modes by default by accessing the grant parameter_ Type discrimination

If you are interested, you can understand it. Let's briefly explain it here

Authorization code: authorization code mode. It is relatively safe, but it can only be used in web projects. A page url is required

client_credentials: the client mode is mainly used to authenticate an app or a service. For example, wechat platform for an application and Alibaba cloud oss for an application. It is not suitable for our common users to log in to the manufacturer through an account and password

Password: the user name and password mode is the commonly used scenario for users of this site to log in through user name and password. This paper mainly selects this mode. Later, we will talk about how to customize the authorization mode to support their own authorization, which is not within the scope of this paper

Although we choose the password mode, we still need to support client authentication, because our certification center may need to support the access of other external services in the future, so we still need to have a clientId for each service and the resource permission identification of the common end

4. Build oauth2 client authentication according to the official memory authentication demo of spring

When we develop any function, we usually want to use the simplest demo to complete the minimum environmental protection certificate and run first. We also do the same. We can directly change the demo on the official website to ensure that we run first

 auth2.0 official website demo address: GitHub - jgrandja/spring-security-oauth-2-4-migrate

Authentication services generally need to do two things

1. Inherit the @ EnableAuthorizationServer configureradapter and start @ EnableAuthorizationServer

2. Inherit WebSecurityConfigurerAdapter and start @ EnableWebSecurity

1 is to add your own server-side custom bean s, such as clientservice userdetailservice

2 is to inject interceptors required by the web service itself or URLs to be intercepted

Don't gossip. There is little code in itself, and it runs in memory mode. I directly the code, and I also made detailed comments on the code

We just need to add two files

AuthorizationServerConfig.java
/*
 * Copyright 2012-2019 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.minicloud.authentication.config;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.userdetails.UserDetailsService;
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 org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;

import javax.annotation.Resource;


/**
 * @author alan.wang
 */
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

    @Resource
    private AuthenticationManager authenticationManager;

    @Autowired
    private UserDetailsService userDetailsService;


    /**
     * @desc :For example, the memory mode is directly injected into one client side of the simulation
     * withClient :clientId
     * secret: clientId Corresponding password, remember spring 5 0 should be preceded by {encryption} ciphertext
     * authorizedGrantTypes: Which authorization modes are accepted? Parameter grant_type discrimination
     * authorities: What permissions do you have, usually at the api level, are basically useless
     * scopes: Read / write level
     * */
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()
                .withClient("test-auth-client").secret("{bcrypt}" + new BCryptPasswordEncoder().encode("123"))
                .authorizedGrantTypes("authorization_code", "refresh_token", "client_credentials", "password")
                .authorities("autho2").scopes("read", "write");


    }

    /**
     * @desc: Set auth2 0 itself has open access rights
     * Here for / oauth/check_token opens the form submission permission
     */
    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {

        security.checkTokenAccess("permitAll()").allowFormAuthenticationForClients();
    }

    /**
     * @desc: It mainly injects custom service s into endpoints (url path of the framework itself)
     * The default userDetailsService and authenticationManager are injected into the,
     */
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints
                .allowedTokenEndpointRequestMethods(HttpMethod.GET, HttpMethod.POST)
                .userDetailsService(userDetailsService)
                .authenticationManager(authenticationManager);


    }




}

 

SecurityConfig.java
package com.minicloud.authentication.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.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;

/**
 * @Author alan.wang
 * @date: 2022-01-17 14:01
 */

@Configuration
@EnableWebSecurity

public class SecurityConfig extends WebSecurityConfigurerAdapter {


    /**
     * @desc:url interception settings for this web service
     * All permissions of / oauth / * * are open here because it is the path of the framework
     * */
    @Override
    public void configure(HttpSecurity http) throws Exception {
        http
                .requestMatchers().anyRequest()
                .and()
                .authorizeRequests()
                .antMatchers("/oauth/**").permitAll();
    }

    /**
     * @desc:Inject the default AuthenticationManager bean
     */
    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }


    /**
     * @desc:Inject the default UserDetailsService bean and add two test users
     * username: user name
     * password: Password, also note the {encryption method} ciphertext
     * roles: Multiple roles can be implemented
     *
     */
    @Bean
    public UserDetailsService userDetailsService()   {
        InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
        manager.createUser(User.builder().username("user1").password("{bcrypt}" + new BCryptPasswordEncoder().encode("123")).roles("USER").build());
        manager.createUser(User.builder().username("admin").password("{bcrypt}" + new BCryptPasswordEncoder().encode("123")).roles("USER", "ADMIN").build());
        return manager;
    }

    /**
     * @desc:Inject PasswordEncoder encryptor
     * PasswordEncoderFactories.createDelegatingPasswordEncoder() The default is bcrypt encryption
     *
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        return PasswordEncoderFactories.createDelegatingPasswordEncoder();
    }


}

After adding the code, restart the authentication center service to verify it

I use user1. Remember that both clientId and password correspond,

http://localhost:8800/oauth/token?username=user1&password=123&grant_type=password&scope=read&client_id=test-auth-client&client_secret=123

ok, you can see that you have returned to access normally_ Token, and reflush_token, start the next step

5. Add the test service module and integrate it into spring cloud nacos

For convenience, I create a separate test module to place all the services related to the test service. In order to test the overall business of micro services in the future, I also include the test service as a business side service into spring cloud nacos

Well, let's create a test business side for integration testing as a resource service. The integration into spring cloud nacos is the same as the above certification center integration. I won't say more

application.yml

server:
  port: 8900

spring:
  application:
    name: @artifactId@
  cloud:
    nacos:
      discovery:
        server-addr: ${NACOS_HOST:127.0.0.1}:${NACOS_PORT:8848}
      config:
        server-addr: ${spring.cloud.nacos.discovery.server-addr}
        file-extension: yml
        shared-configs:
          - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
  profiles:
    active: @profiles.active@

 pom.xml

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

    <artifactId>authentication-center-test</artifactId>


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

        <!--Registry client-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!--Configuration center client-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>
        <!--Security module -->
        <dependency>
            <groupId>org.springframework.security.oauth</groupId>
            <artifactId>spring-security-oauth2</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.security.oauth.boot</groupId>
            <artifactId>spring-security-oauth2-autoconfigure</artifactId>
        </dependency>
    </dependencies>
</project>

Then start them all to see if they are all integrated into nacos

Enter the nacos console to view http://localhost:8848/nacos/

ok, no problem. Start integrating it as a resource service

6. The test service performs authentication test as a resource server

The resource server integration is relatively simple. You only need to inherit the ResourceServerConfigurerAdapter and start it

@Enable resource server, and then we create a controller to verify the controller url

ResourceServerConfig.java
package com.minicloud.authentication.test.config;

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;

/**
 * @Author alan.wang
 * @date: 2022-01-17 16:26
 */
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {


    /**
     * @desc: Set the url that needs to be intercepted or opened
     * The url of the / oauth / * * framework itself is open here
     * Certification is required for / test / * * related
     * */
    @Override
    public void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity
                .authorizeRequests()
                .antMatchers("/oauth/**").permitAll()
                .antMatchers("/test/**").authenticated();

    }
}

 

TestController.java
package com.minicloud.authentication.test.controller;

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @Author alan.wang
 * @date: 2022-01-17 15:54
 */
@RestController
@RequestMapping("/test")
public class TestController {

    @GetMapping("/hello")
    public ResponseEntity hello(){

        return ResponseEntity.ok("ok");
    }
}

application.yml

server:
  port: 8900

spring:
  application:
    name: @artifactId@
  cloud:
    nacos:
      discovery:
        server-addr: ${NACOS_HOST:127.0.0.1}:${NACOS_PORT:8848}
      config:
        server-addr: ${spring.cloud.nacos.discovery.server-addr}
        file-extension: yml
        shared-configs:
          - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
  profiles:
    active: @profiles.active@

security:
  oauth2:
    resource:
      token-info-uri: http://127.0.0.1:8800/oauth/check_token
    client:
      client-id: test-auth-client
      client-secret: 123
      scope: read

Note: token info URI: This is the address of our certification center

We restart the test service and then start the test. First, we directly access our test controller url

http://localhost:8900/test/hello 

 

{
    "error": "unauthorized",
    "error_description": "Full authentication is required to access this resource"
}

It is obvious that access authentication needs to be provided

Let's get access now_ token

http://localhost:8800/oauth/token?username=user1&password=123&grant_type=password&scope=read&client_id=test-auth-client&client_secret=123

{
    "access_token": "6ee98a60-19c6-4843-9f77-954024bc2d9b",
    "token_type": "bearer",
    "refresh_token": "b6bf88c0-1128-4742-af8a-74bc513b7d9b",
    "expires_in": 41459,
    "scope": "read"
}

We got access_token, and then access http://localhost:8900/test/hello

The url of the resource can be accessed normally this time. Pay attention to access_ Bear should be added before token

The length is too long. This article ends here. We are now integrated in the memory environment, which is certainly not the case for real development. Let's take it step by step. In the next article, we will change the memory mode to obtain data from redis and database to achieve the real framework capability

 

 

Keywords: Java Spring Cloud Microservices oauth2

Added by kevinridge on Tue, 18 Jan 2022 04:40:55 +0200