🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
### 【GoWeb开发实战Gin框架】微博项目实战-处理session # Session的处理 我们希望用户登录后可以有写博客的功能,当然也允许用户退出。 ![html3](http://image.chaindesk.cn/html3.png/mark) 如果用户没有登录,直接访问首页,只可以查看文章,标签,相册等,但是没有写博客的功能: ![html4](http://image.chaindesk.cn/html4.png/mark) ## 一、安装gin框架的session 打开终端输入: ~~~shell go get github.com/gin-contrib/sessions ~~~ ![gin_shell](http://image.chaindesk.cn//gin_shell.png/mark) ## 二、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 我们需要如下几个功能: ![html5](http://image.chaindesk.cn/html5.png/mark) 后序的每个页面都有这几个功能。所以我们可以让页面嵌套。 现在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/) 浏览器如下: ![web10_yunxing12](http://image.chaindesk.cn/web10_yunxing12.png/mark) 点击登录按钮,进入登录页, ![web10_yunxing13](http://image.chaindesk.cn/web10_yunxing13.png/mark) 然后输入用户名和密码,点击登录: ![web10_yunxing15](http://image.chaindesk.cn/web10_yunxing15.png/mark) 服务端运行如下: ![gin_yunxing53](http://image.chaindesk.cn/gin_yunxing53.png/mark) 点击退出按钮: ![web10_yunxing17](http://image.chaindesk.cn/web10_yunxing17.png/mark) 服务端也可以看见删除了session: ![gin_yunxing54](http://image.chaindesk.cn/gin_yunxing54.png/mark)