Sa-Token鉴权与网关服务实现

纠错:

在上一部分里我完成了微服务框架的初步实现,但是先说一下之前有一个错误,就是依赖部分

上次的学习中我在总的父模块下引入了spring-boot-dependencies(版本控制)我以为在子模块下就不需要再引用了,虽然没有报错,但是还是需要在starter模块中再引用一次

修改如下:在starter模块下

添加spring-boot-dependencies

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <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>

 下面我们来开始编写鉴权实现

首先我们要清楚我们需要实现的流程

用户访问时需要通过网关层,网关会进行用户鉴权,由nacos分配到指定服务

这里为什么auth服务要在其他服务之上呢,因为用户需要在auth服务中进行登录,获取其专属的token,在请求头中带着token,才能访问其他的服务。

Nacos:

什么是Nacos?目前我对nacos的理解是,管理与动态分配微服务

后面我说的都是自己的理解,可能不是那么准确,请大家自行百度哈哈哈。

黑马SpringCloud微服务全通关,一套精通springcloud全技术栈Eureka、 Nacos、OpenFeign、网关Gateway、 Spring_哔哩哔哩_bilibili

(不是打广告哈哈哈,这个讲的简洁不墨迹,读文章难受的建议食用) 

nacos是一个注册中心 ,我们在创建一个微服务时,需要将微服务注册到nacos上。

我们可以把nacos看成一个map表,键是微服务的名称,值是微服务本身,我们可以通过nacos找到想要的微服务。

比如说网关鉴权,微服务之间的调用,都需要nacos来提供微服务。


nacos搭建

nacos我在自己的服务器上使用的是docker安装,但是这次作为演示,就在windows本机上安装了

链接:https://pan.baidu.com/s/1V4OUO46LZXRym2yzG4DcWQ?pwd=1111 
提取码:1111

 下载好后,进入bin目录,在该目录下打开cmd终端,输入:

startup.cmd -m standalone

 启动成功后我们可以看到一个地址,复制粘贴到浏览器,账号密码都是nacos,就可以成功进入了

nacos配置 

这次我们需要新建两个微服务,一个是auth微服务,一个是gateway微服务

auth服务骨干如下,和之前是一样的,不知道的可以回去看一下,就是改了一个名字

还有网关服务:movie-gateway 

骨干如下:不需要分层

下面我介绍一个工具,是阿里的脚手架。地址:https://start.aliyun.com/

这个工具可以帮我们整理spring could和springboot的一些版本冲突

我的spring boot版本是2.4.2 ,选择对应的版本,在这里搜索需要引入的依赖,点击下方的浏览代码

我们就可以看到对应的版本号和需要引入的依赖了,下面我们开始正式的引入 

movie-catalogue服务:
总模块:
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>2.4.2</version>
            <type>pom</type>
            <scope>compile</scope>
        </dependency>
    </dependencies>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>1.8</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <spring-boot.version>2.4.2</spring-boot.version>
        <spring-cloud-alibaba.version>2021.1</spring-cloud-alibaba.version>
        <spring-cloud.version>2020.0.6</spring-cloud.version>
    </properties>
starter模块: 
    <dependencies>
        <dependency>
            <groupId>com.yizhiliulianta</groupId>
            <artifactId>movie-catalogue-application-controller</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bootstrap</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
            <exclusions>
                <exclusion>
                    <artifactId>snakeyaml</artifactId>
                    <groupId>org.yaml</groupId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <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.artifactId}</finalName>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>2.3.0.RELEASE</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
movie-auth服务:
总模块:
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>2.4.2</version>
            <type>pom</type>
            <scope>compile</scope>
        </dependency>
    </dependencies>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>1.8</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <spring-boot.version>2.4.2</spring-boot.version>
        <spring-cloud-alibaba.version>2021.1</spring-cloud-alibaba.version>
        <spring-cloud.version>2020.0.6</spring-cloud.version>
    </properties>
