主頁 > 企業開發 > shiro、springboot、vue、elementUI CDN模式前后端分離的權限管理demo 附原始碼

shiro、springboot、vue、elementUI CDN模式前后端分離的權限管理demo 附原始碼

2023-02-10 08:29:31 企業開發

原始碼下載地址

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 = "https://www.cnblogs.com/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 = "https://www.cnblogs.com/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 = "https://www.cnblogs.com/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 = "https://www.cnblogs.com/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 = "https://www.cnblogs.com/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 = "https://www.cnblogs.com/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 = "https://www.cnblogs.com/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 = "https://www.cnblogs.com/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 = "https://www.cnblogs.com/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 = "https://www.cnblogs.com/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 >
        <div >
            <div >
                <span>用戶名稱:</span>
                <el-input
                        v-model="username"
                        placeholder="請輸入用戶名稱"
                        clearable></el-input>
            </div>
            <div >
                <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 >
                        <div  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="https://www.cnblogs.com/nqdxt/archive/2023/02/09/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="https://www.cnblogs.com/nqdxt/archive/2023/02/09/transferData"
                        :titles="['待分配角色', '已分配角色']">
                </el-transfer>
                <span slot="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 >
                    <span>用戶名稱:</span>
                    <el-input
                            v-model="username"
                            placeholder="請輸入用戶名稱"
                            size="medium"
                            clearable></el-input>
                </div>
                <div >
                    <span>密碼:</span>
                    <el-input
                            v-model="password"
                            placeholder="請輸入密碼"
                            size="medium"
                            clearable
                            show-password></el-input>
                </div>
                <div >
                    <span>再次輸入密碼:</span>
                    <el-input
                            v-model="password1"
                            placeholder="請再次輸入密碼"
                            size="medium"
                            show-password></el-input>
                </div>
                <div >
                    <span>備注:</span>
                    <el-input
                            v-model="reserve"
                            placeholder="請輸入用戶備注"
                            size="medium"></el-input>
                </div>
                <span slot="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 >
                        <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="https://www.cnblogs.com/nqdxt/archive/2023/02/09/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" >
                    <el-checkbox v-for="permission in permissions" :label="permission.name" :key="permission.name">{{permission.description}}</el-checkbox>
                </el-checkbox-group>
                <span slot="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 >
                    <span>角色名稱:</span>
                    <el-input
                            v-model="name"
                            placeholder="請輸入角色名稱"
                            size="medium"></el-input>
                </div>
                <div >
                    <span>角色描述:</span>
                    <el-input
                            v-model="description"
                            placeholder="請輸入角色描述"
                            size="medium"></el-input>
                </div>
                <span slot="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 >
                        <el-button
                                v-show="permissionsFlag.allot_permission"
                                :plain="true"
                                @click="queryPermissionList"
                                icon="el-icon-search"
                                size="medium">權限查詢</el-button>
                    </div>
                    <el-table
                            :data="https://www.cnblogs.com/nqdxt/archive/2023/02/09/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 = https://www.cnblogs.com/nqdxt/archive/2023/02/09/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 = https://www.cnblogs.com/nqdxt/archive/2023/02/09/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 = https://www.cnblogs.com/nqdxt/archive/2023/02/09/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 = https://www.cnblogs.com/nqdxt/archive/2023/02/09/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 = https://www.cnblogs.com/nqdxt/archive/2023/02/09/[];
                        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 = https://www.cnblogs.com/nqdxt/archive/2023/02/09/[];
                        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 = https://www.cnblogs.com/nqdxt/archive/2023/02/09/[];
                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 >
        <div >
            <div >
                <span>用戶名稱:</span>
                <el-input
                        v-model="username"
                        placeholder="請輸入用戶名稱"
                        clearable></el-input>
            </div>
            <div >
                <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 = "https://www.cnblogs.com/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 = https://www.cnblogs.com/nqdxt/archive/2023/02/09/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=https://www.cnblogs.com/nqdxt/archive/2023/02/09/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、記住我;

轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/543466.html

標籤:其他

上一篇:JavaScript實作陣列物件去重

