go之构建简单的web服务器4.0

这一章实现的是会话管理功能。采用的是cookie+session的方式实现登录功能。
引用了第三方库:github.com/gorilla/sessions
实现了login登录校验以及生成session信息后,我有点茫然:go如何定义一个中间件简单校验是否已登录?
我现在能想到的方案:写个校验是否登录的公共方法,检验成功则返回用户信息,失败则提示用户登录。
然后每个接口都调用一下这个校验方法。

目录架构

在这里插入图片描述

user_login.go代码:

package user
import (
	"fmt"
	"net/http"

	"github.com/gorilla/sessions"
	sql_pk "database/sql"

	storage "etcd_web/storage"
	common "etcd_web/common"
	conf "etcd_web/config"
)

const COOKIENAME string = "user-cookie"

var (
	// key must be 16, 24 or 32 bytes long (AES-128, AES-192 or AES-256)
	key = []byte("jay-secret-key")
	store = sessions.NewCookieStore(key)
)


//用户登录
func Login(w http.ResponseWriter, r *http.Request) {

	user_name := r.FormValue("user_name")
	password := r.FormValue("password")
	
	if user_name == "" || password == "" {
		common.ReturnError(w, conf.FAIL_CODE, "用户名和密码不能为空")
		return
	}

	//查看用户和密码是否正确
	mysqlConnect, err := storage.NewMySqlInit()
	sql := "select id,user_name from etcd_admin where user_name = ? and password = ?"
	row,err :=  mysqlConnect.QueryRow(sql,user_name,password)
	var UserInfo struct {
		User_id int `json:"user_id"`
		User_name string `json:"user_name"`
	}
	err = row.Scan(&UserInfo.User_id,&UserInfo.User_name)
	fmt.Println(err)
	if err != nil {
		if err == sql_pk.ErrNoRows {
			common.ReturnError(w, conf.FAIL_CODE, "用户名或密码不正确")
			return
		} else {
			common.ReturnError(w, conf.FAIL_CODE, err.Error())
			return
		}

	}
	// fmt.Println(UserInfo)
	session, _ := store.Get(r, COOKIENAME)
	// Set user as authenticated
	session.Values["authenticated"] = true
	session.Values["user_id"] = UserInfo.User_id
	session.Values["user_name"] = UserInfo.User_name
	session.Save(r, w)
	common.ReturnSuccess(w, conf.SUCCESS_CODE, "登录成功", UserInfo)
}

//退出登录
func Logout(w http.ResponseWriter, r *http.Request) {
	session, _ := store.Get(r, COOKIENAME)

	// Revoke users authentication
	session.Values["authenticated"] = false
	session.Save(r, w)
	common.ReturnSuccess(w, conf.SUCCESS_CODE, "退出成功", nil)
}


//测试是否有登录
func TestLogin(w http.ResponseWriter, r *http.Request) {
	session, _ := store.Get(r, COOKIENAME)

	// Check if user is authenticated
	if auth, ok := session.Values["authenticated"].(bool); !ok || !auth {
		http.Error(w, "你未登录", http.StatusForbidden)
		return
	}

	user_id := session.Values["user_id"]
	user_name := session.Values["user_name"]
	fmt.Fprintln(w,user_id)
	fmt.Fprintln(w,user_name)
	// Print secret message
	fmt.Fprintln(w, "你已经登录成功了!")
}

checkLogin.go代码:

package common

import (
	"net/http"
	"errors"
	"github.com/gorilla/sessions"
)

const COOKIENAME string = "kpl-cookie"

var (
	// key must be 16, 24 or 32 bytes long (AES-128, AES-192 or AES-256)
	key = []byte("kpl-secret-key")
	store = sessions.NewCookieStore(key)
)



type UserInfo struct{ 
	user_id interface{} `json:"user_id"`
	user_name interface{} `json:"user_name"`
}

//检查用户是否登录,并返回用户信息
func CheckLogin(w http.ResponseWriter, r *http.Request) (*UserInfo,error){
	session, _ := store.Get(r, COOKIENAME)

	// Check if user is authenticated
	if auth, ok := session.Values["authenticated"].(bool); !ok || !auth {
		return nil,errors.New("用户还未登录!")
	}
	var user_info *UserInfo
	user_info = new(UserInfo)
	user_info.user_id = session.Values["user_id"]
	user_info.user_name = session.Values["user_name"]
	return user_info,nil
}

接口中校验是否登录:

//删除管理员
func DelAdmin(w http.ResponseWriter, r *http.Request) {

	//检查是否已经登录
	userInfo,err := common.CheckLogin(w,r)
	fmt.Println(userInfo)
	if err != nil {
		common.ReturnError(w, http.StatusForbidden, "用户未登录")
		return
	}
	
	var sql string
	//获取参数
	id := r.FormValue("id")
	//参数判断
	if id == "" {
		common.ReturnError(w, conf.FAIL_CODE, "用户id不能为空")
		return
	}
	//获取数据库连接
	mysqlConnect, err := mysql.NewMySqlInit()
	if err != nil {
		common.ReturnError(w, conf.FAIL_CODE, fmt.Sprintf("连接出错了:%v", err))
		return
	}

	sql = "delete from etcd_admin where id=?"
	_, err = mysqlConnect.Exec(sql, id)
	if err != nil {
		common.ReturnError(w, conf.FAIL_CODE, fmt.Sprintf("删除出错了:%v", err))
		return
	}

	common.ReturnSuccess(w, conf.SUCCESS_CODE, "删除成功", nil)
}

main.go代码:

package main
import (
	"net/http"
	//内部包 
	// mysql "etcd_web/storage"
	user "etcd_web/user"
  etcd "etcd_web/etcd"
)

func main() {
  // 当访问 http://127.0.0.1:9527/hello 时,进入这个方法
  http.HandleFunc("/hello", HelloHandler)

  //设置管理员(方法提取到etcd_web/user目录下的文件)
  http.HandleFunc("/addAdmin", user.AddAdmin)
  http.HandleFunc("/updateAdmin", user.UpdateAdmin)
  http.HandleFunc("/delAdmin", user.DelAdmin)
  http.HandleFunc("/getAdminList", user.GetAdminList)

  //操作etcd
  http.HandleFunc("/getEtcdData", etcd.GetEtcdData)
  http.HandleFunc("/getEtcdDataWithPrefix", etcd.GetEtcdDataWithPrefix)
  http.HandleFunc("/setEtcdData", etcd.SetEtcdData)
  http.HandleFunc("/delEtcdData", etcd.DelEtcdData)

  //用户登录
  http.HandleFunc("/login",user.Login)
  http.HandleFunc("/logout",user.Logout)
  http.HandleFunc("/testLogin",user.TestLogin)

  // 启动一个Web服务,并监听9527端口
  http.ListenAndServe(":9527",nil)
}

//测试方法
func HelloHandler(w http.ResponseWriter, r *http.Request) {
  w.Write([]byte("<h1>Hello World</h1>"))
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值