starter模块:
    <dependencies>
        <dependency>
            <groupId>com.yizhiliulianta</groupId>
            <artifactId>movie-auth-application-controller</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bootstrap</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
            <exclusions>
                <exclusion>
                    <artifactId>snakeyaml</artifactId>
                    <groupId>org.yaml</groupId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <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.artifactId}</finalName>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>2.3.0.RELEASE</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

其他的模块我就不粘了,直接将matalogue引入的依赖,粘贴到对应的auth模块依赖下就行了

而movie-gateway的依赖在后面展示

nacos配置文件:

movie-auth服务:

下面我们在movie-auth服务下的starter模块的配置目录下新建bootstap.xml文件

spring:
  application:
    name: movie-auth
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.38.189:5000
        enabled: true

application.name:注册到nacos上的服务名

cloud.nacos.discovery.server-addr:nacos的地址(就是开始启动nacos给你的地址和端口)

cloud.nacos.discovery.enabled:启用nacos的服务发现功能

movie-catalogue服务:
spring:
  application:
    name: movie-catalogue
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.38.189:5000
        enabled: true

movie-gateway服务:
spring:
  application:
    name: movie-gateway
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.38.189:5000
        enabled: true

启动所有服务,启动类我就不展示了

打开刚刚的网址,发现所有服务成功注册!

 Sa-Token:

Sa-Token 是一个轻量级 Java 权限认证框架,主要解决:登录认证、权限认证、Session会话、单点登录、OAuth2.0、微服务网关鉴权 等一系列权限相关问题

我不再去详细介绍了,大家知道这是一款很好用的鉴权框架,而且文档非常详细,大家可以之间去食用。

官方地址:Sa-Token

本次是集成redis,redis我就不带大家去安装了,下面是安装包,无脑下一步就好,大家可以去搜一下怎么安装,很简单,我这里安装过了,不去展示了

Redis:

链接:https://pan.baidu.com/s/1njAjHRm8bUzMOCqo3z6whg?pwd=1111 
提取码:1111

 找到刚刚安装的文件夹,然后点击redis-cli.exe

还是依赖...哈哈哈。本次我们要和redis集成,大家可以照抄我的依赖

movie-gateway服务:

总依赖:

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>1.8</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <spring-boot.version>2.4.2</spring-boot.version>
        <spring-cloud-alibaba.version>2021.1</spring-cloud-alibaba.version>
        <spring-cloud.version>2020.0.6</spring-cloud.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <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>

    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.22</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bootstrap</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
            <exclusions>
                <exclusion>
                    <artifactId>snakeyaml</artifactId>
                    <groupId>org.yaml</groupId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-loadbalancer</artifactId>
        </dependency>
        <!-- Sa-Token 权限认证(Reactor响应式集成), 在线文档:https://sa-token.cc -->
        <dependency>
            <groupId>cn.dev33</groupId>
            <artifactId>sa-token-reactor-spring-boot-starter</artifactId>
            <version>1.38.0</version>
        </dependency>
        <!-- Sa-Token 整合 Redis (使用 jackson 序列化方式) -->
        <dependency>
            <groupId>cn.dev33</groupId>
            <artifactId>sa-token-redis-jackson</artifactId>
            <version>1.38.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>
        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
            <version>2.8.6</version>
        </dependency>

    </dependencies>

配置文件: 

下面是配置文件的编写,在application.yml文件下添加

server:
  port: 2000

