1.pom文件添加shiro與aop依賴
<!-- shiro -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.4.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
2.目錄層次
bean存放實體類
config存放配置類
controller存放控制類
dao存放數據接口
service存放業務類
tools存放公共方法
3.建立實體類
主要實體類分別是用戶、角色與權限類
3.1用戶類
省略get與set方法
根據情況一些字段可以不要,但是id、username、password與salt是必要的字段屬性,salt是密碼鹽,加密密碼必要的屬性
這里創建時間與最后一次登錄時間使用的是Long,應為我存儲的時間是時間戳形式,java獲取的時間戳是13位數字超過了無符號int的最大位數
下面的roleList是用戶對應多個角色,而用戶與角色是多對多的關系,所以role類也應該有類似的屬性
3.2角色類
省略get與set
角色類必要的字段也就id與name,可以看情況加上描述與狀態等
角色與權限與用戶都是多對多關系
3.3權限類
省略get與set方法
和角色類類似,必要的字段也不多,只有id、name與relationUrl就是跳轉鏈接
權限與角色是多對多的關系
3.4數據庫表
三個實體類建立之后如果你的數據庫中沒有相關表,將在你保存的那一刻自動在你的數據庫中建立user、role與permission三張表
不過還是建議自己建立,應為自動建立的表沒有注釋,字段也不是最優字段,下面展示表與建表sql
CREATE TABLE `user` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`username` varchar(20) NOT NULL COMMENT '用戶名,登錄時使用',
`password` varchar(32) NOT NULL COMMENT '密碼',
`email` varchar(64) DEFAULT NULL COMMENT '郵箱',
`phone` int(11) unsigned DEFAULT NULL COMMENT '電話號碼',
`nickname` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '昵稱,null時使用username',
`salt` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '密碼鹽',
`ip` varchar(8) DEFAULT NULL COMMENT '最后一次登錄ip',
`create_time` bigint(13) unsigned NOT NULL COMMENT '注冊時間',
`last_login` bigint(13) unsigned DEFAULT NULL COMMENT '最后一次登錄時間',
`is_use` tinyint(1) unsigned NOT NULL DEFAULT '1' COMMENT '狀態:0凍結1正常2刪除',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用戶表';
CREATE TABLE `role` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(20) NOT NULL COMMENT '名稱',
`description` varchar(255) DEFAULT NULL COMMENT '描述',
`is_use` tinyint(1) unsigned NOT NULL DEFAULT '1' COMMENT '狀態:0棄用1正常',
`create_time` bigint(13) unsigned NOT NULL DEFAULT '0' COMMENT '創建時間',
`update_time` bigint(13) unsigned NOT NULL DEFAULT '0' COMMENT '更新時間',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='角色表';
CREATE TABLE `permission` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(20) NOT NULL COMMENT '名稱',
`description` varchar(255) DEFAULT NULL COMMENT '描述',
`type` varchar(32) NOT NULL DEFAULT 'menu' COMMENT '類型:menu,botton',
`relation_url` varchar(255) DEFAULT NULL COMMENT '關聯鏈接',
`permission` varchar(32) NOT NULL DEFAULT '*' COMMENT '權限類型:*全部create新增update修改delete刪除view查看,多個之間英文逗號分隔',
`super_id` int(10) unsigned DEFAULT NULL COMMENT '父級id',
`create_time` bigint(13) unsigned NOT NULL COMMENT '創建時間',
`update_time` bigint(13) unsigned NOT NULL COMMENT '更新時間',
`is_use` tinyint(1) unsigned NOT NULL DEFAULT '1' COMMENT '狀態:0棄用1正常',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='權限表';
4.配置shiro
4.1在config中建立MyRealm.java
這個類作用是做一個鏈接的權限校驗與登錄認證,登錄認證應該都明白,鏈接校驗就是區分一個用戶所擁有的角色是否有訪問這個鏈接的權限
MyRealm類繼承AuthorizingRealm
4.1.1鏈接校驗
鏈接校驗方法用了兩層for循環將該用戶角色下所有的權限遍歷出來一一校對是否有訪問權限
4.1.2登錄認證
方法內有部分注釋也就不全說了,主要要說的是new SimpleAuthentication中的四個參數
user指user類
user.getPassword()指用戶存在數據庫中的密碼
ByteSource.Util.bytes(user.getSalt())指用戶密碼鹽
getName()就是realm的name
4.2同在config包下建立ShiroConfig.java類
4.2.1過濾器方法shiroFilter
注釋已經說得很清楚了,這里就強調一點
就是是這個方法是順序執行的/**一定要放在后面
4.2.2其余方法
需要注意的就是第一個方法的散列算法與散列算法次數,需要與注冊方法相匹配,不然登錄會出問題
5.注冊
注冊與登錄將會以一個流程的形式展示代碼,而不是直接把一個類一個接口的代碼直接粘貼出來
5.1前端注冊頁面
在src/main/resources/templates中建立login.html
這里把注冊和登錄放在一個界面中
前台頁面效果
很簡單的一個界面具體怎么寫就不去討論了
5.2在controller包中建立UserController,然后建立注冊控制方法regist
5.3在Service包中建立UserService類,編寫控制器類需要用到的注冊方法regist()
上面兩個方法基本理解起來應該不難,只是多了兩個工具類的使用
一個是EncryptionUtil與Complex
Complex工具類的isNumber方法就不展示了,這只是個簡單的判斷字符串是否能轉換成Long或其他數字的方法
而EncryptionUtil方法也稍微放后面
5.4在dao包中建立UserRepository倉庫接口
這個接口你不必去實現它,它會自動通過你提供的東西去查詢
比如findByUsername會自動將你提供的string拿去在數據庫中匹配username字段
5.5在tools包中建立Complex.java與EncryptionUtil.java兩個工具類
Complex是復雜工具,存儲的方法都為靜態,可以直接調用與各種類與方法中,里面的方法沒有什么關聯性
EncryptionUtil是專門做加密工作的工具類
這是將傳來的原始密碼字符串進行加密的方法
salt是系統生成的密碼鹽,為32字符的字符串
password則是用md5散列算法將原始密碼+密碼鹽進行兩次加密,這里要與ShiroConfig類中的hashedCredentialsMatcher()方法里面的說明匹配
返回密碼鹽與加密密碼的map
到這里整個注冊流程就算完成了
6.登錄
6.1前端代碼
同樣是在login.html中
這里th:src="@{/validateCode}"是thymeleaf的語法,就是請求后端帶有"/validateCode"注釋的方法,獲取驗證碼,這里先不介紹了
前台展示
5.2控制類
同樣是在UserController中創建登錄方法login()
不過這里的login只處理失敗的情況,成功的情況在ShiroConfig中處理
具體的方法解釋注釋也說的比較明白了
@resource下面的兩行可以忽略,那個是驗證碼方法使用的
topicService是頁面頂部導航欄也不用去管他,需要管的是Complex.setUser
將用戶信息存放到頁面中,方法第一行就是獲取登錄后用戶的信息,當然不止可以存user對象也可以存string
至於Service與Repository就不再重復展示了,登錄需要用到前面提到的UserService.findByNameOrPhone()方法與注冊重疊了