記一次協助排查許可權問題的經歷

youou發表於2021-09-09

  這個事情其實對於每一位後端來講都是很稀鬆平常的事情,但可能筆者這塊經歷較少的緣故,覺得還是比較有意思的,就當做一次備忘錄吧。

  由於公司在某個專案的許可權表的樹層級因定製化緣故做了調整,但許可權表調整之後,測試發現,新建使用者時,勾選某幾個許可權後,發現作為選單的一級許可權沒有問題,但其他的諸如頁面中的許可權都失效了,而測試起初測出的結果是某個模組失效,這塊的介面出不來,甚至都沒聯想到是許可權的緣故(這個模組的非選單類許可權很多,甚至包括它本身頁面的顯示也是由許可權控制的)。

  這時候需要排查原因,根據起初的結果,以為是某個模組的前端程式碼有問題,因為直觀的顯示就是介面出不來,然後就找了我,XXX,介面出不來啦,怎麼搞?

  簡略看了程式碼之後,沒什麼問題,伺服器上的程式碼也沒有問題,所以這時候基本可以排除前端的問題了。

  這時候想到的是許可權的問題,可是,許可權好端端的,怎麼就出問題了呢?我新建了一個使用者,很多許可權都沒問題,但到了上面所說的那個模組,出問題了,果然,出不來。再看返回許可權ID的介面,果然,這個許可權勾選後,沒有。

  好了,問題模擬出來了,本來這個可以直接丟給後端,但抱著試一試的心態找找看,也就有了下面的思考。

  問題的排查過程:

  1、由於公司的介面都有一套特定的規範,所以很好找,找到這個介面的.java檔案,根據特定的類規則,找到dao層的SQL,比較幸運的是這個專案的SQL就是字串拼接,可以直接拿到navcat裡執行,這樣我拿到了這樣的一串SQL。

select DISTINCT FUN_CODE, MENUID, URL from SYS_FUNLIST s, SYS_USERFUNC u where s.FUN_CODE = u.ORG_CODE and u.USER_CODE = 'test0'

  這串SQL的大意其實就是查詢表SYS_FUNLIST中的三個欄位,當這個表中的FUN_CODE這個欄位的值等於另一張SYS_USERFUNC表的ORG_CODE欄位的值時,將結果集過濾出來。

  也就是說使用者的許可權結果集實際上是一張總表中,根據另一張的使用者關聯表過濾出來的結果。而這條SQL的執行結果,與新建使用者儲存時前端傳遞的許可權CODE不一致(出問題的模組字首是12,而這裡只查出了05)。而剛好出問題的那個模組,除了一個入口的選單許可權,其他都沒有。
圖片描述
  2、這樣問題就很明顯了,新建使用者時,有一部分的許可權選擇後無效,無效包括兩種可能,存和取,也就是前端資料傳遞到了後端,但後端沒正常儲存到資料庫,但過往的許可權一直沒有問題,那是不是取的問題?可是查詢的SQL也一直沒人動過,那會是什麼問題導致的呢?我聯想到了最近後端因專案需求調整過這張許可權表的層級,那是不是這個導致的呢?

  3、問題的關鍵在於SYS_USERFUNC這張使用者許可權表,這張由於本人不是後端,起初也不明白做了啥事,但進去之後,發現裡面就只有兩個CODE值,一個使用者的CODE,一個許可權CODE,某個使用者可能出現很多條這個使用者對應的另一個CODE,這時候回頭重新建一個使用者,並勾上有問題模組的許可權,從前端返回的資料來看,這個模組的許可權CODE的字首都是12******,再到使用者許可權表中檢視,發現前端的CODE都正確插入進來了,既然存是沒問題的,那問題就只剩下查了。

  4、將整張的SYS_FUNLIST許可權選單總表看了一遍,發現裡面確實有這個12開頭的許可權,但不是FUN_CODE這個欄位,而是另一個FUNID欄位,可是為何原來的SQL會用這個欄位來關聯呢?原來,這個欄位跟FUNID這個欄位是一樣的,只不過FUNID是主鍵,要在同一張表中分化出各種各樣的許可權樹,需要有另一個具備主鍵唯一性的鍵,設計之初就增加了一個與之一致的欄位,也就是FUN_CODE。

  5、而為什麼會出現上面那個問題?原來,是因為調整了SYS_FUNLIST這張許可權選單總表層級時,不得不將這個FUN_CODE的code值改變,因為前面說的code字首實際上代表著不同的模組,而出問題的那個模組,實際上就是另外的模組,這樣雖然許可權樹是出來了,也正確儲存到關聯表中,但由於存進去的是FUNID,而拿來查的是FUN_CODE,而為了某一個定製做了表的調整,這兩個欄位值不一致了,就導致問題出來了。

  6、那是不是就很好解決了呢?是的,其中第一個方案就是將FUN_CODE的值重新調整成跟FUNID一樣的值,但定製化的許可權樹就沒用了,那怎麼辦呢?改SQL,也就是將上面的FUN_CODE換掉,改成用FUNID去查,也就是這樣:

select DISTINCT FUNID, FUN_CODE, MENUID, URL from SYS_FUNLIST s, SYS_USERFUNC u where s.FUNID = u.ORG_CODE and u.USER_CODE = 'test0'

  這樣,就能正常返回結果集,但由於整條主分支的緣故,不能因為某個定製化的專案影響到其他專案,所以最後的解決方案就是拉一個分支出來,打一個tag,原基線的東西不做變動,這樣問題也就最終解決啦。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/4729/viewspace-2824304/,如需轉載,請註明出處,否則將追究法律責任。

相關文章