Integration and sorting of Springcloud Alibaba and various microservice components

Spring Cloud Alibaba microservice component integration project:

Version Notes:

  • <spring-boot.version>2.6.3</spring-boot.version>
  • <spring-cloud.version>2021.0.1</spring-cloud.version>
  • <spring-cloud-alibaba.version>2021.0.1.0</spring-cloud-alibaba.version>
  • <swagger.fox.version>3.0.0</swagger.fox.version>
  • <knife4j.version>3.0.3</knife4j.version>
  • <nacos.server>1.4.2</nacos.server>
  • <seata.server>1.4.2</seata.server>
  • <sentinel.dashboard>1.8.3</sentinel.dashboard>
  • <skywalking.walking>9.0-8.10</skywalking.walking>

Dependency prefix:

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

    <groupId>com.xiaoshu</groupId>
    <artifactId>alibaba-cloud-example</artifactId>
    <version>1.0-SNAPSHOT</version>

    <packaging>pom</packaging>

    <properties>
        <java.version>1.8</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <maven.compiler.version>3.8.1</maven.compiler.version>

        <spring-boot.version>2.6.3</spring-boot.version>
        <spring-cloud.version>2021.0.1</spring-cloud.version>
        <spring-cloud-alibaba.version>2021.0.1.0</spring-cloud-alibaba.version>

        <swagger.fox.version>3.0.0</swagger.fox.version>
        <knife4j.version>3.0.3</knife4j.version>
        <jasypt.version>3.0.3</jasypt.version>

    </properties>

    <modules>
        <module>cloud-gateway</module>
        <module>cloud-oss</module>
        <module>cloud-upms</module>
        <module>cloud-common</module>
        <module>cloud-auth</module>
    </modules>

    <dependencies>

        <!--bootstrap 启动器-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bootstrap</artifactId>
        </dependency>

        <!--配置文件处理器-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>

        <!--jasypt配置文件加解密-->
        <dependency>
            <groupId>com.github.ulisesbocchio</groupId>
            <artifactId>jasypt-spring-boot-starter</artifactId>
            <version>${jasypt.version}</version>
        </dependency>

        <!--Lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <scope>provided</scope>
        </dependency>

    </dependencies>

    <dependencyManagement>

        <dependencies>
            <!--spring boot 公共版本定义-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <!--spring cloud 公共版本定义 通过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>${spring-cloud-alibaba.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>

    </dependencyManagement>

    <build>
        <finalName>${project.name}</finalName>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <filtering>true</filtering>
            </resource>
        </resources>
        <pluginManagement>
            <plugins>
                <!--spring boot 默认插件-->
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                    <version>${spring-boot.version}</version>
                    <executions>
                        <execution>
                            <goals>
                                <goal>repackage</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>

            </plugins>
        </pluginManagement>
        <plugins>
            <!--代码编译指定版本插件-->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>${maven.compiler.version}</version>
                <configuration>
                    <target>${maven.compiler.target}</target>
                    <source>${maven.compiler.source}</source>
                    <encoding>UTF-8</encoding>
                    <skip>true</skip>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <profiles>
        <profile>
            <id>dev</id>
            <properties>
                <!-- 环境标识,需要与配置文件的名称相对应 -->
                <profiles.active>dev</profiles.active>
            </properties>
            <activation>
                <!-- 默认环境 -->
                <activeByDefault>true</activeByDefault>
            </activation>
        </profile>
    </profiles>

    <!-- 配置内网仓库地址
     <distributionManagement>
         <repository>
             <id>jiuding-releases</id>
             <name>jiuding nexus release repository</name>
             <url>http://ip:port/repository/maven-releases</url>
         </repository>

         <snapshotRepository>
             <id>jiuding-snapshots</id>
             <name>jiuding nexus snapshots repository</name>
             <url>http://ip:port/repository/maven-snapshots</url>
         </snapshotRepository>
     </distributionManagement>
     -->

</project>

nacos

  • Chinese official website: https://nacos.io/zh-cn/docs/v2/quickstart/quick-start.html
  • Introduction: Dynamic service discovery, configuration management and service management platform
  • Startup: sh startup.sh -m standalone
  • Key features:
    • Configuration center, service management
    • Dynamic configuration service; @RefreshScope can dynamically modify the corresponding attributes of yml
    • Dynamic DNS service; supports weighted routing, allowing you to more easily implement middle-tier load balancing, more flexible routing strategies, and traffic control
    • Registry updates make extensive use of copyonwrite ideas to prevent read and write conflicts.
  • use:
    • DataId is service name.yml + ${profiles.active}
    • extension-configs attribute additional configuration for this application
    • The shared-configs attribute represents shared configurations
  • Sustainability:
    • nacos running body/config/nacos-mysql.sql imports the database, modifies application.properties to configure the use of external data sources

Get nacos source code:

  • gitlub download the corresponding version
  • install it
  • The console module is the startup template;
  • Other module poms are introduced, and the console retains the source code to start, which can cooperate with development and debugging.
// 编译install
cd nacos/
mvn -Prelease-nacos -Dmaven.test.skip=true clean install -U  
ls -al distribution/target/
/**
 * Nacos starter.
 *
 * @author nacos
 */
@SpringBootApplication(scanBasePackages = "com.alibaba.nacos")
@ServletComponentScan
@EnableScheduling
public class Nacos {
    
    
    
    public static void main(String[] args) {
    
    
        if(initEnv()){
    
    
            SpringApplication.run(Nacos.class, args);
        }
    }

    /**
     * 单机启动
     */
    private static boolean initEnv() {
    
    
        System.setProperty("nacos.standalone", "true");
        return true;
    }

}

Example of getting nacos service list:

@Data
public class CatalogServiceVo implements Serializable {
    
    
	private Integer count;
	private List<NacosServiceVo> serviceList;
}

@Data
public class NacosServiceVo implements Serializable {
    
    
	private String name;
	private String groupName;
	private Integer clusterCount;
	private Integer ipCount;
	private Integer healthyInstanceCount;
	private String triggerFlag;
}

Object o = catalogServiceV2
		.pageListService(Constants.DEFAULT_NAMESPACE_ID,
				StringUtils.EMPTY,
				StringUtils.EMPTY,
				1, Integer.MAX_VALUE,
				StringUtils.EMPTY,
				false);

CatalogServiceVo catalogService = JSONUtil.toBean(o.toString(), CatalogServiceVo.class);
List<NacosServiceVo> serviceList = catalogService.getServiceList();

sentinel

  • Documentation: https://sentinelguard.io/zh-cn/

  • 启动:java -Dserver.port=8858 -Dcsp.sentinel.dashboard.server=localhost:8858 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.3.jar

  • Usage: Start a service package, configure registration in yml; use interface address to serve resources, configure current limit and other specifications

  • Introduction: The traffic control component of the distributed service architecture mainly uses traffic as the entry point to ensure service stability from multiple dimensions such as current limiting, traffic shaping, circuit breaker degradation, system load protection, and hotspot protection.

    • Core library (code control) @SentinelResource, console
  • concept:

    • Service avalanche: There are many cross-calls between microservices. An exception in one service causes an exception in dependent services, resulting in the unavailability of multiple services.
    • Service degradation: When the service is disconnected, the service cannot be called. At this time, the client returns a default callback value, which is generally used for weakly dependent services such as points services.
  • Flow Control:

    • Rules: Monitor indicators such as QPS or the number of concurrent threads of application traffic, and control the traffic when it reaches the specified threshold to avoid being overwhelmed by peak traffic and ensure application availability.
      • Target items: QPS (requests per second), number of threads (other request threads will be processed only when waiting for the response of the thread with the set number of threads)
      • Associated flow control: Set associated resources. When the associated resources reach the threshold, the current resources are restricted.
      • Link flow control: A->B A->C, set rules for A, and set the ingress resource to C. When the limit indicator is reached, C will be unaffected by flow control B.
      • Hotspot flow control: flow control for a certain hotspot data; hot products, IP restrictions, anti-brushing; (such as flow limit for products with product ID 1)
    • flow control effect
      • Fail fast: reject directly
      • Warm up: During the warm-up period, slowly increase the number of requests placed, 3 flows - 5 flows - 10 flows; cold loading factor: 3; suitable for surge traffic
      • Queuing and waiting: The threshold is 5. If 10 flows come, 5 flows will be waiting. If there are requests processed within the timeout period, a waiting flow will be entered. Suitable for pulse flow
  • Service downgrade:

    • Circuit breaker rules:
      • Slow call ratio: interface response time, minimum number of requests, ratio; enters half-open state after the circuit breaker period ends
      • Abnormal ratio
      • Abnormal number
  • fegin integration:

    • feign.sentinel.enabled=true enabled
  • System rules:

    • A comprehensive solution for global settings, such as load, CPU usage, average RT, QPS, etc. When the set ratio is reached, system protection will be initiated, and all results will be returned to system protection exceptions.
  • Gateway flow control:

    • Integrate pom and introduce spring-cloud-alibaba-sentinel-gateway and yml link console
    • Set rules for routing id, set Api grouping for matching and current limiting settings
  • sentinel-nacos persistence:

    • Rules are stored in memory by default and will be lost after the service is restarted; generally, production environments will configure rule persistence.
    • step:
      • 1.pom introduces dependencies
      • 2.yml configuration sentinel-datasource-nacos
      • 3. Configure corresponding rules json in nacos
spring:
  profiles:
    active: @profiles.active@

  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}
    sentinel:
      transport:
        dashboard: 127.0.0.1:8858
        #clientIp: 127.0.0.1 #服务与sentinel 不在同一服务器时需:指定当前服务ip
      #关闭链路收敛,链路限流
      web-context-unify: false
      #规则持久化
      datasource:
        flow-rule:
          nacos:
            server-addr: 127.0.0.1:8848
            username: nacos
            paswword: nacos
            data-id: cloud-oss-flow-rlue #对应nacos dataId,且nacos要持久化
            rule-type: flow

