五月天青色头像情侣网名,国产亚洲av片在线观看18女人,黑人巨茎大战俄罗斯美女,扒下她的小内裤打屁股

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

醫(yī)療系統(tǒng)的權(quán)限就該這樣設(shè)計,穩(wěn)!

2023-06-27 19:01 作者:bili_41537505867  | 我要投稿

權(quán)限管控可以通俗的理解為權(quán)力限制,即不同的人由于擁有不同權(quán)力,他所看到的、能使用的可能不一樣。對應(yīng)到一個應(yīng)用系統(tǒng),其實(shí)就是一個用戶可能擁有不同的數(shù)據(jù)權(quán)限(看到的)和操作權(quán)限(使用的)。

主流的權(quán)限模型主要分為以下五種:

  • ACL模型:訪問控制列表

  • DAC模型:自主訪問控制

  • MAC模型:強(qiáng)制訪問控制

  • ABAC模型:基于屬性的訪問控制

  • RBAC模型:基于角色的權(quán)限訪問控制

目前主流的權(quán)限模型是RBAC模型,碼猿慢病云管理系統(tǒng)則是使用RBAC模型進(jìn)行權(quán)限控制。

RBAC 基于角色的權(quán)限訪問控制

Role-Based Access Control,核心在于用戶只和角色關(guān)聯(lián),而角色代表對了權(quán)限,是一系列權(quán)限的集合。

RBAC三要素:

  1. 用戶:系統(tǒng)中所有的賬戶

  2. 角色:一系列權(quán)限的集合(如:管理員,開發(fā)者,審計管理員等)

  3. 權(quán)限:菜單,按鈕,數(shù)據(jù)的增刪改查等詳細(xì)權(quán)限。

RBAC中,權(quán)限與角色相關(guān)聯(lián),用戶通過成為適當(dāng)角色的成員而得到這些角色的權(quán)限。

角色是為了完成各種工作而創(chuàng)造,用戶則依據(jù)它的責(zé)任和資格來被指派相應(yīng)的角色,用戶可以很容易地從一個角色被指派到另一個角色。

角色可依新的需求和系統(tǒng)的合并而賦予新的權(quán)限,而權(quán)限也可根據(jù)需要而從某角色中回收。角色與角色的關(guān)系同樣也存在繼承關(guān)系防止越權(quán)。

優(yōu)點(diǎn):便于角色劃分,更靈活的授權(quán)管理;最小顆粒度授權(quán);

在碼猿慢病云管理系統(tǒng)(醫(yī)療系統(tǒng))的用戶、角色、權(quán)限代表什么呢?

1. 用戶

這里的用戶和其他系統(tǒng)并無區(qū)別,則是能登錄系統(tǒng)的用戶,對應(yīng)的表為:codepae/sys_user,字段屬性如下:


其中比較重要的字段:

  1. username:用戶登錄系統(tǒng)的賬號,醫(yī)療系統(tǒng)中則是HIS系統(tǒng)中的工號,(username,hos_id,del_flag)組成唯一索引,同一家醫(yī)院這個賬號必須是唯一

  2. hos_id:醫(yī)院的ID,多租戶架構(gòu)模式下區(qū)分租戶的字段

  3. dept_id:科室ID/病區(qū)ID,醫(yī)院中的醫(yī)生、護(hù)士是按照科室/病區(qū)管理患者的,因此在入職時就會分配到對應(yīng)的科室/病區(qū),比如女人的婦科病,去醫(yī)院看病掛的肯定是婦科,這個婦科門診則是有對應(yīng)的醫(yī)生坐診,不可能找個骨科的醫(yī)生去看婦科的毛病

為什么要有科室、病區(qū)這兩個概念?

科室則是平常我們醫(yī)院掛號經(jīng)??吹降目剖?,比如婦科、骨科、內(nèi)分泌科、心內(nèi)科、心腦血管科等

病區(qū)這個概念是針對住院來說,住過院的應(yīng)該都知道護(hù)士照顧病人是通過病區(qū)->病房->床位號定位病人,比如二十病區(qū)->302房間->10號床

