用go封裝一下封禁功能

来源:https://www.cnblogs.com/weloe/archive/2023/05/25/17431331.html
-Advertisement-
Play Games

本篇為[用go設計開發一個自己的輕量級登錄庫/框架吧]的封禁業務篇,會講講封禁業務的實現,給庫/框架增加新的功能。源碼:https://github.com/weloe/token-go ...


用go封裝一下封禁功能

本篇為用go設計開發一個自己的輕量級登錄庫/框架吧 - 秋玻 - 博客園 (cnblogs.com)的封禁業務篇,會講講封禁業務的實現,給庫/框架增加新的功能。

源碼:https://github.com/weloe/token-go

思路

封禁業務也是在一般項目中比較常見的業務。我們也將它封裝在庫中作為功能之一。

我們同樣使用adapter作為底層的存儲結構,將封禁標示作為k-v結構存儲。

把id和服務名稱service作為key,把封禁的級別level作為value,以此我們能實現一些比較常見的封禁業務。

實現

首先就是封禁方法,首先當然要校驗一下參數,然後存儲封禁標識。要註意的就是level要大於等於1,在封禁後也要調用我們的logger和watcher。

https://github.com/weloe/token-go/blob/8bf577c0309332cb42d17e33b435f06fb74d8e7b/enforcer.go#L390

// Banned ban user, if time == 0,the timeout is not set
func (e *Enforcer) Banned(id string, service string, level int, time int64) error {
	if id == "" || service == "" {
		return fmt.Errorf("parameter cannot be nil")
	}
	if level < 1 {
		return fmt.Errorf("unexpected level = %v, level must large or equal 1", level)
	}
	err := e.adapter.SetStr(e.spliceBannedKey(id, service), strconv.Itoa(level), time)
	if err != nil {
		return err
	}

	// callback
	e.logger.Ban(e.loginType, id, service, level, time)
	if e.watcher != nil {
		e.watcher.Ban(e.loginType, id, service, level, time)
	}

	return nil
}

再來就是解除封禁的實現,很簡單,只要刪除我們封禁存的那條記錄就可以了。

https://github.com/weloe/token-go/blob/8bf577c0309332cb42d17e33b435f06fb74d8e7b/enforcer.go#LL412C6-L412C6

// UnBanned Unblock user account
func (e *Enforcer) UnBanned(id string, services ...string) error {
	if id == "" {
		return fmt.Errorf("parmeter id can not be nil")
	}
	if len(services) == 0 {
		return fmt.Errorf("parmeter services length can not be 0")
	}

	for _, service := range services {
		err := e.adapter.DeleteStr(e.spliceBannedKey(id, service))
		if err != nil {
			return err
		}
		e.logger.UnBan(e.loginType, id, service)
		if e.watcher != nil {
			e.watcher.UnBan(e.loginType, id, service)
		}
	}
	return nil
}

接著還需要提供幾個方便使用的方法

分別用來判斷是否被封禁,獲得封禁的級別,獲得封禁的剩餘時間三個方法

https://github.com/weloe/token-go/blob/8bf577c0309332cb42d17e33b435f06fb74d8e7b/enforcer.go#L434

判斷是否被封禁

// IsBanned if banned return true, else return false
func (e *Enforcer) IsBanned(id string, services string) bool {
	s := e.adapter.GetStr(e.spliceBannedKey(id, services))

	return s != ""
}

https://github.com/weloe/token-go/blob/8bf577c0309332cb42d17e33b435f06fb74d8e7b/enforcer.go#L441

獲得封禁的級別

// GetBannedLevel get banned level
func (e *Enforcer) GetBannedLevel(id string, service string) (int64, error) {
	str := e.adapter.GetStr(e.spliceBannedKey(id, service))
	if str == "" {
		return 0, fmt.Errorf("loginId = %v, service = %v is not banned", id, service)
	}
	time, err := strconv.ParseInt(str, 10, 64)
	if err != nil {
		return 0, err
	}
	return time, nil
}

