shiro、springboot、vue、elementUI CDN模式前后端分离的权限管理demo 附源码

news2024/11/26 2:56:54

shiro、springboot、vue、elementUI CDN模式前后端分离的权限管理demo 附源码

源码下载地址

https://github.com/Aizhuxueliang/springboot_shiro.git
open

前提你电脑的安装好这些工具:jdk8、idea、maven、git、mysql

shiro的主要概念

  1. Shiro是一个强大的简单易用的Java安全框架,主要用来更便捷的认证、授权、加密、会话管理、与Web集成、缓存等;
  2. Shiro使用起来小而简单;
  3. spring中有spring security ,是一个权限框架,它和spring依赖过于紧密,没有shiro使用简单;
  4. shiro不依赖于spring,shiro不仅可以实现web应用的权限管理,还可以实现c/s系统,分布式系统权限管理;

在应用程序角度来观察如何使用Shiro完成工作

subject

Subject:主体,代表了当前“用户”,这个用户不一定是一个具体的人,与当前应用交互的任何东西都是Subject,如网络爬虫,机器人等;即一个抽象概念;所有Subject 都绑定到SecurityManager,与Subject的所有交互都会委托给SecurityManager;可以把Subject认为是一个门面;SecurityManager才是实际的执行者;

SecurityManager:安全管理器;即所有与安全有关的操作都会与SecurityManager 交互;且它管理着所有Subject;可以看出它是Shiro 的核心,它负责与后边介绍的其他组件进行交互,如果学习过SpringMVC,你可以把它看成DispatcherServlet前端控制器;

Realm:域,Shiro从从Realm获取安全数据(如用户、角色、权限),就是说SecurityManager要验证用户身份,那么它需要从Realm获取相应的用户进行比较以确定用户身份是否合法;也需要从Realm得到用户相应的角色/权限进行验证用户是否能进行操作;可以把Realm看成DataSource,即安全数据源。

shiro官方文档

https://shiro.apache.org/architecture.html

前端CDN的方式使用elementUI、vue、vue-router、axios画页面

CDN(内容分发网络)本身是指一种请求资源的方式。说白了就是在本地,通过script头去请求对应的脚本资源的一种方式。我在这里要说的就是直接引用 (demo是直接引用的,注意电脑联网)或者下载Vue.js和elementUI.js放在本地,进行项目开发的方式。而不是通过npm包管理工具去下载vue包。

cdn方式引入elementui 官方API:https://element.eleme.cn/#/zh-CN/component/installation
在这里插入图片描述
cdn方式引入vue-router官方API:https://router.vuejs.org/zh/guide/#html
router

DEMO的整体流程设计

技术层面了解完就该设计业务流程了,如图:
process

demo整体结构

如图:
struct

主要功能页面

1、登录
login

2、用户查询
query_user

3、分配角色
allot_role

4、删除角色
remove_role

5、新建用户
create_user
create_user_1

6、分配权限
allot_permission

7、新建角色
create_role

主要代码

com/example/demo/controller/UserCtrl.java

package com.example.demo.controller;

import com.example.demo.entity.Role;
import com.example.demo.entity.User;
import com.example.demo.service.UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.Map;

/**
 * 控制层
 */
@RestController
@RequestMapping("/user")
public class UserCtrl {

    @Autowired
    private UserService userService;

    /**
     * 登录接口
     *
     * @param user user
     * @return resultMap
     */
    @RequestMapping(value = "/login", method = RequestMethod.POST)
    public Map<String, Object> login(@RequestBody User user) {
        //拿到主体
        Subject subject = SecurityUtils.getSubject();
        try {
            UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(user.getUsername(), user.getPassword());
            subject.login(usernamePasswordToken);
            Object permissions = subject.getSession().getAttribute("permissions");
            subject.getSession().removeAttribute("permissions");
            return userService.resultMap("permissions", permissions, "token",  subject.getSession().getId(), "", "");
        }catch (Exception e){
            e.printStackTrace();
            return userService.resultMap("error", e.getMessage(), "",  "", "", "");
        }
    }

    /**
     * 获取用户的角色类型
     *
     * @param user user
     * @return resultMap
     */
    @RequestMapping(value = "/findRoleListByUserId", method = RequestMethod.POST)
    public Map<String, Object> findRoleListByUserId(@RequestBody User user) {
        try{
            return userService.findRoleListByUserId(user.getId());
        }catch (Exception e){
            e.printStackTrace();
            return userService.resultMap("error", e.getMessage(), "",  "", "", "");
        }
    }

    /**
     * 获取角色的权限类型
     *
     * @param role role
     * @return resultMap
     */
    @RequestMapping(value = "/findPermissionListByRoleId", method = RequestMethod.POST)
    public Map<String, Object> findPermissionListByRoleId(@RequestBody Role role) {
        try{
            return userService.findPermissionListByRoleId(role.getId());
        }catch (Exception e){
            e.printStackTrace();
            return userService.resultMap("error", e.getMessage(), "",  "", "", "");
        }
    }

    /**
     * 更新角色具有的权限
     *
     * @param role role
     * @return resultMap
     */
    @RequestMapping(value = "/updateRolePermission", method = RequestMethod.POST)
    public Map<String, Object> updateRolePermission(@RequestBody Role role) {
        try{
            return userService.updateRolePermission(role);
        }catch (Exception e){
            e.printStackTrace();
            return userService.resultMap("error", e.getMessage(), "",  "", "", "");
        }
    }

    /**
     * 删除角色
     *
     * @param role role
     * @return resultMap
     */
    @RequestMapping(value = "/removeRole", method = RequestMethod.POST)
    public Map<String, Object> removeRole(@RequestBody Role role) {
        try{
            return userService.removeRole(role);
        }catch (Exception e){
            e.printStackTrace();
            return userService.resultMap("error", e.getMessage(), "",  "", "", "");
        }
    }

    /**
     * 添加角色
     *
     * @param role role
     * @return resultMap
     */
    @RequestMapping(value = "/addRole", method = RequestMethod.POST)
    public Map<String, Object> addRole(@RequestBody Role role) {
        try{
            return userService.addRole(role);
        }catch (Exception e){
            e.printStackTrace();
            return userService.resultMap("error", e.getMessage(), "",  "", "", "");
        }
    }

    /**
     * 更新用户具有的角色
     *
     * @param user user
     * @return resultMap
     */
    @RequestMapping(value = "/updateUserRole", method = RequestMethod.POST)
    public Map<String, Object> updateUserRole(@RequestBody User user) {
        try{
            return userService.updateUserRole(user);
        }catch (Exception e){
            e.printStackTrace();
            return userService.resultMap("error", e.getMessage(), "",  "", "", "");
        }
    }

    /**
     * 根据用户提供的条件分页查询用户
     *
     * @param user user
     * @return resultMap
     */
    @RequestMapping(value = "/queryUserListPage", method = RequestMethod.POST)
    public Map<String, Object> queryUserListPage(@RequestBody User user) {
        try{
            return userService.queryUserListPage(user);
        }catch (Exception e){
            e.printStackTrace();
            return userService.resultMap("error", e.getMessage(), "",  "", "", "");
        }
    }

    /**
     * 删除用户
     *
     * @param user user
     * @return resultMap
     */
    @RequestMapping(value = "/removeUser", method = RequestMethod.POST)
    public Map<String, Object> removeUser(@RequestBody User user) {
        try{
            return userService.removeUser(user);
        }catch (Exception e){
            e.printStackTrace();
            return userService.resultMap("error", e.getMessage(), "",  "", "", "");
        }
    }

    /**
     * 新增用户
     *
     * @param user user
     * @return resultMap
     */
    @RequestMapping(value = "/insertUser", method = RequestMethod.POST)
    public Map<String, Object> insertUser(@RequestBody User user) {
        try{
            return userService.insertUser(user);
        }catch (Exception e){
            e.printStackTrace();
            return userService.resultMap("error", e.getMessage(), "",  "", "", "");
        }
    }

}

com/example/demo/service/UserService.java

package com.example.demo.service;