醫(yī)院為了病房能夠更好的管理,節(jié)省醫(yī)護(hù)的資源,一個病區(qū)中包含多個科室的患者,比如新生兒科、產(chǎn)科、兒科這三個科室你會看到里面的住院患者都是住在同一個病區(qū),同一批護(hù)士管理,比如十病區(qū)。

這樣應(yīng)該就能理解了,大部分的HIS系統(tǒng)中,醫(yī)生是劃分到科室管理,比如婦科,骨科,畢竟術(shù)業(yè)有專攻,護(hù)士是按照病區(qū)劃分管理,因?yàn)樽o(hù)士本質(zhì)上是照顧病人,打打針等一些工作,專一性不是那么高;因此在sys_user用戶表中的dept_id既能表示科室也能表示病區(qū)了。

PS:一些比較落后的小醫(yī)院,HIS系統(tǒng)比較老舊,醫(yī)生、護(hù)士還是按照科室管理

2. 角色

在醫(yī)院中的主要角色則是:醫(yī)生和護(hù)士,這個想必大家都能理解

碼猿慢病云管理系統(tǒng)中內(nèi)置了七個角色,已經(jīng)完全夠用了,如下:


  • 管理員:這個是每個醫(yī)院的系統(tǒng)管理員,在添加醫(yī)院的時候會指定一個管理員

  • 系統(tǒng)管理員:這個是整個系統(tǒng)的管理員,擁有最高權(quán)限,可以看到所有醫(yī)院的數(shù)據(jù)

  • 醫(yī)生:醫(yī)生的角色

  • 護(hù)士:護(hù)士的角色

對應(yīng)數(shù)據(jù)庫:codeape/sys_role,如下:


和用戶通過另外一張表存儲關(guān)聯(lián)關(guān)系:codeape/sys_user_role


碼猿慢病云管理系統(tǒng)中醫(yī)生和護(hù)士這兩個角色的最大區(qū)別:護(hù)士需要手持PDA(數(shù)據(jù)采集設(shè)備)采集數(shù)據(jù)(血糖、尿酸、血酮),添加數(shù)據(jù)等操作,醫(yī)生則是每天查看患者的數(shù)據(jù)為治療提供輔助

3. 權(quán)限

碼猿慢病云管理系統(tǒng)中的權(quán)限有如下三類:

  1. 菜單的權(quán)限:客戶端菜單的權(quán)限

  2. 按鈕/接口的權(quán)限:客戶端按鈕/接口的權(quán)限,比如添加患者這個

  3. 科室/病區(qū)的權(quán)限:

1. 菜單的權(quán)限

控制客戶端的菜單顯示,如下:


目前有這幾個根菜單+子菜單。

2. 按鈕權(quán)限

客戶端按鈕的權(quán)限,比如新增、刪除、編輯按鈕的權(quán)限,比如住院患者的4個按鈕,如下:


每個按鈕都有一個權(quán)限標(biāo)識編碼,比如inhos_patinfohot_get,客戶端只需要判斷當(dāng)前登錄用戶的權(quán)限樹中是否存在這個權(quán)限,有則顯示,沒有則不顯示

3. 接口權(quán)限

客戶端的接口權(quán)限和按鈕權(quán)限共用,比如查詢住院患者這個權(quán)限對應(yīng)的標(biāo)識也是:inhos_patinfohot_get

那么這個接口權(quán)限如何控制?碼猿慢病云管理系統(tǒng)中是將接口權(quán)限的鑒權(quán)下沉到各個微服務(wù),交給開發(fā)者在開發(fā)接口時通過@PreAuthorize注解控制權(quán)限,比如查詢住院患者列表的這個接口,如下:

//com.code.ape.codeape.inhos.controller.PatInfoHotController#getPatInfoHotPage @Operation(summary = "分頁查詢在院患者", description = "分頁查詢在院患者") ? ?@GetMapping("/page" ) @InjectAuth ? ?@PreAuthorize("@pms.hasPermission('inhos_patinfohot_get')" ) ? ?public R<Page<PatInfoVO>> getPatInfoHotPage(Page<PatInfoVO> page, PatInfoDTO dto) { ? ? ? ?return R.ok(patInfoHotService.listPage(page,dto)); ? ?}

@PreAuthorize這個注解是Spring Security內(nèi)置的鑒權(quán)接口,其中的value這個屬性支持SPEL表達(dá)式,真實(shí)的實(shí)現(xiàn)代碼如下:

/** * @author 公眾號:碼猿技術(shù)專欄 ? 版權(quán):不才陳某所署,侵權(quán)必究 * {@link com.code.ape.codeape.common.security.component.PermissionService} */public class PermissionService { /** ?* 判斷接口是否有任意xxx,xxx權(quán)限 ?* @param permissions 權(quán)限 ?* @return {boolean} ?*/ public boolean hasPermission(String... permissions) { ?if (ArrayUtil.isEmpty(permissions)) { ? return false; ?} ? ? ? ?//代碼(1) ?Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); ?if (authentication == null) { ? return false; ?} ? ? ? ?//代碼(2) ?Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities(); ?////代碼(3) ? ? ? ?return authorities.stream() ? .map(GrantedAuthority::getAuthority) ? .filter(StringUtils::hasText) ? .anyMatch(x -> PatternMatchUtils.simpleMatch(permissions, x)); } }

邏輯其實(shí)很簡單,上述代碼三個部分:

  • 代碼(1)?:從Spring Security 上下文中獲取當(dāng)前用戶登錄的身份信息Authentication,其中就包括權(quán)限

  • 代碼(2)?:從用戶身份信息Authentication中獲取用戶的權(quán)限樹

  • 代碼(3)?:將當(dāng)前登錄用戶的權(quán)限和@PreAuthorize傳入的權(quán)限比較,判斷是否鑒權(quán)通過

4. 科室/病區(qū)權(quán)限

這個權(quán)限則是比較特殊了,先描述一下場景:

在醫(yī)療系統(tǒng)中,醫(yī)生/護(hù)士是無權(quán)限查看全部科室的數(shù)據(jù)的,只能查看自己負(fù)責(zé)科室/病區(qū)的數(shù)據(jù),這樣是為了避免醫(yī)療事故;你想想如果有個心懷不軌的醫(yī)生,隨意更改其他科室/病區(qū)患者的數(shù)據(jù),導(dǎo)致醫(yī)生誤判病情,這樣的責(zé)任誰來承擔(dān)?

所以醫(yī)療系統(tǒng)中都需要控制醫(yī)護(hù)科室/病區(qū)這個權(quán)限,這樣才能保證不發(fā)生不必要的醫(yī)療事故。

碼猿慢病云管理系統(tǒng)中的科室/病區(qū)權(quán)限如何控制的呢?

在新增醫(yī)護(hù)的時候有個科室權(quán)限的多選器,如下圖:


這樣就能輕松設(shè)置醫(yī)護(hù)的科室/病區(qū)權(quán)限了,這部分對應(yīng)關(guān)系是持久化在codeape/sys_user_dept這張表中,如下:


那么此時當(dāng)前醫(yī)護(hù)的科室/病區(qū)權(quán)限如何計算呢?

先給答案,分為兩種情況;

第一種:WEB端/PAD端

先說第一種:在WEB端/PAD端,醫(yī)護(hù)的權(quán)限=醫(yī)護(hù)所在的科室+醫(yī)護(hù)的科室權(quán)限+關(guān)聯(lián)科室

什么意思?比如白鹿這個護(hù)士,如下圖:


所屬科室為內(nèi)分泌科,科室權(quán)限為神經(jīng)內(nèi)科+內(nèi)分泌科+心內(nèi)科,那么前面兩層的權(quán)限則是神經(jīng)內(nèi)科+內(nèi)分泌科+心內(nèi)科(注意去重)

那么關(guān)聯(lián)科室什么意思?比如神經(jīng)內(nèi)科下面有個神經(jīng)內(nèi)科病區(qū),但是醫(yī)護(hù)的科室在入職時都設(shè)置在了神經(jīng)內(nèi)科,那么他們?nèi)绾文芸吹缴窠?jīng)內(nèi)科病區(qū)的數(shù)據(jù)呢?

