go整合redis、jwt

        本人是做java开发的,最近突然对go提起了兴趣,看了n篇大牛文章后,所谓好好学习天天向上,故有了本篇:

(一)整合redis

"github.com/garyburd/redigo/redis"

举个最简单的例子,存储发送的验证码:

redisutil.go

package redis

import (
	"errors"
	"github.com/garyburd/redigo/redis"
	"math"
	"time"
)


type Redis struct {
	redisCli       *redis.Pool
	maxIdle        int
	maxActive      int
	maxIdleTimeout time.Duration
	maxTimeout     time.Duration
	lazyLimit      bool
	maxSize        int
}

func (r *Redis) getRedisConn() redis.Conn {
	rc := r.redisCli.Get()
	return rc
}

func (r *Redis) GetAllKeys() []string {

	rc := r.getRedisConn()
	defer rc.Close()

	keys, err := redis.Strings(rc.Do("KEYS", "*"))
	if err != nil {
		return make([]string, 0)
	}
	return keys
}

func (r *Redis) Get(key string, timeout int) (string, error) {

	start := time.Now()

	for {
		res, err := r.GetNoWait(key)
		if err != nil {
			return "", err
		} else if res == "" {
			if timeout != -1 {
				lasted := time.Now().Sub(start)
				if r.maxTimeout > lasted {
					t1 := r.maxTimeout
					t2 := time.Duration(timeout)*time.Second - lasted
					time.Sleep(time.Duration(math.Min(float64(t1), float64(t2))))
				} else {
					return "", errors.New("GET timeout")
				}
			} else {
				time.Sleep(r.maxTimeout)
			}
		} else {
			return res, nil
		}
	}
}

func (r *Redis) GetNoWait(key string) (string, error) {

	rc := r.getRedisConn()
	defer rc.Close()

	res, err := redis.String(rc.Do("LPOP", key))

	if err != nil {
		return "", err
	}
	return res, nil
}

func (r *Redis) Put(key string, value string, timeout int) (int, error) {

	start := time.Now()

	for {
		res, err := r.PutNoWait(key, value)

		if err != nil {
			return 0, err
		} else if res == -1 {
			if timeout != -1 {
				lasted := time.Now().Sub(start)
				if r.maxTimeout > lasted {
					t1 := r.maxTimeout
					t2 := time.Duration(timeout)*time.Second - lasted
					time.Sleep(time.Duration(math.Min(float64(t1), float64(t2))))
				} else {
					return 0, errors.New("PUT timeout")
				}
			} else {
				time.Sleep(r.maxTimeout)
			}

		} else {
			return res, nil
		}

	}
}

func (r *Redis) PutNoWait(key string, value string) (int, error) {

	rc := r.getRedisConn()
	defer rc.Close()

	if r.Full(key) {
		return -1, nil
	}

	res, err := redis.Int(rc.Do("RPUSH", key, value))
	if err != nil {
		return 0, err
	}
	return res, nil
}

func (r *Redis) QSize(key string) int {

	rc := r.getRedisConn()
	defer rc.Close()

	res, err := redis.Int(rc.Do("LLEN", key))
	if err != nil {
		return -1
	}

	return res
}

func (r *Redis) Empty(key string) bool {

	rc := r.getRedisConn()
	defer rc.Close()

	res, err := redis.Int(rc.Do("LLEN", key))
	if err != nil {
		return false
	}
	if res == 0 {
		return true
	}
	return false
}

func (r *Redis) Full(key string) bool {

	if r.maxSize != 0 && r.QSize(key) >= r.maxSize {
		return true
	}

	return false
}

redisinterface.go

package redis

import (
	"github.com/garyburd/redigo/redis"
	"time"
)
type RedisFatherInterface interface {
	GetAllKeys() []string
}


type ListInterface interface {
	RedisFatherInterface
	GetNoWait(key string) (string, error)
	Get(key string, timeout int) (string, error)
	Put(key string, value string, timeout int) (int, error)
	PutNoWait(key string, value string) (int, error)
	QSize(key string) int
	Empty(key string) bool
	Full(key string) bool
}