import com.example.demo.entity.Permission;
import com.example.demo.entity.Role;
import com.example.demo.entity.User;
import com.example.demo.mapper.PermissionMapper;
import com.example.demo.mapper.UserMapper;
import com.example.demo.mapper.RoleMapper;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 服务层
 */
@Service
public class UserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private RoleMapper roleMapper;

    @Autowired
    private PermissionMapper permissionMapper;

    public User findUserByName(String userName) {
        User user = userMapper.findUserByName(userName);
        //用户角色的集合
        List<Role> roleList = roleMapper.findRoleListByUserId(user.getId());
        user.setRoleList(roleList);
        return user;
    }

    public Map<String, Object> findRoleListByUserId(int userId){
        //用戶具有的角色集合
        List<Role> beRoleList = roleMapper.findRoleListByUserIdNotPermission(userId);
        //用戶没有的角色集合
        List<Role> notRoleList = roleMapper.findNotRoleListByUserIdNotPermission(userId);
        //所有角色集合
        Collection<?> allRoleList = CollectionUtils.union(beRoleList, notRoleList);
        return this.resultMap("beRoleList", beRoleList, "notRoleList", notRoleList, "allRoleList", allRoleList);
    }

    @Transactional(rollbackFor = {Exception.class})
    public Map<String, Object> updateUserRole(User user){
        int removeUserRole = userMapper.removeUserRoleByUserId(user.getId());
        int addUserRole = 0;
        if (user.getRoleList().size()!=0 && user.getRoleList()!=null){
            addUserRole = userMapper.addUserRole(user);
        }
        return this.resultMap("removeUserRole", removeUserRole, "addUserRole", addUserRole, "", "");
    }

    public Map<String, Object> findPermissionListByRoleId(int roleId){
        //角色具有的权限集合
        List<Permission> bePermissionList = permissionMapper.findByPermissionListByRoleId(roleId);
        //角色没有的权限集合
        List<Permission> notPermissionList = permissionMapper.findNotPermissionListByRoleId(roleId);
        //所有权限集合
        Collection<?> allPermissionList = CollectionUtils.union(bePermissionList, notPermissionList);
        return this.resultMap("bePermissionList", bePermissionList, "notPermissionList", notPermissionList, "allPermissionList", allPermissionList);
    }

    @Transactional(rollbackFor = {Exception.class})
    public Map<String, Object> updateRolePermission(Role role){
        int removeRolePermission = roleMapper.removeRolePermissionByRoleId(role.getId());
        int addRolePermission = 0;
        if (role.getPermissionList().size()!=0 && role.getPermissionList()!=null){
            addRolePermission = roleMapper.addRolePermission(role);
        }
        return this.resultMap("removeRolePermission", removeRolePermission, "addRolePermission", addRolePermission, "", "");
    }

    @Transactional(rollbackFor = {Exception.class})
    public Map<String, Object> removeRole(Role role){
        int removeRolePermission = roleMapper.removeRolePermissionByRoleId(role.getId());
        int removeRole = roleMapper.removeRoleByRoleId(role.getId());
        int removeUserRole = userMapper.removeUserRoleByRoleId(role.getId());
        return this.resultMap("removeRolePermission", removeRolePermission, "removeRole", removeRole, "removeUserRole", removeUserRole);
    }

    public Map<String, Object> queryUserListPage(User user){
        //当前页页码
        int pageNow = user.getReserve1() < 1 ? 1 : user.getReserve1();
        //当前页第一行索引
        user.setReserve1(5*(pageNow - 1));
        List<User> userListPage = userMapper.queryUserListPage(user);
        int userRowCount = userMapper.getUserRowCount(user);
        return this.resultMap("userListPage", userListPage, "userRowCount",  userRowCount, "", "");
    }

    public Map<String, Object> addRole(Role role){
        int addRole = roleMapper.addRole(role);
        return this.resultMap("addRole", addRole, "",  "", "", "");
    }

    @Transactional(rollbackFor = {Exception.class})
    public Map<String, Object> removeUser(User user){
        int removeUser = userMapper.removeUserByUserId(user.getId());
        int removeUserRole = userMapper.removeUserRoleByUserId(user.getId());
        return this.resultMap("removeUser", removeUser, "removeUserRole", removeUserRole, "", "");
    }

    public Map<String, Object> insertUser(User user) {
        int addUser = userMapper.insertUser(user);
        return this.resultMap("addUser", addUser, "", "", "", "");
    }

    public Map<String, Object> resultMap(String str1, Object obj1, String str2, Object obj2, String str3, Object obj3){
        Map<String, Object> resultMap = new HashMap<>();
        if (!"".equals(str1) || !"".equals(obj1))
            resultMap.put(str1, obj1);
        if (!"".equals(str2) || !"".equals(obj2))
            resultMap.put(str2, obj2);
        if (!"".equals(str3) || !"".equals(obj3))
            resultMap.put(str3, obj3);
        return resultMap;
    }

}

CDN模式下的vue、vue-router、template模板挂载操作

参考:src/main/resources/static/index.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <!-- import CSS -->
    <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
</head>
<body>
<div id="app">
    <router-view></router-view>
</div>
<template id="sign">
    <div class="handle">
        <div class="handle-input">
            <div class="high70">
                <span>用户名称:</span>
                <el-input
                        v-model="username"
                        placeholder="请输入用户名称"
                        clearable></el-input>
            </div>
            <div class="high70">
                <span>密码:</span>
                <el-input
                        v-model="password"
                        placeholder="请输入密码"
                        clearable
                        show-password></el-input>
            </div>
            <el-button @click="login" plain>登录</el-button>
        </div>
    </div>