Insert image description here

Seata(AT) distributed transaction component

  • Official website: https://seata.io/zh-cn/docs/overview/what-is-seata.html
  • Usage: Also start a seta service package and configure the corresponding data, and configure the yml to connect to seata; @GlobalTransactionalyou can mark it
  • concept:
    • 2PC: Preprocessing, commit/rollback (distributed transactions are completed in two stages)
      • The transaction coordinator sends a transaction request -" (blocking) Whether the transaction participant (database, service) can execute the transaction, the participant executes the transaction request, successfully executes the transaction operation and writes the undo and redo log and returns a confirmation response, otherwise it returns NO
      • The transaction coordinator sends a commit request to the participants, commits the transaction, and releases the temporary resources of the transaction after completion.
      • We can only try our best to ensure transactions, such as responding to interruptions, etc.
    • AT mode (no intrusion, with lock):
      • Intercept the business SQL table metadata in advance and save the original snapshot; save the new snapshot after executing the business SQL and add row locks
      • Submit successfully, delete snapshot data and row locks
      • If the submission fails, compare the current data with the updated snapshot data to see if they are consistent. If they are consistent, use the pre-update snapshot to restore the business data. If they are inconsistent, dirty data will appear and must be processed manually.
    • TCC mode (intrusion, no lock):
      • Implement Try (one-stage execution), Confirm (two-stage submission), and Cancel (two-stage rollback) according to your own business scenarios, and users can control the specific logic;
