# 登陸注冊
## 1.介紹
web中最基礎的功能就是登陸注冊,接下來我們利用gin實現一個簡單的注冊登陸功能。
### 1.1.注冊
注冊的流程大致為:
```
填寫賬號密碼等信息->提交信息->服務端接收數據->參數校驗->檢查是否已經注冊->密碼加密->數據持久化到數據庫->注冊成功
```
### 1.2.登陸
登陸的流程大致為:
```
填寫賬號密碼等信息->提交信息->服務端接收數據->參數校驗->檢查賬號密碼是否正確->登陸成功
```
## 2.編碼實現
- 新建模型,這里直接使用數據操作章節使用的User模型
```go
type User struct {
ID uint `gorm:"primary_key"`
Username string
Password string
}
```
- 新建一個UserDto,用于數據傳輸使用
dto/user_dto.go
```go
package dto
type UserDto struct {
ID uint
Username string
Password string
}
```
- 使用數據操作章節的user_repository.go作為數據操作
repositories/user/user_repository.go
```go
package user
import (
"cn.sockstack/gin_demo/dto"
"cn.sockstack/gin_demo/models"
)
//CreateUser 創建用戶
func CreateUser(dto dto.UserDto) error {
user := models.User{}
user.Username = dto.Username
user.Password = dto.Password
err := models.DB.Create(&user).Error
return err
}
//GetUserByUsername 通過用戶名查詢用戶
func GetUserByUsername(username string) models.User {
user := models.User{}
models.DB.Find(&user, models.DB.Where("username = ?",username))
return user
}
//UpdateUser 更新用戶信息
func UpdateUser(userDto dto.UserDto) error {
user := models.User{}
if userDto.Username != "" {
user.Username = userDto.Username
}
if userDto.Password != "" {
user.Password = userDto.Password
}
err := models.DB.Model(&user).Update(&user).Error
return err
}
//DeleteUserById 通過Id刪除用戶
func DeleteUserById(id uint) error {
err := models.DB.Delete(&models.User{ID: id}).Error
return err
}
```
- 用戶接口
services/user/user_contract.go
```go
package user
import "cn.sockstack/gin_demo/dto"
type UserContract interface {
Register(dto dto.UserDto) error
Login(dto dto.UserDto) error
}
```
- 用戶服務
services/user/user_service.go
```go
package user
import (
"cn.sockstack/gin_demo/dto"
"cn.sockstack/gin_demo/pkg/hash"
user2 "cn.sockstack/gin_demo/repositories/user"
"errors"
)
type UserService struct {
}
//Register 注冊
func (user UserService) Register(userDto dto.UserDto) error {
//密碼加密
bytes, err := hash.NewHash().Make([]byte(userDto.Password))
if err != nil {
return errors.New(err.Error())
}
userDto.Password = string(bytes)
return user2.CreateUser(userDto)
}
//Login 登陸
func (user UserService)Login(userDto dto.UserDto) error {
model := user2.GetUserByUsername(userDto.Username)
if model.ID == 0 {
return errors.New("賬號不存在")
}
err := hash.NewHash().Check([]byte(model.Password), []byte(userDto.Password))
if err != nil {
return errors.New("密碼錯誤")
}
return nil
}
```
- 登陸注冊入參定義
requests/v1/user.go
```go
package v1
//RegisterRequest 注冊入參
type RegisterRequest struct {
Username string `form:"username" binding:"required"`
Password string `form:"password" binding:"required"`
}
//LoginRequest 登陸入參
type LoginRequest struct {
Username string `form:"username" binding:"required"`
Password string `form:"password" binding:"required"`
}
```
- 用戶控制器
api/user/v1/user.go
```go
package v1
import (
"cn.sockstack/gin_demo/dto"
"cn.sockstack/gin_demo/pkg/e"
v1 "cn.sockstack/gin_demo/requests/v1"
"cn.sockstack/gin_demo/services/user"
"github.com/gin-gonic/gin"
)
//RegisterHandle 注冊
func RegisterHandle(c *gin.Context) (interface{}, error) {
request := v1.RegisterRequest{}
err := c.ShouldBind(&request)
if err != nil {
return nil, e.ApiError{
Status: 422,
Code: 40004,
Message: "參數校驗失敗",
Data: err,
}
}
userDto := dto.UserDto{
Username: request.Username,
Password: request.Password,
}
service := user.UserService{}
err = service.Register(userDto)
if err != nil {
return nil, e.ApiError{
Status: 422,
Code: 40005,
Message: err.Error(),
}
}
return "注冊成功", nil
}
//LoginHandle 登陸
func LoginHandle(c *gin.Context) (interface{}, error) {
request := v1.LoginRequest{}
err := c.ShouldBind(&request)
if err != nil {
return nil, e.ApiError{
Status: 422,
Code: 40004,
Message: "參數校驗失敗",
Data: err,
}
}
userDto := dto.UserDto{
Username: request.Username,
Password: request.Password,
}
service := user.UserService{}
err = service.Login(userDto)
if err != nil {
return nil, e.ApiError{
Status: 422,
Code: 40005,
Message: err.Error(),
}
}
return "登陸成功", nil
}
```
- 定義路由
routers/v1/user.go
```go
package v1
import (
v1 "cn.sockstack/gin_demo/api/v1"
"cn.sockstack/gin_demo/pkg/e"
"github.com/gin-gonic/gin"
)
func UserRouter(r *gin.Engine) {
//注冊
r.POST("/register", e.ErrorWrapper(v1.RegisterHandle))
//登陸
r.POST("/login", e.ErrorWrapper(v1.LoginHandle))
}
```
## 3.總結
這個簡單的例子中,使用了前面學到的所有知識點,比較簡單,但是可以基于該例子整合其他功能,類型:驗證碼,限流,jwt等。
> 更多內容請關注我的博客[SOCKSTACk](https://www.sockstack.cn)