shiro-springboot-swagger-mybatisplus整合基于RBAC的权限管理项目

gitee代码地址https://gitee.com/wufanlove/springboot-shiro-swagger-mybatisplus.git

一、具备基础知识

  1. SpringBoot
    要求至少会使用SpringBoot,默认已经掌握Java基础知识。
  2. mybatis
    默认对数据库操作已经熟练,mysql/jdbc已经掌握。
  3. RBAC
    设计思想。

二、整合

(1)、SpringBoot整合swagger

在SpringBoot项目pom.xml文件中引入依赖

		<dependency>
            <groupId>io.springfoxgroupId>
            <artifactId>springfox-swagger2artifactId>
            <version>2.9.2version>
        dependency>
        <dependency>
            <groupId>io.springfoxgroupId>
            <artifactId>springfox-swagger-uiartifactId>
            <version>2.9.2version>
        dependency>

编写SwaggerConfig配置Swagger相关信息

import io.swagger.annotations.Api;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

/**
 * @email: [email protected]
 * @date: 2021/11/11 9:42
 * 功能:
 * 描述:
 * @author: 吴帆
 **/
@Configuration
@EnableSwagger2
public class SwaggerConfig {

    @Bean
    public Docket createRestApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .useDefaultResponseMessages(false)
                .apiInfo(webApiInfo())
                .select()
                .apis(RequestHandlerSelectors.withClassAnnotation(Api.class))
                .paths(PathSelectors.any())
                .build();
    }
    
    private ApiInfo webApiInfo(){
        return new ApiInfoBuilder()
                .title("接口文档")
                .description("开发接口文档")
                .version("1.0")
                .contact(new Contact("我的git地址", "https://gitee.com/wufanlove", "[email protected]"))
                .build();
    }
}

注意:一定要开启@EnableSwagger2注解,apis(RequestHandlerSelectors.withClassAnnotation(Api.class))意思是只要类上面存在@Api注解的类都会被加载到swagger接口文档。

新建Controller测试类测试swagger文档是否生效

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @email: [email protected]
 * @date: 2021/11/11 9:50
 * 功能:
 * 描述:
 * @author: 吴帆
 **/
@Api(tags = "swagger接口测试")
@RestController
@RequestMapping("/swagger")
public class SwaggerTestController {


    @ApiOperation(value = "测试")
    @PostMapping("/test")
    public String test(){
        return "swagger-test-success";
    }
}

访问ip:端口/项目名称/swagger-ui.html地址查看接口文档信息如下则整合成功
shiro-springboot-swagger-mybatisplus整合基于RBAC的权限管理项目_第1张图片

(2)、SpringBoot整合Mybatis-Plus

引入Mybatis-Plus依赖

		<dependency>
            <groupId>com.baomidougroupId>
            <artifactId>mybatis-plus-boot-starterartifactId>
            <version>3.2.0version>
        dependency>

引入数据库驱动

        <dependency>
            <groupId>mysqlgroupId>
            <artifactId>mysql-connector-javaartifactId>
            <scope>runtimescope>
        dependency>

配置数据信息

# 数据库驱动:
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# 数据库连接地址
spring.datasource.url=jdbc:mysql://192.168.147.135:3306/rbac?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&useSSL=true
# 数据库用户名&密码:
spring.datasource.username=root
spring.datasource.password=123456

自行变为自己实际的数据库相关信息
mybatis-plus相关简单配置

#mapper.xml文件存放位置
mybatis-plus.mapper-locations=classpath:/mapper/**/*.xml
#打印sql日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
#开启驼峰命名规则
mybatis-plus.configuration.map-underscore-to-camel-case=true

#逻辑删除
mybatis-plus.global-config.db-config.logic-delete-field=deleted
mybatis-plus.global-config.db-config.logic-delete-value=1
mybatis-plus.global-config.db-config.logic-not-delete-value=0

创建用户表

