Springcloud Alibaba 及各微服务组件整合梳理

news2024/11/25 18:32:49

Spring Cloud Alibaba 微服务各组件整合项目:

版本说明:

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

依赖前置:

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

  • 中文官网: https://nacos.io/zh-cn/docs/v2/quickstart/quick-start.html
  • 简介: 动态服务发现、配置管理和服务管理平台
  • 启动: sh startup.sh -m standalone
  • 关键特性:
    • 配置中心、服务管理
    • 动态配置服务; @RefreshScope 可以动态修改yml对应属性
    • 动态 DNS 服务 ; 支持权重路由,让您更容易地实现中间层负载均衡、更灵活的路由策略、流量控制
    • 注册表更新大量运用 copyonwrite思想防止读写冲突
  • 使用:
    • DataId 为 服务名称.yml + ${profiles.active}
    • extension-configs属性 本应用额外配置
    • shared-configs 属性表示共享配置
  • 持久化:
    • nacos运行体/config/nacos-mysql.sql 导入数据库,修改 application.properties 配置使用外部数据源

nacos 源码获取:

  • gitlub 下载对应版本
  • install 一下
  • console 模块为启动模板;
  • 其它模块pom引入,console保留源码启动,可以配合开发调试
// 编译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;
    }

}

nacos 服务列表获取示例:

@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

  • 文档: 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

  • 使用:启动一个服务包,yml配置注册;以接口地址以服务资源,配置限流等规格

  • 简介:分布式服务架构的流量控制组件,主要以流量为切入点,从限流,流量整形、熔断降级、系统负载保护、热点保护等多个维度保证服务稳定性

    • 核心库(代码控制) @SentinelResource 、控制台
  • 概念:

    • 服务雪崩:微服务之间存在许多交叉调用,因某服务出现异常导致依赖服务异常,从而导致多服务不可用
    • 服务降级:当服务熔断后,该服务不可调用,此时客户端返回一个缺省回调值,一般用于弱依赖服务如积分服务
  • 流控:

    • 规则:监控应用流量的QPS或并发线程数等指标,当达到指定阀值时对流量进行控制,避免被顺时高峰流量冲垮,保障应用可用性
      • 针对项:QPS (每秒请求数)、 线程数(等待设置线程数的线程响应时,其它请求线程才会被处理 )
      • 关联流控:设置关联资源,当关联资源达到阀值时,当前资源被限制
      • 链路流控: A->B A->C ,针对A 设置规则,入口资源设置 C,当达到限制指标时,C会被流控 B没影响
      • 热点流控:针对某热点数据进行流控; 热点商品、ip限制、防刷;(如针对商品id为1的商品进行限流)
    • 流控效果
      • 快速失败:直接拒绝
      • warm up(预热):在预热时间断内,慢慢的增加放入的请求, 3个流量 - 5个流量 -10个流量;冷加载因子:3 ;适合激增流量
      • 排队等待:阈值为5,来了10个流量则有5个流量等待,在超时时间里有处理完的请求,则进入一个等待流量。适合脉冲流量
  • 服务降级:

    • 熔断规则:
      • 慢调用比例:接口响应时长,最小请求数,比例;在熔断时长结束后进入半开状态
      • 异常比例
      • 异常数
  • fegin 整合:

    • feign.sentinel.enabled=true 开启
  • 系统规则:

    • 针对全局设置的一个兜底方案,如 load、cpu使用率、平均RT、QPS,等达到设置比例时,出发系统防护,全结果返回系统防护异常
  • 网关流控:

    • 整合 pom 引入 spring-cloud-alibaba-sentinel-gateway、yml链接控制台
    • 针对路由id进行规则设置,设置 Api分组进行匹配限流设置
  • sentinel-nacos持久化:

    • 规则默认存储在内存中,服务重启后就会丢失;一般都生产环境都会配置规则持久化
    • 步骤:
      • 1.pom引入依赖
      • 2.yml配置sentinel-datasource-nacos
      • 3.nacos中配置对应规则json
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

在这里插入图片描述