spring:
  cloud:
    gateway:
      routes:
        - id: movie-catalogue
          uri: lb://movie-catalogue
          predicates:
            - Path=/catalogue/**
          filters:
            - StripPrefix=1

        - id: movie-auth
          uri: lb://movie-auth
          predicates:
            - Path=/auth/**
          filters:
            - StripPrefix=1
  # redis配置
  redis:
    # Redis数据库索引(默认为0)
    database: 0
    # 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:
  # token 名称(同时也是 cookie 名称)
  token-name: satoken
  # token 有效期(单位:秒) 默认30天,-1 代表永久有效
  timeout: 2592000
  # token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
  active-timeout: -1
  # 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
  is-concurrent: true
  # 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token)
  is-share: true
  # token 风格(默认可取值:uuid、simple-uuid、random-32、random-64、random-128、tik)
  token-style: random-32
  # 是否输出操作日志
  is-log: true

movie-auth服务:

controller模块依赖:

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.4.2</version>
            <exclusions>
                <exclusion>
                    <artifactId>spring-boot-starter-logging</artifactId>
                    <groupId>org.springframework.boot</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>com.yizhiliulianta</groupId>
            <artifactId>movie-auth-domain</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <!-- Sa-Token 权限认证 -->
        <dependency>
            <groupId>cn.dev33</groupId>
            <artifactId>sa-token-spring-boot-starter</artifactId>
            <version>1.38.0</version>
        </dependency>
    </dependencies>

common模块依赖:

    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.22</version>
        </dependency>
        <!-- 数据映射-->
        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct</artifactId>
            <version>1.4.2.Final</version>
        </dependency>
        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct-processor</artifactId>
            <version>1.4.2.Final</version>
        </dependency>
        <!-- 日志-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-log4j2</artifactId>
            <version>2.4.2</version>
        </dependency>
        <!--  json解析工具-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.24</version>
        </dependency>
        <!--  json工具-->
        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
            <version>2.8.6</version>
            <scope>compile</scope>
        </dependency>
        <!-- 集合,对象,字符串等工具-->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.11</version>
        </dependency>
        <!-- 断言检查-->
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>19.0</version>
        </dependency>
        <!-- Sa-Token 整合 Redis (使用 jackson 序列化方式) -->
        <dependency>
            <groupId>cn.dev33</groupId>
            <artifactId>sa-token-redis-jackson</artifactId>
            <version>1.37.0</version>
        </dependency>
        <!-- 提供Redis连接池 -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
            <version>2.9.0</version>
        </dependency>
    </dependencies>

下面是配置文件的编写,在application.yml文件下添加

server:
  port: 1001

mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

spring:
  datasource:
    username: root
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/movieweb?useUnicode=true&serverTimezone=Asia/Shanghai&useSSL=true&characterEncoding=utf-8
    password: 123456
  # redis配置
  redis:
    # Redis数据库索引(默认为0)
    database: 0
    # 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:
  # token 名称(同时也是 cookie 名称)
  token-name: satoken
  # token 有效期(单位:秒) 默认30天,-1 代表永久有效
  timeout: 2592000
  # token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
  active-timeout: -1
  # 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
  is-concurrent: true
  # 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token)
  is-share: true
  # token 风格(默认可取值:uuid、simple-uuid、random-32、random-64、random-128、tik)
  token-style: random-32
  # 是否输出操作日志
  is-log: true

现在所有的基础环境和依赖,我们都配置完成了

表建立:

我们开始鉴权模块的编写了,首先我们需要三张表,分别是,用户,权限,用户和权限的映射

用户表:(用户名和密码)

权限表:(权限的名字,权限的状态,权限的键)

映射表:(用户的id和权限id的映射)

大家看着自己建表吧,太简单了。

代码实现:

下面开始代码的基础编写,还是和电影一样的流程,dto转bo,domain层做逻辑,我偷懒了,只做了一个新增用户,我不去粘代码了,我就粘贴一下domain层的主要逻辑了,我相信大家是可以写出来的哈哈哈,参考上一篇

domain层:

package com.yizhiliulianta.auth.domain.service.impl;


import cn.dev33.satoken.secure.SaSecureUtil;
import cn.dev33.satoken.stp.SaTokenInfo;
import com.google.gson.Gson;
import com.yizhiliulianta.auth.domain.bo.AuthUserBO;
import com.yizhiliulianta.auth.domain.constants.AuthConstant;
import com.yizhiliulianta.auth.domain.converter.AuthUserBOConverter;
import com.yizhiliulianta.auth.domain.redis.RedisUtil;
import com.yizhiliulianta.auth.domain.service.AuthUserDomainService;
import com.yizhiliulianta.auth.infra.entity.AuthPermission;
import com.yizhiliulianta.auth.infra.entity.AuthUser;
import com.yizhiliulianta.auth.infra.entity.AuthUserPermission;
import com.yizhiliulianta.auth.infra.service.AuthPermissionService;
import com.yizhiliulianta.auth.infra.service.AuthUserPermissionService;
import com.yizhiliulianta.auth.infra.service.AuthUserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.LinkedList;
import java.util.List;

@Service
@Slf4j
public class AuthUserDomainServiceImpl implements AuthUserDomainService {

    @Resource
    private AuthUserService authUserService;

    @Resource
    private AuthPermissionService authPermissionService;
    @Resource
    private AuthUserPermissionService authUserPermissionService;

    @Resource
    private RedisUtil redisUtil;

    private final String salt = "yizhiliulianta";
    private final String userPermissionPrefix = "user.permission";

    @Override
    public Boolean register(AuthUserBO authUserBO) {

        AuthUser authUser = AuthUserBOConverter.INSTANCE.convertBOToAuth(authUserBO);
        if (StringUtils.isNotBlank(authUser.getPassword())){
            authUser.setPassword(SaSecureUtil.md5BySalt(authUser.getPassword(),salt));
        }
        //插入用户
        AuthUser user = authUserService.insert(authUser);
        AuthPermission authPermission = new AuthPermission();
        //获取对应权限信息
        authPermission.setPermissionKey(AuthConstant.PERMISSION_KEY);
        AuthPermission permissionResult = authPermissionService.queryByCondition(authPermission);
        //用户与权限做关联
        Long userId = user.getId();
        Long permissionResultId = permissionResult.getId();
        AuthUserPermission authUserPermission = new AuthUserPermission();
        authUserPermission.setUserId(userId);
        authUserPermission.setPermissionId(permissionResultId);
        authUserPermissionService.insert(authUserPermission);
        //放入redis
        String buildKey = redisUtil.buildKey(userPermissionPrefix, authUser.getUserName());
        List<AuthPermission> authPermissionList = new LinkedList<>();
        authPermissionList.add(permissionResult);
        redisUtil.set(buildKey,new Gson().toJson(authPermissionList));

        return true;
    }

    @Override
    public SaTokenInfo doLogin(String validCode) {
        return null;
    }

    @Override
    public AuthUserBO getUserInfo(AuthUserBO authUserBO) {
        return null;
    }
}

这里就是两张表分别进行插入,首先查询出插入的用户对象和需要绑定的权限,通过映射表的对象,来绑定一个映射对象,继续插入。权限可能是多个,所以我用了一个集合来保存权限,也是直接可以将权限丢入的。

movie-gateway代码实现:

下面我们开始movie-gateway的编写

首先我们需要编写一个权限认证配置器,代码如下:

权限认证配置器:
package com.yizhiliulianta.gateway.auth;

import cn.dev33.satoken.context.SaHolder;
import cn.dev33.satoken.reactor.filter.SaReactorFilter;
import cn.dev33.satoken.router.SaRouter;
import cn.dev33.satoken.stp.StpUtil;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * 权限认证的配置器
 */