CREATE TABLE sys_user(
	id BIGINT (15) NOT NULL AUTO_INCREMENT COMMENT '主键',
	user_name VARCHAR (50) NOT NULL DEFAULT '' COMMENT '用户名称',
	pass_word VARCHAR (50) NOT NULL DEFAULT '' COMMENT '密码',
	salt VARCHAR (50) NOT NULL DEFAULT '' COMMENT '加密盐值',
	deleted INT (11) NOT NULL DEFAULT -1 COMMENT '1逻辑已删除值,0逻辑未删除值',
	create_time DATETIME NOT NULL DEFAULT '1000-01-01 00:00:00' COMMENT '创建时间',
	update_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
	PRIMARY KEY (id)
)ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT '用户表';

在SpringBoot项目中针对用户表建SysUser、SysUserMapper、SysUserMapper.xml、SysUserService、SysUserServiceImpl

新建SysUser 实体类

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.io.Serializable;
import java.util.Date;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

  /**
     * @email: [email protected]
     * @date: 2021/11/11 11:30
     * 功能:
     * 描述:
     * @author: 吴帆
     **/

/**
 * 用户表
 */
@ApiModel(value = "com-hetaozi-login-entity-SysUser")
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@TableName(value = "sys_user")
public class SysUser implements Serializable {
    /**
     * 主键
     */
    @TableId(value = "id", type = IdType.AUTO)
    @ApiModelProperty(value = "主键")
    private Long id;

    /**
     * 用户名称
     */
    @TableField(value = "user_name")
    @ApiModelProperty(value = "用户名称")
    private String userName;

    /**
     * 密码
     */
    @TableField(value = "pass_word")
    @ApiModelProperty(value = "密码")
    private String passWord;

    /**
     * 加密盐值
     */
    @TableField(value = "salt")
    @ApiModelProperty(value = "加密盐值")
    private String salt;

    /**
     * 1逻辑已删除值,0逻辑未删除值
     */
    @TableField(value = "deleted")
    @ApiModelProperty(value = "1逻辑已删除值,0逻辑未删除值")
    private Integer deleted;

    /**
     * 创建时间
     */
    @TableField(value = "create_time")
    @ApiModelProperty(value = "创建时间")
    private Date createTime;

    /**
     * 更新时间
     */
    @TableField(value = "update_time")
    @ApiModelProperty(value = "更新时间")
    private Date updateTime;

    private static final long serialVersionUID = 1L;
}

新建SysUserMapper 接口


import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.hetaozi.login.entity.SysUser;
import java.util.List;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

/**
 * @email: [email protected]
 * @date: 2021/11/11 10:43
 * 功能:
 * 描述:
 * @author: 吴帆
 **/
@Mapper
public interface SysUserMapper extends BaseMapper<SysUser> {
    int updateBatch(List<SysUser> list);

    int updateBatchSelective(List<SysUser> list);

    int batchInsert(@Param("list") List<SysUser> list);

    int insertOrUpdate(SysUser record);

    int insertOrUpdateSelective(SysUser record);
}

新建SysUserMapper.xml


DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.hetaozi.login.mapper.SysUserMapper">
  <resultMap id="BaseResultMap" type="com.hetaozi.login.entity.SysUser">
    
    
    <id column="id" jdbcType="BIGINT" property="id" />
    <result column="user_name" jdbcType="VARCHAR" property="userName" />
    <result column="pass_word" jdbcType="VARCHAR" property="passWord" />
    <result column="salt" jdbcType="VARCHAR" property="salt" />
    <result column="deleted" jdbcType="INTEGER" property="deleted" />
    <result column="create_time" jdbcType="TIMESTAMP" property="createTime" />
    <result column="update_time" jdbcType="TIMESTAMP" property="updateTime" />
  resultMap>
  <sql id="Base_Column_List">
    
    id, user_name, pass_word, salt, deleted, create_time, update_time
  sql>
  <update id="updateBatch" parameterType="java.util.List">
    
    update sys_user
    <trim prefix="set" suffixOverrides=",">
      <trim prefix="user_name = case" suffix="end,">
        <foreach collection="list" index="index" item="item">
          when id = #{item.id,jdbcType=BIGINT} then #{item.userName,jdbcType=VARCHAR}
        foreach>
      trim>
      <trim prefix="pass_word = case" suffix="end,">
        <foreach collection="list" index="index" item="item">
          when id = #{item.id,jdbcType=BIGINT} then #{item.passWord,jdbcType=VARCHAR}
        foreach>
      trim>
      <trim prefix="salt = case" suffix="end,">
        <foreach collection="list" index="index" item="item">
          when id = #{item.id,jdbcType=BIGINT} then #{item.salt,jdbcType=VARCHAR}
        foreach>
      trim>
      <trim prefix="deleted = case" suffix="end,">
        <foreach collection="list" index="index" item="item">
          when id = #{item.id,jdbcType=BIGINT} then #{item.deleted,jdbcType=INTEGER}
        foreach>
      trim>
      <trim prefix="create_time = case" suffix="end,">
        <foreach collection="list" index="index" item="item">
          when id = #{item.id,jdbcType=BIGINT} then #{item.createTime,jdbcType=TIMESTAMP}
        foreach>
      trim>
      <trim prefix="update_time = case" suffix="end,">
        <foreach collection="list" index="index" item="item">
          when id = #{item.id,jdbcType=BIGINT} then #{item.updateTime,jdbcType=TIMESTAMP}
        foreach>
      trim>
    trim>
    where id in
    <foreach close=")" collection="list" item="item" open="(" separator=", ">
      #{item.id,jdbcType=BIGINT}
    foreach>
  update>
  <insert id="batchInsert" keyColumn="id" keyProperty="id" parameterType="map" useGeneratedKeys="true">
    
    insert into sys_user
    (user_name, pass_word, salt, deleted, create_time, update_time)
    values
    <foreach collection="list" item="item" separator=",">
      (#{item.userName,jdbcType=VARCHAR}, #{item.passWord,jdbcType=VARCHAR}, #{item.salt,jdbcType=VARCHAR}, 
        #{item.deleted,jdbcType=INTEGER}, #{item.createTime,jdbcType=TIMESTAMP}, #{item.updateTime,jdbcType=TIMESTAMP}
        )
    foreach>
  insert>
  <insert id="insertOrUpdate" keyColumn="id" keyProperty="id" parameterType="com.hetaozi.login.entity.SysUser" useGeneratedKeys="true">
    
    insert into sys_user
    <trim prefix="(" suffix=")" suffixOverrides=",">
      <if test="id != null">
        id,
      if>
      user_name,
      pass_word,
      salt,
      deleted,
      create_time,
      update_time,
    trim>
    values
    <trim prefix="(" suffix=")" suffixOverrides=",">
      <if test="id != null">
        #{id,jdbcType=BIGINT},
      if>
      #{userName,jdbcType=VARCHAR},
      #{passWord,jdbcType=VARCHAR},
      #{salt,jdbcType=VARCHAR},
      #{deleted,jdbcType=INTEGER},
      #{createTime,jdbcType=TIMESTAMP},
      #{updateTime,jdbcType=TIMESTAMP},
    trim>
    on duplicate key update 
    <trim suffixOverrides=",">
      <if test="id != null">
        id = #{id,jdbcType=BIGINT},
      if>
      user_name = #{userName,jdbcType=VARCHAR},
      pass_word = #{passWord,jdbcType=VARCHAR},
      salt = #{salt,jdbcType=VARCHAR},
      deleted = #{deleted,jdbcType=INTEGER},
      create_time = #{createTime,jdbcType=TIMESTAMP},
      update_time = #{updateTime,jdbcType=TIMESTAMP},
    trim>
  insert>
  <insert id="insertOrUpdateSelective" keyColumn="id" keyProperty="id" parameterType="com.hetaozi.login.entity.SysUser" useGeneratedKeys="true">
    
    insert into sys_user
    <trim prefix="(" suffix=")" suffixOverrides=",">
      <if test="id != null">
        id,
      if>
      <if test="userName != null">
        user_name,
      if>
      <if test="passWord != null">
        pass_word,
      if>
      <if test="salt != null">
        salt,
      if>
      <if test="deleted != null">
        deleted,
      if>
      <if test="createTime != null">
        create_time,
      if>
      <if test="updateTime != null">
        update_time,
      if>
    trim>
    values
    <trim prefix="(" suffix=")" suffixOverrides=",">
      <if test="id != null">
        #{id,jdbcType=BIGINT},
      if>
      <if test="userName != null">
        #{userName,jdbcType=VARCHAR},
      if>
      <if test="passWord != null">
        #{passWord,jdbcType=VARCHAR},
      if>
      <if test="salt != null">
        #{salt,jdbcType=VARCHAR},
      if>
      <if test="deleted != null">
        #{deleted,jdbcType=INTEGER},
      if>
      <if test="createTime != null">
        #{createTime,jdbcType=TIMESTAMP},
      if>
      <if test="updateTime != null">
        #{updateTime,jdbcType=TIMESTAMP},
      if>
    trim>
    on duplicate key update 
    <trim suffixOverrides=",">
      <if test="id != null">
        id = #{id,jdbcType=BIGINT},
      if>
      <if test="userName != null">
        user_name = #{userName,jdbcType=VARCHAR},
      if>
      <if test="passWord != null">
        pass_word = #{passWord,jdbcType=VARCHAR},
      if>
      <if test="salt != null">
        salt = #{salt,jdbcType=VARCHAR},
      if>
      <if test="deleted != null">
        deleted = #{deleted,jdbcType=INTEGER},
      if>
      <if test="createTime != null">
        create_time = #{createTime,jdbcType=TIMESTAMP},
      if>
      <if test="updateTime != null">
        update_time = #{updateTime,jdbcType=TIMESTAMP},
      if>
    trim>
  insert>
