当前位置: 萬仟网 > IT编程>脚本编程>Go语言 > golang简单实现jwt验证(beego、xorm、jwt)

golang简单实现jwt验证(beego、xorm、jwt)

2019年01月13日 09:23  | 萬仟网IT编程  | 我要评论

程序目录结构

简单实现,用户登录后返回一个jwt的token,下次请求带上token请求用户信息接口并返回信息。

app.conf文件内容(可以用个beego直接读取里面的内容)写的是一个jwt的secretkey

jwtkey="12345678"

config.json里面保存的是连接数据库的用户名和密码(这里只是学习如何读取json的配置文件,可以集成到beego的app.conf文件里)

{
"sqltype":"mssql"
,"connstring":"server=.;port=1433;user id=sa;password=123;database=table1"
}

mssqlhelper.go实现连接mssqlserver的数据库

package mssqlhelper
 
import (
	"fmt"
 
	"github.com/akkuman/parseconfig"
	_ "github.com/denisenkom/go-mssqldb"
	"github.com/go-xorm/core"
	"github.com/go-xorm/xorm"
)
 
// 创建 xorm 客户端
func createclient() *xorm.engine {
	var config = parseconfig.new("config.json")
	sqltype := config.get("sqltype")
	fmt.println(sqltype)
	connstring := config.get("connstring")
	fmt.println(connstring)
	engine, err := xorm.newengine(sqltype.(string), connstring.(string))
	if err != nil {
		println("open error:", &err)
	}
	engine.setmapper(core.samemapper{})      //表示struct的类的名称和数据库中相同
	engine.showsql(true)                     //显示sql语句
	engine.logger().setlevel(core.log_debug) //打印sql语句
 
	return engine
}

authorizecontroller.go实现用户登录、获取用户信息接口

package controller
 
import (
	"goapi/dal"
	"goapi/model"
	"encoding/json"
	"fmt"
	"net/http"
	"strconv"
	"strings"
	"time"
 
	"github.com/astaxie/beego/context"
 
	"github.com/astaxie/beego"
	jwt "github.com/dgrijalva/jwt-go"
	"github.com/go-xorm/xorm"
)
 
var engine *xorm.engine
 
type authorizecontroller struct {
	beego.controller
}
 
var filteruser = func(ctx *context.context) {
	token := ctx.input.header("authorization")
 
	b, _ := checktoken(token)
 
	//验证token是否合法
	if !b {
		http.error(ctx.responsewriter, "token verification not pass", http.statusbadrequest)
		return
	}
	fmt.println("request token:", token)
}
 
func init() {
	engine = mssqlhelper.createclient()
    //访问接口前验证token
	beego.insertfilter("/authorize/userinfo", beego.beforerouter, filteruser)
}
 
type token struct {
	token string `json:"token"`
}
 
func fatal(err error) {
	if err != nil {
		beego.error(err)
	}
}
 
//登录
func (this *authorizecontroller) login() {
	var user model.loginmodel
    // url?username=111&password=222 这种形式
	user.username = this.getstring("username")
	user.password = this.getstring("password")
 
    //err := this.parseform(&user) //接收application/x-www-form-urlencoded形式post传递数据,如username=111&password=2222
    // err := json.newdecoder(this.ctx.request.body).decode(&user) //接收json形式post的数据
 
	loginuser := &model.usertable{userloginname: user.username}
	has, err := engine.get(loginuser)
	if err != nil {
		fatal(err)
	}
	if !has {
		fatal(err)
		http.error(this.ctx.responsewriter, "user not exist", http.statusbadrequest)
		return
	}
 
	if user.password != loginuser.userloginpwd {
		this.ctx.output.header("setstatus", strconv.itoa(http.statusbadrequest))
 
		http.error(this.ctx.responsewriter, "password wrong", http.statusbadrequest)
		return
	}
 
	claims := make(jwt.mapclaims)
	claims["exp"] = time.now().add(time.hour * time.duration(1)).unix()
	claims["iat"] = time.now().unix()
	claims["nameid"] = loginuser.userloginname
	claims["user"] = "true"
	token := jwt.newwithclaims(jwt.signingmethodhs256, claims)
 
	tokenstring, err := token.signedstring([]byte(beego.appconfig.string("jwtkey")))
	if err != nil {
		this.ctx.output.header("setstatus", strconv.itoa(http.statusinternalservererror))
		fatal(err)
		http.error(this.ctx.responsewriter, "server is wrong", http.statusinternalservererror)
		return
	}
 
	fmt.println("token:", tokenstring)
	this.ctx.writestring(fmt.sprintf("{\"token\":\"%s\"}", tokenstring))
}
 
 
func (this *authorizecontroller) userinfo() {
	token := this.ctx.input.header("authorization")
 
	b, t := checktoken(token)
	if !b {
		this.ctx.writestring(fmt.sprintf("error:%s", token))
		return
	}
	loginuser := &model.usertable{userloginname: claims["nameid"].(string)}
	has, err := engine.get(loginuser)
	if err != nil {
		fatal(err)
	}
	if !has {
		fatal(err)
		http.error(this.ctx.responsewriter, "user not exist", http.statusbadrequest)
		return
	}
	data, err := json.marshal(loginuser)
	if err != nil {
		fmt.println(err)
	}
	this.ctx.writestring(fmt.sprintf("{\"token\":\"%s\",\"user\":%s}", token, string(data)))
}
 
// 校验token是否有效
func checktoken(token string) (b bool, t *jwt.token) {
	kv := strings.split(token, " ")
	if len(kv) != 2 || kv[0] != "bearer" {
		beego.error("authstring invalid:", token)
		return false, nil
	}
	t, err := jwt.parse(kv[1], func(*jwt.token) (interface{}, error) {
		return []byte(beego.appconfig.string("jwtkey")), nil
	})
	fmt.println(t)
	if err != nil {
		fmt.println("转换为jwt claims失败.", err)
		return false, nil
	}
	return true, t
}

loginmodel.go 提交登录用户名和密码的结构

package model
 
type loginmodel struct {
	username string `xorm:"varchar(50)"`
	password string `xorm:"varchar(50)"`
}

usertable.go 用户信息实体结构

package model
 
type usertable struct {
	userid        int    `xorm:"not null pk int(4)"`
	userloginname string `xorm:"varchar(50)"`
	userloginpwd  string `xorm:"varchar(50)"`
	username      string `xorm:"nvarchar(200)"`
	usermobile    string `xorm:"varchar(11)"`
	userislock    int    `xorm:"bit(1)"`
}

main.go中通过beego启动http的web服务

package main
 
import (
	"goapi/controller"
	"github.com/astaxie/beego"
)
 
func main() {
	beego.autorouter(&controller.authorizecontroller{})
	beego.run()
}

下一步

1、学习如何在拦截器里拦截验证后把某个结果值传递给要访问的接口(目前是在接口里重新解析一遍jwt的token)

2、beego如何实现只允许post访问某个controller的接口(autorouter模式下)

3、struct如何实现中文的说明(就是鼠标放上去会显示中文描述,类似c#类的说明那种)

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

◎已有 0 人评论

Copyright © 2019  萬仟网 保留所有权利. 粤ICP备17035492号-1
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com