SpringCloud+Vue+Python人工智能(fastAPI,机器学习,深度学习)前后端架构各功能实现思路——SpringCloud后端——Sa-Token实现Security权限管理

SpringCloud+Vue+Python人工智能(fastAPI,机器学习,深度学习)前后端架构各功能实现思路——主目录(持续更新):https://blog.csdn.net/grd_java/article/details/144986730

一、Sa-Token集成

1. 引入依赖

base模块作为业务万物之源,切不可亵玩焉,要是什么都让它扛,一旦出问题,整个系统就要招收灭顶之灾


众所周知,base模块是既支持全局网关Gateway又支持通用业务模块common的男人,而gateway与common又有着不可调节的矛盾

gateway是WebFlux,与我们业务微服务的web包完全冲突


那gateway要全局鉴权,而common下的业务模块也需要鉴权,怎么办?sa-token已经考虑到了 这一点,它搞了两个包,一个专门给webflux环境用,一个给正常spring boot web应用去用


在这里插入图片描述


所以,gateway单独引入sa-token-reactor-spring-boot-starter,common引入sa-token-spring-boot-starter


事情就怎么水灵灵的解决了

而sa-token又需要redis的支持,gateway和common下业务微服务都需要使用。此时就将其引入到base模块下即可


如果我们需要业务redis和权限redis分离,还需要引入分离包

1. 根目录pom中统一管理sa-token依赖版本,记住只是管理版本,不是将依赖引入到了根目录pom对应父模块中哦


在这里插入图片描述


在这里插入图片描述

        <!-- Sa-Token 权限认证,在线文档:https://sa-token.cc -->
        <sa-token-spring-boot-starter>1.39.0</sa-token-spring-boot-starter>
        <!-- Sa-Token 权限认证(Reactor响应式集成), 在线文档:https://sa-token.cc -->
        <sa-token-reactor-spring-boot-starter>1.39.0</sa-token-reactor-spring-boot-starter>
        <!-- Sa-Token 插件:整合SSO单点登录 -->
        <sa-token-sso>1.39.0</sa-token-sso>
        <!-- Sa-Token 整合 Redis (使用 jackson 序列化方式) -->
        <sa-token-redis-jackson>1.39.0</sa-token-redis-jackson>
        <!-- Sa-Token插件:权限缓存与业务缓存分离 -->
        <sa-token-alone-redis>1.39.0</sa-token-alone-redis>

        <dependencies>
            <!-- Sa-Token 权限认证,在线文档:https://sa-token.cc -->
            <dependency>
                <groupId>cn.dev33</groupId>
                <artifactId>sa-token-spring-boot-starter</artifactId>
                <version>${sa-token-spring-boot-starter}</version>
            </dependency>
            <!-- Sa-Token 权限认证(Reactor响应式集成), 在线文档:https://sa-token.cc -->
            <dependency>
                <groupId>cn.dev33</groupId>
                <artifactId>sa-token-reactor-spring-boot-starter</artifactId>
                <version>${sa-token-reactor-spring-boot-starter}</version>
            </dependency>
            <!-- Sa-Token 插件:整合SSO -->
            <dependency>
                <groupId>cn.dev33</groupId>
                <artifactId>sa-token-sso</artifactId>
                <version>${sa-token-sso}</version>
            </dependency>

            <!-- Sa-Token 整合 Redis (使用 jackson 序列化方式) -->
            <dependency>
                <groupId>cn.dev33</groupId>
                <artifactId>sa-token-redis-jackson</artifactId>
                <version>${sa-token-redis-jackson}</version>
            </dependency>
            <!-- Sa-Token插件:权限缓存与业务缓存分离 -->
            <dependency>
                <groupId>cn.dev33</groupId>
                <artifactId>sa-token-alone-redis</artifactId>
                <version>${sa-token-alone-redis}</version>
            </dependency>

2. gateway 单独引入响应式依赖


在这里插入图片描述

        <!-- Sa-Token 权限认证(Reactor响应式集成), 在线文档:https://sa-token.cc -->
        <dependency>
            <groupId>cn.dev33</groupId>
            <artifactId>sa-token-reactor-spring-boot-starter</artifactId>
        </dependency>