@Configuration
public class SaTokenConfigure {
    // 注册 Sa-Token全局过滤器 
    @Bean
    public SaReactorFilter getSaReactorFilter() {
        return new SaReactorFilter()
            // 拦截地址 
            .addInclude("/**")    /* 拦截全部path */
            // 鉴权方法:每次访问进入 
            .setAuth(obj -> {
                System.out.println("---- 前端访问path:" + SaHolder.getRequest().getRequestPath());
                // 登录校验 -- 拦截所有路由,并排除/user/doLogin 用于开放登录 
                SaRouter.match("/**", "/auth/user/doLogin", r -> StpUtil.checkPermission("movie:select"));
            });
    }
}

这个配置器的作用是拦截所有路径,进行登录的校验,查看该用户是否具有对应权限,但是登录,不能拦截,所以排除了登录路径

权限认证接口实现:
package com.yizhiliulianta.gateway.auth;

import cn.dev33.satoken.stp.StpInterface;
import com.alibaba.nacos.api.utils.StringUtils;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.yizhiliulianta.gateway.entity.AuthPermission;
import com.yizhiliulianta.gateway.redis.RedisUtil;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 自定义权限验证接口扩展
 */
@Component
public class StpInterfaceImpl implements StpInterface {

    @Resource
    private RedisUtil redisUtil;

