用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
}
再来就是解除封禁的实现,很简单,只要删除我们封禁存的那条记录就可以了。
// 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(),在每个业务前获取封禁级别进行判断就可以简单的实现了。
用go封装一下封禁功能的更多相关文章
- Nginx 通过 Lua + Redis 实现动态封禁 IP
一.背景 为了封禁某些爬虫或者恶意用户对服务器的请求,我们需要建立一个动态的 IP 黑名单.对于黑名单之内的 IP ,拒绝提供服务. 二.架构 实现 IP 黑名单的功能有很多途径: 1.在操作系统层面 ...
- Python爬虫突破封禁的6种常见方法
转 Python爬虫突破封禁的6种常见方法 2016年08月17日 22:36:59 阅读数:37936 在互联网上进行自动数据采集(抓取)这件事和互联网存在的时间差不多一样长.今天大众好像更倾向于用 ...
- openresty开发系列38--通过Lua+Redis 实现动态封禁IP
openresty开发系列38--通过Lua+Redis 实现动态封禁IP 一)需求背景为了封禁某些爬虫或者恶意用户对服务器的请求,我们需要建立一个动态的 IP 黑名单.对于黑名单之内的 IP ,拒绝 ...
- java中如何踢人下线?封禁某个账号后使其会话立即掉线!
需求场景 封禁账号是一个比较常见的业务需求,尤其是在论坛.社区类型的项目中,当出现了违规用户时我们需要将其账号立即封禁. 常规的设计思路是:在设计用户表时增加一个状态字段,例如:status,其值为1 ...
- robots.txt文件没错,为何总提示封禁
大家好,我的robots.txt文件没错,为何百度总提示封禁,哪位高人帮我看看原因,在此谢过. 我的站点www.haokda.com,robots.txt如下: ## robots.txt for P ...
- 利用 ipset 封禁大量 IP
使用 iptables 封 IP,是一种比较简单的应对网络攻击的方式,也算是比较常见.有时候可能会封禁成千上万个 IP,如果添加成千上万条规则,在一台注重性能的服务器或者本身性能就很差的设备上,这就是 ...
- 小木虫emuch遭封禁,新域名muchong.com尚可用
各位虫友: 因为小木虫站点个别虫子违反论坛规定,擅自上传了政治擦边的违规资源.导致小木虫域名 emuch.net 被通信局封禁! 我们第一时间对违规资源进行了删除处理,接下来.我们也将大批量的对站内的 ...
- linux 封禁ip
可以直接服务配置nginx.conf 添加 deny+IP 例如: 封禁单个IP deny 106.5.76.83; #封整个段即从123.0.0.1到123.255.255.254的命令deny 1 ...
- CentOS7 下使用 Firewall防火墙系统封禁允许IP和端口的访问 端口转发 IP转发方法
CENTOS7的防火墙系统默认已经从iptable改成了firewall,使用方法也有所不同,下面是详细介绍 一.管理端口 列出 dmz 级别的被允许的进入端口 # firewall-cmd --zo ...
- linux , nginx: 封禁IP的办法【转】
今天,我们的一台服务器出了问题: 被若干IP地址访问某个接口,该接口会发送短信. 所以,我们可以做两件事: 1. nginx的层面封IP . 2 linux server的层面封IP 先看ngin ...
随机推荐
- mybatis源码-注解sql
Mybatis-注解sql Demo 主启动类 public class MybatisHelloWorld { public static void main(String[] args) thro ...
- 使用sync.Once实现高效的单例模式
1. 简介 本文介绍使用sync.Once来实现单例模式,包括单例模式的定义,以及使用sync.Once实现单例模式的示例,同时也比较了其他单例模式的实现.最后以一个开源框架中使用sync.Once实 ...
- 90 条简单实用的 Python 编程技巧,建议收藏
编码原则 建议 1:理解 Pythonic 概念 -- 详见 Python 中的<Python 之禅> 建议 2:编写 Pythonic 代码 避免不规范代码,比如只用大小写区分变量.使用 ...
- 领域驱动设计DDD应用与最佳实践
领域驱动设计(Domain Driven Design,简称:DDD)设计思想和方法论早在2005年时候就被提出来,但是一直没有重视和推荐使用,直到2015年之后微服务流行之后,再次被人重视和推荐使用 ...
- 移动端网页--better-scroll容易采坑合集
移动端网页--better-scroll容易采坑合集 一.better-scroll源码bug,浏览器需要刷新一次才能正常滑动 在new BScroll时,在options中加入 mouseWheel ...
- [2]SpinalHDL教程——Scala简单入门
第一个 Scala 程序 shell里面输入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!&qu ...
- GPT-NER:通过大型语言模型的命名实体识别
讲在前面,chatgpt出来的时候就想过将其利用在信息抽取方面,后续也发现了不少基于这种大语言模型的信息抽取的论文,比如之前收集过的: https://github.com/cocacola-lab/ ...
- JavaScript基础语法-变量
JavaScript JavaScript - 变量 1. 概念 变量是用于存放数据的容器 通过变量名可以获取数据 并且数据是可修改的 2. 使用 声明变量 只声明不赋值 直接调用 程序会输出unde ...
- 17-js代码压缩
const { resolve } = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); modul ...
- ArrayList实现原理和自动扩容
ArrayList在Java集合中的位置, ArrayList原理: transient Object[] elementData; ArrayList通过数组来实现. 默认构造方法会构造一个容量为1 ...