2021-01-28 分類: 網(wǎng)站建設(shè)
系統(tǒng)安全一直是在系統(tǒng)開發(fā)中不可規(guī)避的問題,而權(quán)限控制又跟系統(tǒng)安全密不可分,大到用戶的訪問,小到一個(gè)頁面的按鈕,都有可能涉及到權(quán)限的控制。而renren-security便給我們提供了一套權(quán)限系統(tǒng)開發(fā)的解決方案。
renren-security是"人人社區(qū)"社區(qū)開源的輕量級權(quán)限管理系統(tǒng)。系統(tǒng)采用SprinBoot、Mybatis、Shiro框架進(jìn)行開發(fā),極低門檻,拿來即用,支持分布式部署、Quartz分布式集群調(diào)度、部門管理、數(shù)據(jù)權(quán)限、云存儲等功能。
運(yùn)行效果
系統(tǒng)結(jié)構(gòu)的設(shè)計(jì)也比較清晰,由admin、api、common等幾個(gè)模塊組成,每個(gè)模塊實(shí)現(xiàn)的功能大體如下:
common:公共模塊,以jar包的形式被其他模塊所依賴。實(shí)現(xiàn)了一些工具類和公共功能。包含時(shí)間處理、分頁、Sql過濾、Xss過濾和Redis切面定義、自定義異常處理等功能。
admin:管理系統(tǒng)模塊,以war包形式獨(dú)立部署。基于前后端分離的思想,主要用來用來開發(fā)后臺管理系統(tǒng)。包含用戶管理、角色管理、部門管理、菜單管理、定時(shí)任務(wù)、文件上傳、API校驗(yàn),同時(shí)采用Redis進(jìn)行數(shù)據(jù)緩存,支持單機(jī)和集群的部署。
api:API接口模塊,以war包形式獨(dú)立部署。模塊主要提供給前端UI調(diào)用的一些業(yè)務(wù)接口,實(shí)現(xiàn)了用戶注冊、登錄、接口權(quán)限認(rèn)證和用戶信息獲取。同時(shí)整合了swagger2實(shí)現(xiàn)了API接口文檔,方便了接口的查詢和調(diào)試。
系統(tǒng)架構(gòu)圖
系統(tǒng)設(shè)計(jì)之初就特別注重安全性,基于Shiro在頁面和接口都實(shí)現(xiàn)了權(quán)限校驗(yàn)。
用戶登錄時(shí)對用戶的賬號密碼進(jìn)行驗(yàn)證,獲取用戶的信息和role權(quán)限,頁面顯示的時(shí)候會根據(jù)用戶擁有的權(quán)限顯示對應(yīng)的狀態(tài),接口請求的時(shí)候也會進(jìn)行用戶權(quán)限的校驗(yàn),數(shù)據(jù)保存到數(shù)據(jù)庫時(shí)候還進(jìn)行Sql和Xss的過濾,整個(gè)過程的核心思路是Shiro對用戶的認(rèn)證和授權(quán)。具體流程如下圖:
權(quán)限校驗(yàn)整體思路
實(shí)現(xiàn)Shiro的認(rèn)證和授權(quán),需要自定義Realm繼承于AuthorizingRealm,同時(shí)重寫doGetAuthenticationInfo(認(rèn)證)和doGetAuthorizationInfo(授權(quán))這兩個(gè)方法。這里對于系統(tǒng)與Shiro的整合就不再做多的說明。
用戶登錄的時(shí)候,將用戶的賬號和密碼包裝成一個(gè)UsernamePasswordToken后,再調(diào)用login提交賬戶認(rèn)證,shiro會自動(dòng)調(diào)用我們重寫的doGetAuthenticationInfo方法。
Subject subject = SecurityUtils.getSubject();UsernamePasswordToken token = new UsernamePasswordToken(username, password);//提交認(rèn)證subject.login(token);//Shiro進(jìn)行認(rèn)證@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException { UsernamePasswordToken token = (UsernamePasswordToken)authcToken; //獲取用戶信息 SysUserEntity user = new SysUserEntity(); user.setUsername(token.getUsername()); user = sysUserDao.selectOne(user); //賬號不存在 if(user == null) { throw new UnknownAccountException("賬號或密碼不正確"); } SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, user.getPassword(), ByteSource.Util.bytes(user.getSalt()), getName()); return info;}
如果認(rèn)證成功,那么在系統(tǒng)的任何地方通過SecurityUtils.getSubject()方法就可以獲取認(rèn)證通過的信息。我們也可以借助它的這點(diǎn)特性,實(shí)現(xiàn)用戶的自動(dòng)登錄。
這里需要補(bǔ)充一點(diǎn),系統(tǒng)把權(quán)限化成了一個(gè)個(gè)的標(biāo)簽保存在數(shù)據(jù)庫中,用戶的權(quán)限中持有對應(yīng)的標(biāo)簽則表示擁有對應(yīng)的操作權(quán)限。而對于Shiro的授權(quán),在doGetAuthorizationInfo中需要獲取用戶的所有權(quán)限列表,通過權(quán)限列表篩選出是否擁有操作權(quán)限。
//Shiro進(jìn)行授權(quán)@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { //獲取認(rèn)證時(shí)候添加到SimpleAuthenticationInfo中的實(shí)例 SysUserEntity user = (SysUserEntity)principals.getPrimaryPrincipal(); Long userId = user.getUserId(); //查詢用戶所有權(quán)限 Set<String> permsSet = new HashSet<String>(); List<String> permsList = sysUserDao.queryAllPerms(userId); for(String perms : permsList){ if(StringUtils.isBlank(perms)){ continue; } permsSet.addAll(Arrays.asList(perms.trim().split(","))); } SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); info.setStringPermissions(permsSet); return info;}
Shiro的授權(quán)是被動(dòng)的,只有被相應(yīng)的條件觸發(fā)才會進(jìn)行用戶授權(quán),方式有以下幾種:
1.作用于頁面。頁面里如果遇到<#if shiro.hasPermission("sys:del")>,Shiro會調(diào)用自定義Realm獲取權(quán)限信息,看"sys:del"是否在權(quán)限數(shù)據(jù)中存在,存在則授權(quán)通過,不存在則拒絕訪問,可應(yīng)用于對一些按鈕和標(biāo)簽的特定開放。
<#if shiro.hasPermission("sys:add")> <a @click="add">新增</a></#if><#if shiro.hasPermission("sys:del")> <a @click="del">刪除</a></#if>
2.通過注解的方式作用于接口。在controller中,方法如果加了@RequiresPermissions("sys:del")注解,Shiro同樣會調(diào)用自定義Realm獲取權(quán)限信息,看"sys:del"是否在權(quán)限數(shù)據(jù)中存在,存在則授權(quán)通過,不存在則拒絕訪問,從而實(shí)現(xiàn)對接口的權(quán)限校驗(yàn)。
@RequestMapping("/delete")@RequiresPermissions("sys:del")public R delete(long deptId){ //判斷是否有子部門 List<Long> deptList = sysDeptService.queryDetpIdList(deptId); if(deptList.size() > 0){ return R.error("請先刪除子部門"); } sysDeptService.deleteById(deptId); return R.ok();}
到此,基本上便實(shí)現(xiàn)了Shiro在頁面和接口的權(quán)限控制。當(dāng)然,Shiro更多是作用于表現(xiàn)層的一個(gè)控制,而出于系統(tǒng)安全考慮也應(yīng)該增加對數(shù)據(jù)的校驗(yàn)。因此在數(shù)據(jù)層面,則可通過Sql過濾和Xss過濾的方式實(shí)現(xiàn)過濾。項(xiàng)目中已經(jīng)為其封裝成工具,原理都是正則匹配和字符串替換,感興趣的伙伴可以直接到項(xiàng)目里查看,這里就不再累述了。
系統(tǒng)除了實(shí)現(xiàn)權(quán)限控制外,也實(shí)現(xiàn)了很多后臺管理系統(tǒng)開發(fā)中常用到的一些功能,像Quartz分布式集群調(diào)度、多數(shù)據(jù)源動(dòng)態(tài)切換以及集群部署下Session管理,感興趣的伙伴也可以查看源碼。
項(xiàng)目地
網(wǎng)頁名稱:如何實(shí)現(xiàn)一個(gè)權(quán)限管理系統(tǒng)?(附源碼)
鏈接分享:http://aaarwkj.com/news37/97787.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供用戶體驗(yàn)、App開發(fā)、網(wǎng)站收錄、搜索引擎優(yōu)化、靜態(tài)網(wǎng)站、企業(yè)建站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容