登陆认证&权限控制(2)—— 基于Spring security 安全框架的权限管理 & 注解式权限控制 & RABC模型

在这里插入图片描述

前言

登陆认证,权限控制是一个系统必不可少的部分,一个开放访问的系统能否在上线后稳定持续运行其实很大程度上取决于登陆认证和权限控制措施是否到位,不然可能系统刚刚上线就会夭折。

Spring Security 是一个能够为基于 Spring 的企业应用系统提供声明式的安全访问控制解决方案的安全框架。

本篇博客介绍Spring Security的使用,结合MySQL,Redis实现基于JWT的注解式的权限认证,并且可以实现给不同的用户显示不同的前端页面。

代码仓库:https://gitee.com/pet365/spring-security-demo

登陆认证&权限控制(2)—— 基于Spring security 安全框架的权限管理 & 注解式权限控制 & RABC模型_第1张图片

其他相关的权限文章如下:

  • 从http请求 到 cookie 到 session & 用 session控制 删改数据的权限

  • 使用token的权限验证方法 & 用户+角色+权限表设计 & SpringBoot项目应用

  • 登陆认证&权限控制(1)——从session到token认证的变迁 & session的问题分析 + CSRF攻击的认识

文章目录

  • 前言
  • 引出
  • 初识spring security安全框架
    • 快速入门
  • spring security的项目应用
    • 安全框架的配置
    • UserDetailsService接口
      • 1、基本概念
      • 2、UserDetailsService获取用户名,密码,权限
      • 3、UserInfo extends User
    • 设置拦截器handler
      • 1、登录成功的拦截器
      • 2、请求访问通过OncePerRequestFilter过滤器
  • 权限相关表设计
    • RBAC基于角色的访问控制
    • 数据库表设计
    • 查询语句
    • 权限的注解式控制
      • 配置打开注解
      • 使用注解控制权限
    • 给不同的用户显示不同的页面
      • 数据库表设计
      • 查询语句
      • 不同用户显示的效果
  • 总结
    • 附录:
      • 1、前端页面
      • 2、MySQL数据库语句

引出


1.Spring Security的使用,结合MySQL,Redis实现基于JWT的注解式的权限认证,并且可以实现给不同的用户显示不同的前端页面;
2.项目中的快速应用和使用,拦截器的设置,安全框架的配置;
3.权限表的设计,基于角色的访问控制RABC模型;
4.启动注解的配置,通过注解实现权限的控制;
5.给不同的用户显示不同的页面,相关的SQL以及前端页面;

初识spring security安全框架

Spring Security 是一个能够为基于 Spring 的企业应用系统提供声明式的安全访问控制解决方案的安全框架。它提供了一组可以在 Spring 应用上下文中配置的 Bean,充分利用了 Spring IoC(Inversion of Control 控制反转),DI(Dependency Injection 依赖注入)和 AOP(面向切面编程)功能,为应用系统提供声明式的安全访问控制功能,减少了为企业系统安全控制编写大量重复代码的工作。

Spring Security 拥有以下特性:

  • 对身份验证和授权的全面且可扩展的支持
  • 防御会话固定、点击劫持,跨站请求伪造等攻击
  • 支持 Servlet API 集成
  • 支持与 Spring Web MVC 集成

Spring、Spring Boot 和 Spring Security 三者的关系如下图所示:

登陆认证&权限控制(2)—— 基于Spring security 安全框架的权限管理 & 注解式权限控制 & RABC模型_第2张图片

快速入门

1、引入依赖


<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-securityartifactId>
dependency>

2、创建一个控制器

@RestController
public class HelloController {
    @GetMapping("hello")
    public String hello(){
        return "Hello Spring security";
    }
}

3、启动项目

访问:http://localhost:8080/hello 结果打开的是一个登录页面,其实这时候我们的请求已经被保护起来了,要想访问,需要先登录。

登陆认证&权限控制(2)—— 基于Spring security 安全框架的权限管理 & 注解式权限控制 & RABC模型_第3张图片

Spring Security 默认提供了一个用户名为 user 的用户,其密码在控制台可以找到

spring security的项目应用

安全框架的配置

登陆认证&权限控制(2)—— 基于Spring security 安全框架的权限管理 & 注解式权限控制 & RABC模型_第4张图片

Spring Security 内置的 Password Encoder 有:

加密算法名称 PasswordEncoder
NOOP NoOpPasswordEncoder.getInstance()
SHA256 new StandardPasswordEncoder()
BCRYPT(官方推荐) new BCryptPasswordEncoder()
LDAP new LdapShaPasswordEncoder()
PBKDF2 new Pbkdf2PasswordEncoder()
SCRYPT new SCryptPasswordEncoder()
MD4 new Md4PasswordEncoder()
MD5 new MessageDigestPasswordEncoder(“MD5”)
SHA_1 new MessageDigestPasswordEncoder(“SHA-1”)
SHA_256 new MessageDigestPasswordEncoder(“SHA-256”)

上述 Password Encoder 中有一个『无意义』的加密器:NoOpPasswordEncoder 。它对原始密码没有做任何处理(现在也被标记为废弃)。

记得使用 @SuppressWarnings(“deprecation”) 去掉 IDE 的警告信息。

package com.tianju.config;

import com.tianju.config.security.handler.*;
import com.tianju.config.security.service.MyUserDetail;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import javax.annotation.Resource;

/**
 * 框架中自定义用户名和密码
 */

@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true,jsr250Enabled = true,prePostEnabled = true) // 开启注解式权限控制
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Resource
    private MyUserDetail myUserDetail;

    @Autowired
    private LoginSuccessHandler loginSuccessHandler;

    @Autowired
    private JwtHandler jwtHandler;

    @Value("${security.isOpen}")
    private Boolean isOpen;

    @Override
    public void configure(AuthenticationManagerBuilder auth) throws Exception {
        /**
         * security硬性要求密码必须是密文
         */
        PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        // 对明文加密
//        String encode = passwordEncoder.encode("123");
//        System.out.println("加密后为:"+encode);
//        auth.inMemoryAuthentication().withUser("pet").password(encode).roles("admin");
        auth.userDetailsService(myUserDetail);
    }

    /**
     * 自定义表单,前端的页面
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception{
        if (isOpen){
            hasSecurity(http);
        }else {
            noSecurity(http);
        }
    }

    /**
     * 不加安全框架,放行所有请求
     * @param http
     */
    private void noSecurity(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .anyRequest().permitAll()
                .and()
                .csrf().disable();
    }


    private void hasSecurity(HttpSecurity http) throws Exception {
        // 自定义页面
        http.formLogin()  // 需要自定义表单
                .loginPage("/login.html") // 自己登陆页面
                .loginProcessingUrl("/api/user/login") // 登陆请求地址
                .successHandler(loginSuccessHandler) // 给前端返回json字符串
                .failureHandler(new LoginFailHandler()) // 登陆失败给前端的字符串Json
                .permitAll() // 对上面两个进行放行
        ;

        http.exceptionHandling()
                .accessDeniedHandler(new NoAuthorityHandler()) // 登陆后没有权限的返回字符串Json
                .authenticationEntryPoint(new NotLoginHandler()) // 未登录
        ;

        //给接口配置权限
        //1:注解的方式
        //2:编码的方式
        http.authorizeRequests()
                // 无需登陆
                .antMatchers("/find","/api/img/upload","/api/img/hi","/api/map/fastMatch",
                        "/api/myLogin/username","/api/ali/pay","/api/ali/notify").permitAll() // 无需登陆
                .anyRequest().authenticated(); // 所有请求都拦截

        // 指定目标过滤器,填自己的过滤器
        http.addFilterBefore(jwtHandler, UsernamePasswordAuthenticationFilter.class);

        // 前后端项目中装禁用掉session(改用jwt)
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
        // CSRF是指跨站请求伪造(Cross-site request forgery)
        // https://www.jianshu.com/p/5ac8deb775b0
        http.csrf().disable(); // 关闭csrf过滤器
    }


    /**
     * 加密的类必须放入IOC容器中
     * @return
     */
    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }
}

UserDetailsService接口

1、基本概念

  • AuthenticationManager

    它是 “表面上” 的做认证和鉴权比对工作的那个人,它是认证和鉴权比对工作的起点。

    ProvierderManager 是 AuthenticationManager 接口的具体实现。

登陆认证&权限控制(2)—— 基于Spring security 安全框架的权限管理 & 注解式权限控制 & RABC模型_第5张图片

登陆认证&权限控制(2)—— 基于Spring security 安全框架的权限管理 & 注解式权限控制 & RABC模型_第6张图片

  • AuthenticationProvider

    它是 “实际上” 的做认证和鉴权比对工作的那个人。从命名上很容易看出,Provider 受 ProviderManager 的管理,ProviderManager 调用 Provider 进行认证和鉴权的比对工作。

    我们最常用到 DaoAuthenticationProvider 是 AuthenticationProvider 接口的具体实现。