<!-- seata -->
 <dependency>
      <groupId>com.alibaba.cloud</groupId>
      <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
  </dependency>
#seata 配置
seata:
  registry:
    type: nacos
    nacos:
      server-addr: 127.0.0.1:8848
      application: seata-server
      username: nacos
      password: nacos
      group: SEATA_GROUP
  config:
    type: nacos
    nacos:
      server-addr: 127.0.0.1:8848
      username: nacos
      password: nacos
      group: SEATA_GROUP
  tx-service-group: my_test_tx_group

Insert image description here

GateWay unified gateway

  • Gateway Swagger: Microservice gateway document, by nacosobtaining the service list and 文档注解obtaining the corresponding interface information
  • Predicates
    • Built-in assertions:
      • time based
      • Request header
      • domain name
      • Request method
      • Request parameters
      • IP matching
      • Cookie
      • 自定义 xxxRoutePredicateFactory extends AbstractRoutePredicateFactory
  • (filters)filters
    • Built-in filtering:
      • AddRequestHeader=key, vlaue add request header
      • 自定义 xxxGateWayFilterFactory extends AbstractNameValueGatewayFilterFactory
      • Global Filter xxx implements GlobalFilter
server:
  port: 9999

spring:

  application:
    name: @artifactId@
  profiles:
    active: @profiles.active@

  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

    sentinel:
      transport:
        dashboard: 127.0.0.1:8858

    gateway:
      discovery:
        locator:
          enabled: true

      routes:
        - id: cloud-auth-route
          uri: lb://cloud-auth
          predicates:
            - Path=/auth/**
          filters:
            - StripPrefix=1

        - id: cloud-oss-biz-route
          uri: lb://cloud-oss-biz
          predicates:
            - Path=/oss/**
          filters:
            - StripPrefix=1

        - id: cloud-upms-biz-route
          uri: lb://cloud-upms-biz
          predicates:
            - Path=/upms/**
          filters:
            - StripPrefix=1

skywalking link tracking

  • Official website: https://skywalking.apache.org/
  • Documentation: https://skyapm.github.io/document-cn-translation-of-skywalking/
  • Introduction: Domestic open source framework, distributed system application performance monitoring tool; distributed link tracking, performance indicator analysis, application service dependency analysis
  • composition:
    • oapservice: skywalking server processing monitoring receiving data port: 11800 12800
    • wepapp-ui: Data display business port: webapp.yml
    • agent: bind the probe to the server and collect data
  • Optional plugins:
    • optional-plugins/gateway
  • Microservice integration:

native integration

  -javaagent:D:\java_project\alibaba-cloud-example\environment\skywalking9.0-8.10\apache-skywalking-apm-bin\skywalking-agent\skywalking-agent.jar
  -Dskywalking.agent.service_name=cloud-gateway
  -Dskywalking.collector.backend_service=127.0.0.1:11800
  • Sustainability:
    • config\application.yml; storage.selector configuration database, the default is H2 memory database
  • Customized link tracking: Implement link tracking for business methods in the project to facilitate troubleshooting
    • Mark @Trace on the business interface, and @Tag for the method (key = "tag name", value = "returnedObj")
  • Performance analysis:
    • For slow interfaces, locate the problem of slow requests and slow responses;
    • Performance analysis items, new tasks
  • log:
    • Add dependencies, configure logback-spring.xml, and pay attention to configuring grpc-log to report logs
    • When skywalking is not deployed locally, be careful to modify skywalking-agent\config\agent.config
<!-- 自定义链路追踪,与服务版本一致 -->
       <dependency>
           <groupId>org.apache.skywalking</groupId>
           <artifactId>apm-toolkit-trace</artifactId>
           <version>8.10.0</version>
       </dependency>

       <!-- 日志追踪 -->
       <dependency>
           <groupId>org.apache.skywalking</groupId>
           <artifactId>apm-toolkit-logback-1.x</artifactId>
           <version>8.10.0</version>
       </dependency>
  • Alert:
    • Alarm-settings.yml rule configuration includes basic default alarm rules for interface response time, average database access time, etc.
    • Web hook, a request will be sent when an alarm occurs; push to interface, WeChat, DingTalk, email, etc...

Outh2 microservice authorization

  • Protocol: A development network standard for authorization, which enables third-party applications to have the right to access http services and handle the relationship between users and resources.
  • process:
    • Now 通用security模块, let’s talk about the ignored path of yml configuration, as well as the controller and interface that ignores the authentication annotation. The corresponding path is registered in security.registry.antMatchers(HttpMethod.valueOf(method), strings.get(0)).permitAll();
    • Correspondingly fegin调用, request headers need to be configured to prevent authentication failure when calling within the microservice.
@Configuration
public class FeignOauth2RequestInterceptor implements RequestInterceptor {
    
    
    private final String AUTHORIZATION_HEADER = "Authorization";
    private final String BEARER_TOKEN_TYPE = "Bearer";
    @Override
    public void apply(RequestTemplate requestTemplate) {
    
    
        SecurityContext securityContext = SecurityContextHolder.getContext();
        Authentication authentication = securityContext.getAuthentication();
        if (authentication != null && authentication.getDetails() instanceof OAuth2AuthenticationDetails) {
    
    
            OAuth2AuthenticationDetails details = (OAuth2AuthenticationDetails) authentication.getDetails();
            requestTemplate.header(AUTHORIZATION_HEADER, String.format("%s %s", BEARER_TOKEN_TYPE, details.getTokenValue()));
        }
    }
}
@Configuration
public class FeignRequestConfiguration {
    
    
    @Bean
    public RequestInterceptor requestInterceptor() {
    
    
        return new FeignOauth2RequestInterceptor();
    }
}
- 针对各个客户端认证,implements ClientDetailsService 配置对应的认证方式
@Component
public class CloudClientDetailsServiceImpl implements ClientDetailsService {
    
    

    @Resource
    private SysOauthClientDetailsFegin sysOauthClientDetailsFegin;

    @Resource
    protected PasswordEncoder passwordEncoder;

    @Override
    public ClientDetails loadClientByClientId(String s) throws ClientRegistrationException {
    
    
        BaseClientDetails target = new BaseClientDetails();
        SysOauthClientDetails param = new SysOauthClientDetails().setClientId(s);
        //fegin调用,获取对应 客户端信息
        SysOauthClientDetails oauthClientDetails = sysOauthClientDetailsFegin.getByClientId(param).getData();
        if (oauthClientDetails==null){
    
    
            throw new SecurityException("未找到应用信息!");
        }
        setClient(target, oauthClientDetails);
        return target;
    }

    /**
     * 赋值客户端信息
     * @param target  target
     * @param oauthClientDetails 客户端数据
     */
    private void setClient(BaseClientDetails target, SysOauthClientDetails oauthClientDetails) {
    
    
        target.setClientId(oauthClientDetails.getClientId());
        target.setClientSecret(passwordEncoder.encode(oauthClientDetails.getClientSecret()));

        if (ArrayUtil.isNotEmpty(oauthClientDetails.getAuthorizedGrantTypes())) {
    
    
            target.setAuthorizedGrantTypes(Arrays.asList(oauthClientDetails.getAuthorizedGrantTypes().split(",")));
        }
        if (StrUtil.isNotBlank(oauthClientDetails.getAuthorities())) {
    
    
            target.setAuthorities(AuthorityUtils.commaSeparatedStringToAuthorityList(oauthClientDetails.getAuthorities()));
        }

        if (StrUtil.isNotBlank(oauthClientDetails.getResourceIds())) {
    
    
            target.setResourceIds(StringUtils.commaDelimitedListToSet(oauthClientDetails.getResourceIds()));
        }

        if (StrUtil.isNotBlank(oauthClientDetails.getWebServerRedirectUri())) {
    
    
            target.setRegisteredRedirectUri(StringUtils.commaDelimitedListToSet(oauthClientDetails.getWebServerRedirectUri()));
        }

        if (StrUtil.isNotBlank(oauthClientDetails.getScope())) {
    
    
            target.setScope(StringUtils.commaDelimitedListToSet(oauthClientDetails.getScope()));
        }

        if (StrUtil.isNotBlank(oauthClientDetails.getAutoapprove())) {
    
    
            target.setAutoApproveScopes(StringUtils.commaDelimitedListToSet(oauthClientDetails.getAutoapprove()));
        }

        if (oauthClientDetails.getAccessTokenValidity() != null) {
    
    
            target.setAccessTokenValiditySeconds(oauthClientDetails.getAccessTokenValidity());
        }

        if (oauthClientDetails.getRefreshTokenValidity() != null) {
    
    
            target.setRefreshTokenValiditySeconds(oauthClientDetails.getRefreshTokenValidity());
        }
    }
}

