学生管理系统 | 青训营

90 阅读3分钟

这是一个基于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数据库。

代码

  1. 数据库连接
// 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{})
}
  1. 学生模型
// 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"`
}
  1. 用户模型
// models/user.go
package models

import "gorm.io/gorm"

type User struct {
	gorm.Model
	Username string `json:"username"`
	Password string `json:"password"`
}
  1. 身份验证中间件
// 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)
	})
}
  1. 用户服务
// 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
}
  1. 用户控制器
// 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)
	}
}
  1. 主入口
// 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)
}