登陆认证&权限控制(2)—— 基于Spring security 安全框架的权限管理 & 注解式权限控制 & RABC模型_第7张图片

  • UserDetailsService

    虽然 AuthenticationProvider 负责进行用户名和密码的比对工作,但是它并不清楚用户名和密码的『标准答案』,而标准答案则是由 UserDetailsService 来提供。简单来说,UserDetailsService 负责提供标准答案 ,以供 AuthenticationProvider 使用。

登陆认证&权限控制(2)—— 基于Spring security 安全框架的权限管理 & 注解式权限控制 & RABC模型_第8张图片

  • UserDetails

    UserDetails 它是存放用户认证信息和权限信息的标准答案的 “容器” ,它也是 UserDetailService “应该” 返回的内容。

登陆认证&权限控制(2)—— 基于Spring security 安全框架的权限管理 & 注解式权限控制 & RABC模型_第9张图片

  • PasswordEncoder

    Spring Security 要求密码不能是明文,必须经过加密器加密。这样,AuthenticationProvider 在做比对时,就必须知道『当初』密码时使用哪种加密器加密的。所以,AuthenticationProvider 除了要向 UserDetailsService 『要』用户名密码的标准答案之外,它还需要知道配套的加密算法(加密器)是什么

登陆认证&权限控制(2)—— 基于Spring security 安全框架的权限管理 & 注解式权限控制 & RABC模型_第10张图片

2、UserDetailsService获取用户名,密码,权限

登陆认证&权限控制(2)—— 基于Spring security 安全框架的权限管理 & 注解式权限控制 & RABC模型_第11张图片

3、UserInfo extends User

登陆认证&权限控制(2)—— 基于Spring security 安全框架的权限管理 & 注解式权限控制 & RABC模型_第12张图片

package com.tianju.config.security.entity;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.User;

import java.util.Collection;

public class UserInfo extends User {
    private Integer userId; // 用户的id
    private String realName; // 真实姓名

    public UserInfo(String username, String password,
                    Collection<? extends GrantedAuthority> authorities, Integer userId, String realName) {
        super(username, password, authorities);
        this.userId = userId;
        this.realName = realName;
    }

    public Integer getUserId() {
        return userId;
    }

    public String getRealName() {
        return realName;
    }
}

设置拦截器handler

登陆认证&权限控制(2)—— 基于Spring security 安全框架的权限管理 & 注解式权限控制 & RABC模型_第13张图片

1、登录成功的拦截器

登陆认证&权限控制(2)—— 基于Spring security 安全框架的权限管理 & 注解式权限控制 & RABC模型_第14张图片

