package utils
import (
"errors"
"github.com/astaxie/beego"
"github.com/dgrijalva/jwt-go"
"time"
)
type TokenClaims struct {
jwt.StandardClaims
Uid int64 `json:"uid"`
Uname string `json:"uname"`
Wx bool `json:"wx"`
}
//生成一个token
func TokenMake(claims *TokenClaims) (string,error){
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
tokenString, err := token.SignedString([]byte(beego.AppConfig.String(beego.AppConfig.String("jwtkey"))))
if err != nil {
return "",errors.New("获取令牌失败")
}
return tokenString,nil
}
//生成一个token by uid
func TokenMakeByUid(id int64,username string,wx bool) (string,error){
claims := TokenClaims{
Uid: id,
Uname: username,
Wx: wx,
}
claims.IssuedAt = time.Now().Unix()
claims.ExpiresAt = time.Now().Add(time.Hour * 5).Unix()
return TokenMake(&claims)
}
//刷新token
func TokenRefresh(claims *TokenClaims) (string , error) {
exp := claims.ExpiresAt
exp = time.Unix(exp, 0).Add(time.Hour * 10).Unix()
now := time.Now().Unix()
if now<=exp {
claims.ExpiresAt = time.Now().Add(time.Second * 10).Unix()
return TokenMake(claims)
}
return "",errors.New("超时太久不能刷新令牌")
}
//检测token
func TokenCheck(tokenString string) (bool,*TokenClaims,error){
token, err := jwt.ParseWithClaims(tokenString, &TokenClaims{}, func(token *jwt.Token) (interface{}, error) {
return []byte(beego.AppConfig.String(beego.AppConfig.String(beego.AppConfig.String("jwtkey")))), nil
})
//beego.Debug(token,err)
if token==nil{
return false,nil, errors.New("令牌验证无效")
}
if err != nil {
if ve, ok := err.(*jwt.ValidationError); ok {
if claims, ok := token.Claims.(*TokenClaims); ok {
return token.Valid,claims, errors.New(ve.Error())
}else{
return false,nil, errors.New("令牌转换失败[01]")
}
}else{
return false,nil, err
}
}else{
beego.Debug(token.Claims)
if claims, ok := token.Claims.(*TokenClaims); ok {
return token.Valid,claims,nil
}else{
return false,nil, errors.New("令牌转换失败[02]")
}
}
}
package commands
import (
"github.com/astaxie/beego"
"github.com/astaxie/beego/context"
_ "github.com/go-sql-driver/mysql"
"hqxxapi/utils"
"time"
)
var FilterUser = func(ctx *context.Context) {
tokenString := ctx.Input.Header("Authorization")
totokenString2 := ctx.Input.Query("token")
if tokenString == "" && totokenString2 !="" {
tokenString = totokenString2
}
//beego.Debug("token:"+token)
//beego.Debug("token2:"+token2)
if tokenString == "admin" {
tokenString,_ = utils.TokenMakeByUid(184,"admin",false)
}
if tokenString == "" {
ctx.Output.Header("content-type", "application/json; charset=utf-8")
utils.JsonResponse(501,map[string]interface{}{"code": 501, "message": "没有令牌,请重新登录!"},ctx.ResponseWriter)
return
}
isok,claims,err := utils.TokenCheck(tokenString)
beego.Debug(isok,claims, err)
if claims!=nil{
tm := time.Unix(claims.ExpiresAt, 0)
beego.Debug("token过期时间:"+ tm.Format("2006-01-02 15:04:05"))
}
if isok == false {
if claims==nil{
ctx.Output.Header("content-type", "application/json; charset=utf-8")
utils.JsonResponse(502,map[string]interface{}{"code": 501, "message": "令牌无效,请重新登录!"},ctx.ResponseWriter)
return
}
if claims.Wx{
//微信不验证过期
}else{
if err.Error()=="Token is expired" {
newtokenString,err := utils.TokenRefresh(claims)
if err ==nil{
ctx.Output.Header("content-type", "application/json; charset=utf-8")
utils.JsonResponse(503,map[string]interface{}{"code": 503, "message": "Token过期,请刷新!","data": newtokenString},ctx.ResponseWriter)
return
}
}
ctx.Output.Header("content-type", "application/json; charset=utf-8")
utils.JsonResponse(502,map[string]interface{}{"code": 502, "message": "Token过期,请重新登录!"},ctx.ResponseWriter)
return
}
}
if claims.Uid <=0 {
ctx.Output.Header("content-type", "application/json; charset=utf-8")
utils.JsonResponse(502,map[string]interface{}{"code": 502, "message": "Token中uid内容错误,请重新登录!"},ctx.ResponseWriter)
return
}
}
func StartToken(){
//token
beego.InsertFilter("/api/*", beego.BeforeRouter, FilterUser)
}
package controllers
import (
"github.com/astaxie/beego"
"hqxxapi/models"
"hqxxapi/utils"
)
type BaseController struct {
beego.Controller
Uid int
IsLogin bool
Permissions []string
}
type ResultJson struct {
Code int `json:"code"`
Message string `json:"message"`
Count int64 `json:"count"`
Data interface{} `json:"data,omitempty"`
}
func (c *BaseController) Prepare() {
tokenString := c.Ctx.Input.Header("Authorization")
totokenString2 := c.Ctx.Input.Query("token")
if tokenString == "" && totokenString2!="" {
tokenString = totokenString2
}
if tokenString == "admin" {
tokenString,_ = utils.TokenMakeByUid(184,"admin",false)
}
var err error
isok,claims,err := utils.TokenCheck(tokenString)
if isok == false {
if claims.Wx{
//微信不验证过期
c.IsLogin = true
c.Uid = int(claims.Uid)
}else{
c.IsLogin = false
c.Uid = int(claims.Uid)
}
}else{
c.IsLogin = true
c.Uid = int(claims.Uid)
}
c.Permissions,err = models.UserLoginPermissions(c.Uid)
if err != nil {
c.OutJson(ResultJson{Code:504,Message:err.Error()})
}
}
func (c *BaseController) OutJson(res ResultJson){
c.Ctx.Output.SetStatus(200)
c.Data["json"] = res
c.ServeJSON()
c.StopRun()
}
//判断是否有某几个权限
//c.HasPermission([]string{"aa"})
func (c *BaseController) HasPermission(prv []string) (bool,string) {
for _,v := range prv{
if utils.InArray(v,c.Permissions)==false{
c.OutJson(ResultJson{Code:505,Message:"没有权限,请使用有["+v+"]权限的账号登录登录!"})
return false,v
}
}
return true,""
}
//判断是否有某几个权限
//c.MustPermission([]string{"a","b","c"})
func (c *BaseController) MustPermission(prv []string) {
if c.IsLogin==false {
c.OutJson(ResultJson{Code:503,Message:"必须登录才能使用,请重新登录!"})
}
has,v := c.HasPermission(prv)
if has==false{
c.OutJson(ResultJson{Code:505,Message:"没有权限,请使用有["+v+"]权限的账号登录登录!"})
}
}
func JsonResponse(code int,response interface{}, w http.ResponseWriter) {
json, err := json.Marshal(response)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.WriteHeader(code)
//w.WriteHeader(http.StatusOK)
w.Header().Set("Content-Type", "application/json; charset=utf-8")
w.Write(json)
}