SpringSecurity權(quán)限管理系統(tǒng)實戰(zhàn)—一灾馒、項目簡介和開發(fā)環(huán)境準備

目錄

SpringSecurity權(quán)限管理系統(tǒng)實戰(zhàn)—一、項目簡介和開發(fā)環(huán)境準備
SpringSecurity權(quán)限管理系統(tǒng)實戰(zhàn)—二、日志昧碉、接口文檔等實現(xiàn)
SpringSecurity權(quán)限管理系統(tǒng)實戰(zhàn)—三、主要頁面及接口實現(xiàn)
SpringSecurity權(quán)限管理系統(tǒng)實戰(zhàn)—四阴孟、整合SpringSecurity(上)
SpringSecurity權(quán)限管理系統(tǒng)實戰(zhàn)—五晌纫、整合SpringSecurity(下)
SpringSecurity權(quán)限管理系統(tǒng)實戰(zhàn)—六、SpringSecurity整合jwt
SpringSecurity權(quán)限管理系統(tǒng)實戰(zhàn)—七永丝、處理一些問題
SpringSecurity權(quán)限管理系統(tǒng)實戰(zhàn)—八锹漱、AOP記錄用戶、異常日志
SpringSecurity權(quán)限管理系統(tǒng)實戰(zhàn)—九慕嚷、數(shù)據(jù)權(quán)限的配置

前言

博主的文筆有些差哥牍,大家多擔待

一、簡介

? 在企業(yè)應用中喝检,認證和授權(quán)是非常重要的一部分內(nèi)容嗅辣,業(yè)界最出名的兩個框架就是大名鼎鼎的 Shiro和Spring Security。本次我選取的是和SpringBoot更好兼容的SpringSecurity挠说。

二澡谭、什么是RBAC

? RBAC是Role Based Access Control的縮寫,是基于角色的訪問控制损俭。一般都是分為用戶(user)蛙奖, 角色(role),權(quán)限(permission)三個實體杆兵,角色(role)和權(quán)限(permission)是多對多的 關(guān)系雁仲,用戶(user)和角色(role)也是多對多的關(guān)系。用戶(user)和權(quán)限(permission) 之間沒有直接的關(guān)系琐脏,都是通過角色作為代理攒砖,才能獲取到用戶(user)擁有的權(quán)限缸兔。

? 以下是RBAC0的模型

rbac.png

詳細解釋見

三、系統(tǒng)功能

  • 用戶管理:提供用戶的相關(guān)配置
  • 角色管理:對權(quán)限與菜單進行分配
  • 菜單管理:已實現(xiàn)菜單動態(tài)路由吹艇,后端可配置化惰蜜,支持多級菜單
  • 字典管理:可維護常用一些固定的數(shù)據(jù)
  • 系統(tǒng)日志:記錄用戶操作日志與異常日志
  • SQL監(jiān)控:采用druid 監(jiān)控數(shù)據(jù)庫訪問性能
  • 代碼生成:高靈活度生成前后端代碼,減少大量重復的工作任務
  • 接口管理:方便統(tǒng)一查看管理接口

由于本系統(tǒng)是邊開發(fā)寫此文檔的掐暮,所以可能上述的功能在后續(xù)的開發(fā)中會有刪改蝎抽。

四、環(huán)境搭建

本次系統(tǒng)非前后端分離項目路克,基于SpringBoot+Layui,后臺模板選用的是Pear Admin Layui (我目前見過最漂亮的layui后臺模板樟结,放張圖片讓大家感受一下)

![sql.png](https://upload-images.jianshu.io/upload_images/13222772-0141bb1fc1fd8376.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

數(shù)據(jù)庫設(shè)計

目前先這樣,之后還會擴展精算。

在idea中新建SpringBoot項目,導入所需依賴

  
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <!--這里需要先把SpringSecurity注銷-->
<!--        <dependency>-->
<!--            <groupId>org.springframework.boot</groupId>-->
<!--            <artifactId>spring-boot-starter-security</artifactId>-->
<!--        </dependency>-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <!--swagger-->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.9.2</version>
        </dependency>
        <!--swagger ui-->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.9.2</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>5.2.7.RELEASE</version>
            <scope>compile</scope>
        </dependency>
    </dependencies>

  

在項目中把架構(gòu)搭好瓢宦,創(chuàng)建對應數(shù)據(jù)庫表的eneity、dao灰羽、service驮履、controller,非常簡單不想占用篇幅廉嚼。需要注意的就是實體類中的create_time,和update_time,由于這兩個和id是在多張表中都有出現(xiàn)玫镐,所以我們可以把它們抽離出來,有需要的實體類直接繼承就可以了

@Data
public abstract class BaseEntity<ID extends Serializable> implements Serializable {

    private static final long serialVersionUID = 8925514045582235838L;
    private ID id;
    private Date createTime = new Date();
    @JsonFormat(pattern = "yyyy-MM-dd  HH:mm:ss")
    private Date updateTime = new Date();

}

再插一嘴怠噪,@Data是lambok提供的一個注解恐似,可以用于生成實體類的get和set方法。使用需要導入maven依賴傍念,在idea中也要安裝相應插件矫夷。如何安裝使用使用詳見

然后將PearAdmin的資源放入templates下

templates.png

那么接下來我們先把項目運行起來,在index.html中加入thymeleaf的命名空間憋槐,通過thymeleaf的語法重新引入下資源双藕。

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
        <link rel="stylesheet" th:href="@{/PearAdmin/component/layui/css/layui.css}" />
        <link rel="stylesheet" th:href="@{/PearAdmin/admin/css/pearTab.css}" />
        <link rel="stylesheet" th:href="@{/PearAdmin/admin/css/pearTheme.css}" />
        <link rel="stylesheet" th:href="@{/PearAdmin/admin/css/pearLoad.css}" />
        <link rel="stylesheet" th:href="@{/PearAdmin/admin/css/pearFrame.css}" />
        <link rel="stylesheet" th:href="@{/PearAdmin/admin/css/pearAdmin.css}" />
        <link rel="stylesheet" th:href="@{/PearAdmin/admin/css/pearNotice.css}" />
        <link rel="stylesheet" th:href="@{/PearAdmin/admin/css/pearSocial.css}" />
        <link rel="stylesheet" th:href="@{/PearAdmin/admin/css/pearMenu.css}" />

        <style id="pearone-bg-color"></style>
    </head>
    <body class="layui-layout-body pear-admin">
        <!-- 布局框架 -->
        <div class="layui-layout layui-layout-admin">
            <div class="layui-header">
                <ul class="layui-nav layui-layout-left">
                    <li class="collaspe layui-nav-item"><a href="#" class="layui-icon layui-icon-shrink-right"></a></li>
                    <li class="refresh layui-nav-item"><a href="#" class="layui-icon layui-icon-refresh-1"></a></li>
                </ul>
                <div id="control" class="layui-layout-control"></div>
                <ul class="layui-nav layui-layout-right">
                    <li class="layui-nav-item layui-hide-xs"><a href="#" class="fullScreen layui-icon layui-icon-screen-full"></a></li>
                    <li class="layui-nav-item layui-hide-xs"><a  class="layui-icon layui-icon-website"></a></li>
                    <li class="layui-nav-item layui-hide-xs" id="headerNotice"></li>
                    <li class="layui-nav-item" lay-unselect="">
                        <a href="javascript:;"><img th:src="@{/PearAdmin/admin/images/avatar.jpg}" class="layui-nav-img">就眠儀式</a>
                        <dl class="layui-nav-child">
                            <dd><a href="javascript:;" class="pearson">個人信息</a></dd>
                            <dd><a href="javascript:;">安全配置</a></dd>
                            <dd><a href="login.html">注銷登陸</a></dd>
                        </dl>
                    </li>

                    <li class="setting layui-nav-item"><a href="#" class="layui-icon layui-icon-more-vertical"></a></li>
                </ul>
            </div>
            <div class="layui-side layui-bg-black">
                <div class="layui-logo">
                    <img class="logo" th:src="@{/PearAdmin/admin/images/logo.png}" />
                    <span class="title">Plus Admin</span>
                </div>
                <div class="layui-side-scroll">
                    <div id="sideMenu"></div>
                </div>
            </div>
            <div class="layui-body">
                <div id="content"></div>
            </div>
        </div>
        <!-- 移動端 遮蓋層 -->
        <div class="pear-cover"></div>
        <!-- 初始加載 動畫-->
        <div class="loader-main">
            <div class="loader"></div>
        </div>
        <!-- 聊天組件 -->
        <div id="social" class="layui-hide-xs"></div>
        <!-- 移動端 的 收縮適配 -->
        <div class="collaspe pe-collaspe layui-hide-sm">
            <i class="layui-icon layui-icon-shrink-right"></i>
        </div>
        <script th:src="@{/PearAdmin/component/layui/layui.js}" charset="utf-8"></script>
        <script>
            layui.use(['pearAdmin', 'jquery', 'pearSocial', 'layer'], function() {
                var pearAdmin = layui.pearAdmin;
                var $ = layui.jquery;
                var layer = layui.layer;
                var pearSocial = layui.pearSocial;
                var pearAuth = layui.pearAuth;

                var config = {
                    keepLoad: 2000, // 主 頁 加 載 過 度 時 長 可為 false
                    muiltTab: true, // 是 否 開 啟 多 標 簽 頁 true 開啟 false 關(guān)閉
                    control: false, // 是 否 開 啟 多 系 統(tǒng) 菜 單 true 開啟 false 關(guān)閉
                    theme: "dark-theme", // 默 認 主 題 樣 式 dark-theme 默認主題 light-theme 亮主題
                    index: '/console/console1', // 默 認 加 載 主 頁,這里需要該
                    data: 'PearAdmin/admin/data/menu.json', // 菜 單 數(shù) 據(jù) 加 載 地 址
                    select: '0', // 默 認 選 中 菜 單 項
                    notice: 'PearAdmin/admin/data/notice.json', // 消 息 列 表 數(shù) 據(jù)
                    auth: 'PearAdmin/admin/data/permission.json' // 前端權(quán)限限制,false 關(guān)閉該功能
                };

                var setting = {
                    elem: 'social'
                }

                pearSocial.render(setting);
                pearAdmin.render(config);
            })
        </script>
    </body>
</html>

因為這里默認的index界面是console1.html阳仔,所以console1.html里的資源和json也要重新引入忧陪,這里就不放出代碼了。

Pear自帶了一些json數(shù)據(jù)近范,這里我們先用他的嘶摊,把路徑改成自己項目的。新建一個HelloController顺又,在里面配置下路由

@Controller
public class HelloController {
    @GetMapping(value = "/console/console1")
    @ApiOperation(value = "轉(zhuǎn)發(fā)console1請求")
    public String console1(){
        return "console/console1";
    }

    @GetMapping(value = "/system/organization")
    public String organization(){
        return "system/organization";
    }

    @GetMapping(value = "/system/user")
    public String user(){
        return "system/user";
    }

    @GetMapping(value = "/system/role")
    public String role(){
        return "system/role";
    }

    @GetMapping(value = "/system/power")
    public String power(){
        return "system/power";
    }

    @GetMapping(value = "/page/comment")
    public String comment(){
        return "page/comment";
    }
}

我們啟動項目,看一下效果


index.png

Pear的菜單是通過menu.json來動態(tài)生成的等孵。之后的這個數(shù)據(jù)需要后端返回稚照,但是我先用這個假數(shù)據(jù)。我把我修改過的menu.json貼上來,避免有些同學頁面出不來果录。

[{
        "id": 1,
        "title": "工作空間",
        "type": 0,
        "icon": "layui-icon layui-icon-console",
        "href": "",
        "children": [{
            "id": 0,
            "title": "控制后臺",
            "icon": "layui-icon layui-icon-console",
            "type": 1,
            "openType": "_iframe",
            "href": "console/console1"
        }]
    },
    {
        "id": 4,
        "title": "系統(tǒng)管理",
        "icon": "layui-icon layui-icon-set-fill",
        "type": 0,
        "href": "",
        "children": [{
                "id": 44,
                "title": "部門管理",
                "icon": "layui-icon layui-icon-username",
                "type": 1,
                "openType": "_iframe",
                "href": "system/organization"
            },{
                "id": 41,
                "title": "用戶管理",
                "icon": "layui-icon layui-icon-username",
                "type": 1,
                "openType": "_iframe",
                "href": "system/user"
            },
            {
                "id": 42,
                "title": "角色管理",
                "icon": "layui-icon layui-icon-user",
                "type": 1,
                "openType": "_iframe",
                "href": "system/role"
            },
            {
                "id": 43,
                "title": "權(quán)限管理",
                "icon": "layui-icon layui-icon-user",
                "type": 1,
                "openType": "_iframe",
                "href": "system/power"
            }
        ]
    },
    {
        "id": 2,
        "title": "擴展組件",
        "icon": "layui-icon layui-icon-component",
        "type": 0,
        "href": "",
        "children": [
            {
                "id": 22,
                "title": "進階組件",
                "icon": "layui-icon layui-icon-face-smile",
                "type": 0,
                "href": "view/common/message.html",
                "children": [
                    {
                            "id": 225,
                            "title": "卡片列表",
                            "icon": "layui-icon layui-icon-face-smile",
                            "type": 1,
                            "openType": "_iframe",
                            "href": "view/common/senior/card.html"
                        },
                    {
                        "id": 224,
                        "title": "樹狀結(jié)構(gòu)",
                        "icon": "layui-icon layui-icon-face-smile",
                        "type": 1,
                        "openType": "_iframe",
                        "href": "view/common/senior/dtree.html"
                    }
                ]
            }
        ]
    },
    {
        "id": 3,
        "title": "常用頁面",
        "icon": "layui-icon layui-icon-face-cry",
        "type": 0,
        "href": "",
        "children": [{
            "id": 302,
            "title": "登錄頁面",
            "icon": "layui-icon layui-icon-face-smile",
            "type": 1,
            "openType": "_iframe",
            "href": "login"
        },
        {
            "id": 303,
            "title": "留言板",
            "icon": "layui-icon layui-icon-face-smile",
            "type": 1,
            "openType": "_iframe",
            "href": "page/comment"
        }
        ]
    },
    {
        "id": "error",
        "title": "錯誤頁面",
        "icon": "layui-icon layui-icon-auz",
        "type": 0,
        "href": "",
        "children": [{
                "id": 403,
                "title": "403",
                "icon": "layui-icon layui-icon-face-smile",
                "type": 1,
                "openType": "_iframe",
                "href": "view/error/403.html"
            },
            {
                "id": 404,
                "title": "404",
                "icon": "layui-icon layui-icon-face-cry",
                "type": 1,
                "openType": "_iframe",
                "href": "view/error/404.html"
            },

            {
                "id": 500,
                "title": "500",
                "icon": "layui-icon layui-icon-face-cry",
                "type": 1,
                "openType": "_iframe",
                "href": "view/error/500.html"
            }

        ]
    }
]

五上枕、技術(shù)棧

將會涉及到的技術(shù)棧(待完善)

1、SpringBoot

2弱恒、SpringSecurity

3辨萍、MyBatis

4、Apache Log4j2

5返弹、JWT

6锈玉、Druid

7、Swagger

8义起、Redis

9拉背、Layui

10、Pear Admin Layui

六默终、說明

以上源代碼同步在giteegithub中椅棺,如果可以的話,請給我一個star齐蔽,謝謝

七两疚、目前已完成

Admin端
image text
image text
image text
image text
image text
image text
image text
image text
image text
image text
image text
image text
image text
image text
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市含滴,隨后出現(xiàn)的幾起案子诱渤,更是在濱河造成了極大的恐慌,老刑警劉巖蛙吏,帶你破解...
    沈念sama閱讀 216,544評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件源哩,死亡現(xiàn)場離奇詭異,居然都是意外死亡鸦做,警方通過查閱死者的電腦和手機励烦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來泼诱,“玉大人坛掠,你說我怎么就攤上這事≈瓮玻” “怎么了屉栓?”我有些...
    開封第一講書人閱讀 162,764評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長耸袜。 經(jīng)常有香客問我友多,道長,這世上最難降的妖魔是什么堤框? 我笑而不...
    開封第一講書人閱讀 58,193評論 1 292
  • 正文 為了忘掉前任域滥,我火速辦了婚禮纵柿,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘启绰。我一直安慰自己昂儒,他們只是感情好,可當我...
    茶點故事閱讀 67,216評論 6 388
  • 文/花漫 我一把揭開白布委可。 她就那樣靜靜地躺著渊跋,像睡著了一般。 火紅的嫁衣襯著肌膚如雪着倾。 梳的紋絲不亂的頭發(fā)上拾酝,一...
    開封第一講書人閱讀 51,182評論 1 299
  • 那天,我揣著相機與錄音屈呕,去河邊找鬼微宝。 笑死,一個胖子當著我的面吹牛虎眨,可吹牛的內(nèi)容都是我干的蟋软。 我是一名探鬼主播,決...
    沈念sama閱讀 40,063評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼嗽桩,長吁一口氣:“原來是場噩夢啊……” “哼岳守!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起碌冶,我...
    開封第一講書人閱讀 38,917評論 0 274
  • 序言:老撾萬榮一對情侶失蹤湿痢,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后扑庞,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體譬重,經(jīng)...
    沈念sama閱讀 45,329評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,543評論 2 332
  • 正文 我和宋清朗相戀三年罐氨,在試婚紗的時候發(fā)現(xiàn)自己被綠了臀规。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,722評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡栅隐,死狀恐怖塔嬉,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情租悄,我是刑警寧澤谨究,帶...
    沈念sama閱讀 35,425評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站泣棋,受9級特大地震影響胶哲,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜潭辈,卻給世界環(huán)境...
    茶點故事閱讀 41,019評論 3 326
  • 文/蒙蒙 一鸯屿、第九天 我趴在偏房一處隱蔽的房頂上張望俩檬。 院中可真熱鬧,春花似錦碾盟、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至榔组,卻和暖如春熙尉,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背搓扯。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評論 1 269
  • 我被黑心中介騙來泰國打工检痰, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人锨推。 一個月前我還...
    沈念sama閱讀 47,729評論 2 368
  • 正文 我出身青樓铅歼,卻偏偏與公主長得像,于是被迫代替她去往敵國和親换可。 傳聞我的和親對象是個殘疾皇子椎椰,可洞房花燭夜當晚...
    茶點故事閱讀 44,614評論 2 353