下一篇:基于 Ubuntu 服務器配置原生的 Socks5 網關代理服務器

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • IEEE1588PTP在數字化變電站時鐘同步方面的應用

    IEEE1588ptp在數字化變電站時鐘同步方面的應用 京準電子科技官微——ahjzsz 一、電力系統時間同步基本概況 隨著對IEC 61850標準研究的不斷深入,國內外學者提出基于IEC61850通信標準體系建設數字化變電站的發展思路。數字化變電站與常規變電站的顯著區別在于程序層傳統的電流/電壓互 ......

    uj5u.com 2020-09-10 03:51:52 more
  • HTTP request smuggling CL.TE

    CL.TE 簡介 前端通過Content-Length處理請求,通過反向代理或者負載均衡將請求轉發到后端,后端Transfer-Encoding優先級較高,以TE處理請求造成安全問題。 檢測 發送如下資料包 POST / HTTP/1.1 Host: ac391f7e1e9af821806e890 ......

    uj5u.com 2020-09-10 03:52:11 more
  • 網路滲透資料大全單——漏洞庫篇

    網路滲透資料大全單——漏洞庫篇漏洞庫 NVD ——美國國家漏洞庫 →http://nvd.nist.gov/。 CERT ——美國國家應急回應中心 →https://www.us-cert.gov/ OSVDB ——開源漏洞庫 →http://osvdb.org Bugtraq ——賽門鐵克 →ht ......

    uj5u.com 2020-09-10 03:52:15 more
  • 京準講述NTP時鐘服務器應用及原理

    京準講述NTP時鐘服務器應用及原理京準講述NTP時鐘服務器應用及原理 安徽京準電子科技官微——ahjzsz 北斗授時原理 授時是指接識訓通過某種方式獲得本地時間與北斗標準時間的鐘差,然后調整本地時鐘使時差控制在一定的精度范圍內。 衛星導航系統通常由三部分組成:導航授時衛星、地面檢測校正維護系統和用戶 ......

    uj5u.com 2020-09-10 03:52:25 more
  • 利用北斗衛星系統設計NTP網路時間服務器

    利用北斗衛星系統設計NTP網路時間服務器 利用北斗衛星系統設計NTP網路時間服務器 安徽京準電子科技官微——ahjzsz 概述 NTP網路時間服務器是一款支持NTP和SNTP網路時間同步協議,高精度、大容量、高品質的高科技時鐘產品。 NTP網路時間服務器設備采用冗余架構設計,高精度時鐘直接來源于北斗 ......

    uj5u.com 2020-09-10 03:52:35 more
  • 詳細解讀電力系統各種對時方式

    詳細解讀電力系統各種對時方式 詳細解讀電力系統各種對時方式 安徽京準電子科技官微——ahjzsz,更多資料請添加VX 衛星同步時鐘是我京準公司開發研制的應用衛星授時時技術的標準時間顯示和發送的裝置,該裝置以M國全球定位系統(GLOBAL POSITIONING SYSTEM,縮寫為GPS)或者我國北 ......

    uj5u.com 2020-09-10 03:52:45 more
  • 如何保證外包團隊接入企業內網安全

    不管企業規模的大小,只要企業想省錢,那么企業的某些服務就一定會采用外包的形式,然而看似美好又經濟的策略,其實也有不好的一面。下面我通過安全的角度來聊聊使用外包團的安全隱患問題。 先看看什么服務會使用外包的,最常見的就是話務/客服這種需要大量重復性、無技術性的服務,或者是一些銷售外包、特殊的職能外包等 ......

    uj5u.com 2020-09-10 03:52:57 more
  • PHP漏洞之【整型數字型SQL注入】

    0x01 什么是SQL注入 SQL是一種注入攻擊,通過前端帶入后端資料庫進行惡意的SQL陳述句查詢。 0x02 SQL整型注入原理 SQL注入一般發生在動態網站URL地址里,當然也會發生在其它地發,如登錄框等等也會存在注入,只要是和資料庫打交道的地方都有可能存在。 如這里http://192.168. ......

    uj5u.com 2020-09-10 03:55:40 more
  • [GXYCTF2019]禁止套娃

    git泄露獲取原始碼 使用GET傳參,引數為exp 經過三層過濾執行 第一層過濾偽協議,第二層過濾帶引數的函式,第三層過濾一些函式 preg_replace('/[a-z,_]+\((?R)?\)/', NULL, $_GET['exp'] (?R)參考當前正則運算式,相當于匹配函式里的引數 因此傳遞 ......

    uj5u.com 2020-09-10 03:56:07 more
  • 等保2.0實施流程

    流程 結論 ......

    uj5u.com 2020-09-10 03:56:16 more
最新发布
  • 使用Django Rest framework搭建Blog

    在前面的Blog例子中我們使用的是GraphQL, 雖然GraphQL的使用處于上升趨勢,但是Rest API還是使用的更廣泛一些. 所以還是決定回到傳統的rest api framework上來, Django rest framework的官網上給了一個很好用的QuickStart, 我參考Qu ......

    uj5u.com 2023-04-20 08:17:54 more
  • 記錄-new Date() 我忍你很久了!

    這里給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 大家平時在開發的時候有沒被new Date()折磨過?就是它的諸多怪異的設定讓你每每用的時候,都可能不小心踩坑。造成程式意外出錯,卻一下子找不到問題出處,那叫一個煩透了…… 下面,我就列舉它的“四宗罪”及應用思考 可惡的四宗罪 1. Sa ......

    uj5u.com 2023-04-20 08:17:47 more
  • 使用Vue.js實作文字跑馬燈效果

    實作文字跑馬燈效果,首先用到 substring()截取 和 setInterval計時器 clearInterval()清除計時器 效果如下: 實作代碼如下: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta ......

    uj5u.com 2023-04-20 08:12:31 more
  • JavaScript 運算子

    JavaScript 運算子/運算子 在 JavaScript 中,有一些運算子可以使代碼更簡潔、易讀和高效。以下是一些常見的運算子: 1、可選鏈運算子(optional chaining operator) ?.是可選鏈運算子(optional chaining operator)。?. 可選鏈操 ......

    uj5u.com 2023-04-20 08:02:25 more
  • CSS—相對單位rem

    一、概述 rem是一個相對長度單位,它的單位長度取決于根標簽html的字體尺寸。rem即root em的意思,中文翻譯為根em。瀏覽器的文本尺寸一般默認為16px,即默認情況下: 1rem = 16px rem布局原理:根據CSS媒體查詢功能,更改根標簽的字體尺寸,實作rem單位隨螢屏尺寸的變化,如 ......

    uj5u.com 2023-04-20 08:02:21 more
  • 我的第一個NPM包:panghu-planebattle-esm(胖虎飛機大戰)使用說明

    好家伙,我的包終于開發完啦 歡迎使用胖虎的飛機大戰包!! 為你的主頁添加色彩 這是一個有趣的網頁小游戲包,使用canvas和js開發 使用ES6模塊化開發 效果圖如下: (覺得圖片太sb的可以自己改) 代碼已開源!! Git: https://gitee.com/tang-and-han-dynas ......

    uj5u.com 2023-04-20 08:01:50 more
  • 如何在 vue3 中使用 jsx/tsx?

    我們都知道,通常情況下我們使用 vue 大多都是用的 SFC(Signle File Component)單檔案組件模式,即一個組件就是一個檔案,但其實 Vue 也是支持使用 JSX 來撰寫組件的。這里不討論 SFC 和 JSX 的好壞,這個仁者見仁智者見智。本篇文章旨在帶領大家快速了解和使用 Vu ......

    uj5u.com 2023-04-20 08:01:37 more
  • 【Vue2.x原始碼系列06】計算屬性computed原理

    本章目標:計算屬性是如何實作的?計算屬性快取原理以及洋蔥模型的應用?在初始化Vue實體時,我們會給每個計算屬性都創建一個對應watcher,我們稱之為計算屬性watcher ......

    uj5u.com 2023-04-20 08:01:31 more
  • http1.1與http2.0

    一、http是什么 通俗來講,http就是計算機通過網路進行通信的規則,是一個基于請求與回應,無狀態的,應用層協議。常用于TCP/IP協議傳輸資料。目前任何終端之間任何一種通信方式都必須按Http協議進行,否則無法連接。tcp(三次握手,四次揮手)。 請求與回應:客戶端請求、服務端回應資料。 無狀態 ......

    uj5u.com 2023-04-20 08:01:10 more
  • http1.1與http2.0

    一、http是什么 通俗來講,http就是計算機通過網路進行通信的規則,是一個基于請求與回應,無狀態的,應用層協議。常用于TCP/IP協議傳輸資料。目前任何終端之間任何一種通信方式都必須按Http協議進行,否則無法連接。tcp(三次握手,四次揮手)。 請求與回應:客戶端請求、服務端回應資料。 無狀態 ......

    uj5u.com 2023-04-20 08:00:32 more