</template>
<template id="manager">
    <el-tabs :tab-position="tabPosition">
        <el-tab-pane label="用户设置" v-if="permissionsFlag.query_user || permissionsFlag.add_user || permissionsFlag.allot_roles || permissionsFlag.remove_user">
            <el-row type="flex" justify="center">
                <el-col :span="18">
                    <div class="handle-area">
                        <div class="demo-input" v-show="permissionsFlag.query_user || permissionsFlag.add_user || permissionsFlag.allot_roles || permissionsFlag.remove_user">
                            <span>用户ID:</span>
                            <el-input
                                    v-model="id"
                                    placeholder="请输入用户ID"
                                    type="number"
                                    size="medium"
                                    clearable></el-input>
                            <span>用户名称:</span>
                            <el-input
                                    v-model="username"
                                    placeholder="请输入用户名称"
                                    size="medium"
                                    clearable></el-input>
                            <el-button
                                    :plain="true"
                                    @click="queryUserList"
                                    icon="el-icon-search"
                                    size="medium">查询用户</el-button>
                        </div>
                        <el-button
                                v-show="permissionsFlag.add_user"
                                :plain="true"
                                @click="handleAddUser"
                                icon="el-icon-user"
                                size="medium">新建用户</el-button>
                    </div>
                    <el-table
                            :data="tableData"
                            border
                            highlight-current-row>
                        <el-table-column
                                prop="id"
                                label="用户ID">
                        </el-table-column>
                        <el-table-column
                                prop="username"
                                label="用户名称">
                        </el-table-column>
                        <el-table-column
                                label="操作">
                            <template slot-scope="scope">
                                <el-button
                                        v-show="permissionsFlag.allot_roles"
                                        type="text"
                                        icon="el-icon-set-up"
                                        @click="handleEditUser(scope.$index, scope.row)">分配角色
                                </el-button>
                                <el-button
                                        v-show="permissionsFlag.remove_user"
                                        type="text"
                                        icon="el-icon-remove-outline"
                                        @click="handleDeleteUser(scope.$index, scope.row)">删除用户
                                </el-button>
                            </template>
                        </el-table-column>
                    </el-table>
                    <el-pagination
                            layout="total, prev, pager, next, jumper"
                            :total="userRowCount"
                            :page-size="5"
                            :current-page.sync="currentPage"
                            @current-change="queryUserListPage"
                            :hide-on-single-page="hidePageFlag"
                            background>
                    </el-pagination>
                </el-col>
            </el-row>
            <el-dialog :title="roleTitle" :visible.sync="dialogEditUser" :before-close="handleClose">
                <el-transfer
                        v-model="transferValue"
                        :data="transferData"
                        :titles="['待分配角色', '已分配角色']">
                </el-transfer>
                <span slot="footer" class="dialog-footer">
			        <el-button @click="handleClose">取 消</el-button>
			        <el-button type="primary" @click="assignRoles">确 定</el-button>
		        </span>
            </el-dialog>
            <el-dialog title="新建用户" :visible.sync="dialogAddUser" :before-close="handleClose">
                <div class="high70">
                    <span>用户名称:</span>
                    <el-input
                            v-model="username"
                            placeholder="请输入用户名称"
                            size="medium"
                            clearable></el-input>
                </div>
                <div class="high70">
                    <span>密码:</span>
                    <el-input
                            v-model="password"
                            placeholder="请输入密码"
                            size="medium"
                            clearable
                            show-password></el-input>
                </div>
                <div class="high70">
                    <span>再次输入密码:</span>
                    <el-input
                            v-model="password1"
                            placeholder="请再次输入密码"
                            size="medium"
                            show-password></el-input>
                </div>
                <div class="high70">
                    <span>备注:</span>
                    <el-input
                            v-model="reserve"
                            placeholder="请输入用户备注"
                            size="medium"></el-input>
                </div>
                <span slot="footer" class="dialog-footer">
			        <el-button @click="handleClose">取 消</el-button>
			        <el-button type="primary" @click="insertUser">确 定</el-button>
		        </span>
            </el-dialog>
        </el-tab-pane>

        <el-tab-pane label="角色设置" v-if="permissionsFlag.allot_roles || permissionsFlag.query_role || permissionsFlag.add_role || permissionsFlag.remove_role || permissionsFlag.allot_permission">
            <el-row type="flex" justify="center">
                <el-col :span="18">
                    <div class="handle-area">
                        <el-button
                                v-show="permissionsFlag.allot_roles || permissionsFlag.query_role || permissionsFlag.add_role || permissionsFlag.remove_role || permissionsFlag.allot_permission"
                                :plain="true"
                                @click="queryRoleList"
                                icon="el-icon-search"
                                size="medium">角色查询</el-button>
                        <el-button
                                v-show="permissionsFlag.add_role"
                                :plain="true"
                                @click="handleAddRole"
                                icon="el-icon-circle-plus-outline"
                                size="medium">新建角色</el-button>
                    </div>
                    <el-table
                            :data="roleData"
                            border
                            highlight-current-row>
                        <el-table-column
                                prop="id"
                                label="角色ID">
                        </el-table-column>
                        <el-table-column
                                prop="name"
                                label="角色名称">
                        </el-table-column>
                        <el-table-column
                                prop="description"
                                label="角色描述">
                        </el-table-column>
                        <el-table-column
                                label="操作">
                            <template slot-scope="scope">
                                <el-button
                                        v-show="permissionsFlag.allot_permission"
                                        type="text"
                                        icon="el-icon-s-operation"
                                        @click="handleEditRole(scope.$index, scope.row)">分配权限
                                </el-button>
                                <el-button
                                        v-show="permissionsFlag.remove_role"
                                        type="text"
                                        icon="el-icon-remove-outline"
                                        @click="handleDeleteRole(scope.$index, scope.row)">删除角色
                                </el-button>
                            </template>
                        </el-table-column>
                    </el-table>
                </el-col>
            </el-row>
            <el-dialog :title="permissionsTitle" :visible.sync="dialogEditRole" :before-close="handleClose">
                <el-checkbox-group v-model="checkedPermissions" class="el-checkbox-group-dialog">
                    <el-checkbox v-for="permission in permissions" :label="permission.name" :key="permission.name">{{permission.description}}</el-checkbox>
                </el-checkbox-group>
                <span slot="footer" class="dialog-footer">
			        <el-button @click="handleClose">取 消</el-button>
			        <el-button type="primary" @click="assignPermissions">确 定</el-button>
		        </span>
            </el-dialog>
            <el-dialog title="新建角色" :visible.sync="dialogAddRole" :before-close="handleClose">
                <div class="high70">
                    <span>角色名称:</span>
                    <el-input
                            v-model="name"
                            placeholder="请输入角色名称"
                            size="medium"></el-input>
                </div>
                <div class="high70">
                    <span>角色描述:</span>
                    <el-input
                            v-model="description"
                            placeholder="请输入角色描述"
                            size="medium"></el-input>
                </div>
                <span slot="footer" class="dialog-footer">
			        <el-button @click="handleClose">取 消</el-button>
			        <el-button type="primary" @click="insertRole">确 定</el-button>
		        </span>
            </el-dialog>
        </el-tab-pane>

        <el-tab-pane label="权限列表" v-if="permissionsFlag.allot_permission">
            <el-row type="flex" justify="center">
                <el-col :span="18">
                    <div class="handle-area">
                        <el-button
                                v-show="permissionsFlag.allot_permission"
                                :plain="true"
                                @click="queryPermissionList"
                                icon="el-icon-search"
                                size="medium">权限查询</el-button>
                    </div>
                    <el-table
                            :data="permissionData"
                            border
                            highlight-current-row>
                        <el-table-column
                                prop="id"
                                label="权限ID">
                        </el-table-column>
                        <el-table-column
                                prop="name"
                                label="权限名称">
                        </el-table-column>
                        <el-table-column
                                prop="description"
                                label="权限描述">
                        </el-table-column>
                    </el-table>
                </el-col>
            </el-row>
        </el-tab-pane>
    </el-tabs>
</template>
</body>
<!-- import Vue before Element -->
<script src="https://unpkg.com/vue@2/dist/vue.js"></script>
<!-- import JavaScript -->
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
<!-- import Axios -->
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<!-- import Router -->
<script src="https://cdn.staticfile.org/vue-router/2.7.0/vue-router.min.js"></script>
<script>
    const Sign = {
        props: ['todo'],
        template: '#sign',
        data() {
            return {
                username: '',
                password: '',
                permissionsStr: [],
                token: ''
            }
        },
        methods: {
            login() {
                axios.defaults.headers.post['Content-Type'] = 'application/json;charset=UTF-8';
                axios({
                    method: 'post',
                    url: '/user/login',
                    data: JSON.stringify({
                        username: this.username,
                        password: this.password
                    })
                }).then(response => {
                    if(typeof response.data.error !== 'undefined' || response.data.error != null){
                        this.username = '';
                        this.password = '';
                        ELEMENT.Notification.error({
                            title: '登录失败!',
                            message: response.data.error,
                            position: 'top-right',
                            showClose: false,
                            offset: 110
                        });
                        return;
                    }
                    this.permissionsStr = response.data.permissions;
                    this.token = response.data.token;
                    this.$router.push({
                        name: 'manager',
                        params: {
                            token: this.token,
                            permissionsStr: this.permissionsStr
                        }
                    });
                }).catch(error => {
                    console.log(error);
                    ELEMENT.Message(error);
                });
            }
        },
        mounted() {
            console.log('组件Sign被挂载了');
        }
    };
    const Manager = {
        // todo-item 组件现在接受一个
        // "prop",类似于一个自定义 attribute。
        // 这个 prop 名为 todo。
        props: ['todo'],
        template: '#manager',
        data() {
            return {
                // 角色信息
                roleData: [],
                roleId: null,
                name: '',
                description: '',
                dialogEditRole: false,
                dialogAddRole: false,
                permissions: [],
                checkedPermissions: [],
                permissionList: [],
                permissionsTitle: '',
                // 权限信息
                permissionData: [],
                // 穿梭框
                transferValue: [],
                transferData: [],
                // 表格及分页
                tableData: [],
                tabPosition: 'top',
                userRowCount: 0,
                currentPage: 0,
                hidePageFlag: true,
                // 弹框
                dialogEditUser: false,// 分配角色弹框
                dialogAddUser: false,// 新建用户弹框
                // 用户信息
                allRoleList: [],
                roleList: [],
                id: null,
                username: '',
                password: '',
                password1: '',
                reserve: '',
                roleTitle: '',
                permissionsStr: [],
                permissionsFlag: {
                    query_user: false,
                    add_user: false,
                    remove_user: false,
                    allot_roles: false,
                    query_role: false,
                    add_role: false,
                    remove_role: false,
                    allot_permission: false
                },
                token: ''

            }
        },
        methods: {
            queryPermissionList() {
                axios.defaults.headers.token = this.token;
                axios.defaults.headers.post['Content-Type'] = 'application/json;charset=UTF-8';
                axios({
                    method: 'post',
                    url: '/user/findPermissionListByRoleId',
                    data: JSON.stringify({
                        id: 0
                    })
                }).then(response => {
                    if(typeof response.data.error !== 'undefined' || response.data.error != null){
                        ELEMENT.Notification.error({
                            title: '查询失败!',
                            message: response.data.error,
                            position: 'top-right',
                            showClose: false,
                            offset: 110
                        });
                        return;
                    }
                    this.permissionData = response.data.allPermissionList;
                }).catch(error => {
                    console.log(error);
                    ELEMENT.Message(error);
                });
            },
            queryRoleList() {
                axios.defaults.headers.token = this.token;
                axios.defaults.headers.post['Content-Type'] = 'application/json;charset=UTF-8';
                axios({
                    method: 'post',
                    url: '/user/findRoleListByUserId',
                    data: JSON.stringify({
                        id: 0
                    })
                }).then(response => {
                    if(typeof response.data.error !== 'undefined' || response.data.error != null){
                        ELEMENT.Notification.error({
                            title: '查询失败!',
                            message: response.data.error,
                            position: 'top-right',
                            showClose: false,
                            offset: 110
                        });
                        return;
                    }
                    this.roleData = response.data.allRoleList;
                }).catch(error => {
                    console.log(error);
                    ELEMENT.Message(error);
                });

            },
            handleEditRole(index, row){
                axios.defaults.headers.token = this.token;
                axios.defaults.headers.post['Content-Type'] = 'application/json;charset=UTF-8';
                axios({
                    method: 'post',
                    url: '/user/findPermissionListByRoleId',
                    data: JSON.stringify({
                        id: row.id
                    })
                }).then(response => {
                    console.log(response.data);
                    if(typeof response.data.error !== 'undefined' || response.data.error != null){
                        ELEMENT.Notification.error({
                            title: '查询失败!',
                            message: response.data.error,
                            position: 'top-right',
                            showClose: false,
                            offset: 110
                        });
                        return;
                    }
                    this.permissions = response.data.allPermissionList;
                    for(let item of response.data.bePermissionList){
                        this.checkedPermissions.push(item.name);
                    }
                    this.roleId = row.id;
                    this.name = row.name;
                    this.permissionsTitle = '为角色'+row.name+'分配权限';
                    this.dialogEditRole = true;
                }).catch(error => {
                    console.log(error);
                    ELEMENT.Message(error);
                });
            },
            handleDeleteRole(index, row){
                ELEMENT.MessageBox.confirm('此操作将永久删除角色'+row.name+', 是否继续?', '提示', {
                    confirmButtonText: '确定',
                    cancelButtonText: '取消',
                    type: 'warning'
                }).then(() => {
                    axios.defaults.headers.token = this.token;
                    axios.defaults.headers.post['Content-Type'] = 'application/json;charset=UTF-8';
                    axios({
                        method: 'post',
                        url: '/user/removeRole',
                        data: JSON.stringify({
                            id: row.id
                        })
                    }).then(response => {
                        if(typeof response.data.error !== 'undefined' || response.data.error != null){
                            ELEMENT.Notification.error({
                                title: '角色'+row.name+',删除失败!',
                                message: response.data.error,
                                position: 'top-right',
                                showClose: false,
                                offset: 110
                            });
                            return;
                        }
                        if (response.data.removeRolePermission >= 0 && response.data.removeRole >= 0 && response.data.removeUserRole >= 0) {
                            this.queryRoleList();
                            ELEMENT.Notification({
                                title: '删除成功',
                                message: '角色'+row.name+',删除成功!',
                                type: 'success',
                                position: 'top-right',
                                showClose: false,
                                offset: 110
                            });
                        }
                    }).catch(error => {
                        ELEMENT.Message({ type: 'info', message: error});
                    });
                }).catch(() => {
                    ELEMENT.Message({ type: 'info', message: '已取消删除'});
                });
            },
            handleAddRole(){
                this.dialogAddRole = true;
                this.name = '';
                this.description = '';
            },
            insertRole(){
                axios.defaults.headers.token = this.token;
                axios.defaults.headers.post['Content-Type'] = 'application/json;charset=UTF-8';
                axios({
                    method: 'post',
                    url: '/user/addRole',
                    data: JSON.stringify({
                        name: this.name,
                        description: this.description
                    })
                }).then(response => {
                    if(typeof response.data.error !== 'undefined' || response.data.error != null){
                        ELEMENT.Notification.error({
                            title: '角色'+this.name+',添加失败!',
                            message: response.data.error,
                            position: 'top-right',
                            showClose: false,
                            offset: 110
                        });
                        this.dialogAddRole = false;
                        this.name = '';
                        this.description = '';
                        return;
                    }
                    if(response.data.addRole > 0) {
                        this.queryRoleList();
                        ELEMENT.Notification({
                            title: '添加成功',
                            message: '角色'+this.name+',添加成功!',
                            type: 'success',
                            position: 'top-right',
                            showClose: false,
                            offset: 110
                        });
                        this.dialogAddRole = false;
                        this.name = '';
                        this.description = '';
                    }
                    console.log(response.data);
                }).catch(error => {
                    ELEMENT.Message({ type: 'info', message: error});
                });
            },
            assignPermissions(){
                for(let item of this.permissions){
                    for(let i in this.checkedPermissions){
                        if (this.checkedPermissions[i] == item.name) {
                            this.permissionList.push(item);
                        }
                    }
                }
                axios.defaults.headers.token = this.token;
                axios.defaults.headers.post['Content-Type'] = 'application/json;charset=UTF-8';
                axios({
                    method: 'post',
                    url: '/user/updateRolePermission',
                    data: JSON.stringify({
                        id: this.roleId,
                        permissionList: this.permissionList,
                    })
                }).then(response => {
                    if(typeof response.data.error !== 'undefined' || response.data.error != null){
                        this.dialogEditRole = false;
                        ELEMENT.Notification.error({
                            title: '为角色'+this.name+',分配权限失败!',
                            message: response.data.error,
                            position: 'top-right',
                            showClose: false,
                            offset: 110
                        });
                        this.roleId = null;
                        this.name = null;
                        this.permissions = [];
                        this.checkedPermissions = [];
                        this.permissionList = [];
                        this.permissionsTitle = '';
                        return;
                    }
                    if (response.data.removeRolePermission >= 0 && response.data.addRolePermission >= 0) {
                        this.dialogEditRole = false;
                        ELEMENT.Notification({
                            title: '更新成功',
                            message: '为角色'+this.name+',分配权限成功!',
                            type: 'success',
                            position: 'top-right',
                            showClose: false,
                            offset: 110
                        });
                        this.roleId = null;
                        this.name = null;
                        this.permissions = [];
                        this.checkedPermissions = [];
                        this.permissionList = [];
                        this.permissionsTitle = '';
                    }
                    console.log(response.data);
                }).catch(error => {
                    console.log(error);
                    ELEMENT.Message(error);
                });
            },
            // ------------------------用户设置部分--------------
            queryUserList() {
                axios.defaults.headers.token = this.token;
                axios.defaults.headers.post['Content-Type'] = 'application/json;charset=UTF-8';
                axios({
                    method: 'post',
                    url: '/user/queryUserListPage',
                    data: JSON.stringify({
                        id: this.id,
                        username: this.username
                    })
                }).then(response => {
                    if(typeof response.data.error !== 'undefined' || response.data.error != null){
                        ELEMENT.Notification.error({
                            title: '查询用户失败!',
                            message: response.data.error,
                            position: 'top-right',
                            showClose: false,
                            offset: 110
                        });
                        return;
                    }
                    console.log(response.data);
                    this.tableData = response.data.userListPage;
                    this.userRowCount = response.data.userRowCount;
                    if(this.userRowCount > 5) {
                        this.hidePageFlag = false;
                    } else {
                        this.hidePageFlag = true;
                    }
                    this.currentPage = 1;
                }).catch(error => {
                    console.log(error);
                    ELEMENT.Message(error);
                });
            },
            queryUserListPage() {
                axios.defaults.headers.token = this.token;
                axios.defaults.headers.post['Content-Type'] = 'application/json;charset=UTF-8';
                axios({
                    method: 'post',
                    url: '/user/queryUserListPage',
                    data: JSON.stringify({
                        id: this.id,
                        username: this.username,
                        reserve1: this.currentPage
                    })
                }).then(response => {
                    if(typeof response.data.error !== 'undefined' || response.data.error != null){
                        ELEMENT.Notification.error({
                            title: '查询用户失败!',
                            message: response.data.error,
                            position: 'top-right',
                            showClose: false,
                            offset: 110
                        });
                        return;
                    }
                    console.log(response.data);
                    this.tableData = response.data.userListPage;
                    this.userRowCount = response.data.userRowCount;
                    if(this.userRowCount > 5) {
                        this.hidePageFlag = false;
                    } else {
                        this.hidePageFlag = true;
                    }
                }).catch(error => {
                    console.log(error);
                    ELEMENT.Message(error);
                });
            },
            handleEditUser(index, row) {
                axios.defaults.headers.token = this.token;
                axios.defaults.headers.post['Content-Type'] = 'application/json;charset=UTF-8';
                axios({
                    method: 'post',
                    url: '/user/findRoleListByUserId',
                    data: JSON.stringify({
                        id: row.id
                    })
                }).then(response => {
                    if(typeof response.data.error !== 'undefined' || response.data.error != null){
                        this.dialogEditUser = false;
                        ELEMENT.Notification.error({
                            title: '为用户'+row.username+'分配角色失败!',
                            message: response.data.error,
                            position: 'top-right',
                            showClose: false,
                            offset: 110
                        });
                        return;
                    }
                    console.log(response.data);
                    for(let item of response.data.allRoleList){
                        this.transferData.push({
                            key: item.id,
                            label: item.description
                        });
                    }
                    for(let item of response.data.beRoleList){
                        this.transferValue.push(item.id);
                    }
                    this.id = row.id;
                    this.username = row.username;
                    this.allRoleList = response.data.allRoleList;
                    this.roleTitle = '为用户'+row.username+'分配角色';
                    this.dialogEditUser = true;
                }).catch(error => {
                    console.log(error);
                    ELEMENT.Message(error);
                });
            },
            assignRoles() {
                for(let item of this.allRoleList){
                    for(let i in this.transferValue){
                        if (this.transferValue[i] == item.id) {
                            this.roleList.push(item);
                        }
                    }
                }
                axios.defaults.headers.token = this.token;
                axios.defaults.headers.post['Content-Type'] = 'application/json;charset=UTF-8';
                axios({
                    method: 'post',
                    url: '/user/updateUserRole',
                    data: JSON.stringify({
                        id: this.id,
                        username: this.username,
                        roleList: this.roleList
                    })
                }).then(response => {
                    if(typeof response.data.error !== 'undefined' || response.data.error != null){
                        this.dialogEditUser = false;
                        ELEMENT.Notification.error({
                            title: '为用户'+row.username+'分配角色失败!',
                            message: response.data.error,
                            position: 'top-right',
                            showClose: false,
                            offset: 110
                        });
                        this.id = null;
                        this.username = '';
                        this.allRoleList = [];
                        this.roleList = [];
                        this.transferData = [];
                        this.transferValue = [];
                        return;
                    }
                    if (response.data.removeUserRole >= 0 && response.data.addUserRole >= 0) {
                        this.dialogEditUser = false;
                        ELEMENT.Notification({
                            title: '更新成功',
                            message: '为用户'+this.username+',分配角色成功!',
                            type: 'success',
                            position: 'top-right',
                            showClose: false,
                            offset: 110
                        });
                        this.id = null;
                        this.username = '';
                        this.allRoleList = [];
                        this.roleList = [];
                        this.transferData = [];
                        this.transferValue = [];
                    }
                    console.log(response.data);
                }).catch(error => {
                    console.log(error);
                });

            },
            handleDeleteUser(index, row) {
                //this.ruleForm = Object.assign({}, row, index); //这句是关键!!!
                ELEMENT.MessageBox.confirm('此操作将永久删除用户'+row.id+', 是否继续?', '提示', {
                    confirmButtonText: '确定',
                    cancelButtonText: '取消',
                    type: 'warning'
                }).then(() => {
                    axios.defaults.headers.token = this.token;
                    axios.defaults.headers.post['Content-Type'] = 'application/json;charset=UTF-8';
                    axios({
                        method: 'post',
                        url: '/user/removeUser',
                        data: JSON.stringify({
                            id: row.id
                        })
                    }).then(response => {
                        if(typeof response.data.error !== 'undefined' || response.data.error != null){
                            ELEMENT.Notification.error({
                                title: '用户'+row.username+',删除失败!',
                                message: response.data.error,
                                position: 'top-right',
                                showClose: false,
                                offset: 110
                            });
                            return;
                        }
                        if (response.data.removeUser >= 0 && response.data.removeUserRole >= 0) {
                            if(((this.userRowCount - 1) % 5 == 0) && ((this.userRowCount - 1) / 5 == (this.currentPage - 1))) {
                                this.currentPage = this.currentPage - 1;
                            }
                            this.queryUserListPage();
                            ELEMENT.Notification({
                                title: '删除成功',
                                message: '用户'+row.username+',删除成功!',
                                type: 'success',
                                position: 'top-right',
                                showClose: false,
                                offset: 110
                            });
                        }
                    }).catch(error => {
                        ELEMENT.Message({ type: 'info', message: error});
                    });
                }).catch(() => {
                    ELEMENT.Message({ type: 'info', message: '已取消删除'});
                });
            },
            handleClose() {
                // 用户设置
                this.dialogEditUser = false;
                this.dialogAddUser = false;
                this.id = null;
                this.username = '';
                this.password = '';
                this.password1 = '';
                this.reserve = '';
                this.allRoleList = [];
                this.roleList = [];
                this.transferData = [];
                this.transferValue = [];
                this.roleTitle = '';
                // 角色设置
                this.dialogEditRole = false;
                this.dialogAddRole = false;
                this.roleId = null;
                this.name = null;
                this.permissions = [];
                this.checkedPermissions = [];
                this.permissionList = [];
                this.permissionsTitle = '';
                ELEMENT.Message({
                    message: '取消操作,系统不会保留任何更改',
                    type:'warning'
                });
            },
            handleAddUser(){
                this.dialogAddUser = true;
                this.id = null;
                this.username = '';
                this.password = '';
                this.password1 = '';
                this.reserve = '';
            },
            insertUser() {
                axios.defaults.headers.token = this.token;
                axios.defaults.headers.post['Content-Type'] = 'application/json;charset=UTF-8';
                axios({
                    method: 'post',
                    url: '/user/insertUser',
                    data: JSON.stringify({
                        username: this.username,
                        password: this.password,
                        reserve: this.reserve
                    })
                }).then(response => {
                    if(response.data.addUser > 0) {
                        this.dialogAddUser = false;
                        this.password = '';
                        this.password1 = '';
                        this.reserve = '';
                        this.queryUserList();
                        ELEMENT.Notification({
                            title: '添加成功',
                            message: '用户'+this.username+',添加成功!',
                            type: 'success',
                            position: 'top-right',
                            showClose: false,
                            offset: 110
                        });
                    }
                    if(typeof response.data.error !== 'undefined' || response.data.error != null){
                        this.dialogAddUser = false;
                        this.password = '';
                        this.password1 = '';
                        this.reserve = '';
                        this.queryUserList();
                        ELEMENT.Notification.error({
                            title: '用户'+this.username+',添加失败!',
                            message: response.data.error,
                            position: 'top-right',
                            showClose: false,
                            offset: 110
                        });
                        return;
                    }
                    console.log(response.data);
                }).catch(error => {
                    ELEMENT.Message({ type: 'info', message: error});
                });
            }
        },
        mounted() {
            console.log('组件Manager被挂载了');
        },
        created() {
            this.permissionsStr = this.$route.params.permissionsStr;
            this.token = this.$route.params.token;
            for(let key in this.permissionsFlag){
                for(let i in this.permissionsStr){
                    if(this.permissionsStr[i] == key){
                        this.permissionsFlag[key] = true;
                    }
                }
                console.log(key + '---' + this.permissionsFlag[key])
            }
        }
    };
    const router = new VueRouter({
        routes:[
            {
                path: '/',
                name: 'sign',
                component: Sign
            },
            {
                path: '/manager',
                name: 'manager',
                component: Manager
            }
        ]
    });
    new Vue({
        router,
        el: '#app',
        data: {},
        methods: {}
    })
</script>
<style>
    .el-pagination {
        display: flex;
        justify-content: flex-end;
        align-items: center;
        height: 60px;
    }
    .el-transfer {
        display: flex;
        justify-content: center;
        align-items: center;
    }
    .handle-area {
        display: flex;
        align-items: center;
        justify-content: space-between;
        height: 70px;
        flex-wrap: nowrap;
    }
    .demo-input {
        display: flex;
        align-items: center;
    }
    .demo-input span {
        white-space: nowrap;
    }
    .el-dialog__body {
        display: flex;
        flex-direction: column;
        justify-content: center;
        flex-wrap: nowrap;
        height: 280px;
    }
    .el-checkbox-group-dialog {
        height: 100%;
        display: flex;
        flex-direction: column;
        justify-content: center;
        margin: auto;
    }
    .el-checkbox {
        height: 30px;
        line-height: 30px;
    }
    .high70 {
        height: 70px;
    }
    .handle {
        position: absolute;
        width: 100%;
        height: 100%;
        top: 0;
        left: 0;
        margin: 0;
        background-image: url(banner.jpg);
        background-position: center;
        background-repeat: no-repeat;
        background-size: cover;
        overflow: hidden;
        display: flex;
        justify-content: center;
        align-items: center;
    }
    .handle-input {
        display: flex;
        flex-direction: column;
    }
