这是一个基于Go的Web应用程序,使用MVC架构设计,实现了学生信息管理系统。通过jwt进行身份验证,并将数据持久化到MySQL数据库。
基本介绍
此项目采用Golang编写,使用了MVC架构设计,分为以下几个部分:
- Models:定义了学生和用户的数据结构。
- Controllers:处理HTTP请求并与模型和视图交互。
- Services:包括用户验证和JWT生成的逻辑。
- Middlewares:定义了进行JWT验证的中间件。
- Database:负责数据库连接。
实现介绍
项目通过JWT来进行用户验证,只有携带了有效的JWT令牌的请求才能访问受保护的端点。
Models中定义了学生和用户数据结构。Services中有用户验证和JWT令牌生成逻辑。Controllers包括了学生信息的CRUD操作和用户登录。Middlewares有一个用于JWT验证的中间件。Database文件则负责连接到MySQL数据库。
代码
- 数据库连接
// database/connection.go
package database
import (
"gorm.io/driver/mysql"
"gorm.io/gorm"
"your_project_name/models"
)
var (
DB *gorm.DB
)
func Connect() {
// 连接到MySQL数据库
connection, err := gorm.Open(mysql.Open("root:123456@tcp(localhost:3306)/student?charset=utf8mb4&parseTime=True&loc=Local"), &gorm.Config{})
if err != nil {
panic("Could not connect to the database!")
}
DB = connection
// 自动迁移学生和用户模型
connection.AutoMigrate(&models.Student{}, &models.User{})
}
- 学生模型
// models/student.go
package models
import "gorm.io/gorm"
type Student struct {
gorm.Model
Name string `json:"name"`
Age int `json:"age"`
Grade string `json:"grade"`
}
- 用户模型
// models/user.go
package models
import "gorm.io/gorm"
type User struct {
gorm.Model
Username string `json:"username"`
Password string `json:"password"`
}
- 身份验证中间件
// middlewares/auth_middleware.go
package middlewares
import (
"net/http"
"strings"
"your_project_name/services"
"github.com/dgrijalva/jwt-go"
)
func AuthMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// 验证JWT令牌
authorizationHeader := r.Header.Get("Authorization")
if authorizationHeader == "" {
http.Error(w, "Authorization header required", http.StatusUnauthorized)
return
}
parts := strings.Split(authorizationHeader, " ")
if len(parts) != 2 || parts[0] != "Bearer" {
http.Error(w, "Invalid authorization header", http.StatusUnauthorized)
return
}
claims := &jwt.StandardClaims{}
token, err := jwt.ParseWithClaims(parts[1], claims, func(token *jwt.Token) (interface{}, error) {
return services.JwtKey, nil
})
if err != nil || !token.Valid {
http.Error(w, "Invalid token", http.StatusUnauthorized)
return
}
next.ServeHTTP(w, r)
})
}
- 用户服务
// services/user_service.go
package services
import (
"crypto/sha256"
"encoding/hex"
"time"
"your_project_name/models"
"your_project_name/database"
"github.com/dgrijalva/jwt-go"
)
var jwtKey = []byte("your_secret_key")
func CreateUser(username string, password string) models.User {
// 密码加密
hashedPassword := sha256.Sum256([]byte(password))
user := models.User{Username: username, Password: hex.EncodeToString(hashedPassword[:])}
database.DB.Create(&user)
return user
}
func ValidateUser(username string, password string) bool {
var user models.User
database.DB.Where("username = ?", username).First(&user)
// 验证密码
hashedPassword := sha256.Sum256([]byte(password))
return user.Password == hex.EncodeToString(hashedPassword[:])
}
func GenerateToken(username string) (string, error) {
// 生成JWT
expirationTime := time.Now().Add(24 * time.Hour)
claims := &jwt.StandardClaims{
Subject: username,
ExpiresAt: expirationTime.Unix(),
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
tokenString, err := token.SignedString(jwtKey)
return tokenString, err
}
- 用户控制器
// controllers/user_controller.go
package controllers
import (
"encoding/json"
"net/http"
"your_project_name/services"
)
func Login(w http.ResponseWriter, r *http.Request) {
var credentials struct {
Username string `json:"username"`
Password string `json:"password"`
}
json.NewDecoder(r.Body).Decode(&credentials)
// 验证用户
if services.ValidateUser(credentials.Username, credentials.Password) {
token, err := services.GenerateToken(credentials.Username)
if err != nil {
http.Error(w, "Error generating token", http.StatusInternalServerError)
return
}
json.NewEncoder(w).Encode(map[string]string{"token": token})
} else {
http.Error(w, "Invalid username or password", http.StatusUnauthorized)
}
}
- 主入口
// main.go
package main
import (
"net/http"
"your_project_name/controllers"
"your_project_name/database"
"your_project_name/middlewares"
"github.com/gorilla/mux"
)
func main() {
database.Connect()
router := mux.NewRouter()
router.HandleFunc("/login", controllers.Login).Methods("POST")
// 以下路由受身份验证保护
protectedRouter := router.PathPrefix("/").Subrouter()
protectedRouter.Use(middlewares.AuthMiddleware)
protectedRouter.HandleFunc("/students", controllers.GetStudents).Methods("GET")
protectedRouter.HandleFunc("/students/{id}", controllers.GetStudent).Methods("GET")
protectedRouter.HandleFunc("/students", controllers.CreateStudent).Methods("POST")
protectedRouter.HandleFunc("/students/{id}", controllers.UpdateStudent).Methods("PUT")
protectedRouter.HandleFunc("/students/{id}", controllers.DeleteStudent).Methods("DELETE")
http.ListenAndServe(":8000", router)
}
学生控制器
// controllers/student_controller.go
package controllers
import (
"encoding/json"
"net/http"
"strconv"
"your_project_name/models"
"your_project_name/database"
"github.com/gorilla/mux"
)
func GetStudents(w http.ResponseWriter, r *http.Request) {
var students []models.Student
database.DB.Find(&students)
json.NewEncoder(w).Encode(students)
}
func GetStudent(w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r)
id, err := strconv.Atoi(params["id"])
if err != nil {
http.Error(w, "Invalid ID", http.StatusBadRequest)
return
}
var student models.Student
database.DB.First(&student, id)
json.NewEncoder(w).Encode(student)
}
func CreateStudent(w http.ResponseWriter, r *http.Request) {
var student models.Student
json.NewDecoder(r.Body).Decode(&student)
database.DB.Create(&student)
json.NewEncoder(w).Encode(student)
}
func UpdateStudent(w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r)
id, err := strconv.Atoi(params["id"])
if err != nil {
http.Error(w, "Invalid ID", http.StatusBadRequest)
return
}
var student models.Student
database.DB.First(&student, id)
json.NewDecoder(r.Body).Decode(&student)
database.DB.Save(&student)
json.NewEncoder(w).Encode(student)
}
func DeleteStudent(w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r)
id, err := strconv.Atoi(params["id"])
if err != nil {
http.Error(w, "Invalid ID", http.StatusBadRequest)
return
}
var student models.Student
database.DB.Delete(&student, id)
w.WriteHeader(http.StatusNoContent)
}