likes
comments
collection
share

Go 原生开发博客项目系列(第五篇)

作者站长头像
站长
· 阅读数 54

项目原视频地址:www.bilibili.com/video/BV1VS…

加载登录页面

e-book-website/router/router.go

加载路由

func Router() {
   // ....
   http.HandleFunc("/login", views.HTML.Login)
}

common.Template 加载模板

e-book-website/views/Login.go

package views

import (
   "blog-go/common"
   "blog-go/config"
   "net/http"
)

func (*HTMLApi) Login(w http.ResponseWriter, r *http.Request) {
   login := common.Template.Login

   login.WriteData(w, config.Cfg.Viewer)
}

点击首页的登录按钮,就可以跳转到 login 页面。

Go 原生开发博客项目系列(第五篇)

Login 接口

e-book-website/router/router.go

func Router() {
   // ....
   http.HandleFunc("/login", views.HTML.Login)
   http.HandleFunc("/api/v1/login", api.API.Login)
}

e-book-website/api/login.go

package api

import (
   "blog-go/common"
   "fmt"
   "net/http"
)

func (*Api) Login(w http.ResponseWriter, r *http.Request) {
   params := common.GetRequestJsonParam(r)
   userName := params["username"].(string)
   passwd := params["passwd"].(string)
   fmt.Println(userName, passwd)
}

GetRequestJsonParam 函数获取 request 中的请求参数。

e-book-website/common/common.go

func GetRequestJsonParam(r *http.Request) map[string]interface{} {
   var params map[string]interface{}
   body, _ := ioutil.ReadAll(r.Body)
   _ = json.Unmarshal(body, &params)
   return params
}

在页面的输入框中输入一些测试信息,点击登录。可以获取到输入的信息。

在下一行,添加 Login 登录函数

loginRes, _ := service.Login(userName, passwd)

Md5

MD5的全称是Message-Digest Algorithm 5(信息-摘要算法),它的作用是让大容量信息在用数字签名软件签署私人密匙前被“压缩”成一种保密的格式(就是把一个任意长度的字节串变换成一定长的大整数)。不管是md2、md4还是md5,它们都需要获得一个随机长度的信息并产生一个128位的信息摘要。MD5 算法的哈希值大小为 128 位。是一种不可逆的算法。

cloud.tencent.com/developer/s…

package utils

import (
   "crypto/md5"
   "fmt"
   "strings"
)

func Md5Crypt(str string, salt ...interface{}) (CryptStr string) {
   if l := len(salt); l > 0 {
      slice := make([]string, l+1)
      str = fmt.Sprintf(str+strings.Join(slice, "%v"), salt...)
   }
   // 总和返回数据的 MD5 校验和。
   return fmt.Sprintf("%x", md5.Sum([]byte(str)))
}

从数据库中获取用户

select * from user where user_name=? and password = ? limit 1

e-book-website/databases/user.go

// ....
func GetUser(userName, passwd string) *models.User {
   row := DB.QueryRow("select * from user where user_name=? and password = ? limit 1", userName, passwd)
   if row.Err() != nil {
      log.Println(row.Err())
      return nil
   }
   var user = &models.User{}
   err := row.Scan(&user.Uid, &user.UserName, &user.Passwd, &user.Avatar, &user.CreateAt, &user.UpdateAt)
   if err != nil {
      log.Println(err)
      return nil
   }
   return user
}

将数据进行传入

e-book-website/service/login.go

func Login(userName, passwd string) (*models.LoginRes, error) {
   passwd = utils.Md5Crypt(passwd, "go")
   user := databases.GetUser(userName, passwd)
   if user == nil {
      return nil, errors.New("账号或密码错误")
   }
}

Token是什么

所谓的Token,其实就是服务端生成的一串加密字符串、以作客户端进行请求的一个“令牌”。当用户第一次使用账号密码成功进行登录后,服务器便生成一个Token及Token失效时间并将此返回给客户端,若成功登陆,以后客户端只需在有效时间内带上这个Token前来请求数据即可,无需再次带上用户名和密码。

gojwt

  • jwt.StandardClaims 负载 jwt 信息

    • ExpiresAt 过期时间
    • IssuedAt 签发时间
  • 创建 CustomClaims 结构体,用来封装 jwt 信息

  • jwt.NewWithClaims 创建 jwt

    • jwt.SigningMethodHS256 使用 SigningMethodHS256 签名
    • claims 负载信息
  • token.SignedString 转换成 str 字符串

e-book-website/utils/jwt.go

package utils

import (
   gojwt "github.com/dgrijalva/jwt-go"
   "os"
   "time"
)

var jwtKey []byte

func init() {
   jwtKey = []byte(os.Getenv("JWT_SECRET"))
}

type Claims struct {
   Uid int
   gojwt.StandardClaims
}

func Award(uid *int) (string, error) {
   // 过期时间 默认7天
   expireTime := time.Now().Add(7 * 24 * time.Hour)
   claims := &Claims{
      Uid: *uid,
      StandardClaims: gojwt.StandardClaims{
         ExpiresAt: expireTime.Unix(),
         IssuedAt:  time.Now().Unix(),
      },
   }
   // 生成token
   token := gojwt.NewWithClaims(gojwt.SigningMethodHS256, claims)
   tokenStr, err := token.SignedString(jwtKey)
   if err != nil {
      return "", err
   }
   return tokenStr, nil
}

生成 Token 之后,返回给前端。

package service

import (
   "blog-go/databases"
   "blog-go/models"
   "blog-go/utils"
   "errors"
   "fmt"
)

func Login(userName, passwd string) (*models.LoginRes, error) {
   passwd = utils.Md5Crypt(passwd, "go")

   user := databases.GetUser(userName, passwd)
   if user == nil {
      return nil, errors.New("账号或密码错误")
   }
   uid := user.Uid
   token, err := utils.Award(&uid)
   fmt.Println(err)
   if err != nil {
      return nil, errors.New("token 生成失败")
   }
   var userInfo models.UserInfo
   userInfo.Uid = user.Uid
   userInfo.UserName = user.UserName
   userInfo.Avatar = user.Avatar
   var lr = &models.LoginRes{
      token,
      userInfo,
   }
   return lr, nil
}

重启项目

就可以看到用户点击登录,在 localStorage 可以看到存储的信息。

转载自:https://juejin.cn/post/7129311354434879496
评论
请登录