</style>
</html>

具体看index.html 代码,如果没看懂,参考网址:
https://blog.csdn.net/laow1314/article/details/109323527
https://blog.csdn.net/qq_29722281/article/details/85016524

权限相关表

最基础的CRUD操作无法体现shiro的功能,需引入RBAC (Role-Based Access Control)思想,配置至少需要三张主表分别代表用户(user)、角色(role)、权限(permission),及两个附表分别是用户和角色(user_role),角色与权限(role_permission)表,表结构如下:
ER

对应的实体如下:
1、com/example/demo/entity/User.java

package com.example.demo.entity;

import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.*;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

@Data
@ToString
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class User {
    /**
     * 主键
     */
    private int id;
    /**
     * 用户名
     */
    private String username;
    /**
     * 密码
     */
    private String password;
    /**
     * 保留字段
     */
    private String reserve;

    /**
     * 保留字段1
     */
    private int reserve1;
    /**
     * 角色集合
     */
    private List<Role> roleList = new ArrayList<>();

    public User(String json) throws IOException {
        User user = new ObjectMapper().readValue(json,User.class);
        this.id = user.getId();
        this.username = user.getUsername();
        this.password = user.getPassword();
        this.reserve = user.getReserve();
        this.reserve1 = user.getReserve1();
        this.roleList = user.getRoleList();
    }
}

2、com/example/demo/entity/Role.java

package com.example.demo.entity;

import lombok.*;

import java.util.ArrayList;
import java.util.List;

@Data
@ToString
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class Role {
    /**
     * 主键
     */
    private int id;
    /**
     * 角色名称
     */
    private String name;
    /**
     * 角色描述
     */
    private String description;
    /**
     * 权限集合
     */
    private List<Permission> permissionList=new ArrayList<>();

}

3、com/example/demo/entity/Permission.java

package com.example.demo.entity;

import lombok.*;

@Data
@ToString
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class Permission {
    /**
     * 主键
     */
    private int id;
    /**
     * 权限名称
     */
    private String name;
    /**
     * 权限描述
     */
    private String description;

}

前后端分离项目中使用shiro的session鉴别用户身份

1、src/main/resources/static/index.html

<template id="sign">
    <div class="handle">
        <div class="handle-input">
            <div class="high70">
                <span>用户名称:</span>
                <el-input
                        v-model="username"
                        placeholder="请输入用户名称"
                        clearable></el-input>
            </div>
            <div class="high70">
                <span>密码:</span>
                <el-input
                        v-model="password"
                        placeholder="请输入密码"
                        clearable
                        show-password></el-input>
            </div>
            <el-button @click="login" plain>登录</el-button>
        </div>
    </div>
</template>
login() {
            axios.defaults.headers.post['Content-Type'] = 'application/json;charset=UTF-8';
            axios({
                method: 'post',
                url: '/user/login',
                data: JSON.stringify({
                    username: this.username,
                    password: this.password
                })
            }).then(response => {
                if(typeof response.data.error !== 'undefined' || response.data.error != null){
                    this.username = '';
                    this.password = '';
                    ELEMENT.Notification.error({
                        title: '登录失败!',
                        message: response.data.error,
                        position: 'top-right',
                        showClose: false,
                        offset: 110
                    });
                    return;
                }
                this.permissionsStr = response.data.permissions;
                this.token = response.data.token;
                this.$router.push({
                    name: 'manager',
                    params: {
                        token: this.token,
                        permissionsStr: this.permissionsStr
                    }
                });
            }).catch(error => {
                console.log(error);
                ELEMENT.Message(error);
            });
        }

2、com/example/demo/controller/UserCtrl.java

   /**
     * 登录接口
     *
     * @param user user
     * @return resultMap
     */
    @RequestMapping(value = "/login", method = RequestMethod.POST)
    public Map<String, Object> login(@RequestBody User user) {
        //拿到主体
        Subject subject = SecurityUtils.getSubject();
        try {
            UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(user.getUsername(), user.getPassword());
            subject.login(usernamePasswordToken);
            Object permissions = subject.getSession().getAttribute("permissions");
            subject.getSession().removeAttribute("permissions");
            return userService.resultMap("permissions", permissions, "token",  subject.getSession().getId(), "", "");
        }catch (Exception e){
            e.printStackTrace();
            return userService.resultMap("error", e.getMessage(), "",  "", "", "");
        }
    }