3. common引入业务模块需要的依赖


在这里插入图片描述

        <!-- Sa-Token 权限认证,在线文档:https://sa-token.cc -->
        <dependency>
            <groupId>cn.dev33</groupId>
            <artifactId>sa-token-spring-boot-starter</artifactId>
        </dependency>

4. base模块引入sa-token的redis依赖


在这里插入图片描述

        <!-- Sa-Token 整合 Redis (使用 jackson 序列化方式) -->
        <dependency>
            <groupId>cn.dev33</groupId>
            <artifactId>sa-token-redis-jackson</artifactId>
        </dependency>
        <!-- 提供Redis连接池 -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>
        <!-- Sa-Token插件:权限缓存与业务缓存分离 -->
        <dependency>
            <groupId>cn.dev33</groupId>
            <artifactId>sa-token-alone-redis</artifactId>
        </dependency>

2. rbac数据库表

经典5张表,实现后台系统权限控制


在这里插入图片描述

/*
 Navicat Premium Data Transfer

 Source Server         : localhost3306
 Source Server Type    : MySQL
 Source Server Version : 80017
 Source Host           : localhost:3306
 Source Schema         : sys

 Target Server Type    : MySQL
 Target Server Version : 80017
 File Encoding         : 65001

 Date: 10/02/2022 15:30:20
*/

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for sys_menu
-- ----------------------------
DROP TABLE IF EXISTS `sys_menu`;
CREATE TABLE `sys_menu`  (
  `id` char(20) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT 'id',
  `pid` char(20) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT '父菜单id',
  `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT '菜单名',
  `type` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT '菜单类型(目录,按钮)',
  `permission` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT '菜单权限',
  `url` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT 'url',
  `path` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT 'path',
  `component` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT '组件',
  `iconCls` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT '图标',
  `keepAlive` tinyint(1) NULL DEFAULT NULL COMMENT '是否保持激活',
  `requireAuth` tinyint(1) NULL DEFAULT NULL COMMENT '是否要求权限',
  `enabled` tinyint(1) NULL DEFAULT NULL COMMENT '是否启用',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_bin ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of sys_menu
-- ----------------------------
INSERT INTO `sys_menu` VALUES ('1490549095108968448', '0', '首页', 'menu', 'home', NULL, '/', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_menu` VALUES ('1490549401968443392', '0', '权限管理', 'menu', 'security', NULL, '/security', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_menu` VALUES ('1490549872766484480', '1490549401968443392', '用户管理', 'menu', 'security', NULL, 'user', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_menu` VALUES ('1490549939053264896', '1490549401968443392', '角色管理', 'menu', 'security', NULL, 'role', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_menu` VALUES ('1490550012319367168', '1490549401968443392', '菜单管理', 'menu', 'security', NULL, 'menu', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_menu` VALUES ('1490551718331547648', '1490549872766484480', '添加按钮', 'button', 'btn:security', 'security/sys-user-role/add', '', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_menu` VALUES ('1490633481049341952', '1490549872766484480', '展示权限(用户是否可以浏览此页面)', 'view', '/', NULL, NULL, NULL, NULL, NULL, NULL, NULL);

-- ----------------------------
-- Table structure for sys_role
-- ----------------------------
DROP TABLE IF EXISTS `sys_role`;
CREATE TABLE `sys_role`  (
  `id` char(20) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT 'id',
  `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT '角色名',
  `name_zh` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT '角色描述',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_bin ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of sys_role
-- ----------------------------
INSERT INTO `sys_role` VALUES ('1', 'ROLE_admin', '超级管理员');
INSERT INTO `sys_role` VALUES ('1490553559727472640', 'ROLE_author', '作者');
INSERT INTO `sys_role` VALUES ('2', 'ROLE_user', '普通用户');

-- ----------------------------
-- Table structure for sys_role_menu
-- ----------------------------
DROP TABLE IF EXISTS `sys_role_menu`;
CREATE TABLE `sys_role_menu`  (
  `rid` char(20) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT '角色id',
  `mid` char(20) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT '菜单id'
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_bin ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of sys_role_menu
-- ----------------------------
INSERT INTO `sys_role_menu` VALUES ('1', '1490549095108968448');
INSERT INTO `sys_role_menu` VALUES ('1', '1490549401968443392');
INSERT INTO `sys_role_menu` VALUES ('1', '1490549872766484480');
INSERT INTO `sys_role_menu` VALUES ('1', '1490551718331547648');
INSERT INTO `sys_role_menu` VALUES ('1', '1490549939053264896');
INSERT INTO `sys_role_menu` VALUES ('1', '1490550012319367168');
INSERT INTO `sys_role_menu` VALUES ('1490553559727472640', '1490549095108968448');
INSERT INTO `sys_role_menu` VALUES ('2', '1490549095108968448');
INSERT INTO `sys_role_menu` VALUES ('2', '1490633481049341952');
INSERT INTO `sys_role_menu` VALUES ('2', '1490549939053264896');
INSERT INTO `sys_role_menu` VALUES ('2', '1490550012319367168');

-- ----------------------------
-- Table structure for sys_user
-- ----------------------------
DROP TABLE IF EXISTS `sys_user`;
CREATE TABLE `sys_user`  (
  `id` char(20) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '用户id',
  `username` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '用户名',
  `password` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '密码',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_bin ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of sys_user
-- ----------------------------
INSERT INTO `sys_user` VALUES ('1', 'admin', '$2a$10$/BnlSX.KM14t9c9j5p9TUerKXkpuvcvmvEf5J2i2Jb8OEv9Dp178K');
INSERT INTO `sys_user` VALUES ('1490553814707601408', '游客', '$2a$10$hidoRf81Kpibr1seSl7QVeOrm/3x2rpwzWYkRsKxjcm6sd192ZoN2');
INSERT INTO `sys_user` VALUES ('1490553884043640832', '作者', '$2a$10$TEvZ5Cd/HxItTFzNpC3n3e7AmfA5KVXndvMdo6a99VtN1Rb7EIyyy');

-- ----------------------------
-- Table structure for sys_user_role
-- ----------------------------
DROP TABLE IF EXISTS `sys_user_role`;
CREATE TABLE `sys_user_role`  (
  `uid` char(20) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '用户id',
  `rid` char(20) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '角色id'
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_bin ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of sys_user_role
-- ----------------------------
INSERT INTO `sys_user_role` VALUES ('1489965313679163392', '1');
INSERT INTO `sys_user_role` VALUES ('2', '1');
INSERT INTO `sys_user_role` VALUES ('2', '1490188252357853184');
INSERT INTO `sys_user_role` VALUES ('2', '2');
INSERT INTO `sys_user_role` VALUES ('1489978103777198080', '1490188227389161472');
INSERT INTO `sys_user_role` VALUES ('1489978103777198080', '1490188199299907584');
INSERT INTO `sys_user_role` VALUES ('1489978103777198080', '1490188252357853184');
INSERT INTO `sys_user_role` VALUES ('1490553814707601408', '2');
INSERT INTO `sys_user_role` VALUES ('1490553884043640832', '1490553559727472640');
INSERT INTO `sys_user_role` VALUES ('1', '1');
INSERT INTO `sys_user_role` VALUES ('1', '1490553559727472640');
INSERT INTO `sys_user_role` VALUES ('1', '2');
INSERT INTO `sys_user_role` VALUES ('1', '1');
INSERT INTO `sys_user_role` VALUES ('1', '1490553559727472640');
INSERT INTO `sys_user_role` VALUES ('1', '2');

SET FOREIGN_KEY_CHECKS = 1;

3. 创建对应数据库表的MVC架构

如果懒得自己创建,就参考主目录中,mybatis plus整合,里面有代码生成器,可以一键生成


https://blog.csdn.net/grd_java/article/details/145061518


在这里插入图片描述

4. sa配置

gateway和鉴权微服务都需要单独配置,sa-token需要使用redis,因此需要配置redis,并且我们这里是业务redis和鉴权reids分离的

sa-token: 中的token-name必须与所有其它微服务一致


在这里插入图片描述

feign:
    okhttp:
        enabled: true #feign组件

server:
    port: 7071 # 当前服务端口号

# 日志放置的路径和级别
project:
    folder: E:/webser/yd_oa_cloud/ 
log:
    root:
        level: debug
############## Sa-Token 配置 (文档: https://sa-token.cc) ##############
    
# 业务redis
spring:
  # redis配置
  redis:
    # Redis数据库索引(默认为0)
    database: 1
    # Redis服务器地址
    host: 127.0.0.1
    # Redis服务器连接端口
    port: 6379
    # Redis服务器连接密码(默认为空)
    # password:
    # 连接超时时间
    timeout: 10s
    lettuce:
        pool:
            # 连接池最大连接数
            max-active: 200
            # 连接池最大阻塞等待时间(使用负值表示没有限制)
            max-wait: -1ms
            # 连接池中的最大空闲连接
            max-idle: 10
            # 连接池中的最小空闲连接
            min-idle: 0

# Sa-Token 配置
sa-token: 
    # token 名称(同时也是 cookie 名称)
    token-name: authorization
    # token 有效期(单位:秒) 默认30天,-1 代表永久有效
    timeout: 60 # 设置为60秒,方便测试
    # token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
    active-timeout: -1
    # 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
    is-concurrent: false
    # 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token)
    is-share: true
    # token 风格(默认可取值:uuid、simple-uuid、random-32、random-64、random-128、tik)
    token-style: uuid
    # 是否输出操作日志
    is-log: true
    # 配置 Sa-Token 单独使用的 Redis 连接 
    alone-redis: 
        # Redis数据库索引(默认为0)
        database: 2
        # Redis服务器地址
        host: 127.0.0.1
        # Redis服务器连接端口
        port: 6379
        # Redis服务器连接密码(默认为空)
        password: 
        # 连接超时时间
        timeout: 10s
        lettuce:
            pool:
                # 连接池最大连接数
                max-active: 200
                # 连接池最大阻塞等待时间(使用负值表示没有限制)
                max-wait: -1ms
                # 连接池中的最大空闲连接
                max-idle: 10
                # 连接池中的最小空闲连接
                min-idle: 0

二、security微服务

此微服务为认证微服务。负责登录,认证,鉴权。这里会将rbac相关业务操作一起写在这里。如有需求,rbac也应该单独一个微服务负责,但是大多数项目没有这个必要,浪费资源

是否需要单点登录?如果需要则此微服务需要引入单点登录相关依赖,但是我这里暂时不需要单点登录,日后扩展新系统时,会扩充单点登录功能,这里建议大家和我一样,先写普通单系统登录,日后公司需要

下面的依赖我不会在现在引入我的项目中


在这里插入图片描述

        <!-- Sa-Token 插件:整合SSO -->
        <dependency>
            <groupId>cn.dev33</groupId>
            <artifactId>sa-token-sso</artifactId>
        </dependency>

1. 添加sa-token配置

和gateway一样,需要redis等配置,如果需要单点登录,就额外加上单点登录的配置,代码块中一并给出,自己选择

nacos配置中心


在这里插入图片描述


在这里插入图片描述

在这里插入图片描述

server:
    port: 7072
spring:
  servlet:
    multipart:
      max-file-size: 10MB
      max-request-size: 15MB
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/yd_oa_db?serverTimeZone=GMT%2B8&useUnicode=true&characterEncoding=utf-8&autoReconnect=true&allowMultiQueries=true
    username: root
    password: root
    driver-class-name: com.mysql.cj.jdbc.Driver
    hikari:
      pool-name: HikariCPDatasource
      minimum-idle: 5
      idle-timeout: 180000
      maximum-pool-size: 10
      auto-commit: true
      max-lifetime: 1800000
      connection-timeout: 30000
      connection-test-query: SELECT 1
  # redis配置
  redis:
    # Redis数据库索引(默认为0)
    database: 1
    # Redis服务器地址
    host: 127.0.0.1
    # Redis服务器连接端口
    port: 6379
    # Redis服务器连接密码(默认为空)
    # password:
    # 连接超时时间
    timeout: 10s
    lettuce:
        pool:
            # 连接池最大连接数
            max-active: 200
            # 连接池最大阻塞等待时间(使用负值表示没有限制)
            max-wait: -1ms
            # 连接池中的最大空闲连接
            max-idle: 10
            # 连接池中的最小空闲连接
            min-idle: 0
  
#mybatis 大小写转驼峰
mybatis:
  configuration:
    map-underscore-to-camel-case: true
mybatis-plus:
  # 对于 Maven 多模块项目,扫描路径应以 classpath*: 开头,以加载多个 JAR 包中的 XML 文件。
  mapper-locations: classpath*:mappers/*.xml #配置mapper xml文件的路径

# Sa-Token 配置
sa-token: 
    # token 名称(同时也是 cookie 名称)
    token-name: authorization
    # token 有效期(单位:秒) 默认30天,-1 代表永久有效
    timeout: 18000 # 5小时,5*60*60
    # token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
    active-timeout: -1
    # 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
    is-concurrent: false
    # 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token)
    is-share: true
    # token 风格(默认可取值:uuid、simple-uuid、random-32、random-64、random-128、tik)
    token-style: uuid
    # 是否输出操作日志
    is-log: true
    
    # ------- SSO-模式二相关配置
    sso-server:
      # Ticket有效期 (单位: 秒),默认五分钟
      ticket-timeout: 300
      # 所有允许的授权回调地址
      allow-url: "*"



    # 配置 Sa-Token 单独使用的 Redis 连接 
    alone-redis: 
        # Redis数据库索引(默认为0)
        database: 2
        # Redis服务器地址
        host: 127.0.0.1
        # Redis服务器连接端口
        port: 6379
        # Redis服务器连接密码(默认为空)
        password: 
        # 连接超时时间
        timeout: 10s
        lettuce:
            pool:
                # 连接池最大连接数
                max-active: 200
                # 连接池最大阻塞等待时间(使用负值表示没有限制)
                max-wait: -1ms
                # 连接池中的最大空闲连接
                max-idle: 10
                # 连接池中的最小空闲连接
                min-idle: 0

代码中也不要忘了


在这里插入图片描述

spring:
  profiles:
    active: dev #定义环境为开发环境
  application:
    name: yd-oa-java-security # 服务名字,服务之间相互调用都依赖这个名字,注意不可以使用下划线,因为Gateway不支持下划线
  # spring cloud相关配置
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848 # localhost:8848为默认的nacos本地端口位置
      config:
        server-addr: 127.0.0.1:8848 # 配置中心地址
        file-extension: yml # 配置中心的文件后缀类型
        # 配置中心要加载的yml文件名为yd_oa_java_gateway-dev.yml这样式的,也就是服务名-环境.后缀
        shared-configs: ${spring.application.name}-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} # 对应nacos配置中心的Data Id

2. 启动类

Spring Boot第一步, 小小启动类就上强度


在这里插入图片描述

package com.yd_oa_java_cloud.security;

import cn.dev33.satoken.SaManager;
import cn.dev33.satoken.sso.SaSsoManager;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
//启动类,springIOC容器加载时 扫描的包范围为com.yd_oa_java_cloud,主要要将你想要spring管理的包都放在一个固定路径下
//我们写代码时,经常创建包搞一个什么com.XXXXX.XXXXX,然后配置时就用com.XXXXX
@MapperScan("com.yd_oa_java_cloud.*.mapper")
@SpringBootApplication(scanBasePackages = {"com.yd_oa_java_cloud"})
public class YdOaCloudSecurityRunApplication {
    public static void main(String[] args) {
        SpringApplication.run(YdOaCloudSecurityRunApplication.class,args);
        System.out.println();
        System.out.println("启动成功,Sa-Token 配置如下:" + SaManager.getConfig());
        System.out.println("---------------------- Sa-Token SSO 统一认证中心启动成功 ----------------------");
        System.out.println("配置信息:" + SaSsoManager.getServerConfig());
        System.out.println();
    }
}

启动后,看看打印的配置信息是否正确


在这里插入图片描述

启动后,成功注册到nacos


在这里插入图片描述

三、rbac功能开发

具体rbac需要的接口由于篇幅原因,放在另一篇文章中:https://blog.csdn.net/grd_java/article/details/145081600

四、登录,网关统一鉴权,网关openfeign远程调用

具体代码由于篇幅原因,放在另一篇文章中:https://blog.csdn.net/grd_java/article/details/145165507
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ydenergy_殷志鹏

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值