Seata(AT) 分布式事务组件

  • 官网: https://seata.io/zh-cn/docs/overview/what-is-seata.html
  • 使用:同样启动一个seta服务包配置好对应数据,yml配置连接seata;@GlobalTransactional 标注则可以
  • 概念:
    • 2PC:预处理、提交/回滚 (分布式事务完成分两阶段)
      • 事务协调者发送事务请求-》(阻塞) 事务参与者(数据库、服务)是否可执行事务,参与者执行事务请求,成功执行事务操作并写入undo、redo 日志后返回确认应答,否返回NO
      • 事务协调者向参与者发送commit请求,提交事务,完成后释放事务暂用资源
      • 只能尽力保证事务,如响应中断等
    • AT模式(无侵入,有锁):
      • 拦截业务sql提前表元数据,保存原快照;执行业务SQL后保存新快照,并添加行锁
      • 提交成功,删除快照数据以及行锁
      • 提交失败,对比当前数据与更新后快照数据是否一致,一致则用更新前快照还原业务数据,不一致则出现脏毒,人为处理
    • TCC模式(侵入,无锁):
      • 根据自己的业务场景实现 Try(一阶段执行) 、 Confirm(二阶段提交) 、 Cancel(二阶段回滚),由用户自己控制具体逻辑;
<!-- 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

在这里插入图片描述

GateWay 统一网关

  • 网关Swagger: 微服务网关文档,通过nacos获取服务列表,根据文档注解获取对应接口信息
  • 断言路由(predicates)
    • 内置断言:
      • 基于时间
      • 请求头
      • 域名
      • 请求方式
      • 请求参数
      • ip匹配
      • Cookie
      • 自定义 xxxRoutePredicateFactory extends AbstractRoutePredicateFactory
  • (过滤器)filters
    • 内置过滤:
      • AddRequestHeader=key, vlaue 添加请求头
      • 自定义 xxxGateWayFilterFactory extends AbstractNameValueGatewayFilterFactory
      • 全局过滤器 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 链路跟踪

  • 官网:https://skywalking.apache.org/
  • 文档:https://skyapm.github.io/document-cn-translation-of-skywalking/
  • 简介:国产开源框架,分布式系统应用程序性能监视工具;分布式链路跟踪,性能指标分析,应用服务依赖分析
  • 组成:
    • oapservice: skywalking服务端处理监控接收数据 端口:11800 12800
    • wepapp-ui: 数据展示业务 端口: webapp.yml
    • agent: 服务端绑定探针,收集数据
  • 可选插件:
    • optional-plugins/gateway
  • 微服务集成:

本地集成

  -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
  • 持久化:
    • config\application.yml ; storage.selector 配置数据库,默认是H2内存数据库
  • 自定义链路追踪:对项目中的业务方法,实现链路跟踪,方便排查问题
    • 在业务接口上标记 @Trace ,以及针对方法 @Tag(key = “标记名称”,value = “returnedObj”)
  • 性能剖析:
    • 针对慢接口,定位慢请求慢响应问题;
    • 性能剖析项,新建任务
  • 日志:
    • 添加依赖,配置 logback-spring.xml ,注意配置 grpc-log上报日志
    • skywalking未部署在本地时,注意修改 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>
  • 告警:
    • 针对接口响应时间、数据库访问平均时间等进行告警 alarm-settings.yml 规则配置包含基本默认告警规则
    • 网络钩子,告警时会发送请求;推送到接口、微信、钉钉、邮件等…

Outh2 微服务授权

  • 协议:关于授权的开发网络标准,使得第三方应用有权利去访问http服务,处理用户与资源之间的关系
  • 流程:
    • 通用security模块,讲yml配置的忽略路径、以及忽略鉴权注解标注的controller、接口,对应路径注册入security中 registry.antMatchers(HttpMethod.valueOf(method), strings.get(0)).permitAll();
    • 对应的fegin调用,需要配置请求头,防止微服务内调用鉴权失败
@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());
        }
    }
}

认证服务器配置:

/**
 * @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);
    }
}
  • 概念:
    • 资源服务器:托管受保护资源的服务器(具体服务器),能够接受并使用访问令牌响应受保护的资源请求;各微服务为资源服务器,如提供接口
    • 资源所有者:能够授予对受保护资源的访问权限的实体。当资源所有者是一个人时,它称为最终用户
    • 授权服务器:请求授权成功后,服务器向客户端发布访问令牌认证资源所有者并获得授权
    • 客户端:对我们的产品来说,QQ、微信登录是第三方登录系统。我们又需要第三方登录系统的资源
  • 授权模式:
    • 授权码(authorization-code)
    • 授权码-隐藏式(implicit)纯前端应用
    • 密码式(password):直接对应用提供用户名和密码
    • 客户端凭证(client credentials):没有前端的命令行应用,即在命令行下请求令牌
  • 默认端点 DefaultSecurityFilterChain:
    • /oauth/token
    • /oauth/token_key
    • /oauth/check_token
  • token携带方式:
    • GET ?access_token=xxx
    • POST header Authorization:bearer 99a996e4-5fde-42ea-b5fb-2cc47d926925
  • 各微服务整合:
    • 除auth服务外,其它服务也是资源服务器
  • Jwt整合实现(对称加密):
    • new JwtTokenStore(jwtAccessTokenConverter())
    • AuthorizationServerEndpointsConfigurer 暴露 .accessTokenConverter(jwtAccessTokenConverter())
    • common模块配置token解析:ResourceServerConfig extends ResourceServerConfigurerAdapter,配置统一扫描包
  • 非对称加密: https://oomake.com/download/openssl 工具下载 openssl
    • 生成私钥:
      • 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
    • 生成公钥:
      • keytool -list -rfc --keystore xiaoshu-jwt.jks | openssl x509 -inform pem -pubkey
    • 注意maven配置resource
# token 校检
security:
  oauth2:
    resource:
      #相当于拿token换取用户信息
      user-info-uri: http://localhost:3000/getUserInfo

授权码模式

  • 流程:
    • 1.第三方应该,先在授权服务器登记,生成 clientId clientSecert
    • 2.登录后,访问重定向链接; 比如:QQ扫码第三方平台,也是要先登录QQ后,才会确认授权
    • 3.确认授权后,获取code,通过code获取token
      • state:是状态值,不透明,防止跨站点请求伪造
      • redirect_uri:重定向地址,必须是公网 https请求
      • 授权是在登录之后。
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"
}

静默授权模式

  • 流程:
    • 1.先在授权服务器登记,生成 clientId clientSecert,配置认证模式为,静默授权
 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

密码授权模式

  • 流程:
    1. 先在授权服务器登记,生成 clientId clientSecert
    2. 暴露 AuthenticationManager 认证管理器,配置授权方式为密码授权
 post
     localhost:3000/oauth/token?grant_type=password&username=name&password=pwd
 head: 
     Authorization: Basic d2ViOndlYi1zZWNyZXQ= (vaue:为三方应用的 cinetId和clientSecret组合的 base64编码)

客户端授权模式

  • 流程:
    1. 先在授权服务器登记,生成 clientId clientSecert
    2. 直接发起请求获取token
    3. 访问基本权限接口,不能访问特定权限接口!
 post
    localhost:3000/oauth/token?grant_type=client_credentials
 head: 
     Authorization: Basic d2ViOndlYi1zZWNyZXQ= (vaue:为三方应用的 cinetId和clientSecret组合的 base64编码)

Swagger 微服务整合

  • 文档:https://doc.xiaominfo.com/
  • 微服务整合:https://gitee.com/xiaoym/swagger-bootstrap-ui-demo
  • 网关整合:微服务整合swagger文档,涉及多个服务的切换, 所有进入文档首页,会请求resource接口,返回各服务对应文档资源
    • implements SwaggerResourcesProvider 重写 get(),结合网关查询各微服务接口资源信息
    • 添加 SwaggerHandler -> SwaggerResourcesProvider 获取接口资源
        <!-- 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>
  • 各服务整合:
    • 注:此demo项目spring boot 版本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","2810030998@qq.com"))
                .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");
    }
}

公共 yml配置:

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
  
        

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

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

相关文章

抖音的外卖行业入局,为中小外卖企业创业者的机会给了哪些机会?

一则关于抖音进入外卖市场的消息&#xff0c;让美团“非常受伤”。 2月8日&#xff0c;美团(03690.HK&#xff09;盘中跌幅超9%。截至收盘&#xff0c;美团报收153.1港元&#xff0c;跌幅6.48%。美团大幅下跌的根源就是前一天关于抖音外卖进展的消息传闻。 2月7日&#xff0c…

一站式 Elasticsearch 集群指标监控与运维管控平台

上篇文章写了一下消息运维管理平台&#xff0c;今天带来的是ES的监控和运维平台。目前初创企业&#xff0c;不像大型互联网公司&#xff0c;可以重复的造轮子。前期还是快速迭代试错阶段&#xff0c;方便拿到市场反馈&#xff0c;及时调整自己的战略和产品方向。让自己活下去&a…

大数据入门怎么学习

大数据学习不能停留在理论的层面上&#xff0c;大数据方向切入应是全方位的&#xff0c;基础语言的学习只是很小的一个方面&#xff0c;编程落实到最后到编程思想。学习前一定要对大数据有一个整体的认识。 大数据是数据量多吗&#xff1f;其实并不是&#xff0c;通过Hadoop其…

chatGPT 官网使用详细教程 (亲测可行)

文章目录1. chatGPT 介绍2. 进入官网3. 开始使用1. chatGPT 介绍 chatGPT 是一款由 OpenAI 开发的聊天机器人模型&#xff0c;它能够模拟人类的语言行为&#xff0c;与用户进行自然的交互。它的名称来源于它所使用的技术—— GPT-3架构&#xff0c;即生成式语言模型的第3代…

三极管-晶体管开关速度有两种方法

晶体管开关速度有两种方法可以考虑一下 1、使用加速电容 在基极限流电阻并联小容量的电容&#xff08;一般pF级别&#xff09;&#xff0c;当输入信号上升、下降时候能够使限流电阻瞬间被旁路并提供基极电流&#xff0c;所以在晶体管由导通状态变化到截止状态时能够迅速从基极…

【强训】Day13

努力经营当下&#xff0c;直至未来明朗&#xff01; 文章目录一、选择二、编程1. 参数解析2. ★跳石板答案1. 选择2. 编程普通小孩也要热爱生活&#xff01; 一、选择 一个关系数据库文件中的各条记录 &#xff08;&#xff09; A 前后顺序不能任意颠倒&#xff0c;一定要按照…

C语言typedef的用法详解

C语言允许为一个数据类型起一个新的别名&#xff0c;就像给人起“绰号”一样。起别名的目的不是为了提高程序运行效率&#xff0c;而是为了编码方便。例如有一个结构体的名字是 stu&#xff0c;要想定义一个结构体变量就得这样写&#xff1a;struct stu stu1;struct 看起来就是…

图解项目延期的原因及解决应对方案大全

项目管理中经常出现项目延期的情况&#xff0c;面对项目延期的风险如何应对是考验每个项目经理管理水平的时候&#xff0c;很多人纵然是工作多年也没有对延期的种种情况进行总结思考。咱们社区的小竹对大家常见的项目延期情况及处理方案进行了详细全面的总结&#xff0c;供大家…

微服务 分片 运维管理

微服务 分片 运维管理分片分片的概念分片案例环境搭建案例改造成任务分片Dataflow类型调度代码示例运维管理事件追踪运维平台搭建步骤使用步骤分片 分片的概念 当只有一台机器的情况下&#xff0c;给定时任务分片四个&#xff0c;在机器A启动四个线程&#xff0c;分别处理四个…

Python类型-语句-函数

文章目录类型动态类型:变量类型会随着程序的运行发生改变注释控制台控制台输入input()运算符算术关系逻辑赋值总结语句判断语句while循环for循环函数链式调用和嵌套调用递归关键字传参在C/java中&#xff0c;整数除以整数结果还是整数&#xff0c;并不会将小数部分舍弃&#xf…

线上CPU飙高诊断定位

1. 先准备一段java程序&#xff0c;后台运行 2. 使用 top命令查看cpu的进程使用情况 在这里看到了一个进程占据了99.3%的cpu利用率&#xff0c;这显然是出现了cpu飙升的情况&#xff0c;这会到期系统其他进程得不到cpu的使用权&#xff0c;从而出现卡顿&#xff0c;因此需要进行…

第五章——大数定律和中心极限定理

文章目录1、大数定律1.1、弱大数定理&#xff08;辛钦大数定理&#xff09;1.2、伯努利大数定理2、中心极限定理2.1、独立同分布的中心极限定理2.2、李雅普诺夫定理2.3、棣莫弗——拉普拉斯定理2.4、中心极限定理的应用2.4.1、独立同分布的中心极限定理的应用2.4.2、棣莫弗——…

文件同步是什么?解析6个最佳的文件同步应用软件

文件同步应用程序是一项服务或程序&#xff0c;它提供了一种便捷的方式来在多台计算机或移动设备上自动文件同步。在登录文件同步应用程序的任何地方&#xff0c;都可以使用相同的文件来打开&#xff0c;编辑&#xff0c;复制&#xff0c;流式传输等&#xff0c;就像在最初上传…

重磅!微软推出首款 ChatGPT 版搜索引擎!

微软近期推出了首款 ChatGPT 版搜索引擎&#xff0c;今天带大家一起来看一下。 一夜之间&#xff0c;全球最大的科技公司仿佛都回到了自己年轻时的样子。 在谷歌宣布「实验性对话式人工智能服务」Bard 之后仅 24 小时&#xff0c;北京时间 2 月 8 日凌晨两点&#xff0c;微软发…

Linux安装达梦8数据库

Linux安装达梦8数据库 服务器系统&#xff1a;centos7 数据库版本&#xff1a;达梦8 先获取安装包&#xff1a;https://eco.dameng.com/download/?_blank 选择相应版本下载,下载完解压之后会得到一个iso文件&#xff0c;把他上传到服务器上&#xff0c;建议上传到/opt目录下…

深度复盘-重启 etcd 引发的异常

作者信息&#xff1a; 唐聪、王超凡&#xff0c;腾讯云原生产品中心技术专家&#xff0c;负责腾讯云大规模 TKE 集群和 etcd 控制面稳定性、性能和成本优化工作。 王子勇&#xff0c;腾讯云专家级工程师&#xff0c; 腾讯云计算产品技术服务专家团队负责人。 概况 作为当前中国…

linux Ubuntu KUbuntu 系统安装相关

系统安装 本来想快到中午的时候调试一下服务器上的http请求接收代码。我的电脑上装的是kali的U盘系统&#xff0c;然后我的U盘居然找不到了(然后之前安装的系统不知道是否是写入软件的原因&#xff0c;没办法解析DNS,我都用的转发的,这让我体验非常差。kali的系统工具很多&…

若依框架---树状层级部门数据库表

&#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是小童&#xff0c;Java开发工程师&#xff0c;CSDN博客博主&#xff0c;Java领域新星创作者 &#x1f4d5;系列专栏&#xff1a;前端、Java、Java中间件大全、微信小程序、微信支付、若依框架、Spring全家桶 &#x1f4…

linux 安装,卸载jdk8

1>安装1 xshell,xsftp 教育版下载 https://www.xshell.com/zh/free-for-home-school/ 2下载jdk包 https://www.oracle.com/java/technologies/downloads/3在usr下新建java文件夹把jdk包拉进去解压tar -zxvf 4首先使用vim打开etc目录下的profile文件 --> vim /etc/profile…

【参加CUDA线上训练营】零基础cuda,一文认识cuda基本概念

【参加CUDA线上训练营】零基础cuda,一文认识cuda基本概念1.术语2.线程层次2.1 Block、Warp与Thread之间的关系2.2 Thread index1.术语 \\%序号名称描述1HostCPU和内存&#xff08;host memory&#xff09;2DeviceGPU和显存&#xff08;device memory&#xff09;3SMStreaming M…