Authentication server configuration:

/**
 * @author xiaoshu
 * @description 认证服务器配置
 * 配置token存储
 * 配置第三方应用
 * @date 2022年11月13日 12:44
 */
@ConditionalOnProperty(prefix = "auth",name = "method",havingValue = "redis")
@Configuration
@EnableAuthorizationServer
//@EnableResourceServer //资源服务器,获取资源前不需要登录,携带token就可以了
@EnableGlobalMethodSecurity(prePostEnabled = true) //开启方法级别权限
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
    
    
    @Resource
    private RedisConnectionFactory redisConnection;

    @Resource
    protected PasswordEncoder passwordEncoder;

    /**
     * 注入认证管理器
     */
    @Resource
    private AuthenticationManager authenticationManager;

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

    @Resource
    private ClientDetailsService cloudClientDetailsServiceImpl;

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
    
    
        clients.withClientDetails(cloudClientDetailsServiceImpl);
    }

    /**
     * 配置第三方应用 "authorization_code", "password", "client_credentials", "implicit", "refresh_token"
     * 1. code吗授权 authorization_code
     * 2. 静默授权   implicit
     * 3. 密码授权 (特别信任第三方应用)  password
     * 4. 客户端授权 (直接通过浏览器就能获取token) client_credentials
     * @param clients
     * @throws Exception
     */
    /*@Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
       clients.inMemory()
               //code授权
               .withClient("web")
               .secret(passwordEncoder.encode("web-secret"))
               .scopes("all") //配置第三方应用的业务作用域
               .authorizedGrantTypes("authorization_code") //授权类型
               .accessTokenValiditySeconds(7200)
               .redirectUris("https://www.baidu.com")
               .and()
               //静默授权
               .withClient("wx")
               .secret(passwordEncoder.encode("wx"))
               .scopes("all")
               .authorizedGrantTypes("implicit")
               .accessTokenValiditySeconds(3600)
               .redirectUris("https://www.baidu.com")
               .and()
               //密码授权, 这里要查询数据库用户,密码
               .withClient("admin")
               .secret(passwordEncoder.encode("admin"))
               .scopes("all")
               .authorizedGrantTypes("password")
               .accessTokenValiditySeconds(3600)
               .redirectUris("https://www.baidu.com")
               .and()
               //客户端授权
               .withClient("client")
               .secret(passwordEncoder.encode("client-secert"))
               .scopes("all")
               .authorizedGrantTypes("client_credentials")
               .accessTokenValiditySeconds(500)
               .redirectUris("https://www.baidu.com");
    }*/

    /**
     * 需要暴露授权服务给token存储
     * 暴露授权服务器给认证管理器
     * @param endpoints
     * @throws Exception
     */
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
    
    
        endpoints.tokenStore(tokenStore()).authenticationManager(authenticationManager);
    }
}
  • concept:
    • Resource server: a server (specific server) that hosts protected resources and can accept and use access tokens to respond to protected resource requests; each microservice is a resource server, such as providing an interface
    • Resource owner: An entity that can grant access to a protected resource. When the resource owner is a person, it is called the end user
    • Authorization server: After the authorization request is successful, the server issues an access token to the client to authenticate the resource owner and obtain authorization.
    • Client: For our products, QQ and WeChat login are third-party login systems. We also need resources for third-party login systems
  • Authorization mode:
    • Authorization-code
    • Authorization code - implicit pure front-end application
    • Password: Provide username and password directly to the application
    • Client credentials: A command line application without a front end, that is, requesting a token from the command line
  • Default endpoint DefaultSecurityFilterChain:
    • /oauth/token
    • /oauth/token_key
    • /oauth/check_token
  • Token carrying method:
    • GET ?access_token=xxx
    • POST header Authorization:bearer 99a996e4-5fde-42ea-b5fb-2cc47d926925
  • Integration of each microservice:
    • In addition to the auth service, other services are also resource servers
  • Jwt integration implementation (symmetric encryption):
    • new JwtTokenStore(jwtAccessTokenConverter())
    • AuthorizationServerEndpointsConfigurer 暴露 .accessTokenConverter(jwtAccessTokenConverter())
    • Common module configuration token analysis: ResourceServerConfig extends ResourceServerConfigurerAdapter, configure unified scanning package
  • Asymmetric encryption: https://oomake.com/download/openssl tool download openssl
    • Generate private key:
      • keytool -genkeypair -alias xiaoshu-jwt -validity 3650 -keyalg RSA -dname “CN=jwt,OU=jtw,O=jwt,L=zurich,S=zurich,C=CH” -keypass 730730 -keystore xiaoshu-jwt.jks -storepass 730730
    • Generate public key:
      • keytool -list -rfc --keystore xiaoshu-jwt.jks | openssl x509 -inform pem -pubkey
    • Pay attention to maven configuration resource
# token 校检
security:
  oauth2:
    resource:
      #相当于拿token换取用户信息
      user-info-uri: http://localhost:3000/getUserInfo

Authorization code mode

  • process:
    • 1. The third party should first register with the authorization server and generate clientId clientSecert.
    • 2. After logging in, access the redirect link; for example, if you scan the QQ code on a third-party platform, you must log in to QQ first before the authorization is confirmed.
    • 3. After confirming the authorization, obtain the code and obtain the token through the code.
      • state: is the state value, opaque to prevent cross-site request forgery
      • redirect_uri: redirect address, must be a public https request
      • Authorization is after login.
localhost:3000/oauth/authorize?response_type=code&client_id=web&state=sxt&redirect_uri=https://www.baidu.com
post
localhost:3000/outh/token?grant_type=authorization_code&code=iXB5jU&redirect_uri=https://www.baidu.com
  head: 
      Authorization: Basic d2ViOndlYi1zZWNyZXQ= (vaue:为三方应用的 cinetId和clientSecret组合的 base64编码)

{
"access_token": "xxx",
"token_type": "bearer",
"expires_in": 7199,
"scope": "all"
}

Silent authorization mode

  • process:
    • 1. First register with the authorization server, generate clientId clientSecert, configure the authentication mode to silent authorization
 localhost:3000/oauth/authorize?response_type=token&client_id=wx&state=sxt&redirect_uri=https://www.baidu.com
 确认授权后,直接返回token:
 https://www.baidu.com/#access_token=xxx&token_type=bearer&state=sxt&expires_in=3599&scope=all

Password authorization mode

  • process:
    1. First register with the authorization server and generate clientId clientSecert
    2. Expose the AuthenticationManager authentication manager and configure the authorization method as password authorization
 post
     localhost:3000/oauth/token?grant_type=password&username=name&password=pwd
 head: 
     Authorization: Basic d2ViOndlYi1zZWNyZXQ= (vaue:为三方应用的 cinetId和clientSecret组合的 base64编码)

Client authorization mode

  • process:
    1. First register with the authorization server and generate clientId clientSecert
    2. Directly initiate a request to obtain the token
    3. Access basic permission interfaces and cannot access specific permission interfaces!
 post
    localhost:3000/oauth/token?grant_type=client_credentials
 head: 
     Authorization: Basic d2ViOndlYi1zZWNyZXQ= (vaue:为三方应用的 cinetId和clientSecret组合的 base64编码)

Swagger microservice integration

  • Documentation: https://doc.xiaominfo.com/
  • Microservice integration: https://gitee.com/xiaoym/swagger-bootstrap-ui-demo
  • Gateway integration: Microservices integrate swagger documents, involving switching of multiple services. When entering the document homepage, the resource interface will be requested and the document resources corresponding to each service will be returned.
    • implements SwaggerResourcesProvider rewrites get() and combines the gateway to query the resource information of each microservice interface
    • Add SwaggerHandler -> SwaggerResourcesProvider to obtain interface resources
        <!-- knife4j-->
        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>knife4j-spring-boot-starter</artifactId>
            <version>${knife4j.version}</version>
        </dependency>

        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-boot-starter</artifactId>
            <version>${swagger.fox.version}</version>
        </dependency>
  • Integration of various services:
    • Note: This demo project spring boot version 2.6.x
@Configuration
@EnableOpenApi //注解启动用Swagger的使用,同时在配置类中对Swagger的通用参数进行配置
public class Swagger3Config implements EnvironmentAware {
    
    

    private String applicationName;

    private String applicationDescription;

    @Bean
    public Docket createRestApi(){
    
    
        //返回文档概要信息
        return new Docket(DocumentationType.OAS_30)
                .apiInfo(apiInfo())
                .select()
                .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
                .paths(PathSelectors.any())
                .build()
                .globalRequestParameters(getGlobalRequestParameters())
                .globalResponses(HttpMethod.GET,getGlobalResponseMessage())
                .globalResponses(HttpMethod.POST,getGlobalResponseMessage());
    }

    /**
     * 生成接口信息,包括标题,联系人等
     * @return ApiInfo
     */
    private ApiInfo apiInfo() {
    
    
        return new ApiInfoBuilder()
                .title(applicationName+"接口文档")
                .description(applicationDescription)
                .contact(new Contact("小树","http://www.baidu.com","[email protected]"))
                .version("1.0")
                .build();
    }


    /**
     * 封装全局通用参数
     * @return List<RequestParameter>
     */
    private List<RequestParameter> getGlobalRequestParameters() {
    
    
        List<RequestParameter> parameters=new ArrayList<>();
        RequestParameter headToken = new RequestParameterBuilder()
                .name("Authorization")
                .description("Bearer xxxx")
                .required(true)
                .in(ParameterType.HEADER)
                .query(q -> q.model(m -> m.scalarModel((ScalarType.STRING))))
                .required(Boolean.FALSE)
                .build();
        parameters.add(headToken);
        return parameters;
    }

