当前位置: 首页 > 编程日记 > 正文

gin实现登录逻辑,包含cookie,session

users/login.html

{{define "users/login.html"}}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登录页面</title>
</head>
<body>
   <form method="post" action="/login">
      username:<input style="align-content: center" type="text" name="username" onfocus="change()"><br/>
      password:<input type="password" name="password" onfocus="change()"><br/>
      <input type="submit" value="login">
   </form>
   <h1 id = "tag" style="color: red">{{.Message}}</h1>
</body>
<script>
    function change() {
     let tag = document.getElementById("tag");
     tag.innerHTML="<h1></h1>";
    }
</script>
</html>
{{end}}

default/index.html

{{define "default/index.html"}}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>index页面</title>
</head>
<body>
<h1 style="color: chocolate; align-content: center">{{.Content}}</h1>
</body>
</html>
{{end}}

controllers/users.go

package controllers

import (
	"github.com/gin-contrib/sessions"
	"github.com/gin-gonic/gin"
	"net/http"
)

package controllers

type Auth struct {
	Username string
	Password string
}

const DefaultAuthInfoKey = "AUTH"

func LoginGet() gin.HandlerFunc {
	return func(ctx *gin.Context) {
		ctx.HTML(http.StatusOK, "users/login.html", nil)
	}
}

func LogoutGet() gin.HandlerFunc {
	return func(ctx *gin.Context) {
		session := sessions.Default(ctx)
		session.Delete(DefaultAuthInfoKey)
		session.Options(sessions.Options{
			Path:     "/",
			Domain:   "localhost",
			MaxAge:   0,
			Secure:   true,
			HttpOnly: false,
			SameSite: 0,
		})
		session.Save()
		ctx.Redirect(http.StatusFound, "/login")
		ctx.Abort()
	}
}

func LoginPost() gin.HandlerFunc {
	return func(ctx *gin.Context) {
		username := ctx.PostForm("username")
		password := ctx.PostForm("password")

		if username != "admin" || password != "admin" {
			ctx.HTML(http.StatusOK, "users/login.html", gin.H{
				"Message": "用户名或密码错误!",
			})
			ctx.Abort()
			return
		}

		//登录成功
		auth := Auth{Username: username, Password: password}
		ctx.Set(DefaultAuthInfoKey, auth)

		session := sessions.Default(ctx)
		session.Set(DefaultAuthInfoKey, auth)
		session.Save() //TODO 必须Save,否则不生效
		ctx.Redirect(http.StatusFound, "/")
	}
}

func Index() gin.HandlerFunc {
	return func(ctx *gin.Context) {
		ctx.HTML(http.StatusOK, "default/index.html", gin.H{
			"Content": "欢迎回来:" + ctx.MustGet(DefaultAuthInfoKey).(Auth).Username,
		})
	}
}

routers/router.go

package routers

import (
	"encoding/gob"
	"github.com/coolbit/gin_sample/controllers"
	"github.com/coolbit/gin_sample/middleware"
	"github.com/gin-contrib/sessions"
	"github.com/gin-contrib/sessions/cookie"
	"github.com/gin-gonic/gin"
	"net/http"
)

var router *gin.Engine

func GetRouter() *gin.Engine {
	return router
}

func AuthRequired() gin.HandlerFunc {
	return func(ctx *gin.Context) {
		session := sessions.Default(ctx)
		auth := session.Get(controllers.DefaultAuthInfoKey)
		au, ok := auth.(controllers.Auth)
		if !ok || au.Username == "" {
			ctx.Redirect(http.StatusFound, "/login")
			ctx.Abort()
			return
		}
		ctx.Set(controllers.DefaultAuthInfoKey, auth) // 设置权限信息,供给当前请求链路使用
		session.Options(sessions.Options{             // 必须Save后才生效
			Path:     "/",
			Domain:   "localhost",
			MaxAge:   7 * 24 * 60 * 60, // 7天
			Secure:   true,
			HttpOnly: false,
			SameSite: 0,
		})

		session.Set(controllers.DefaultAuthInfoKey, au)
		session.Save() //"已刷新session"
	}
}

func init() {
	router = gin.Default()
	// Set a lower memory limit for multipart forms (default is 32 MiB)
	router.MaxMultipartMemory = 8 << 20 // 8 MiB
	router.Static("/static", "static")
	router.LoadHTMLGlob("views/**/*")
	
	gob.Register(controllers.Auth{}) // TODO 这个必须有,没有就写不了cookie
	
	store := cookie.NewStore([]byte("我是密钥"))
	router.Use(sessions.Sessions("SESSION_ID", store))
	router.GET("/login", controllers.LoginGet())
	router.POST("/login", controllers.LoginPost())

	router.Use(AuthRequired()) // 鉴权插件设置在这里
	router.GET("/", controllers.Index())
}