mapper>

新建SysUserService

import java.util.List;
import com.hetaozi.login.entity.SysUser;
import com.baomidou.mybatisplus.extension.service.IService;
/**
 * @email: [email protected]
 * @date: 2021/11/11 10:43
 * 功能:
 * 描述:
 * @author: 吴帆
 **/
public interface SysUserService extends IService<SysUser>{


    int updateBatch(List<SysUser> list);

    int updateBatchSelective(List<SysUser> list);

    int batchInsert(List<SysUser> list);

    int insertOrUpdate(SysUser record);

    int insertOrUpdateSelective(SysUser record);

}

新建SysUserServiceImpl 继承ServiceImpl,实现SysUserService

import org.springframework.stereotype.Service;
import java.util.List;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hetaozi.login.mapper.SysUserMapper;
import com.hetaozi.login.entity.SysUser;
import com.hetaozi.login.service.SysUserService;
/**
 * @email: [email protected]
 * @date: 2021/11/11 10:43
 * 功能:
 * 描述:
 * @author: 吴帆
 **/
@Service
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements SysUserService{

    @Override
    public int updateBatch(List<SysUser> list) {
        return baseMapper.updateBatch(list);
    }
    @Override
    public int updateBatchSelective(List<SysUser> list) {
        return baseMapper.updateBatchSelective(list);
    }
    @Override
    public int batchInsert(List<SysUser> list) {
        return baseMapper.batchInsert(list);
    }
    @Override
    public int insertOrUpdate(SysUser record) {
        return baseMapper.insertOrUpdate(record);
    }
    @Override
    public int insertOrUpdateSelective(SysUser record) {
        return baseMapper.insertOrUpdateSelective(record);
    }
}

新建测试类测试整合Mybatis-Plus是否成功,检测执行通过及说明整合成功。

package com.hetaozi.login;

import com.hetaozi.login.entity.SysUser;
import com.hetaozi.login.service.SysUserService;
import org.junit.Assert;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.Date;
import java.util.List;

@RunWith(SpringRunner.class)
@SpringBootTest
class SysUserTest {

    @Autowired
    private SysUserService sysUserService;

    @Test
    void saveUserTest() {

        SysUser user = SysUser.builder()
                .userName("admin")
                .passWord("123456")
                .salt("45678")
                .createTime(new Date())
                .updateTime(new Date())
                .build();
        int update = sysUserService.insertOrUpdate(user);

        Assert.assertEquals(1,update);

    }

    @Test
    void sysUserListTest() {

        List<SysUser> list = sysUserService.list();

        Assert.assertNotNull(list);
    }

}

mybatis-plus学习请参照官网https://mp.baomidou.com/,国内网站哟。以上内容提供参考。

(2)、SpringBoot整合shiro

引入依赖

        <dependency>
            <groupId>org.apache.shirogroupId>
            <artifactId>shiro-springartifactId>
            <version>1.4.1version>
        dependency>