3、com/example/demo/config/UserRealm.java

    /**
     * 认证
     * @param authenticationToken
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        //从token中获取用户信息
        String uesrName = (String) authenticationToken.getPrincipal();
        User user = userService.findUserByName(uesrName);
        if (user == null) {
            return null;
        }
        //权限集合
        Set<String> stringPermissionSet = new HashSet<>();
        user.getRoleList().forEach(role -> {
            stringPermissionSet.addAll(role.getPermissionList().stream().map(Permission::getName).collect(Collectors.toList()));
        });
        SecurityUtils.getSubject().getSession().setAttribute("permissions", stringPermissionSet);
        //密码
        String pwd = user.getPassword();
        if (pwd == null || "".equals(pwd)) {
            return null;
        }
        return new SimpleAuthenticationInfo(uesrName, pwd, this.getClass().getName());
    }

4、com/example/demo/service/UserService.java

    public User findUserByName(String userName) {
        User user = userMapper.findUserByName(userName);
        //用户角色的集合
        List<Role> roleList = roleMapper.findRoleListByUserId(user.getId());
        user.setRoleList(roleList);
        return user;
    }

5、src/main/resources/mapper/UserMapper.xml

    <resultMap id="resultUser" type="com.example.demo.entity.User">
        <result property="id" column="id" />
		<result property="username" column="username" />
		<result property="password" column="password" />
    </resultMap>

    <select id="findUserByName" resultMap="resultUser" parameterType="String">
		select
			id,
			username,
		    password
		from user where
		    username = #{userName}
	</select>

6、src/main/resources/mapper/RoleMapper.xml

    <resultMap id="roleResult" type="com.example.demo.entity.Role">
        <result property="id" column="id" />
		<result property="name" column="name" />
        <result property="description" column="description" />
		<collection property="permissionList" column="id" select="com.example.demo.mapper.PermissionMapper.findByPermissionListByRoleId" />
    </resultMap>

	<resultMap id="roleResultNotPermission" type="com.example.demo.entity.Role">
		<result property="id" column="id" />
		<result property="name" column="name" />
		<result property="description" column="description" />
	</resultMap>

    <select id="findRoleListByUserId" resultMap="roleResult" parameterType="int">
		select
			r.id id,
			r.name name,
			r.description description
		from
			user_role ur
		left join role r on
			ur.role_id = r.id
		where
			ur.user_id = #{userId}
	</select>

7、src/main/resources/mapper/PermissionMapper.xml

    <resultMap id="permissionResult" type="com.example.demo.entity.Permission">
        <result property="id" column="id" />
		<result property="name" column="name" />
        <result property="description" column="description" />
    </resultMap>

    <select id="findByPermissionListByRoleId" resultMap="permissionResult" parameterType="int">
        select
            p.id id,
            p.name name,
            p.description description
        from
            role_permission rp
        left join permission p on
            rp.permission_id = p.id
        where
            rp.role_id = #{roleId}
	</select>

8、页面
login_fail

9、src/main/resources/static/index.html

queryPermissionList() {
                axios.defaults.headers.token = this.token;
                axios.defaults.headers.post['Content-Type'] = 'application/json;charset=UTF-8';
                axios({
                    method: 'post',
                    url: '/user/findPermissionListByRoleId',
                    data: JSON.stringify({
                        id: 0
                    })
                }).then(response => {
                    if(typeof response.data.error !== 'undefined' || response.data.error != null){
                        ELEMENT.Notification.error({
                            title: '查询失败!',
                            message: response.data.error,
                            position: 'top-right',
                            showClose: false,
                            offset: 110
                        });
                        return;
                    }
                    this.permissionData = response.data.allPermissionList;
                }).catch(error => {
                    console.log(error);
                    ELEMENT.Message(error);
                });
            },

10、com/example/demo/config/UserSessionManager.java

package com.example.demo.config;

import org.apache.shiro.web.servlet.ShiroHttpServletRequest;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.apache.shiro.web.util.WebUtils;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.Serializable;

public class UserSessionManager extends DefaultWebSessionManager {
    public static final String AUTHORIZATION="token";

    public UserSessionManager() {
        super();
    }

    @Override
    protected Serializable getSessionId(ServletRequest request, ServletResponse response) {
        //获取sessionId
        String sessionId= WebUtils.toHttp(request).getHeader(AUTHORIZATION);
        if (sessionId!=null && sessionId!=""){
            request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE,
                    ShiroHttpServletRequest.COOKIE_SESSION_ID_SOURCE);
            request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID, sessionId);
            request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_IS_VALID, Boolean.TRUE);
            return sessionId;
        }else {
            return super.getSessionId(request,response);
        }
    }

}

11、参考链接:
https://blog.csdn.net/qq_25046827/article/details/124540457
https://blog.csdn.net/palerock/article/details/73457415

前端控制按钮显隐,后端请求路径拦截配置

用户登陆成功后会返回用户具有的权限列表,根据权限列表控制前端控制按钮显隐及后端请求拦截路径,
总结如下:
permission

相关代码
com/example/demo/config/ShiroConfig.java

package com.example.demo.config;

import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

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

@Configuration
public class ShiroConfig {
    @Bean
    public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
        System.out.println("ShiroConfig ShiroFilterFactoryBean 执行");
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        //设置SecurityManager
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        //如果访问需要登录的某个接口,却没有登录,则调用此接口(如果不是前后端分离,则跳转页面)
        //shiroFilterFactoryBean.setLoginUrl("/index.html");
        //登录成功后,跳转的链接,若前后端分离,没必要设置这个
        //shiroFilterFactoryBean.setSuccessUrl("");
        //登录成功,未授权会调用此方法
        //shiroFilterFactoryBean.setUnauthorizedUrl("/user/*");
        //拦截路径,必须使用:LinkedHashMap,要不然拦截效果会时有时无,因为使用的是无序的Map
        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
        //key=正则表达式路径,value=org.apache.shiro.web.filter.mgt.DefaultFilter
        //退出过滤器
        //filterChainDefinitionMap.put("/logout", "logout");
        //匿名可以访问,游客模式
        filterChainDefinitionMap.put("/", "anon");
        filterChainDefinitionMap.put("/user/login", "anon");
        //登录用户才可以访问
        filterChainDefinitionMap.put("/user/**", "authc");
        //管理员角色才能访问
        //filterChainDefinitionMap.put("/user/**", "roles[admin]");
        //有权限才能访问
        filterChainDefinitionMap.put("/user/queryUserListPage", "perms[query_user, add_user, allot_roles, remove_user]");
        filterChainDefinitionMap.put("/user/insertUser", "perms[add_user]");
        filterChainDefinitionMap.put("/user/removeUser", "perms[remove_user]");
        filterChainDefinitionMap.put("/user/findRoleListByUserId", "perms[allot_roles, query_role, add_role, remove_role, allot_permission]");
        filterChainDefinitionMap.put("/user/updateUserRole", "perms[allot_roles]");
        filterChainDefinitionMap.put("/user/addRole", "perms[add_role]");
        filterChainDefinitionMap.put("/user/removeRole", "perms[remove_role]");
        filterChainDefinitionMap.put("/user/findPermissionListByRoleId", "perms[allot_permission]");
        filterChainDefinitionMap.put("/user/updateRolePermission", "perms[allot_permission]");
        //authc:url必须通过认证才可以访问
        //anon:url可以匿名访问
        //过滤链是顺序执行,从上而下,一般把/**,放到最下面
        filterChainDefinitionMap.put("/**", "authc");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilterFactoryBean;
    }

    @Bean
    public SecurityManager securityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        //如果不是前后端分离,不用设置setSessionManager
        securityManager.setSessionManager(sessionManager());
        securityManager.setRealm(userRealm());
        return securityManager;
    }

    /**
     * 自定义realm
     *
     * @return
     */
    @Bean
    public UserRealm userRealm() {
        UserRealm userRealm = new UserRealm();
        //因为数据库密码存的是明文,所以无需使用双重md5校验
//        customRealm.setCredentialsMatcher(hashedCredentialsMatcher());
        return userRealm;
    }

    /**
     * 密码验证器,双重md5
     *
     * @return
     */
    @Bean
    public HashedCredentialsMatcher hashedCredentialsMatcher() {
        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
        //设置散列算法,使用md5算法
        hashedCredentialsMatcher.setHashAlgorithmName("md5");
        //散列次数,使用2次md5算法,相当于md5(md5(xxx))
        hashedCredentialsMatcher.setHashIterations(2);
        return hashedCredentialsMatcher;
    }

    /**
     * 自定义SessionManager
     *
     * @return
     */
    @Bean
    public SessionManager sessionManager() {
        UserSessionManager userSessionManager = new UserSessionManager();
        //超时时间,默认 30分钟,会话超时,单位毫秒
//        customSessionManager.setGlobalSessionTimeout(200000);
        return userSessionManager;
    }
}

待完成

1、密码加解密;
2、记住我;

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

麻省理工出版 | 2023年最新深度学习综述手册

UCL Simon Prince的新书&#xff1a;《Understanding Deep Learning》 &#xff0c;在2023年2月6日由MIT Press出版。他之前写过很受欢迎的《Computer Vision: Models, Learning, and Inference》。 关于这本最新的深度学习手册&#xff0c;作者这样介绍它&#xff1a; 正如书…

数据结构与算法基础-学习-09-线性表之栈的理解、初始化顺序栈、判断顺序栈空、获取顺序栈长度的实现

一、个人理解栈是线性表的一种衍生&#xff0c;和之前的顺序表和链表在插入和删除元素上有较大差异&#xff0c;其他基本相同&#xff0c;栈是数据只能插入表的尾部&#xff08;栈顶&#xff09;&#xff0c;删除数据时只能删除表的尾部&#xff08;栈顶&#xff09;数据&#…

2022Q4手机银行新版本聚焦提升客群专属、财富开放平台、智能化能力,活跃用户规模6.91亿人

易观&#xff1a;2022年第4季度&#xff0c;手机银行APP迭代升级加快&#xff0c;手机银行作为零售银行服务及经营的主阵地&#xff0c;与零售银行业务发展的联系日益紧密。迭代升级一方面可以顺应零售银行发展战略及方向&#xff0c;对手机银行业务布局进行针对性调整优化&…

前端面经详解

目录 css 盒子充满屏幕 A.给div设置定位 B.设置html,body的宽高 C.相对当前屏幕高度&#xff08;强烈推荐&#xff09; 三列布局&#xff1a;左右固定&#xff0c;中间自适应 flex布局&#xff08;强烈推荐&#xff09; grid布局 magin负值法 自身浮动 绝对定位 圣…

基于PHP的招聘网站

摘要在Internet高速发展的今天&#xff0c;我们生活的各个领域都涉及到计算机的应用&#xff0c;其中包括在线招聘的网络应用&#xff0c;在外国在线招聘已经是很普遍的方式&#xff0c;不过国内的在线招聘可能还处于起步阶段。招聘网站具有招聘信息功能的双向选择&#xff0c;…

UMI入门(创建react项目)

1、umI的环境要求确保 node 版本是 10.13 或以上React 16.8.0 及以上的 React2、什么时候不用 umi需要支持 IE 8 或更低版本的浏览器需要支持 React 16.8.0 以下的 React需要跑在 Node 10 以下的环境中有很强的 webpack 自定义需求和主观意愿需要选择不同的路由方案3、与其他框…

领域搜索算法之经典The Lin-Kernighan algorithm

领域搜索算法之经典The Lin-Kernighan algorithmThe Lin-Kernighan algorithm关于算法性能提升的约束参考文献领域搜索算法是TSP问题中的三大经典搜索算法之一&#xff0c;另外两种分别是回路构造算法和组合算法。 而这篇文章要介绍的The Lin-Kernighan algorithm属于领域搜索算…

精华文稿|迈向统一的点云三维物体检测框架

分享嘉宾 | 杨泽同 文稿整理 | William 嘉宾介绍 Introduction 3D检测是在三维世界中去定位和分类不同的物体&#xff0c;与传统2D检测的区别在于它有一个深度信息。目前&#xff0c;大部分的工作是倾向于用点云去做三维检测&#xff0c;点云实际上是通过传感器去扫描出来的一…

Redis 的安装 + SpringBoot 集成 Redis

1.安装 Redis此处的 Redis 安装是针对 Linux 版本的安装, 因为 Redis 官方没有提供 Windows 版本, 只提供了 Linux 版本. 但是我们可以通过Windows 去远程连接 Redis.1.1 使用 yum 安装 Redis使用如下命令, 将 Redis 安装到 Linux 服务器:yum -y install redis1.2 启动 Redis使…

科技云报道:开源真的香,风险知多少?

科技云报道原创。 过去几年&#xff0c;开源界一片火热&#xff0c;开源软件技术已全面进军操作系统、云原生、人工智能、大数据、半导体、物联网等行业领域。 数据显示&#xff0c;我国超九成企业在使用或正计划使用开源技术。 与此同时&#xff0c;全球各大开源组织相继兴…

苹果手机专用蓝牙耳机有哪些?与iphone兼容性好的蓝牙耳机

蓝牙耳机摆脱了线缆的束缚&#xff0c;在地以各种方式轻松通话。自从蓝牙耳机问世以来&#xff0c;一直是行动商务族提升效率的好工具&#xff0c;苹果产品一直都是受欢迎的数码产品&#xff0c;下面推荐几款与iphone兼容性好的蓝牙耳机。 第一款&#xff1a;南卡小音舱蓝牙耳…

Springboot部署阿里云短信服务

一、阿里云短信模板配置&#xff08;获取SignName[签名名称]、TemplateCode[模板CODE]&#xff09; 1. 进入阿里云首页直接搜索短信服务&#xff0c;并点击国内消息进入国内文本短信管理页面 2. 选择签名管理点击添加签名 填写签名信息并提交 注&#xff1a;下面的签名来源如…

全栈自动化测试技术笔记(一):前期调研怎么做

昨天下午在家整理书架&#xff0c;把很多看完的书清理打包好&#xff0c;预约了公益捐赠机构上门回收。 整理的过程中无意翻出了几年前的工作记事本&#xff0c;里面记录了很多我刚开始做自动化和性能测试时的笔记。 虽然站在现在的角度来看&#xff0c;那个时候无论是技术细…

【Java 面试合集】描述下Objec类中常用的方法(未完待续中...)

描述下Objec类中常用的方法 1. 概述 首先我们要知道Object 类是所有的对象的基类&#xff0c;也就是所有的方法都是可以被重写的。 那么到底哪些方法是我们常用的方法呢&#xff1f;&#xff1f;&#xff1f; cloneequalsfinalizegetClasshashCodenotifynotifyAlltoStringw…

你知道 GO 中什么情况会变量逃逸吗?

你知道 GO 中什么情况会变量逃逸吗&#xff1f;首先我们先来看看什么是变量逃逸 Go 语言将这个以前我们写 C/C 时候需要做的内存规划和分配&#xff0c;全部整合到了 GO 的编译器中&#xff0c;GO 中将这个称为 变量逃逸 GO 通过编译器分析代码的特征和代码的生命周期&#x…

在RT-Thread STM32F407平台下配置SPI flash为U盘

记录下SPI Flash U盘实现过程中踩过的坑&#xff0c;与您分享。前提条件是&#xff0c;需要先将SPI Flash 配置到elm fal文件系统&#xff0c;并挂载成功。如下图然后开始配置USB1&#xff0c;在CubeMX&#xff0c;选择SUB_OTG_FS2 选择USB Device3&#xff0c;确认USB时钟为48…

流程控制之循环

文章目录五、流程控制之循环5.1 步进循环语句for5.1.1 带列表的for循环语句5.1.2 不带列表的for循环语句5.1.3 类C风格的for循环语句5.2 while循环语句5.2.1 while循环读取文件5.2.2 while循环语句示例5.3 until循环语句5.4 select循环语句5.5 嵌套循环5.4 利用break和continue…

【八大数据排序法】堆积树排序法的图形理解和案例实现 | C++

第二十一章 堆积树排序法 目录 第二十一章 堆积树排序法 ●前言 ●认识排序 1.简要介绍 2.图形理解 3.算法分析 ●二、案例实现 1.案例一 ● 总结 前言 排序算法是我们在程序设计中经常见到和使用的一种算法&#xff0c;它主要是将一堆不规则的数据按照递增…

BinaryAI全新代码匹配模型BAI-2.0上线,“大模型”时代的安全实践

导语BinaryAI&#xff08;https://www.binaryai.net&#xff09;科恩实验室在2021年8月首次发布二进制安全智能分析平台—BinaryAI&#xff0c;BinaryAI可精准高效识别二进制文件的第三方组件及其版本号&#xff0c;旨在推动SCA&#xff08;Software Composition Analysis&…

网络通信协议是什么?

网络通信基本模式 常见的通信模式有如下2种形式&#xff1a;Client-Server(CS) 、 Browser/Server(BS) 实现网络编程关键的三要素 IP地址&#xff1a;设备在网络中的地址&#xff0c;是唯一的标识。 端口&#xff1a;应用程序在设备中唯一的标识。 协议: 数据在网络中传输的…