main.go

package main

import (
	"github.com/coolbit/gin_sample/routers"
)

func main() {
	routers.GetRouter().Run(":80")
}

登录后才能使用的系统的登录逻辑,借助cookie,session

  1. 客户端发起http://localhost/请求。
  2. 请求须经过后端AuthRequired中间件鉴权。该中间件查看session中是否保存了请求携带的cookie对应的用户信息,若有。则登录成功;若没有,则重定向到http://localhost/login进行登录。
  3. GET方法请求http://localhost/login时只返回页面,不需鉴权逻辑。
  4. POST方法请求http://localhost/login时,不需鉴权逻辑。进行登录验证,并记录session,为当前context设置Key为"AUTH"的有效用户信息。方便该次请求链路使用。登录成功则重定向到http://localhost/

相关文章:

【Mongdb之数据同步篇】什么是Oplog、Mongodb 开启oplog,java监听oplog并写入关系型数据库、Mongodb动态切换数据源

oplog是local库下的一个固定集合,Secondary就是通过查看Primary 的oplog这个集合来进行复制的。每个节点都有oplog,记录这从主节点复制过来的信息,这样每个成员都可以作为同步源给其他节点。Oplog 可以说是Mongodb Replication的纽带了。

Velocity Engine基础

回到顶部Velocity是一个基于Java的模板引擎,可以通过特定的语法获取在java对象的数据 , 填充到模板中,从而实现界面和java代码的分离!Velocity Template Language (VTL) , 是Velocity 中提供的一种模版语言 , 旨在提供最简单和最干净的方法来将动态内容合并到网页中。简单来说VTL可以将程序中的动态数展示到网页中注释非解析内容 , 引用和指令。

配置nginx+keepalived高可用代理数据库ip端口

需求:配置nginx+keepalived高可用反向代理数据库ip端口(数据库服务器无法增加新SCAN IP或者需要隐藏数据库IP的情况下适用)本机ip为:192.168.20.10和192.168.20.11。2.任意节点关机或重启系统,浮动ip也会自动漂移到另外节点。1.任意节点停nginx:浮动ip会自动漂移到另外节点。安装依赖包和nginx和keepalived。浮动IP为:192.168.20.20。配置keepalived.conf。两台centos7.9。

如何在Nginx中配置防盗链?

防盗链是一种防止网站资源被非法下载的技术。当用户尝试直接访问一个受保护的资源时,服务器会返回一个403 Forbidden错误,提示用户该资源受到保护,不能直接访问。这样可以避免用户通过搜索引擎或其他方式获取到未经授权的资源。通过以上步骤,我们可以在Linux系统中的Nginx Web服务器中使用Shell脚本实现防盗链的配置。这种方法可以有效地保护网站资源不被非法下载,提高用户体验,同时防止恶意攻击。在实际项目中,我们可以根据实际需求灵活配置受保护资源的URL和处理方式。

vue3项目中使用vite-plugin-mock

-设置模拟数据的存储文件夹,如果不是index.js需要写明完整路径。supportTs?: boolean;--是否读取ts文件模块,设置为true时不能读取js文件。--是否在控制台显示请求日志。4、利用axios调用。

Golang 搭建 WebSocket 应用(八) - 完整代码

本文应该是本系列文章最后一篇了,前面留下的一些坑可能后面会再补充一下,但不在本系列文章中了。

深入浅出:Golang内存逃逸机制与性能优化技巧

内存逃逸发生在编译期间,当编译器判断一个变量的生命周期超出了其当前作用域,它会将该变量分配到堆上,而非栈上。这种情况虽然保证了程序的正确性,但会增加垃圾回收的负担,从而影响程序性能。通过本文的深入探讨,我们了解了Golang内存逃逸的基本原理,以及它是如何影响程序性能的。我们探讨了内存逃逸的常见场景,并通过具体的代码示例展示了这些问题的出现和解决方法。最重要的是,我们学习了一系列性能优化技巧,包括数据结构优化、减少不必要的指针使用、利用栈空间、使用内存池,以及定期进行性能分析。

编码技巧:如何在Golang中高效解析和生成XML

在本文中,我们详细探讨了在Golang中高效处理XML的各个方面。从基础的XML概念到解析和生成XML文件的具体步骤,再到错误处理、调试技巧以及一些高级技巧和最佳实践,我们提供了一个全面的指南,旨在帮助读者掌握在Golang中处理XML的技能。理解Golang中XML处理的基本概念和方法。使用包来解析和生成XML文件。有效地处理常见的XML解析和生成中的错误。应用最佳实践和高级技巧来优化XML处理的性能和安全性。

如何用pthon连接mysql和mongodb数据库【极简版】