一種方案可以在科室權(quán)限那一欄再加上神經(jīng)內(nèi)科病區(qū),這種當(dāng)然可行,但是你要為每個醫(yī)護(hù)都設(shè)置一遍。

第二種方案:可以將神經(jīng)內(nèi)科和神經(jīng)內(nèi)科病區(qū)關(guān)聯(lián)起來,這樣只要有神經(jīng)內(nèi)科這個權(quán)限,那么就必然有神經(jīng)內(nèi)科病區(qū)這個權(quán)限,這個在碼猿慢病云管理系統(tǒng)中也有設(shè)置關(guān)聯(lián)關(guān)系,如下圖:


在添加科室的時候可以選擇根節(jié)點(diǎn)科室。

對應(yīng)的關(guān)系持久化在codeape/sys_dept_relation中,結(jié)構(gòu)如下:

字段類型注釋ancestorbigint祖先節(jié)點(diǎn)(科室/病區(qū)ID)descendantbigint子節(jié)點(diǎn)(科室/病區(qū)ID)

科室/病區(qū)權(quán)限在用戶登錄時就會查詢出來放到SecurityContext上下文中,具體的方法如下圖:


那在醫(yī)護(hù)查詢數(shù)據(jù)如何去根據(jù)這個科室/病區(qū)權(quán)限過濾呢?

在請求DTO中有個基礎(chǔ)實(shí)體類com.code.ape.codeape.common.core.entity.BaseParam,如下:

@Datapublic class BaseParam { ? /** ? ?* 醫(yī)院Id ? ?*/ ? private Long hosId; ? /** ? ?* 用戶ID ? ?*/ ? private Long userId; ? /** ? ?* 醫(yī)護(hù)的科室權(quán)限 ? ?*/ ? private List<Long> dataAuth; ? /** ? ?* 請求來源客戶端ID ? ?*/ ? private String clientId; ? /** ? ?* 設(shè)備的SN號 ? ?*/ ? private String sn; }

這個類中的所有屬性都會自動注入,只需要在controller方法中標(biāo)注一個注解:@InjectAuth,如何做到的呢?

@InjectAuth這個注解是通過AOP方式自動注入?yún)?shù),代碼如下:

@Slf4j@RequiredArgsConstructor@Aspectpublic class CodeapeInjectAuthAspect implements Ordered { @SneakyThrows @Around("@annotation(injectAuth) &&" + ? "(@annotation(org.springframework.web.bind.annotation.PostMapping)||" + ? "@annotation(org.springframework.web.bind.annotation.GetMapping)||" + ? "@annotation(org.springframework.web.bind.annotation.DeleteMapping)||" + ? "@annotation(org.springframework.web.bind.annotation.PutMapping)||" + ? "@annotation(org.springframework.web.bind.annotation.RequestMapping))") public Object around(ProceedingJoinPoint joinPoint, InjectAuth injectAuth) { ?if (injectAuth.enable()){ ? CodeapeUser codeapeUser = Objects.requireNonNull(SecurityUtils.getUser()); ? Object[] args = joinPoint.getArgs(); ? for (int i = 0; i < args.length; i++) { ? ?if (!(args[i] instanceof BaseParam)) { ? ? continue; ? ?} ? ?BaseParam baseParam = (BaseParam) args[i]; ? ?/** ? ? * 1. web端:權(quán)限就是當(dāng)前登錄用戶的權(quán)限 ? ? * 2. pda端,權(quán)限則是設(shè)備的權(quán)限+當(dāng)前登錄用戶的權(quán)限 ? ? * 這里的權(quán)限取值是token中的deptAuths,這個在登錄的時候就查詢出來,緩存在redis中,所以這里直接用就可以 ? ? */ ? ?//醫(yī)院管理員+系統(tǒng)管理員不賦予權(quán)限 ? ?boolean flag= ArrayUtil.contains(codeapeUser.getRoleCodes(),SecurityConstants.SYSTEM_ADMIN_CODE) ?||ArrayUtil.contains(codeapeUser.getRoleCodes(),SecurityConstants.HOS_ADMIN_CODE); ? ?baseParam.setDataAuth(flag?null:Arrays.asList(codeapeUser.getDeptAuths())); ? ?baseParam.setHosId(codeapeUser.getHosId()); ? ?baseParam.setUserId(codeapeUser.getId()); ? ?baseParam.setClientId(codeapeUser.getClientId()); ? ?baseParam.setSn(codeapeUser.getSn()); ? } ?} ?return joinPoint.proceed(); } @Override public int getOrder() { ?return Ordered.HIGHEST_PRECEDENCE + 4; } }

直接取的是CodeapeUser中的deptAuths,CodeapeUser則是SecurityContext上下文的用戶身份信息

這樣則能夠取到用戶的科室/病區(qū)權(quán)限,然后則能在SQL中根據(jù)這個dataAuth屬性去過濾數(shù)據(jù)了,比如分頁查詢住院患者的接口,controller方法如下:

com.code.ape.codeape.inhos.controller.PatInfoHotController#getPatInfoHotPage



SQL如下:

com.code.ape.codeape.inhos.mapper.PatInfoHotMapper#selectPatInfoPage


這部分的SQL片段則是根據(jù)住院患者的科室去過濾。

第二種PDA端

這里的PDA指的是護(hù)士的手持設(shè)備,這個設(shè)備和智能手機(jī)一樣,根據(jù)自己賬號登錄上去,給大家大致畫一下PDA上都有哪些內(nèi)容,如下圖:


其實(shí)就和APP是一樣的,里面可以看到大致四塊內(nèi)容(當(dāng)然還有其他):

  1. 患者管理:這個是顯示所有的住院患者,護(hù)士可以選擇對應(yīng)的患者進(jìn)行數(shù)據(jù)采集,這樣采集的數(shù)據(jù)才能和患者自定綁定

  2. 檢測任務(wù):這個則是醫(yī)生下的醫(yī)囑任務(wù),按照時間段顯示,比如醫(yī)生下的三餐前后測血糖這個醫(yī)囑任務(wù),則經(jīng)過護(hù)士拆分后,則變成了6個子任務(wù):空腹測血糖、早餐后測血糖、午餐前測血糖、午餐后測血糖、晚餐前測血糖、晚餐后測血糖。那么在每個時間段顯示要測血糖的患者床位即可,護(hù)士選擇對應(yīng)的床位則可以測血糖

  3. 檢測記錄:這里是展示所有患者測量的血糖數(shù)據(jù),按照時間段表格形式的展示

  4. 質(zhì)控:這個則是設(shè)備的質(zhì)控,護(hù)士每天要定時對設(shè)備進(jìn)行質(zhì)控(質(zhì)量檢測),查看這臺設(shè)備測量是否準(zhǔn)確

那么問題來了,PDA上需要顯示的數(shù)據(jù)是整個醫(yī)院的數(shù)據(jù)嗎?顯然不可能,也是需要根據(jù)護(hù)士科室/病區(qū)權(quán)限過濾,可以看到上方有一個科室的篩選項(xiàng),默認(rèn)是所有科室,則是當(dāng)前登錄用戶的所有科室權(quán)限

那么PDA端的醫(yī)護(hù)權(quán)限和WEB端一樣嗎?

當(dāng)然不是,因?yàn)樵O(shè)備存在以下兩種網(wǎng)絡(luò)情況:

  1. 在線:連上wifi或者SIM卡,這樣能夠時刻保持網(wǎng)絡(luò)暢通的情況下,屬于在線狀態(tài),拉數(shù)據(jù)/上傳數(shù)據(jù)直接訪問服務(wù)端即可

  2. 離線:有些醫(yī)院沒有內(nèi)網(wǎng)的wifi或者SIM卡,只能連有線網(wǎng)絡(luò),一旦設(shè)備拔掉網(wǎng)線去病房檢測,則是離線的狀態(tài)

離線情況下就需要設(shè)備本地做緩存了,那么這個緩存的數(shù)據(jù)到底拉哪些數(shù)據(jù)?不可能將整個醫(yī)院的數(shù)據(jù)都拉下來,設(shè)備的內(nèi)存是有限的。這個時候就需要用到設(shè)備的權(quán)限了,在添加設(shè)備的時候有兩個的選項(xiàng),如下:


科室和關(guān)聯(lián)科室這兩個選項(xiàng),一般一臺設(shè)備只供一個病區(qū)使用,此時將科室選項(xiàng)選擇對應(yīng)的病區(qū)即可,那么特殊情況下,比如一病區(qū)和二病區(qū)共用一臺設(shè)備,此時就需要用到關(guān)聯(lián)科室了。

此時應(yīng)該明白了設(shè)備的權(quán)限=科室+關(guān)聯(lián)科室

只要設(shè)備連上網(wǎng)絡(luò),在用戶不登錄的情況下,調(diào)用接口獲取數(shù)據(jù)的時候就應(yīng)該獲取的是設(shè)備權(quán)限的數(shù)據(jù)。

那登錄該臺設(shè)備的用戶權(quán)限呢?應(yīng)該怎么取值呢?很簡單,分為兩種情況:

  1. 用戶的權(quán)限和設(shè)備的權(quán)限取并集

  2. 用戶的權(quán)限和設(shè)備的權(quán)限取交集

按照正常的邏輯是應(yīng)該是第二種情況取交集,因?yàn)槟阕o(hù)士沒有這個權(quán)限就不應(yīng)該看到該科室/病區(qū)的數(shù)據(jù),但是實(shí)際情況是很多醫(yī)院的護(hù)士都是輪轉(zhuǎn)的,比如這個月到一病區(qū),下個月到二病區(qū),他們的科室/病區(qū)權(quán)限的維護(hù)并不是很及時,主要是信息科的人員太懶了,這樣的話就會導(dǎo)致如果按照第二種情況取交集,那么這個護(hù)士登錄該臺設(shè)備就看不到自己所管的科室/病區(qū)的數(shù)據(jù)了。所以在碼猿慢病云管理系統(tǒng)中是采用的第一種方案。

相關(guān)代碼在com.code.ape.codeape.common.security.service.CodeapePDAUserDetailsServiceImpl#getUserDetails,如下圖:


總結(jié)

這節(jié)內(nèi)容介紹了RBAC權(quán)限模型以及碼猿慢病云管理系統(tǒng)中權(quán)限是如何設(shè)計的,最重要的是科室/病區(qū)權(quán)限的設(shè)計,大家一定要理解其中的邏輯,幾乎所有的醫(yī)療系統(tǒng)都是按照這個邏輯處理的。


醫(yī)療系統(tǒng)的權(quán)限就該這樣設(shè)計,穩(wěn)!的評論 (共 條)

分享到微博請遵守國家法律
芷江| 类乌齐县| 通河县| 上杭县| 鄂伦春自治旗| 海宁市| 从化市| 瑞昌市| 黎川县| 嘉祥县| 建水县| 凤阳县| 滕州市| 枞阳县| 呼伦贝尔市| 辽阳市| 循化| 荔波县| 嵊州市| 新丰县| 舒兰市| 白水县| 灵石县| 平泉县| 四平市| 安乡县| 桃源县| 南平市| 措美县| 白玉县| 郑州市| 崇信县| 海安县| 开封市| 鄂伦春自治旗| 迁安市| 酒泉市| 固始县| 通许县| 如东县| 奉新县|