etcd+jwt实现鉴权

本文基于搭建好etcd集群,若为搭建请移步:https://www.jianshu.com/p/ec0e4911236d
etcd我们使用其存储key/value的功能,存储jwt的私有key,也可以通过etcd来更新key。

设计思路:

内部服务通过go-micro api相互访问时,为了保证访问的安全,防止来自外部的攻击,我们在服务间通过token来识别。
各服务在请求对方是在header中加入token,token使用jwt生成,jwt 的私有key来自etcd。

为什么这么做

我们使用go-micro api 作为网关 ,使用etcd作为服务发现,此时访问各服务的出入口在go-micro api,其对外的地址和端口是固定的,若我们不做防护,来自外部的访问,就可以直接访问到我们内部的服务,很不安全。

为什么使用etcd来存储私有key

这样做是为了,使用相同的私有key,不用每个服务都设置一遍,而且可以实现热更新key,当私有key存在泄漏风险时,通过etcdctl指令更新key即可,无需部署发布。

ok,下面我们说如何在etcd中存储数据,以及如何使用golang代码访问etcd获取数据
当搭建完etcd后,使用一下指令进入其中一个etcd,因为我们搭建的etcd是集群,所以任意一个修改,都是生效的。
使用如下指令进入etcd

docker exec -it 7ffad5617908 /bin/bash
如果不可用改为:
docker exec -it 7ffad5617908 /bin/sh

指定 Etcd API 的版本,默认是 2。指定版本是为了想要在任意位置访问到 etcd 和 etcdctl,如果不设置,代码是无法获取到值的。

执行指令:
export ETCDCTL_API=3

查看版本

etcdctl version

可看到如下输出


图片.png

然后,设置jwt的key

etcdctl put jwtkey 123456

说明:

etcdctl :是etcd指令标识
put:标识新增或更新值
jwtkey:是值名称
123456:是值

至此,etcd就设置好了,开始写golang代码获取etcd中jwtkey的值

package myetcd

import (
    "context"
        "fmt"
    "github.com/coreos/etcd/clientv3"
)
//etcdAddr 是etcd地址(如:192.168.109.131:12379,12379是etcd容器开放对外的端口)
//key ,传jwtkey即可
func GetKey(etcdAddr string,key string)(value string){
    cli, err := clientv3.New(clientv3.Config{
        Endpoints:   []string{etcdAddr},
    })
    if err != nil {
        fmt.Println("connect etcd failed, err:%s", err.Error())
        return
    }

    mylog.Info("connect etcd success")
    defer cli.Close()
    kv := clientv3.NewKV(cli)

    resp, err := kv.Get(context.TODO(), key)
    if err != nil {
        fmt.Println("get etcd key failed, key:%s, err:%s", key, err.Error())
        return
    }
    for _, ev := range resp.Kvs {
        value = string(ev.Value)
    }
    return
}

至此就可以获取到jwtkey了,
下面使用jwt生成token

package token

import (
    jwt "github.com/dgrijalva/jwt-go"
    "github.com/kukayyou/commonlib/myetcd"
    "sync"
    "time"
)

// CustomClaims 自定义的 metadata在加密后作为 JWT 的第二部分返回给客户端
type ServerClaims struct {
    Server string `json:"server"`
    jwt.StandardClaims
}

// Token jwt服务
var (
    rwlock     sync.RWMutex
    PrivateKey string = "orangetutor"
)

//获取私钥
func get() []byte {
    rwlock.RLock()
    defer rwlock.RUnlock()

    return []byte(PrivateKey)
}

//设置私钥
func put(newKey string) {
    rwlock.Lock()
    defer rwlock.Unlock()

    PrivateKey = newKey
}

//检测jwt私钥是否改变
func Init(opt string) {
    go func() {
        for {
            key := myetcd.GetKey(opt, "jwtkey")//获取etcd中的jwtkey
            put(key)
            time.Sleep(time.Second * 10)
        }
    }()
}

//创建token,server是服务名,这里也可以不使用这个字段
//expireTime 是token过期时间
func CreateServerToken(server string, expireTime int64) (string, error) {
    claims := ServerClaims{
        server,
        jwt.StandardClaims{
            Issuer:    ISSUSER,
            IssuedAt:  time.Now().Unix(),
            ExpiresAt: expireTime,
        },
    }

    jwtToken := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
    return jwtToken.SignedString(get())
}

//检验token
func CheckServerToken(tokenStr string) (*ServerClaims, error) {
    t, err := jwt.ParseWithClaims(tokenStr, &ServerClaims{}, func(token *jwt.Token) (interface{}, error) {
        return get(), nil
    })

    if err != nil {
        return nil, err
    }
    // 解密转换类型并返回
    if claims, ok := t.Claims.(*ServerClaims); ok && t.Valid {
        return claims, nil
    }

    return nil, err
}

ok,全部搞定

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,490评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,581评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,830评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,957评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,974评论 6 393
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,754评论 1 307
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,464评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,357评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,847评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,995评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,137评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,819评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,482评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,023评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,149评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,409评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,086评论 2 355