### 【GoWeb开发实战Gin框架】微博项目实战-处理session
# Session的处理
我们希望用户登录后可以有写博客的功能,当然也允许用户退出。

如果用户没有登录,直接访问首页,只可以查看文章,标签,相册等,但是没有写博客的功能:

## 一、安装gin框架的session
打开终端输入:
~~~shell
go get github.com/gin-contrib/sessions
~~~

## 二、Controller
我们修改登录的Post方法,在登录的时候,我们设置session:
~~~go
func LoginPost(c *gin.Context){
...
if id > 0 {
/*
设置了session后悔将数据处理设置到cookie,然后再浏览器进行网络请求的时候回自动带上cookie
因为我们可以通过获取这个cookie来判断用户是谁,这里我们使用的是session的方式进行设置
*/
session := sessions.Default(c)
session.Set("loginuser", username)
session.Save()
c.JSON(http.StatusOK, gin.H{"code": 1, "message": "登录成功"})
} else {
c.JSON(http.StatusOK, gin.H{"code": 0, "message": "登录失败"})
}
}
~~~
注意,在gin框架中,无论是Set一个session,还是Delete一个session,都要调用Save()方法进行保存。
接下来,在设置路由之前,我们需要使用session的中间件:
~~~go
package routers
import (
"github.com/gin-gonic/gin"
"blogweb_gin/controllers"
"github.com/gin-contrib/sessions"
"github.com/gin-contrib/sessions/cookie"
)
func InitRouter() *gin.Engine {
router := gin.Default()
router.LoadHTMLGlob("views/*")
//设置session midddleware
store := cookie.NewStore([]byte("loginuser"))
router.Use(sessions.Sessions("mysession", store))
{
//注册:
router.GET("/register", controllers.RegisterGet)
router.POST("/register", controllers.RegisterPost)
//登录
router.GET("/login", controllers.LoginGet)
router.POST("/login", controllers.LoginPost)
}
return router
}
~~~
通过Use()方法设置session中间件。
我们新添加一个路由:
~~~go
//首页
router.GET("/", controllers.HomeGet)
~~~
当访问/,这个根路径的时候,我们表示访问首页。
接下来创建一个新的Controller,session\_controller.go,用于获取session,查看用户是否登录:
~~~go
//获取session
func GetSession(c *gin.Context) bool {
session := sessions.Default(c)
loginuser := session.Get("loginuser")
fmt.Println("loginuser:", loginuser)
if loginuser != nil {
return true
} else {
return false
}
}
~~~
然后再创建一个Controller,用于控制首页。home\_controller.go文件,在HomeGet方法 中,渲染home页面即可。
~~~go
func HomeGet(c *gin.Context) {
//获取session,判断用户是否登录
islogin := GetSession(c)
c.HTML(http.StatusOK, "home.html", gin.H{"IsLogin": islogin})
}
~~~
## 三、View
我们需要如下几个功能:

后序的每个页面都有这几个功能。所以我们可以让页面嵌套。
现在views目录下创建一个html页面:nav.html,内容如下:
~~~html
<div id="nav">
<div id="nav-write-article">
<ul>
{{/*如果已经登录,才会显示"写博客"*/}}
{{if .IsLogin}}
<li><a href="/article/add">写博客</a></li>
{{end}}
</ul>
</div>
<div id="nav-menu">
<ul>
<li><a href="/">首页</a></li>
<li><a href="/tags">标签</a></li>
<li><a href="/album">相册</a></li>
<li><a href="/aboutme">关于我</a></li>
</ul>
</div>
<div id="nav-login">
<ul>
{{if .IsLogin}}
<li><a href="">退出</a></li>
{{else}}
<li><a href="/login">登录</a></li>
<li><a href="/register">注册</a></li>
{{end}}
</ul>
</div>
</div>
~~~
当然这里需要判断用户是否登录,如果登录,显示写博客功能,以及可以退出。否则显示登录或注册。
接下来,我们创建一个新的页面:home.html,内容如下:
~~~html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>首页</title>
<link href="../static/css/blogsheet.css" rel="stylesheet">
</head>
<body>
{{template "nav.html" .}}
</body>
</html>
~~~
通过页面的嵌套,我们可以将标签显示到home页面上。
> 特别注意,{{template "nav.html" .}},后面的`.`,这是传递当前参数到子模板
同样,我们将之前的login.html页面和register.html页面,也将nav嵌套进来,代码如下:
login.html
~~~html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登录</title>
<link rel="stylesheet" type="text/css" href="../static/css/lib/login.css">
<link rel="stylesheet" type="text/css" href="../static/css/blogsheet.css">
<script src="../static/js/lib/jquery-3.3.1.min.js"></script>
<script src="../static/js/lib/jquery.url.js"></script>
<script src="../static/js/blog.js"></script>
</head>
<body>
<!--
<div id="nav">
<div id="nav-login">
<ul>
<li><a href="/login">登录</a></li>
<li><a href="/register">注册</a></li>
</ul>
</div>
</div>
-->
{{template "nav.html"}}
<div class="htmleaf-container">
<div class="wrapper">
{{/*注册表单*/}}
<div class="container">
<h1>Welcome</h1>
<form id="login-form" class="form">
<input type="text" name="username" placeholder="请输入用户名">
<input type="password" name="password" placeholder="请输入密码" id="login-password">
<br>
<button type="submit" id="login-button">登录</button>
</form>
</div>
{{/*背景动画*/}}
<ul class="bg-bubbles">
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
</div>
</div>
</body>
</html>
~~~
register.html
~~~html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>注册</title>
<link rel="stylesheet" type="text/css" href="../static/css/lib/login.css">
<link rel="stylesheet" type="text/css" href="../static/css/blogsheet.css">
<script src="../static/js/lib/jquery-3.3.1.min.js"></script>
<script src="../static/js/lib/jquery.url.js"></script>
<script src="../static/js/blog.js"></script>
</head>
<body>
<!--
<div id="nav">
<div id="nav-login">
<ul>
<li><a href="/login">登录</a></li>
<li><a href="/register">注册</a></li>
</ul>
</div>
</div>
-->
{{template "nav.html"}}
<div class="htmleaf-container">
<div class="wrapper">
{{/*注册表单*/}}
<div class="container">
<h1>Welcome</h1>
<form id="register-form" class="form">
<input type="text" name="username" placeholder="Username">
<input type="password" name="password" placeholder="Password" id="register-password">
<input type="password" name="repassword" placeholder="rePassword">
<br>
<button type="submit" id="login-button">Register</button>
</form>
</div>
{{/*背景动画*/}}
<ul class="bg-bubbles">
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
</div>
</div>
</body>
</html>
~~~
## 四、退出
我们先在nav.html页面中,添加退出的代码:
~~~html
<div id="nav-login">
<ul>
{{if .IsLogin}}
<li><a href='javascript:if(confirm("确定退出吗?")){location="/exit"}'>退出</a></li>
{{else}}
<li><a href="/login">登录</a></li>
<li><a href="/register">注册</a></li>
{{end}}
</ul>
</div>
~~~
然后重新注册一个路由,用于处理退出:
~~~go
func InitRouter() *gin.Engine {
router := gin.Default()
router.LoadHTMLGlob("views/*")
//设置session midddleware
store := cookie.NewStore([]byte("loginuser"))
router.Use(sessions.Sessions("mysession", store))
{
//注册:
router.GET("/register", controllers.RegisterGet)
router.POST("/register", controllers.RegisterPost)
//登录
router.GET("/login", controllers.LoginGet)
router.POST("/login", controllers.LoginPost)
//首页
router.GET("/", controllers.HomeGet)
//退出
router.GET("/exit", controllers.ExitGet)
}
return router
}
~~~
然后再创建一个go文件:exit\_controller.go
~~~go
package controllers
import (
"github.com/gin-gonic/gin"
"github.com/gin-contrib/sessions"
"net/http"
"fmt"
)
func ExitGet(c *gin.Context) {
//清除该用户登录状态的数据
session := sessions.Default(c)
session.Delete("loginuser")
session.Save()
//session.Clear()
fmt.Println("delete session...",session.Get("loginuser"))
c.Redirect(http.StatusMovedPermanently,"/")
}
~~~
清除session后,重定位到/路径上。
## 五、运行效果
我们重启项目后,打来浏览器输入网址:[http://127.0.0.1:8081/](http://127.0.0.1:8081/)
浏览器如下:

点击登录按钮,进入登录页,

然后输入用户名和密码,点击登录:

服务端运行如下:

点击退出按钮:

服务端也可以看见删除了session:
