Go 原生开发博客项目系列(第五篇)
项目原视频地址: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 页面。
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, ¶ms)
return params
}
在页面的输入框中输入一些测试信息,点击登录。可以获取到输入的信息。
在下一行,添加 Login 登录函数
loginRes, _ := service.Login(userName, passwd)
Md5
MD5的全称是Message-Digest Algorithm 5(信息-摘要算法),它的作用是让大容量信息在用数字签名软件签署私人密匙前被“压缩”成一种保密的格式(就是把一个任意长度的字节串变换成一定长的大整数)。不管是md2、md4还是md5,它们都需要获得一个随机长度的信息并产生一个128位的信息摘要。MD5 算法的哈希值大小为 128 位。是一种不可逆的算法。
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