欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-04-09 18:00:30
程序目录结构 简单实现,用户登录后返回一个jwt的token,下次请求带上token请求用户信息接口并返回信息。 app.conf文件内容(可以用个beego直接读取里面的内容)写的是一个jwt的secretkey config.json里面保存的是连接数据库的用户名和密码(这里只是学习如何读取js ......

程序目录结构

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

简单实现,用户登录后返回一个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#类的说明那种)