2、请求访问通过OncePerRequestFilter过滤器

  • 1:是否携带了jwt

  • 2:解密清求头jwt

    不能解开:放行(到下一个过滤器》

    能解开:走到下一步

  • 3:对比redis中的jwt

    不一样:放行(到下一个过滤器)

    一样:走到下一步

  • 4:给jwt续期

  • 5:让容器中放入一个凭证(登陆凭证)

package com.tianju.config.security.handler;

import com.tianju.config.security.service.MyUserDetail;
import com.tianju.util.JwtUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 1:是否携带了jwt
 * 2:解密清求头jwt
 *      不能解开:放行(到下一个过滤器》
 *      能解开:走到下一步
 * 3:对比redis中的jwt
 *      不一样:放行(到下一个过滤器)
 *      一样:走到下一步
 * 4:给jwt续期
 * 5:让容器中放入一个凭证(登陆凭证)
 */
@Component
@Slf4j
public class JwtHandler extends OncePerRequestFilter {
    @Autowired
    private RedisTemplate<String,Object> stringRedisTemplate;
    @Autowired
    private MyUserDetail myUserDetail;

    @SneakyThrows
    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response,
                                    FilterChain filterChain)
            throws ServletException, IOException {
        //1.获取请求头中的前端jwt
        String jwt = request.getHeader("jwt");
        //2.判断能否获取到jwt
        if (jwt == null) {
            filterChain.doFilter(request, response);
            log.warn("未携带Jwt");
            return;
        }
        //3.判断能否解密jwt
        if (!JwtUtil.decode(jwt)) {
            filterChain.doFilter(request, response);
            log.warn("未能解密jwt");
            return;
        }
        //4.通过jwt获取用户信息,然后根据key获取redis中的jwt
        Map userInfo = JwtUtil.getUserInfo(jwt);
        Long userId = (Long) userInfo.get("userId");
        String redisJwt = (String) stringRedisTemplate.opsForValue().get("jwt" + userId.intValue());
        //5.核验两个jwt
        if (!jwt.equals(redisJwt)) {
            filterChain.doFilter(request, response);
            log.warn("redis里的和前端的不一致");
            return;
        }
        //6.给jwt续期
        stringRedisTemplate.opsForValue().set("jwt" + userId, jwt, 30, TimeUnit.DAYS);
        //7.往security容器中放登录凭证
        //实现步骤:获取security上下文类,往里面放一个凭证
        String username = (String) userInfo.get("username");
        UserDetails userDetails = myUserDetail.loadUserByUsername(username);

        UsernamePasswordAuthenticationToken upa = new UsernamePasswordAuthenticationToken(userDetails.getUsername(),
                                                  userDetails.getPassword(),userDetails.getAuthorities());

        SecurityContextHolder.getContext().setAuthentication(upa);
        /**
         * 记得放行
         */
        filterChain.doFilter(request, response);
    }
}

权限相关表设计

RBAC基于角色的访问控制

RBAC(Role-Based Access Control,基于角色的访问控制)模型是一种广泛用于访问控制的安全模型。它基于角色的概念,将权限授权和访问管理组织起来。

在RBAC模型中,有以下几个核心概念:

  • 角色(Role):角色是一组权限的集合,代表了用户在系统中所扮演的角色或身份。用户可以被分配一个或多个角色。
  • 权限(Permission):权限是对系统资源的操作权限。例如,读取、写入、执行等。权限定义了用户或角色可以进行的操作。
  • 用户(User):用户是系统的最终使用者,他们可以被分配一个或多个角色。
  • 资源(Resource):资源是受到访问控制保护的对象,可以是系统中的数据、功能、服务等。

数据库表设计

登陆认证&权限控制(2)—— 基于Spring security 安全框架的权限管理 & 注解式权限控制 & RABC模型_第15张图片

查询语句

SELECT 
ut.id,
ut.username,
ut.realname,
ut.password,
art.role_name,
art.role_note,
at.auth_name,
at.auth_url

FROM auth_user_tab ut
LEFT JOIN auth_role_user_tab arut ON arut.user_id=ut.id
LEFT JOIN auth_role_tab art ON art.role_id=arut.role_id
LEFT JOIN auth_role_privs_tab arpt ON arpt.rp_role=arut.role_id
LEFT JOIN auth_tab at ON at.auth_id=arpt.rp_privs

权限的注解式控制

配置打开注解

Spring Security 支持三套注解:

注解类型 注解
jsr250 注解 @DenyAll、@PermitAll、@RolesAllowed
secured 注解 @Secured
prePost 注解 @PreAuthorize、@PostAuthorize

使用什么注解在@EnableGlobalMethodSecurity开启,默认是关闭的,例如

@EnableWebSecurity
@EnableGlobalMethodSecurity(jsr250Enabled  = true,securedEnabled=true) //开启jsr250和secured注解
public class SecurityConfig extends WebSecurityConfigurerAdapter {
}

实际开发中最常用的写法 使用 @PreAuthorize(“hasRole(‘admin’)”)

登陆认证&权限控制(2)—— 基于Spring security 安全框架的权限管理 & 注解式权限控制 & RABC模型_第16张图片

使用注解控制权限

登陆认证&权限控制(2)—— 基于Spring security 安全框架的权限管理 & 注解式权限控制 & RABC模型_第17张图片

package com.tianju.controller;

import com.baomidou.mybatisplus.extension.api.R;
import com.tianju.entity.GoodType;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/good/type")
public class GoodTypeController {

    @GetMapping
    @PreAuthorize("hasAnyAuthority('/good/query')")
    public String get(Integer id){
        return "查询的方法:"+id;
    }

    @PostMapping
    @PreAuthorize("hasAnyAuthority('/good/add')")
    public String add(GoodType goodType){
        return "新增商品的方法:"+goodType;
    }

    @DeleteMapping
    @PreAuthorize("hasAnyAuthority('/good/del')")
    public String deleteById(Integer id){
        return "删除的方法:"+id;
    }

    @PutMapping
    @PreAuthorize("hasAnyAuthority('/good/update')")
    public String updateById(GoodType goodType){
        return "修改的方法:"+goodType;
    }

}

给不同的用户显示不同的页面

数据库表设计

登陆认证&权限控制(2)—— 基于Spring security 安全框架的权限管理 & 注解式权限控制 & RABC模型_第18张图片

查询语句

SELECT
		aut.username,
		t_menu.id,
		t_menu.name,
		t_menu.link,
		t_menu.parentid,
		t_menu.icon
FROM auth_user_tab AS aut
				 LEFT JOIN t_employee_menu ON aut.id = t_employee_menu.employeeId
				 LEFT JOIN t_menu ON t_employee_menu.menuId = t_menu.id

不同用户显示的效果

admin用户登录

登陆认证&权限控制(2)—— 基于Spring security 安全框架的权限管理 & 注解式权限控制 & RABC模型_第19张图片

peter用户登录

登陆认证&权限控制(2)—— 基于Spring security 安全框架的权限管理 & 注解式权限控制 & RABC模型_第20张图片


总结

1.Spring Security的使用,结合MySQL,Redis实现基于JWT的注解式的权限认证,并且可以实现给不同的用户显示不同的前端页面;
2.项目中的快速应用和使用,拦截器的设置,安全框架的配置;
3.权限表的设计,基于角色的访问控制RABC模型;
4.启动注解的配置,通过注解实现权限的控制;
5.给不同的用户显示不同的页面,相关的SQL以及前端页面;

附录:

1、前端页面

登陆认证&权限控制(2)—— 基于Spring security 安全框架的权限管理 & 注解式权限控制 & RABC模型_第21张图片

<template>
  <el-container style="height: 100%">
    <el-header style="background-color: rgb(249, 195, 195);">

    </el-header>
    <el-container>
      <el-aside width="200px" style="background-color: rgb(241, 241, 202);">
        <el-col width="200px">
          <el-menu
            router
            default-active="2"
            class="el-menu-vertical-demo">
            <el-submenu :index="menu.id+''" 
            v-for="menu in menuList" :key="menu.id+''">
              <template slot="title">
                <i :class="menu.icon"></i>
                <span>{{ menu.name }}</span>
              </template>
                  <el-menu-item :index="cmenu.link" 
                  v-for="cmenu in menu.childrenMenu" :key="cmenu.id+''">
                    {{ cmenu.name }}
                  </el-menu-item>
            </el-submenu>
          </el-menu>
      </el-col>

      </el-aside>
      <el-main style="background-color: rgb(182, 182, 231);">
        <router-view></router-view>
      </el-main>
    </el-container>
  </el-container>

</template>

<script>
  export default{
    data() {
      return {

        // 定义一个数据,菜单从数据中循环出来table tr
        // 找出一级菜单和二级菜单循环体
        menuList:[
          {id:'1',name:'公共模块',icon:'el-icon-menu',
          childrenMenu:[
            {id:'2',name:'调查问卷',link:'/bookList'},
            {id:'3',name:'资料中心',link:'bcd'},
            {id:'4',name:'工资中心',link:'cde'},
          ]},
          {id:'5',name:'业务目标',icon:'el-icon-document',
          childrenMenu:[
            {id:'5',name:'短期目标',link:'def'},
            {id:'6',name:'长期目标',link:'efg'},
          ]},
        ]

      };
    },
    methods: {
      // 查询用户拥有菜单
      queryUserMenu(){
        console.log("findMenu")
        this.$axios.get('/api/menu')
        .then(response=>{
          let resp = response.data
          console.log(resp)
          if (resp.resultCode.code==20000) {
            this.menuList = resp.results

          }
        })
      },
    },
    created(){
      this.queryUserMenu()
    }
    

}
</script>

<style scoped>

</style>

2、MySQL数据库语句

/*
 Navicat Premium Data Transfer

 Source Server         : 127.0.0.1
 Source Server Type    : MySQL
 Source Server Version : 80022
 Source Host           : 127.0.0.1:3306
 Source Schema         : auth_pet

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

 Date: 06/11/2023 15:44:35
*/

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for auth_role_privs_tab
-- ----------------------------
DROP TABLE IF EXISTS `auth_role_privs_tab`;
CREATE TABLE `auth_role_privs_tab`  (
  `rp_id` bigint NOT NULL AUTO_INCREMENT COMMENT '角色权限的中间表relationship',
  `rp_role` bigint NULL DEFAULT NULL COMMENT '对应的是角色id',
  `rp_privs` bigint NULL DEFAULT NULL COMMENT '对应的权限id',
  `created` datetime NULL DEFAULT NULL,
  `updated` datetime NULL DEFAULT NULL,
  `create_by` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
  PRIMARY KEY (`rp_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 17 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of auth_role_privs_tab
-- ----------------------------
INSERT INTO `auth_role_privs_tab` VALUES (1, 1, 1, '2023-08-06 17:26:48', '2023-08-06 17:26:53', 'admin');
INSERT INTO `auth_role_privs_tab` VALUES (2, 1, 2, '2023-08-06 17:27:09', '2023-08-06 17:27:12', 'admin');
INSERT INTO `auth_role_privs_tab` VALUES (3, 1, 3, '2023-08-06 17:28:14', '2023-08-06 17:28:21', 'admin');
INSERT INTO `auth_role_privs_tab` VALUES (4, 1, 4, '2023-08-06 17:28:17', '2023-08-06 17:28:24', 'admin');
INSERT INTO `auth_role_privs_tab` VALUES (5, 1, 5, '2023-08-06 17:28:19', '2023-08-06 17:28:26', 'admin');
INSERT INTO `auth_role_privs_tab` VALUES (6, 1, 6, '2023-10-07 19:32:23', '2023-10-07 19:32:26', 'admin');
INSERT INTO `auth_role_privs_tab` VALUES (7, 1, 7, '2023-10-07 19:32:29', '2023-10-07 19:32:31', 'admin');
INSERT INTO `auth_role_privs_tab` VALUES (8, 2, 1, '2023-10-07 19:53:21', NULL, NULL);
INSERT INTO `auth_role_privs_tab` VALUES (9, 2, 2, '2023-10-07 19:53:25', NULL, NULL);
INSERT INTO `auth_role_privs_tab` VALUES (10, 2, 3, '2023-10-07 19:53:28', NULL, NULL);
INSERT INTO `auth_role_privs_tab` VALUES (11, 2, 4, '2023-10-07 19:53:30', NULL, NULL);
INSERT INTO `auth_role_privs_tab` VALUES (12, 5, 5, NULL, NULL, NULL);
INSERT INTO `auth_role_privs_tab` VALUES (13, 5, 6, NULL, NULL, NULL);
INSERT INTO `auth_role_privs_tab` VALUES (14, 5, 7, NULL, NULL, NULL);
INSERT INTO `auth_role_privs_tab` VALUES (15, 3, NULL, NULL, NULL, NULL);
INSERT INTO `auth_role_privs_tab` VALUES (16, 4, 1, NULL, NULL, NULL);

-- ----------------------------
-- Table structure for auth_role_tab
-- ----------------------------
DROP TABLE IF EXISTS `auth_role_tab`;
CREATE TABLE `auth_role_tab`  (
  `role_id` bigint NOT NULL AUTO_INCREMENT COMMENT '角色的id,角色表',
  `role_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '角色的name',
  `role_note` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '备注一下',
  `state` int NULL DEFAULT NULL COMMENT '状态,0启用,1删除',
  `created` datetime NULL DEFAULT NULL,
  `updated` datetime NULL DEFAULT NULL,
  `create_by` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
  PRIMARY KEY (`role_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 8 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of auth_role_tab
-- ----------------------------
INSERT INTO `auth_role_tab` VALUES (1, '老板Boss', '全部权限', 0, '2023-08-06 17:24:43', '2023-08-06 17:24:46', 'admin');
INSERT INTO `auth_role_tab` VALUES (2, '商品管理员工', '商品相关', 0, '2023-08-06 17:25:03', '2023-08-06 17:25:05', 'admin');
INSERT INTO `auth_role_tab` VALUES (3, '未实名用户', '无任何权限', 0, '2023-08-06 17:25:38', '2023-08-06 17:25:41', 'admin');
INSERT INTO `auth_role_tab` VALUES (4, '普通用户', '商品查询', 0, '2023-10-07 19:49:34', '2023-10-07 19:49:37', 'admin');
INSERT INTO `auth_role_tab` VALUES (5, '人事部门员工', '人事相关', 0, '2023-10-07 19:49:40', '2023-10-07 19:49:41', 'admin');
INSERT INTO `auth_role_tab` VALUES (7, '老板Boss1', NULL, 0, '2023-11-05 22:27:04', '2023-11-05 22:44:52', 'admin');

-- ----------------------------
-- Table structure for auth_role_user_tab
-- ----------------------------
DROP TABLE IF EXISTS `auth_role_user_tab`;
CREATE TABLE `auth_role_user_tab`  (
  `id` int NOT NULL AUTO_INCREMENT COMMENT '角色,用户关联表,用户可能有多个角色',
  `user_id` int NULL DEFAULT NULL COMMENT '用户表的主键id',
  `role_id` int NULL DEFAULT NULL COMMENT '角色表的主键id',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 6 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of auth_role_user_tab
-- ----------------------------
INSERT INTO `auth_role_user_tab` VALUES (1, 1, 1);
INSERT INTO `auth_role_user_tab` VALUES (2, 2, 2);
INSERT INTO `auth_role_user_tab` VALUES (3, 3, 5);
INSERT INTO `auth_role_user_tab` VALUES (4, 4, 4);
INSERT INTO `auth_role_user_tab` VALUES (5, 5, 3);

-- ----------------------------
-- Table structure for auth_tab
-- ----------------------------
DROP TABLE IF EXISTS `auth_tab`;
CREATE TABLE `auth_tab`  (
  `auth_id` int NOT NULL AUTO_INCREMENT COMMENT '权限表的id',
  `auth_name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '权限的名称',
  `auth_url` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '权限的url,安全框架用',
  PRIMARY KEY (`auth_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 8 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of auth_tab
-- ----------------------------
INSERT INTO `auth_tab` VALUES (1, '商品查询', '/good/query');
INSERT INTO `auth_tab` VALUES (2, '商品新增', '/good/add');
INSERT INTO `auth_tab` VALUES (3, '商品删除', '/good/del');
INSERT INTO `auth_tab` VALUES (4, '商品修改', '/good/update');
INSERT INTO `auth_tab` VALUES (5, '员工查询', '/emp/query');
INSERT INTO `auth_tab` VALUES (6, '员工新增', '/emp/add');
INSERT INTO `auth_tab` VALUES (7, '员工开除', '/emp/del');

-- ----------------------------
-- Table structure for auth_user_tab
-- ----------------------------
DROP TABLE IF EXISTS `auth_user_tab`;
CREATE TABLE `auth_user_tab`  (
  `id` int NOT NULL AUTO_INCREMENT,
  `username` varchar(25) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '用户名',
  `realname` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '真实姓名',
  `password` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '密码',
  `tel` varchar(25) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '手机号',
  `gender` varchar(5) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '性别',
  `identity` varchar(25) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '身份证号',
  `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
  `update_time` datetime NULL DEFAULT NULL COMMENT '修改时间',
  `operator` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '操作人',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 6 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of auth_user_tab
-- ----------------------------
INSERT INTO `auth_user_tab` VALUES (1, 'admin', '超级管理', '123', '19800305334', '女', '433123456787', NULL, NULL, NULL);
INSERT INTO `auth_user_tab` VALUES (2, 'peter', '商品管理', '123', '18802229403', '男', '433123456788', NULL, NULL, NULL);
INSERT INTO `auth_user_tab` VALUES (3, 'shirley', '人事管理', '123', NULL, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `auth_user_tab` VALUES (4, 'tom', '普通登陆用户', '123', NULL, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `auth_user_tab` VALUES (5, 'test', '未实名认证', NULL, NULL, NULL, NULL, NULL, NULL, NULL);

-- ----------------------------
-- Table structure for t_employee_menu
-- ----------------------------
DROP TABLE IF EXISTS `t_employee_menu`;
CREATE TABLE `t_employee_menu`  (
  `id_menu` int NOT NULL AUTO_INCREMENT,
  `employeeId` int NULL DEFAULT NULL COMMENT '员工id',
  `menuId` int NULL DEFAULT NULL COMMENT '菜单表id',
  PRIMARY KEY (`id_menu`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 31 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of t_employee_menu
-- ----------------------------
INSERT INTO `t_employee_menu` VALUES (1, 1, 1);
INSERT INTO `t_employee_menu` VALUES (2, 1, 2);
INSERT INTO `t_employee_menu` VALUES (3, 1, 3);
INSERT INTO `t_employee_menu` VALUES (4, 1, 4);
INSERT INTO `t_employee_menu` VALUES (5, 1, 5);
INSERT INTO `t_employee_menu` VALUES (6, 1, 6);
INSERT INTO `t_employee_menu` VALUES (7, 1, 7);
INSERT INTO `t_employee_menu` VALUES (9, 1, 9);
INSERT INTO `t_employee_menu` VALUES (10, 1, 10);
INSERT INTO `t_employee_menu` VALUES (11, 1, 11);
INSERT INTO `t_employee_menu` VALUES (12, 1, 12);
INSERT INTO `t_employee_menu` VALUES (13, 1, 13);
INSERT INTO `t_employee_menu` VALUES (14, 1, 14);
INSERT INTO `t_employee_menu` VALUES (15, 1, 15);
INSERT INTO `t_employee_menu` VALUES (16, 1, 16);
INSERT INTO `t_employee_menu` VALUES (17, 1, 17);
INSERT INTO `t_employee_menu` VALUES (18, 1, 18);
INSERT INTO `t_employee_menu` VALUES (19, 1, 19);
INSERT INTO `t_employee_menu` VALUES (20, 1, 20);
INSERT INTO `t_employee_menu` VALUES (21, 1, 21);
INSERT INTO `t_employee_menu` VALUES (22, 1, 22);
INSERT INTO `t_employee_menu` VALUES (23, 1, 23);
INSERT INTO `t_employee_menu` VALUES (24, 1, 24);
INSERT INTO `t_employee_menu` VALUES (25, 1, 25);
INSERT INTO `t_employee_menu` VALUES (27, 1, 27);
INSERT INTO `t_employee_menu` VALUES (29, 2, 1);
INSERT INTO `t_employee_menu` VALUES (30, 2, 2);

-- ----------------------------
-- Table structure for t_menu
-- ----------------------------
DROP TABLE IF EXISTS `t_menu`;
CREATE TABLE `t_menu`  (
  `id` int NOT NULL AUTO_INCREMENT,
  `name` varchar(15) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '权限名称',
  `link` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '菜单链接',
  `parentid` int NULL DEFAULT NULL COMMENT '父级',
  `status` int NULL DEFAULT NULL COMMENT '1:正常 0:禁用',
  `percode` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '权限编码',
  `icon` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '图标',
  PRIMARY KEY (`id`) USING BTREE,
  INDEX `FK_ParentID`(`parentid`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 29 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of t_menu
-- ----------------------------
INSERT INTO `t_menu` VALUES (1, '系统管理', '', NULL, NULL, NULL, 'el-icon-location');
INSERT INTO `t_menu` VALUES (2, '商品类别', 'goodsType', 1, NULL, NULL, '');
INSERT INTO `t_menu` VALUES (3, '计量单位', 'unit', 1, NULL, NULL, NULL);
INSERT INTO `t_menu` VALUES (4, '仓库管理', 'warehouse', NULL, NULL, NULL, 'el-icon-s-data');
INSERT INTO `t_menu` VALUES (5, '原材料入库', 'rawMaterialList', 4, NULL, NULL, NULL);
INSERT INTO `t_menu` VALUES (6, '原材料领库', 'pickRawList', 4, NULL, NULL, NULL);
INSERT INTO `t_menu` VALUES (7, '订单管理', NULL, NULL, NULL, NULL, 'el-icon-s-tools');
INSERT INTO `t_menu` VALUES (9, '区域管理', 'district', 1, NULL, NULL, NULL);
INSERT INTO `t_menu` VALUES (10, '商品资料', 'goodsList', 1, NULL, NULL, NULL);
INSERT INTO `t_menu` VALUES (11, '供应商资料', 'supplier', 1, NULL, NULL, NULL);
INSERT INTO `t_menu` VALUES (12, '客户资料', 'customer', 1, NULL, NULL, NULL);
INSERT INTO `t_menu` VALUES (13, '仓库管理', 'warehouse', 1, NULL, NULL, NULL);
INSERT INTO `t_menu` VALUES (14, '部门管理', 'department', 1, NULL, NULL, NULL);
INSERT INTO `t_menu` VALUES (15, '员工管理', 'employee', 1, NULL, NULL, NULL);
INSERT INTO `t_menu` VALUES (16, '成品入库', 'finishedPickRaw', 4, NULL, NULL, NULL);
INSERT INTO `t_menu` VALUES (17, '次品入库', 'defectiveGoodsIn', 4, NULL, NULL, NULL);
INSERT INTO `t_menu` VALUES (18, '成品发货', 'finishedGoodsOut', 4, NULL, NULL, NULL);
INSERT INTO `t_menu` VALUES (19, '次品发货', 'defectiveGoodsSend', 4, NULL, NULL, NULL);
INSERT INTO `t_menu` VALUES (20, '财务管理', NULL, NULL, NULL, NULL, 'el-icon-s-data');
INSERT INTO `t_menu` VALUES (21, '应收款管理', 'income', 20, NULL, NULL, NULL);
INSERT INTO `t_menu` VALUES (22, '应付款管理', 'expenses', 20, NULL, NULL, NULL);
INSERT INTO `t_menu` VALUES (23, '数据统计', NULL, NULL, NULL, NULL, 'el-icon-s-data');
INSERT INTO `t_menu` VALUES (24, '仓库报表', 'storeStatistics', 23, NULL, NULL, NULL);
INSERT INTO `t_menu` VALUES (25, '财务报表', 'financialStatistics', 23, NULL, NULL, NULL);
INSERT INTO `t_menu` VALUES (27, '订单查询', 'orderSearch', 7, NULL, NULL, NULL);

SET FOREIGN_KEY_CHECKS = 1;

你可能感兴趣的:(SpringBoot,spring,安全,java)