golang简单实现jwt验证(beego、xorm、jwt)
程序员文章站
2022-04-09 18:00:30
程序目录结构 简单实现,用户登录后返回一个jwt的token,下次请求带上token请求用户信息接口并返回信息。 app.conf文件内容(可以用个beego直接读取里面的内容)写的是一个jwt的secretkey config.json里面保存的是连接数据库的用户名和密码(这里只是学习如何读取js ......
程序目录结构
简单实现,用户登录后返回一个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#类的说明那种)
上一篇: 华为回应波兰员工事件:已终止雇佣关系