type RedisInterface interface {
	ListInterface
}

func ProducetRedis() (RedisInterface, error) {
	redisObj := &Redis{
		maxIdle:        100,
		maxActive:      130,
		maxIdleTimeout: time.Duration(60) * time.Second,
		maxTimeout:     time.Duration(30) * time.Second,
		lazyLimit:      true,
		maxSize:        100,
	}
	redisObj.redisCli = &redis.Pool{
		MaxIdle:     redisObj.maxIdle,
		MaxActive:   redisObj.maxActive,
		IdleTimeout: redisObj.maxIdleTimeout,
		Wait:        true,
		Dial: func() (redis.Conn, error) {
			con, err := redis.Dial(
				"tcp",
				"127.0.0.1:6379", // address
				redis.DialPassword(""),
				redis.DialDatabase(int(0)),
				redis.DialConnectTimeout(redisObj.maxTimeout),
				redis.DialReadTimeout(redisObj.maxTimeout),
				redis.DialWriteTimeout(redisObj.maxTimeout),
			)
			if err != nil {
				return nil, err
			}
			return con, nil
		},
	}

	return redisObj, nil
}

 controller中存储、获取:

func main()  {
	//放入验证码及关联手机号
	redisCli,err := redis.ProducetRedis()
	if err != nil {
		fmt.Println("redis链接错误",err.Error())
		return
	}
	redisCli.Put("18888888888","8888",3600)
	//根据key取出code
	code,_ := redisCli.GetNoWait("18888888888")
	fmt.Println(code)
}

(二) 整合jwt

用到 "github.com/dgrijalva/jwt-go" 以及 路由mux  "github.com/gorilla/mux"

登录生成token的方法:

func GenerateToken(user *model.User) (string, error) {
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
		"account": user.Account,
		"exp" : time.Now().Add(time.Hour * 2).Unix(),
	})

	return token.SignedString([]byte("secret"))
}

在登录接口中调用生成,并将token返回给前端,需要鉴权的接口每次调用需要在header中传入token。

router.go 

package router

import (
	"github.com/gorilla/mux"
	"myfirstgoproject/api"
	"net/http"
)

type Route struct {
	Method     string
	Pattern    string
	Handler    http.HandlerFunc
	Middleware mux.MiddlewareFunc
}
var routes []Route

func init() {
    register("POST", "/user/edit_pwd", api.EditPwd, auth.TokenMiddleware)
	register("POST", "/user/send_msg", api.SendMsg, nil)
	register("POST", "/user/login", api.Login, nil)
	register("POST", "/user/register", api.Register, nil)
}
func register(method, pattern string, handler http.HandlerFunc, middleware mux.MiddlewareFunc) {
	routes = append(routes, Route{method, pattern, handler, middleware})
}

func NewRouter() *mux.Router {
	router := mux.NewRouter()
	for _, route := range routes {
		r := router.Methods(route.Method).
			Path(route.Pattern)
		if route.Middleware != nil {
			r.Handler(route.Middleware(route.Handler))
		} else {
			r.Handler(route.Handler)
		}
	}
	return router
}

auth.go 实现身份验证鉴权的中间件方法

package auth

import (
	"fmt"
	"github.com/dgrijalva/jwt-go"
	"myfirstgoproject/util"
	"net/http"
)

func TokenMiddleware(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		tokenStr := r.Header.Get("accessToken")
		if tokenStr == "" {
			fmt.Println("error authorized nil")
		} else {
			token, _ := jwt.Parse(tokenStr, func(token *jwt.Token) (interface{}, error) {
				if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
					return nil, fmt.Errorf("not authorization")
				}
				return []byte("secret"), nil
			})
			if !token.Valid {
				fmt.Println("error authorized nil")
			} else {
				next.ServeHTTP(w, r)
			}
		}
	})
}

对需要身份验证的路由添加中间件auth.TokenMiddleware

当访问edit_pwd时如果header中没有accessToken参数,将不能访问。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值