    private final String userPermissionPrefix = "user.permission";

    //获取权限
    @Override
    public List<String> getPermissionList(Object loginId, String loginType) {
        String authKey = redisUtil.buildKey(userPermissionPrefix, loginId.toString());
        String authValue = redisUtil.get(authKey);
        if (StringUtils.isBlank(authValue)){
            return Collections.emptyList();
        }

        List<AuthPermission> permissionList = new Gson().fromJson(authValue, new TypeToken<List<AuthPermission>>(){
        }.getType());

        return permissionList.stream().map(AuthPermission::getPermissionKey).collect(Collectors.toList());
    }

    //获取角色
    @Override
    public List<String> getRoleList(Object loginId, String loginType) {
        return null;
    }

}

重写两个方法,因为本次演示一下satoken的使用,并没有添加角色role的实现,所以我只实现了获取权限的方法。首先拼接一个key,去redis中去取,得到的值就是我们刚刚放入的权限详细信息,我们将其转换成java对象,通过steam流获取它的key键,就是我们数据库中的permissionkey,也就是配置器中的验证数据。

验证操作:

下面我们在auth服务中,验证一下整体的流程,在controller添加两个验证方法,代码如下

    // 会话登录接口
    @RequestMapping("doLogin")
    public SaResult doLogin(String name, String pwd) {
        // 第一步:比对前端提交的账号名称、密码
        if("zhang".equals(name) && "123456".equals(pwd)) {
            // 第二步:根据账号id,进行登录
            StpUtil.login("一支榴莲挞");
            SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
            return SaResult.data(tokenInfo);
        }
        return SaResult.error("登录失败");
    }

    // 查询登录状态  ---- http://localhost:8081/acc/isLogin
    @RequestMapping("isLogin")
    public SaResult isLogin() {
        return SaResult.ok("是否登录:" + StpUtil.isLogin());
    }

dologin方法中接收前端传来的参数来模拟传入的账号密码,如果一致则登录成功,利用satoken的login方法进行登录,这里的”你好“就是一个模拟,在后面我们会和微信登录对接,这里放的是真实的用户名,然后返回一个对应的token,而下面的方法就是验证刚刚的鉴权有没用成功。

下面请出我们的apipost

首先第一步,我们要实现用户的注册

添加成功!

下面我们开始来测试网关

 很完美,成功了,我们可以看到token和loginid,我们将token复制,添加到请求头,开始用islogin接口进行测试

我们观察到成功了,证明我们的网关和auth打通了,但是大家可能会有疑问,鉴权真的打通了吗 

那我们再次操作一下,首先是我们不带token

可以看到无权限,失败了,因为网关拦截住了,证明token是没有问题的,那么下面就是鉴权

我们在配置器中修改一下权限规则,我这里随便修改一下,改成abc,我们重启服务试一下

没有通过网关,证明没有权限,与配置的规则不匹配,这下我们可以发现,网关和satoken成功配置,下一次我们要实现的是微信公众号与登录进行打通。

总结:

让我们回顾一下这次的任务流程,首先是编写了用户与权限的增删改查(只完成了增哈哈哈偷懒了),然后将三个服务注册到nacos中,引入satoken鉴权框架,并于redis集成,通过缓存来获取用户权限。

用户登录实现的过程:注册----》登录-----》获取token----》网关拦截,通过token在redis中获取权限信息来判断是否符合规则

附录: 

代码不是很全,因为类真的很多,如果大家想要代码的话可以私信我,下次完成微信打通,我将代码放到gitee上,方便大家拉取

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

全新取图系统搭建,广泛应用,轻松解决找图难问题!

