当前位置:   article > 正文

SpringBoot+SpringSecurity+Vue实现动态权限(一)_springboot + spring security+vue

springboot + spring security+vue

前言

之前都是使用若依框架来实现的动态权限和菜单功能,但是一直想尝试自己来实现动态权限。所以这两天准备整合一下自己的所学知识,依据RBAC权限模型,使用SpringBoot+SpringSecurity+Vue来自己实现一下动态权限。

数据库结构

在数据库设计方面是根据RBAC权限模型来设计的,分别有user(用户)表,role(角色)表,permission(权限)表,user_role(用户角色)表和role_permission(角色权限)表。大致字段如下:
在这里插入图片描述

技术选型

为了方便开发,选择了市面上主流的框架SpringBoot+Vue,安全框架使用SpringSecurity,ORM框架使用MyBatis-Plus。缓存使用Redis。

构建项目

构建一个普通的SpringBoot项目,在pom文件导入以下依赖:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.6.8</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.lyx.autoperm</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>autoperm</name>
    <description>配合SpringSecurity动态权限</description>
    <properties>
        <java.version>1.8</java.version>
        <mysql.version>8.0.28</mysql.version>
        <druid.version>1.2.6</druid.version>
        <mybatisPlus.version>3.5.1</mybatisPlus.version>
        <fastjson.version>1.2.78</fastjson.version>
        <jwt.version>0.9.1</jwt.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!-- Mysql驱动 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>${mysql.version}</version>
        </dependency>

        <!-- DRUID -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>${druid.version}</version>
        </dependency>

        <!-- mybatis-plus -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>${mybatisPlus.version}</version>
        </dependency>

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
            <version>${mybatisPlus.version}</version>
        </dependency>

        <!-- 模板引擎 -->
        <dependency>
            <groupId>org.apache.velocity</groupId>
            <artifactId>velocity-engine-core</artifactId>
            <version>2.0</version>
        </dependency>
        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>2.3.28</version>
            <scope>compile</scope>
        </dependency>
        <!-- fastjson -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>${fastjson.version}</version>
        </dependency>
        <!-- redis -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <!-- Token生成与解析-->
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>${jwt.version}</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113

代码生成

使用mybatisplus生成实体类,controller和service的java文件。

@SpringBootTest
class AutopermApplicationTests {

    @Autowired
    private DruidDataSource dataSource;

    @Test
    void contextLoads() {
        FastAutoGenerator.create(dataSource.getUrl(), dataSource.getUsername(), dataSource.getPassword())
                .globalConfig(builder -> {
                    builder.author("liyongxuan") // 设置作者
                            .enableSwagger() // 开启 swagger 模式
                            .fileOverride() // 覆盖已生成文件
                            .outputDir("D://"); // 指定输出目录
                })
                .packageConfig(builder -> {
                    builder.parent("com.lyx") // 设置父包名
                            .moduleName("autoperm") // 设置父包模块名
                            .entity("entity")
                            .controller("controller")
                            .service("service")
                            .serviceImpl("impl")
                            .pathInfo(Collections.singletonMap(OutputFile.mapper, "E:\\WorkSpace\\autoperm\\src\\main\\java\\com\\lyx\\autoperm\\mapper"))
                            .pathInfo(Collections.singletonMap(OutputFile.entity, "E:\\WorkSpace\\autoperm\\src\\main\\java\\com\\lyx\\autoperm\\entity"))
                            .pathInfo(Collections.singletonMap(OutputFile.service, "E:\\WorkSpace\\autoperm\\src\\main\\java\\com\\lyx\\autoperm\\service"))
                            .pathInfo(Collections.singletonMap(OutputFile.serviceImpl, "E:\\WorkSpace\\autoperm\\src\\main\\java\\com\\lyx\\autoperm\\service\\impl"))
                            .pathInfo(Collections.singletonMap(OutputFile.mapperXml, "E:\\WorkSpace\\autoperm\\src\\main\\resources\\mybatis")); // 设置mapperXml生成路径
                })
                .strategyConfig(builder -> {
                    builder.addInclude("L_ROLE") // 设置需要生成的表名
                            .addInclude("L_USER")
                            .addInclude("L_PERMISSON")
                            .addInclude("L_USER_ROLE")
                            .addInclude("L_ROLE_PERMISSON")
                            .addTablePrefix("L_"); // 设置过滤表前缀
                })
                .templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板,默认的是Velocity引擎模板
                .execute();
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

生成实体类后将User类继承UserDetails,同时继承其方法。我们这里只是用enabled来判断状态,所以isAccountNonExpired、isAccountNonLocked、isCredentialsNonExpired三个方法直接返回true.

@TableName("L_USER")
public class User implements Serializable, UserDetails {

    private static final long serialVersionUID = 1L;

     /**
       * 用户编号
       */
    private String id;

     /**
       * 用户名
       */
    private String username;

     /**
       * 密码
       */
    private String password;

     /**
       * 真实姓名
       */
    private String name;

     /**
       * 年龄
       */
    private String age;

     /**
       * 性别
       */
    private String sex;

     /**
       * 手机号
       */
    private String phone;

     /**
       * 家庭住址
       */
    private String address;

     /**
       * 启用状态
       */
    private Integer enable;

     /**
       * 创建时间
       */
    private String createTime;

    @TableField(exist = false)
    private Set<String> permissions;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

     /**
       * 默认不适用该状态
       */
    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    /**
     * 默认不适用该状态
     */
    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    /**
     * 默认不适用该状态
     */
    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return enable==1?true:false;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return null;
    }

    public void setPermissions(Set<String> permissions) {
        this.permissions = permissions;
    }

    public Set<String> getPermissions() {
        return permissions;
    }

    @Override
    public String getPassword() {
        return password;
    }

    @Override
    public String getUsername() {
        return username;
    }

    public void setPassword(String password) {
        this.password = password;
    }
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    public String getAge() {
        return age;
    }

    public void setAge(String age) {
        this.age = age;
    }
    public Integer getEnable() {
        return enable;
    }

    public void setEnable(Integer enable) {
        this.enable = enable;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public String getCreateTime() {
        return createTime;
    }

    public void setCreateTime(String createTime) {
        this.createTime = createTime;
    }
    
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181

在UserServiceImpl中实现UserDetailsService,SpringSecurity就是调用UserDetailsServiceloadUserByUsername来查询用户信息以及权限列表的。

    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException{
        // 校验用户名密码是否为空
        if(StringUtils.isEmpty(username)) throw new UserException(UserCodeEnum.USERNAME_IS_EMPTY);
        // 查询用户
        User userFromDB = userMapper.selectOne(new QueryWrapper<User>().eq("username", username));
        // 判断用户是否为空或账号不存在
        if(null == userFromDB){
            throw new UsernameNotFoundException("用户不存在");
        }
        // 查询登录用户的权限列表
        Set<String> permissions = permissionMapper.queryPermissions(userFromDB.getId());
        if(!CollectionUtils.isEmpty(permissions)){
            userFromDB.setPermissions(permissions);
        }

        return userFromDB;
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

源码地址

https://github.com/Lyx0912/autopermission

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/article/detail/53910
推荐阅读
相关标签
  

闽ICP备14008679号