# 登陆注册
## 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)