https://github.com/weloe/token-go/blob/8bf577c0309332cb42d17e33b435f06fb74d8e7b/enforcer.go#L454

獲得封禁的剩餘時間

// GetBannedTime get banned time
func (e *Enforcer) GetBannedTime(id string, service string) int64 {
	timeout := e.adapter.GetStrTimeout(e.spliceBannedKey(id, service))
	return timeout
}

有了這幾個方法,我們就可以使用token-go更為方便是實現登錄業務了。

對於一般的業務,我們其實可以無視封禁級別。只需要使用Banned()進行封禁,在每個需要校驗是否被封禁的業務前進行IsBanned()的判斷就行了。

測試例子:

func TestEnforcer_Banned(t *testing.T) {
	err, enforcer, _ := NewTestEnforcer(t)
	if err != nil {
		t.Fatalf("NewTestEnforcer() failed: %v", err)
	}
	err = enforcer.Banned("1", "comment", 1, 100)
	if err != nil {
		t.Fatalf("Banned() failed: %v", err)
	}
	isBanned := enforcer.IsBanned("1", "comment")
	if !isBanned {
		t.Errorf("unexpected isBanned is false")
	}

	err = enforcer.UnBanned("1", "comment")
	if err != nil {
		t.Fatalf("UnBanned() failed: %v", err)
	}
	isBanned = enforcer.IsBanned("1", "comment")
	if isBanned {
		t.Errorf("unexpected isBanned is false")
	}
}

當然我們對於一個業務會有一些較為複雜的封禁,比如discuss交流業務,如果級別為1我們會禁止評論,如果級別為2我們會禁止評論和點贊,級別為3我們會禁止評論、點贊和收藏。

