知识小结-05token的原理与使用

1、token主要有两个作用:
(1)防止表单重复提交(设置在多少时间内)

原理:在服务器端生成一个唯一的随机标识号,专业术语称为Token(令牌),同时在当前用户的Session域中保存这个Token。

然后将Token发送到客户端的Form表单中,在Form表单中使用隐藏域来存储这个Token,表单提交的时候连同这个Token一起提交到服务器端,

然后在服务器端判断客户端提交上来的Token与服务器端生成的Token是否一致,如果不一致,那就是重复提交了,

此时服务器端就可以不处理重复提交的表单。如果相同则处理表单提交,处理完后清除当前用户的Session域中存储的标识号

https://blog.csdn.net/qq_38714573/article/details/78771862

(2)用来作身份验证(登陆获得token后判断请求带的token是否相同)

原理:使用基于 Token 的身份验证方法,在服务端不需要存储用户的登录记录。大概的流程是这样的:

客户端使用用户名跟密码请求登录
服务端收到请求,去验证用户名与密码
验证成功后,服务端会签发一个 Token,再把这个 Token 发送给客户端
客户端收到 Token 以后可以把它存储起来,比如放在 Cookie 里或者 Local Storage 里
客户端每次向服务端请求资源的时候需要带着服务端签发的 Token
服务端收到请求,然后去验证客户端请求里面带着的 Token,如果验证成功,就向客户端返回请求的数据

https://blog.csdn.net/qq_32784541/article/details/79655146

2、token验证流程
1,注册用户信息,前端将用户名及密码发给后端

2,后端接收参数并存入数据库,再生成token返回给前端(token主要是用来验证用户的登录状态)
3,前端接收到后端返回的token,就把它存在sessionStorage里面
4,前端实现登录,将用户名跟密码传送给后台,并带上token。
5,后端返回一个新的token给前端,并且验证用户名和密码是否正确,将结果返回给前端。
6,前端接收到后端返回的消息,执行相应的操作,同时把token存到sessionStorage里面。
7,登录成功之后,跳转到首页,并且请求首页的数据回来,带上token传给后端。
8,后端接收到前端传来的token,判断是否有效。若有效,就返回相应的数据信息给前端;若无效,则返回“登录失败,重新登录类似的字段”。
9,前端接收到后端返回的消息,并执行相应的操作。
https://blog.csdn.net/weixin_43748930/article/details/87901038

3、代码解析
//token里面添加用户信息,验证token后可能会用到用户信息

type MyClaims struct {
   UserName string `json:"user_name"`
 UserId   string `json:"user_id"`
 jwt.StandardClaims
}

// 根据用户名生成token,传递给客户端
func GenToken(username string, userId string) (token string) {
   myClaims := MyClaims{
      username,
      userId,
      jwt.StandardClaims{
         NotBefore: int64(time.Now().Unix()),
         ExpiresAt: int64(time.Now().Unix() + 86400), // 86400 为一天
 Issuer:    "duxiaoman",
      },
   }
   key := beego.AppConfig.String("TokenSignKey")
   fmt.Println(key)
   ss := jwt.NewWithClaims(jwt.SigningMethodHS256, myClaims)
   token, _ = ss.SignedString([]byte(key))
   return token
}
//beego.AppConfig.String()读取配置信息

读取不同模式下配置参数的方法是“模式::配置参数名”,比如:beego.AppConfig.String(“dev::mysqluser”)

https://blog.csdn.net/qq_33610643/article/details/53511058

// 解析token,判断token 是否有效 有效的话提取用户信息

func ValidateTokenMiddleware(tokenString string) (username string, userId string, isOk bool) {
   olog.Debug("start validate token")
   token, err := jwt.ParseWithClaims(tokenString, &MyClaims{}, func(token *jwt.Token) (interface{}, error) {
      return []byte(beego.AppConfig.String("TokenSignKey")), nil
   })
   claims, ok := token.Claims.(*MyClaims)
   if ok && token.Valid {
      username = claims.UserName
      userId = claims.UserId
      isOk = ok
      olog.Debug("token is validate")
   } else {
      olog.Debug("token is not validate ,err is ", err)
   }
   return
}

// 登陆后其他操作,认证请求用户是否有token

var AuthFilter = func(ctx *context.Context) {
   if ctx.Request.RequestURI != "/fsg-resource/ui/auth/login" {
      olog.Debug("start auth request")
      token := ctx.Request.Header.Get("Authorization")
      if token != "" {
         username, userId, isOk := ValidateTokenMiddleware(token)
         olog.Debug("request is ok ,username is ", username)
         if isOk {
            ctx.Input.SetData("username", username)
            ctx.Input.SetData("userID", userId)
         }
         if !isOk {
            olog.Debug("request token is not validate")
            ctx.Redirect(401, "/401")
         }
      } else {
         olog.Debug("request token is not exists")
         ctx.Redirect(401, "/401")
      }
   }
}

URI,是uniform resource identifier,统一资源标识符,用来唯一的标识一个资源。

而URL是uniform resource locator,统一资源定位器,它是一种具体的URI,即URL可以用来标识一个资源,而且还指明了如何locate这个资源。

https://www.jianshu.com/p/449b30411964

获取token:token := ctx.Request.Header.Get(“Authorization”)
在HTTP请求中token通常放在Authorization字段中
根据token获取用户信息:username, userId, isOk := ValidateTokenMiddleware(token)

https://hacpai.com/article/1540349739379

ctx.Input.SetData(“username”, username)
GetData用于从控制器中的过滤器获取数据。它允许您传递不仅仅是字符串的值。

从Beego文档中:GetData获取输入中数据的值

SetData输入中数据的设置值。GetData和SetData用于将数据从过滤器传递到控制器

https://stackoverflow.com/questions/50373654/functionality-of-beego-syntax-ctx-input-getdatavariable-name

完整的token代码

https://www.cnblogs.com/dust90/p/11168585.html

https://www.cnblogs.com/zhzhlong/articles/10009141.html

https://studygolang.com/articles/24285?fr=sidebar

// 认证ticket,正确返回token

func AuthTicket(ticket string, nexturl string) (userInfo map[string]interface{}, err error) {
   olog.Debug("认证ticket")
   url := fmt.Sprintf("%s?service=%s?next=%s&ticket=%s&appKey=%s", global.UUAPAuthUrl, global.ServiceUrl, nexturl, ticket, global.UUAPAppKey)
   olog.Debug(url)
   resp, err := http.Get(url)
   if err == nil {
      defer resp.Body.Close()
      body, err := ioutil.ReadAll(resp.Body)
      username, err := parserXml(string(body))
      if err == nil {
         // 获取到username 生成token
 userInfo = UserAuth(username)
         token := GenToken(username, strconv.Itoa(userInfo["userID"].(int)))
         userInfo["token"] = token
         olog.Debug("认证ticket 成功", ticket)
      }
   }
   return
}

ctx.Input.SetData()与c.Ctx.Input.GetData()的原理

ctx.Input.SetData()一对一的关系

用户认证之后会有token,每次请求都会拿着这个token来,token解析之后里面是用户的信息。

每次请求都会先去验证token,验证成功会setData 用户名,然后 在controller里才能get到值 。

发布了10 篇原创文章 · 获赞 0 · 访问量 78

猜你喜欢

转载自blog.csdn.net/weixin_42282999/article/details/104459151