此次整合基于RBAC权限管理思想整合,RBAC(Role-Based Access Control),也就是所谓的**“基于角色的访问控制权限”**。
shiro-springboot-swagger-mybatisplus整合基于RBAC的权限管理项目_第2张图片
sys_user用户表、sys_role角色表、sys_permission权限表,及其sys_user_role用户与角色关系表,sys_role_permission角色与权限关系表即可实现简单的基于RBAC登陆授权管理


CREATE DATABASE   IF NOT EXISTS `rbac`  DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;

USE `rbac`;

DROP TABLE IF EXISTS `sys_user`;
CREATE TABLE `sys_user` (
  `id` bigint(15) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `user_name` varchar(50) NOT NULL DEFAULT '' COMMENT '用户名称',
  `pass_word` varchar(50) NOT NULL DEFAULT '' COMMENT '密码',
  `salt` varchar(50) NOT NULL DEFAULT '' COMMENT '加密盐值',
  `deleted` int(5) NOT NULL DEFAULT '0' COMMENT '1逻辑已删除值,0逻辑未删除值',
  `create_time` datetime NOT NULL DEFAULT '1000-01-01 00:00:00' COMMENT '创建时间',
  `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COMMENT='用户表';
insert  into `sys_user`(`id`,`user_name`,`pass_word`,`salt`,`deleted`,`create_time`,`update_time`) values 
(1,'admin','a5ccf40e54bd4b7bedf9a187a127cccc','6hrOEXY35OnYWEC8juIB7A==',0,'2021-11-11 07:10:02','2021-11-11 07:19:48'),
(2,'zhangsan','bae2b0281aefbf09e420088a65054146','18pJfdQaANi4Sg7LRILbEQ==',0,'2021-11-11 08:28:46','2021-11-11 08:29:30');



DROP TABLE IF EXISTS `sys_role`;
CREATE TABLE `sys_role` (
  `id` bigint(15) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `role_name` varchar(50) NOT NULL DEFAULT '' COMMENT '角色名称',
  `sort` int(11) NOT NULL DEFAULT '-1' COMMENT 's排序',
  `create_time` datetime NOT NULL DEFAULT '1000-01-01 00:00:00' COMMENT '创建时间',
  `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'updateTime',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COMMENT='角色';
insert  into `sys_role`(`id`,`role_name`,`sort`,`create_time`,`update_time`) values 
(1,'超级用户',1,'1000-01-01 00:00:00','2021-11-11 08:29:20'),
(2,'普通用户',2,'1000-01-01 00:00:00','2021-11-11 08:29:16');



DROP TABLE IF EXISTS `sys_permission`;
CREATE TABLE `sys_permission` (
  `id` bigint(15) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `permission_name` varchar(50) NOT NULL DEFAULT '' COMMENT '权限',
  `sort` int(11) NOT NULL DEFAULT '-1' COMMENT '排序',
  `create_time` datetime NOT NULL DEFAULT '1000-01-01 00:00:00' COMMENT '创建时间',
  `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'updateTime',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COMMENT='权限';
insert  into `sys_permission`(`id`,`permission_name`,`sort`,`create_time`,`update_time`) values 
(1,'user:add',1,'1000-01-01 00:00:00','2021-11-11 08:29:51'),
(2,'user:update',2,'1000-01-01 00:00:00','2021-11-11 08:29:53'),
(3,'user:list',3,'1000-01-01 00:00:00','2021-11-11 08:29:54');



DROP TABLE IF EXISTS `sys_user_role`;
CREATE TABLE `sys_user_role` (
  `id` bigint(15) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `user_id` bigint(15) NOT NULL DEFAULT '-1' COMMENT '用户id',
  `role_id` bigint(15) NOT NULL DEFAULT '-1' COMMENT '角色id',
  `create_time` datetime NOT NULL DEFAULT '1000-01-01 00:00:00' COMMENT '创建时间',
  `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'updateTime',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COMMENT='用户角色关联表';
insert  into `sys_user_role`(`id`,`user_id`,`role_id`,`create_time`,`update_time`) values 
(1,1,1,'1000-01-01 00:00:00','2021-11-11 08:14:30'),
(2,2,2,'1000-01-01 00:00:00','2021-11-11 08:29:42');


DROP TABLE IF EXISTS `sys_role_permission`;
CREATE TABLE `sys_role_permission` (
  `id` bigint(15) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `role_id` bigint(15) NOT NULL DEFAULT '-1' COMMENT '角色id',
  `permission_id` bigint(15) NOT NULL DEFAULT '-1' COMMENT '权限id',
  `create_time` datetime NOT NULL DEFAULT '1000-01-01 00:00:00' COMMENT '创建时间',
  `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'updateTime',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COMMENT='角色权限关联表';
insert  into `sys_role_permission`(`id`,`role_id`,`permission_id`,`create_time`,`update_time`) values 
(1,1,1,'1000-01-01 00:00:00','2021-11-11 08:15:21'),
(2,1,2,'1000-01-01 00:00:00','2021-11-11 08:15:25'),
(3,1,3,'1000-01-01 00:00:00','2021-11-11 08:15:32'),
(4,2,3,'1000-01-01 00:00:00','2021-11-11 08:30:08');


执行上面sql语句,并新建对应的entity、mapper、service如下相关数据。
shiro-springboot-swagger-mybatisplus整合基于RBAC的权限管理项目_第3张图片

  • UserRealm新建

import com.hetaozi.login.entity.SysUser;
import com.hetaozi.login.service.SysUserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.Set;

/**
 * @email: [email protected]
 * @date: 2021/11/11 14:20
 * 功能:
 * 描述:
 * @author: 吴帆
 **/
@Slf4j
public class UserRealm  extends AuthorizingRealm {

    @Autowired
    private SysUserService sysUserService;

    /**
     * 授权认证
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        log.info("授权认证...");
        SysUser user = (SysUser) SecurityUtils.getSubject().getPrincipal();
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();

        // 角色
        Set<String> roles = user.getRoles();
        //权限
        Set<String> permissions =user.getPermissions();

        authorizationInfo.setRoles(roles);
        authorizationInfo.setStringPermissions(permissions);
        return authorizationInfo;
    }


    /**
     * 登陆认证
     * @param authenticationToken
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        log.info("登陆认证...");
        String username = (String) authenticationToken.getPrincipal();
		
		//更具用户名称查询用户信息,在这这查询时可以塞入用户拥有的角色集合,权限集合,菜单等
        SysUser user = sysUserService.getUserByUserName(username);

        if (user == null) {
            // 账号不存在
            throw new UnknownAccountException();
        }

        String salt = user.getSalt();
        return new SimpleAuthenticationInfo(user,
                user.getPassWord(),
                ByteSource.Util.bytes(salt),
                getName());
    }
}

  • ShiroConfig的相关配置

import java.util.LinkedHashMap;
import java.util.Map;

import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;

/**
 * @author 260497
 */
@Configuration
public class ShiroConfig {


    @Bean
    public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {

        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);

        //拦截器.
        Map<String,String> filterMap = new LinkedHashMap<>();
        filterMap.put("/system/login", "anon");
        //放开swagger相关请求,否则swagger不能访问
        filterMap.put("/swagger-ui.html", "anon");
        filterMap.put("/swagger-resources", "anon");
        filterMap.put("/swagger-resources/configuration/security", "anon");
        filterMap.put("/swagger-resources/configuration/ui", "anon");
        filterMap.put("/v2/api-docs", "anon");
        filterMap.put("/webjars/springfox-swagger-ui/**", "anon");
        filterMap.put("/**", "authc");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
        return shiroFilterFactoryBean;
    }

	//此处的加密规则必须和存入数据库的密码加密规则一至
    @Bean
    public HashedCredentialsMatcher hashedCredentialsMatcher(){
        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
        //设置加密算法
        hashedCredentialsMatcher.setHashAlgorithmName("md5");
        //设置加密的次数
        hashedCredentialsMatcher.setHashIterations(5);
        return hashedCredentialsMatcher;
    }

    @Bean
    public UserRealm userRealm(){
        UserRealm userRealm = new UserRealm();
        //存入登陆验证时使用的加密算法
        userRealm.setCredentialsMatcher(hashedCredentialsMatcher());
        return userRealm;
    }


    @Bean
    public SecurityManager securityManager(){
        DefaultWebSecurityManager securityManager =  new DefaultWebSecurityManager();
        securityManager.setRealm(userRealm());
        return securityManager;
    }



    /**
     *  开启shiro aop注解支持.
     *  使用代理方式;所以需要开启代码支持;
     * @param securityManager
     * @return
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(@Qualifier("securityManager") SecurityManager securityManager){
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }


    @Bean("lifecycleBeanPostProcessor")
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }


    @Bean
    @DependsOn({"lifecycleBeanPostProcessor"})
    public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        advisorAutoProxyCreator.setProxyTargetClass(true);
        return advisorAutoProxyCreator;
    }

}
  • 登陆相关异常处理
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.authz.UnauthorizedException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * @author 260497
 */
@Slf4j
@ControllerAdvice
public class MyLoginException {

    @ResponseBody
    @ExceptionHandler(UnauthorizedException.class)
    public String handleShiroException(Exception ex) {
        return "没有权限";
    }

    @ResponseBody
    @ExceptionHandler(AuthorizationException.class)
    public String AuthorizationException(Exception ex) {
        log.error("登陆认证失败,失败信息:",ex);
        return "认证失败";
    }
}
  • 登陆相关接口Controller

/**
 * @email: [email protected]
 * @date: 2021/11/11 14:57
 * 功能:
 * 描述:
 * @author: 吴帆
 **/
@RestController
@Api(tags = "系统登陆相关接口")
@RequestMapping("/system")
public class LoginController {

    @ApiOperation(value = "登陆")
    @PostMapping("login")
    public String login(String userName, String passWord){
        if ("".equals(userName.trim()) || "".equals(passWord.trim())) {
            return "账号或密码不能为空";
        }
        try {
            UsernamePasswordToken token = new UsernamePasswordToken(userName, passWord);
            Subject subject = SecurityUtils.getSubject();
            subject.login(token);

            // 处理菜单

            return "登录成功";
        } catch (IncorrectCredentialsException ice) {
            return "密码错误";
        } catch (UnknownAccountException uae) {
            return "账号不存在";
        } catch (LockedAccountException e) {
            return "账号被锁定";
        } catch (ExcessiveAttemptsException eae) {
            return "操作频繁,请稍后再试";
        }
    }


    @ApiOperation(value = "登出")
    @GetMapping("loginOut")
    public String loginOut(){
        Subject subject = SecurityUtils.getSubject();
        subject.logout();
        return "登出";
    }

}

  • 测试登陆认证
    使用postman或直接访问swagger测试登陆
    系统目前数据库初始化了用户admin(密码123456)拥有角色超级用户,超级管理员拥有权限user:add、user:list、user:update
    初始化了用户zhangsan(密码123456)拥有角色普通用户,普通用户拥有权限user:list。
    shiro-springboot-swagger-mybatisplus整合基于RBAC的权限管理项目_第4张图片
    登陆成功,说明登陆授权配置正确。

  • 测试权限授权
    新建UserController类测试授权


import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @email: [email protected]
 * @date: 2021/11/11 15:21
 * 功能:
 * 描述:
 * @author: 吴帆
 **/
@Api(tags = "用户接口")
@RestController
@RequestMapping("/user")
public class UserController {


    @ApiOperation(value = "新增用户")
    @RequiresPermissions(value = "user:add")
    @PostMapping("/add")
    public String add(){
        return "新增用户成功!";
    }

    @ApiOperation(value = "修改用户")
    @RequiresPermissions(value = "user:update")
    @PostMapping("/update")
    public String update(){
        return "修改用户";
    }

    @ApiOperation(value = "用户列表查询")
    @RequiresPermissions(value = "user:list")
    @PostMapping("/list")
    public String list(){
        return "用户列表查询";
    }

    @ApiOperation(value = "超级用户测试没有权限")
    @RequiresPermissions(value = "user:unPermission")
    @PostMapping("/unPermission")
    public String unPermission(){
        return "505";
    }
}

使用admin登陆分别访问
127.0.0.1:8080/user/add
127.0.0.1:8080/user/update
127.0.0.1:8080/user/list
均能正常访问
shiro-springboot-swagger-mybatisplus整合基于RBAC的权限管理项目_第5张图片
访问127.0.0.1:8080/user/unPermission提示没有权限,说明权限配置没有问题
shiro-springboot-swagger-mybatisplus整合基于RBAC的权限管理项目_第6张图片

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