zoukankan      html  css  js  c++  java
  • 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#类的说明那种)

  • 相关阅读:
    SpringBoot+SpringCloud
    bootstrap-thymeleaf-分页
    排序-Java
    native2ascii运用
    标准W3C盒子模型和IE盒子模型
    在既定状态下截图
    java.util.zip.ZipException: error in opening zip file
    安装 haproxy
    mysql集群
    最简redis集群配置
  • 原文地址:https://www.cnblogs.com/wdw984/p/10259169.html
Copyright © 2011-2022 走看看