前言 在数字化高速发展的时代&#xff0c;图片已成为人们日常交流不可或缺的一部分。每个社交平台我们都需要头像、背景等去打造属于我们自己的一张名片。为了满足大众日益增长的需求&#xff0c;并创造更多的收益机会&#xff0c;搭建一款先进的取图系统真的很必要。 一、这款…

SQL Server 安装后,服务器再改名,造成名称不一致,查询并修改数据库服务器真实名称

SELECT SERVERNAME -- 1.查询旧服务器名称 SELECT serverproperty(servername) AS new --2.查询新服务器名称 -- 3.更新服务器名称 IF SERVERPROPERTY(servername) <> 新服务器名称替换 BEGIN DECLARE server_name NVARCHAR(128) SET server_name 新服务器…

警惕!这本SCIE正在被​“On Hold”!

【欧亚科睿学术】 近期&#xff0c;经小编查询&#xff0c;一本近乎百分百录用率、且生信友好的“毕业神刊”——JOURNAL OF BIOLOGICAL REGULATORS AND HOMEOSTATIC AGENTS被科睿唯安打上了“On Hold”标识。 图片来源&#xff1a;科睿唯安&#xff08;2024年6月13日查&#…

D 25章 进程的终止

D 25章 进程的终止 440 25.1 进程的终止&#xff1a;_exit()和exit() 440 1. _exit(int status)&#xff0c; status 定义了终止状态&#xff0c;父进程可调用 wait 获取。仅低8位可用&#xff0c; 调用 _exit() 总是成功的。 2.程序一般不会调用 _exit()&#xff0c; 而是…

做了2年前端,盘点前端技术栈!大佬轻喷~

前言 自己写了快两年前端&#xff0c;但是大致总结一下哈哈哈哈我觉得这个话题蛮有意思的&#xff0c;可以看看大家的技术广度&#xff0c;可以进行分享和学习以及讨论所以这里说一下我对我的前端技术&#xff0c;做一下盘点和总结因为我的开发年限有限&#xff0c;所以我觉得…

C++面试准备

变量作用&#xff1a;给一段指定的内存空间起名&#xff0c;方便操作这段内存。 常量&#xff1a;用于记录程序中不可更改的数据。 #include <iostream> using namespace std;#define DAY 7 int main() {cout << "一周有" << DAY << "…

设置systemctl start kibana启动kibana

1、编辑kibana.service vi /etc/systemd/system/kibana.service [Unit] DescriptionKibana Server Manager [Service] Typesimple Useres ExecStart/home/es/kibana-7.10.2-linux-x86_64/bin/kibana PrivateTmptrue [Install] WantedBymulti-user.target 2、启动kibana # 刷…

Vue 简单自定义标签

Vue 简单自定义标签 思路&#xff1a; 1、计算每个项离父级左侧宽 left 2、计算当前滑块的宽&#xff0c;绝对定位 3、下一个项的宽/2-滑块的宽/2下一项离父级左侧的宽 left 4、使用定位left&#xff08;性能较差一点&#xff09; 或 translate 移动距离 <template><…

实用软件下载:硕思LOGO设计师最新安装包及详细安装教程

​硕思Logo设计师是一款操作灵活简单&#xff0c;且功能强大的logo制作软件&#xff0c;它可以通过简单的点击就可以为网站、博客、论坛和邮件创建专业的logo、条幅、按钮、标题、图标和签名等。 该软件提供了很多精心设计的模板和丰富的资源&#xff0c;为更好的创建logo艺术…

NestJS学习笔记

一、安装NestJS CLI工具 环境检查 //查看node版本 node -v//查看npm版本 npm -v 安装nest/cli 使用npm全局安装nestjs/cli npm i -g nestjs/cli 查看nest版本 nest -v 结果如图&#xff1a; 创建nest项目 //命令行创建nest项目 nest new 【项目名】 VScode扩展下载 1、…

linux 安装sftp及使用sftp上传和下载

一、centos7 安装sftp 1.安装 OpenSSH 服务&#xff1a; sudo yum install openssh-server2.启动 SSH 服务&#xff0c;并设置为开机启动&#xff1a; sudo systemctl start sshd sudo systemctl enable sshd3.创建一个新用户&#xff0c;用于SFTP连接&#xff08;替换your_…