這個時候我們只需要再加上GetBannedLevel(),在每個業務前獲取封禁級別進行判斷就可以簡單的實現了。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 基本數據類型和字元串類型的自動轉換<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> <%@ page contentType="text/html;charset=UTF-8" language="j ...
  • [toc] 你好!我是[@馬哥python說](https://www.zhihu.com/people/13273183132),一名10年程式猿,正在試錯用pyecharts開發可視化大屏的非常規排版。 以下,我用8種ThemeType展示的同一個可視化數據大屏,可視化主題是分析**“淄博燒烤” ...
  • 來源:https://www.duidaima.com/Group/Topic/JAVA/11942 ## **1、什麼是狀態機** ### 1.1 什麼是狀態 先來解釋什麼是“狀態”( State )。現實事物是有不同狀態的,例如一個自動門,就有 open 和 closed 兩種狀態。我們通常所說 ...
  • [toc] # 高階函數 高階函數是將函數用作參數或返回值的函數,還可以把函數賦值給一個變數。 所有函數類型都有一個圓括弧括起來的參數類型列表以及一個返回類型:(A, B) -> C 表示接受類型分別為 A 與 B 兩個參數並返回一個 C 類型值的函數類型。 參數類型列表可以為空,如 () -> A ...
  • 本文將為大家詳細講解Java中的Map集合,這是我們進行開發時經常用到的知識點,也是大家在學習Java中很重要的一個知識點,更是我們在面試時有可能會問到的問題。文章較長,乾貨滿滿,建議大家收藏慢慢學習。文末有本文重點總結,主頁有全系列文章分享。技術類問題,歡迎大家和我們一起交流討論! ...
  • # 0.相關確定 本教程使用的版本號為專業版PyCharm 2022.3.2,如果您是初學者,為了更好的學習本教程,避免不必要的麻煩,請您下載使用與本教程一致的版本號。 # 1.PyCharm的下載 官網下載:https://www.jetbrains.com/pycharm/download/ot ...
  • Servlet是web體系裡面最重要的部分,下麵羅列幾道常見的面試題,小伙伴們一定要好好記住哈。 1.Servlet是單例的嗎,如何證明? Servlet一般都是單例的,並且是多線程的。如何證明Servlet是單例模式呢?很簡單,重寫Servlet的init方法,或者添加一個構造方法。然後,在web ...
  • Rocksdb作為當下nosql中性能的代表被各個存儲組件(mysql、tikv、pmdk、bluestore)作為存儲引擎底座,其基於LSM tree的核心存儲結構(將隨機寫通過數據結構轉化為順序寫)來提供高性能的寫吞吐時保證了讀性能。同時大量的併發性配置來降低compaction的影響。 ...
一周排行
    -Advertisement-
    Play Games
  • 下麵是一個標準的IDistributedCache用例: public class SomeService(IDistributedCache cache) { public async Task<SomeInformation> GetSomeInformationAsync (string na ...
  • 這個庫提供了在啟動期間實例化已註冊的單例,而不是在首次使用它時實例化。 單例通常在首次使用時創建,這可能會導致響應傳入請求的延遲高於平時。在註冊時創建實例有助於防止第一次Request請求的SLA 以往我們要在註冊的時候實例單例可能會這樣寫: //註冊: services.AddSingleton< ...
  • 最近公司的很多項目都要改單點登錄了,不過大部分都還沒敲定,目前立刻要做的就只有一個比較老的項目 先改一個試試手,主要目標就是最短最快實現功能 首先因為要保留原登錄方式,所以頁面上的改動就是在原來登錄頁面下加一個SSO登錄入口 用超鏈接寫的入口,頁面改造後如下圖: 其中超鏈接的 href="Staff ...
  • Like運算符很好用,特別是它所提供的其中*、?這兩種通配符,在Windows文件系統和各類項目中運用非常廣泛。 但Like運算符僅在VB中支持,在C#中,如何實現呢? 以下是關於LikeString的四種實現方式,其中第四種為Regex正則表達式實現,且在.NET Standard 2.0及以上平... ...
  • 一:背景 1. 講故事 前些天有位朋友找到我,說他們的程式記憶體會偶發性暴漲,自己分析了下是非托管記憶體問題,讓我幫忙看下怎麼回事?哈哈,看到這個dump我還是非常有興趣的,居然還有這種游戲幣自助機類型的程式,下次去大玩家看看他們出幣的機器後端是不是C#寫的?由於dump是linux上的程式,剛好win ...
  • 前言 大家好,我是老馬。很高興遇到你。 我們為 java 開發者實現了 java 版本的 nginx https://github.com/houbb/nginx4j 如果你想知道 servlet 如何處理的,可以參考我的另一個項目: 手寫從零實現簡易版 tomcat minicat 手寫 ngin ...
  • 上一次的介紹,主要圍繞如何統一去捕獲異常,以及為每一種異常添加自己的Mapper實現,並且我們知道,當在ExceptionMapper中返回非200的Response,不支持application/json的響應類型,而是寫死的text/plain類型。 Filter為二方包異常手動捕獲 參考:ht ...
  • 大家好,我是R哥。 今天分享一個爽飛了的面試輔導 case: 這個杭州兄弟空窗期 1 個月+,面試了 6 家公司 0 Offer,不知道問題出在哪,難道是杭州的 IT 崩盤了麽? 報名面試輔導後,經過一個多月的輔導打磨,現在成功入職某上市公司,漲薪 30%+,955 工作制,不咋加班,還不捲。 其他 ...
  • 引入依賴 <!--Freemarker wls--> <dependency> <groupId>org.freemarker</groupId> <artifactId>freemarker</artifactId> <version>2.3.30</version> </dependency> ...
  • 你應如何運行程式 互動式命令模式 開始一個互動式會話 一般是在操作系統命令行下輸入python,且不帶任何參數 系統路徑 如果沒有設置系統的PATH環境變數來包括Python的安裝路徑,可能需要機器上Python可執行文件的完整路徑來代替python 運行的位置:代碼位置 不要輸入的內容:提示符和註 ...