    /**
     * 封装通用相应信息
     * @return List<Response>
     */
    private List<Response> getGlobalResponseMessage() {
    
    
        List<Response> responseList=new ArrayList<>();
        responseList.add(new ResponseBuilder().code("404").description("未找到资源").build());
        return responseList;
    }

    @Bean
    public WebMvcEndpointHandlerMapping webEndpointServletHandlerMapping(
            WebEndpointsSupplier webEndpointsSupplier, ServletEndpointsSupplier servletEndpointsSupplier,
            ControllerEndpointsSupplier controllerEndpointsSupplier, EndpointMediaTypes endpointMediaTypes,
            CorsEndpointProperties corsProperties, WebEndpointProperties webEndpointProperties, Environment environment) {
    
    
        List<ExposableEndpoint<?>> allEndpoints = new ArrayList<>();
        Collection<ExposableWebEndpoint> webEndpoints = webEndpointsSupplier.getEndpoints();
        allEndpoints.addAll(webEndpoints);
        allEndpoints.addAll(servletEndpointsSupplier.getEndpoints());
        allEndpoints.addAll(controllerEndpointsSupplier.getEndpoints());
        String basePath = webEndpointProperties.getBasePath();
        EndpointMapping endpointMapping = new EndpointMapping(basePath);
        boolean shouldRegisterLinksMapping = webEndpointProperties.getDiscovery().isEnabled() &&
                (org.springframework.util.StringUtils.hasText(basePath) || ManagementPortType.get(environment).equals(ManagementPortType.DIFFERENT));
        return new WebMvcEndpointHandlerMapping(endpointMapping, webEndpoints, endpointMediaTypes, corsProperties.toCorsConfiguration(), new EndpointLinksResolver(allEndpoints, basePath), shouldRegisterLinksMapping, null);
    }

    @Override
    public void setEnvironment(Environment environment) {
    
    
        this.applicationDescription = environment.getProperty("spring.application.description");
        this.applicationName = environment.getProperty("spring.application.name");
    }
}

Public yml configuration:

spring:
  mvc:
    pathmatch:
      matching-strategy: ANT_PATH_MATCHER #整合swagger时 springboot2.6.x如果不加该配置会报错

  redis:
    host: 127.0.0.1
    password: 

# token 校检
security:
  oauth2:
    resource:
      #相当于拿token换取用户信息
      user-info-uri: http://localhost:3000/token/user
    client:
      ignore-urls:
        - /v2/api-docs  

springfox:
  documentation:
    swagger-ui:
      enabled: true # false关闭swagger-ui界面 但不关闭openapi
  
        

Guess you like

Origin blog.csdn.net/hesqlplus730/article/details/128947007