发现宝藏 前言 1. 连接mysql 1.1 安装 PyMySQL 1.2 导入 PyMySQL 1.3 建立连接 1.4 创建游标对象 1.5 执行查询 1.6 关闭连接 1.7 完整示例 2. 连接mongodb 2.1 安装 PyMongo 2.2 导入 PyMongo 2.3 建立连接 2.4

Linux安装MongoDB教程

将解压后的 mongodb-linux-x86_64-rhel70-4.2.23 中的所有文件全部移动到 /usr/local/mongodb 中 :注意/*是所有子文件。也可以不用设置环境变量进行启动,但是不设置环境变量启动的话要每次启动写很多启动参数,比较麻烦,所以做好配置环境变量。在 mongodb 下创建 data 和 logs 目录,以及日志文件mongodb.log。在 /usr/local 目录中创建 mongodb 文件夹。启动 MongoDB(-conf 使用配置文件方式启动)

CentOS 7 设置 Jar包、MinIO、Nginx 开机自启动

根据需要,自己修改 Description 和 ExecStart 的内容即可(ExecStart后面的java命令需要全路径)ExecStart 服务运行执行的命令,放上面创建的脚本位置。[Install] 服务安装的相关设置,可设置为多用户。如果用 yum install 命令安装的,如果使用源码手动编译的则需要手动创建。文件,xxx 就是自定义的服务名称。After:设置在某个服务启动后启动。Description:服务的描述。可以使用这个命令来查看服务启动日志。里面的环境变量是必须的,将。

Nginx实战 | 高性能HTTP和反向代理神器Nginx前世今生,以及它的“繁花之境”

Nginx 的历史可以追溯到 1990 年代末期,当时互联网开始迅速发展,传统的 HTTP 服务器如 Apache 开始显得力不从心,无法满足日益增长的访问量和并发请求。Nginx 的设计理念是追求极高的性能和稳定性,同时还具有较低的内存消耗和资源占用,这使得它能够处理大量并发请求,非常适合于需要处理高负载的服务器环境。通过这些测试和优化方法,你可以了解 Nginx 的性能瓶颈,并采取相应的措施来提高其性能。Nginx 的测试和优化可以通过多种方式进行,包括负载测试、性能测试、配置优化和代码级优化。

thinkphp操作mongo数据的三种方法

'hostname' => '10.10.10.10', // MongoDB服务器地址。'hostport' => 2017, // MongoDB服务器端口。'database' => 'chatname', // 数据库名称。后面接着就可以任意使用Connection各类方法。后面接着就可以任意使用Collection各类方法。使用MongoDB PHP驱动程序,方法三。后面接着就可以任意使用db下的增删改查。使用tp中的db类,方法二。使用tp中的扩展,方法一。

nginx下载安装 | mac | 前端项目在nginx上运行

大家好,我是星恒,今天给大家带来的是nginx的安装配置,以及如何在nginx运行前端项目的教程,话不多说,我们直接开始。

Win系统修改Nginx配置结合内网穿透实现远程访问多个Web站点

登录cpolar web UI管理界面,点击左侧仪表盘的隧道管理——隧道列表,找到所要配置的隧道,点击右侧的编辑。接下来,我们通过强大的且稳定的内网穿透工具cpolar,将本地nginx服务暴露至公网环境,以实现穿透多个站点端口需求,无需公网IP,也不用设置路由器。提示更新隧道成功,点击左侧仪表盘的状态——在线隧道列表,可以看到公网地址已经更新为保留成功的二级子域名,将其复制下来。来访问两个站点,测试访问成功,现在该公网地址不会随机变化了。

哪些大公司正在使用Go语言

随着计算机科学和软件开发的快速发展,编程语言的选择变得愈加关键。在这个多元化的编程语境中,Go语言(简称Golang)以其简洁、高效、并发处理能力等特性逐渐受到业界关注。越来越多的大型科技公司纷纷采用Go语言作为其软件开发的首选语言,这种趋势反映了Go语言在构建可靠、高性能和易于维护的系统方面的卓越表现。😊🙏如果大家对相关文章感兴趣,可以关注公众号"架构殿堂",会持续更新AIGC,java基础面试题, netty, spring boot, spring cloud等系列文章,一系列干货随时送达!

深入理解 Nginx 工作原理:Master-Worker 架构与性能优化

Nginx是一个高性能的开源 Web 服务器,以其卓越的性能、高并发处理能力和可扩展性而闻名。其独特的工作方式及架构设计为 Web 服务器领域带来了创新。本文将深入探讨 Nginx 的工作原理,重点关注其 Master-Worker 架构以及性能优化策略,帮助大家更好地理解 Nginx 如何处理并发请求并实现高效的网络服务。

Django 防止 XSS 跨站脚本攻击

跨站脚本攻击(XSS)是 Web 应用中常见的安全漏洞,它允许攻击者在用户浏览器中执行恶意脚本。在 Django 开发中,了解并防御 XSS 攻击至关重要。本文将详细介绍 XSS 攻击的工作原理,Django 中的防御机制,以及如何在 Django 应用中实施有效的防御措施。

Linux配置nginx开机自启

1.先创建开机自启脚本。3.启动nginx服务。

讲解nginx.pid“ failed (2: The system cannot find the file specified

该脚本首先检查Nginx进程是否在运行,如果未运行则尝试重新生成"nginx.pid"文件,并启动Nginx服务。然后,脚本会启动Nginx服务。通过使用该脚本,你可以自动处理"nginx.pid" failed 错误,并重新生成所需的"nginx.pid"文件。nginx.pid 文件是Nginx Web服务器在运行过程中生成的一个文件,用于存储Nginx主进程的进程ID(PID)。它表明Nginx无法找到指定的"nginx.pid"文件,这个文件用于存储Nginx主进程的进程ID(PID)。

linux配置nginx开机自启&nginx部署与systemctl控制启动&/etc/systemd/system 和 /lib/systemd/system 的区别

目录/lib/systemd/system 以及/usr/lib/systemd/system 其实指向的是同一目录,在/目录下执行命令lltotal 28该目录中包含的是软件包安装的单元,也就是说通过 yum、dnf、rpm 等软件包管理命令管理的 systemd 单元文件,都放置在该目录下。/etc/systemd/system/(系统管理员安装的单元, 优先级更高)在一般的使用场景下,每一个 Unit(服务等) 都有一个配置文件,告诉 Systemd 怎么启动这个 Unit。

nginx常用操作命令

都启动了同一个Nginx进程。不一样的是:1、Systemd 是一系列工具的集合,其作用也远远不仅是启动操作系统,它还接管了后台服务、结束、状态查询。2、Systemd更方便作服务管理,启动管理Nginx更佳方便。3、Systemd可以作开机服务管理,让服务跟随系统启动。

C/C++,FEISTDLIB的部分源代码

C/C++,FEISTDLIB的部分源代码

C/C++,动态 DP 问题的计算方法与源程序

C/C++,动态 DP 问题的计算方法与源程序

C/C++,图算法——Dinic最大流量算法

C/C++,图算法——Dinic最大流量算法

Nginx反向代理跳过国内备案(以宝塔面板为例)

Nginx代理跳过大陆备案验证,需要两台服务器,一台已备案或者免备案,一台国内主力服务器放你的项目。B服务器在配置文件里设置listen监听端口号。先把域名解析到A服务器。然后在A服务器里配置。

Nginx基础篇:Nginx搭建、Nginx反向代理、文件服务器部署配置。

Nginx (engine x) 是一个高性能的HTTP和反向代理web服务器,同时也提供了IMAP/POP3/SMTP服务。Nginx是由伊戈尔·赛索耶夫为俄罗斯访问量第二的Rambler.ru站点(俄文:Рамблер)开发的,公开版本1.19.6发布于2020年12月15日。其将源代码以类BSD许可证的形式发布,因它的稳定性、丰富的功能集、简单的配置文件和低系统资源的消耗而闻名。2022年01月25日,nginx 1.21.6发布。

Nginx按指定格式记录访问日志

其实我们在用常用的web服务器上都有这项功能,我们这里用Nginx举例,我们的访问日志一般正常都是什么设备在什么地址访问了我们的什么资源,后端服务器的响应时间是多少,客户端请求处理的总时间是多少;一般我们作为开发人员关注的日志只是在应用程序层面的,我们称它为应用程序日志,访问日志和错误日志可以被认为是应用程序日志的一部分,因为它们都与应用程序的运行状态和用户访问行为有关。:代表User-Agent HTTP头部,指示发起请求的客户端的用户代理(例如,浏览器)。:代表发起请求的客户端的IP地址。

gRPC三种流和消息格式

服务端实现protocol buffer定义的方法,客户端保留一个存根,提供服务端方法的抽象,客户端只需要调用存根中的方法,就可以远程调用服务端方法。客户端多个请求发给服务端,服务端发送一个响应给客户端,比如更新业务,客户端的读个请求发过来,服务端更新完返回一个成功的结果。通信时可以是一个请求,服务端多次响应,比如查询业务,服务端模糊匹配找到一次就返回客户端一次响应这样的多次响应。客户端发送,包含3个部分:请求头信息、长度前缀的消息、流结束标记。在写入消息前,先写入长度消息表明每条消息的大小。

C/C++,组合算法——K人活动选择问题(Activity-Selection-Problem)的源程序

C/C++,组合算法——K人活动选择问题(Activity-Selection-Problem)的源程序