STM32理论 —— μCOS-Ⅲ(2/2):时间管理、消息队列、信号量、任务内嵌信号量/队列、事件标志、软件定时器

文章目录 9. 时间管理9.1 OSTimeDly()9.2 OSTimeDlyHMSM()9.3 OSTimeDlyResume()9.4 延时函数实验 10. 消息队列10.1 创建消息队列函数OSQCreate()10.2 发送消息到消息队列函数(写入队列)OSQPost()10.3 获取消息队列中的消息函数(读出队列)OSQPend()10.4 消息队列操作实验 11. …

【Unity】官方文档学习-光照系统

目录 1 前言 2 光照介绍 2.1 直接光与间接光 2.2 实时光照与烘焙光照 2.3 全局光照 3 光源 3.1 Directional Light 3.1.1 Color 3.1.2 Mode 3.1.3 Intensity 3.1.4 Indirect Multiplier 3.1.5 Shadow Type 3.1.6 Baked Shadow Angle 3.1.7 Realtime Shadows 3.1…

具有不确定性感知注意机制的肺结节分割和不确定区域预测| 文献速递-深度学习结合医疗影像疾病诊断与病灶分割

Title 题目 Lung Nodule Segmentation and UncertainRegion Prediction With an Uncertainty-Aware Attention Mechanism 具有不确定性感知注意机制的肺结节分割和不确定区域预测 01 文献速递介绍 肺结节分割在肺癌计算机辅助诊断&#xff08;CAD&#xff09;系统中至关重…

终结国企虚假贸易:监管闭环下的关系排查与风控增强

2024年5月28日&#xff0c;国务院正式公布《国有企业管理人员处分条例》&#xff08;以下简称《条例》&#xff09;&#xff0c;将于2024年9月1日起施行。作为国家经济的重要支柱&#xff0c;国有企业的管理人员在企业运营中扮演着至关重要的角色&#xff0c;《条例》的颁布&am…

Sm4【国密4加密解密】

当我们开发金融、国企、政府信息系统时&#xff0c;不仅要符合网络安全的等保二级、等保三级&#xff0c;还要求符合国密的安全要求&#xff0c;等保测评已经实行很久了&#xff0c;而国密测评近两年才刚开始。那什么是密码/国密&#xff1f;什么是密评&#xff1f;本文就关于密…

Android低代码开发 - InputMenuPanelItem详解

我们知道MenuPanel是一个菜单面板容器&#xff0c;它里面可以放各式各样的菜单和菜单组。今天我们就来详细讲解输入菜单这个东西。 InputMenuPanelItem源码 package dora.widget.panel.menuimport android.content.Context import android.text.Editable import android.text…

Vue2/Vue3使用video播放视频--捕获截图

基本步骤 在JavaScript中&#xff0c;实现从<video>元素中截图的基本步骤如下&#xff1a; 1、创建Canvas元素&#xff1a;首先&#xff0c;需要创建一个<canvas>元素&#xff0c;因为截图操作会借助Canvas的绘图上下文来完成。 2、获取Video帧&#xff1a;从<v…

Elasticsearch-经纬度查询(8.x)

目录 一、开发环境 二、pom文件 三、ES配置文件 四、ES相关字段 五、ES半径查询 ES的字段类型:geo_point&#xff0c;可以实现以一个点为中心的半径查询(geo_distance query) ES地理位置查询: 半径查询(geo_distance query)查询指定矩形内的数据(geo_bounding_box query…

现代易货模式:重塑物品价值,引领交换新潮流

在日益繁荣的现代社会&#xff0c;物品交换文化正逐渐兴起&#xff0c;一种新型的交易模式——现代易货模式&#xff0c;正在成为市场的新宠。它不仅是对传统“以物易物”模式的现代化演绎&#xff0c;更是对物品价值再认识和交换方式创新的体现。 现代易货模式&#xff0c;简言…