一起来捋一捋前后端分离登录过程的思路并实现全过程
本文将实现前后端分离开发模式下的登录过程
需要使用到的技术栈为:
- go/java web框架(gin/springboot)
- mysql orm框架(gorm/mybatis)
- vue(前端框架)
看似不起眼的登录其实还是有很多值得探讨的地方
在保证安全的情况也也要增加用户的体验
现在的开发中一般都采用前后端分离的模式
采用jwt token进行鉴权
若token失效,此时需要重新登录
并且调用其他请求时,请求头中必须携带token
从一定程度上保证了安全性
关于登录的流程分为以下几步
- 用户输入用户名和密码并登录(即提交表单)
- 后端查询数据库,验证用户名于密码是否匹配,若匹配,返回token给前端
- 前端登录,进入到主页面(/view.html),并将token存在localStorage中(若对安全性要求高,不建议存在本地,应当使用Redis进行存储)
- 若用户没有登录直接输入/view.html,重定向到登录页(根据localStorage中的token判断)
- 登录之后每次请求时请求头中携带token,后端会对token进行检验
- 若token无效或者过期,后端返回错误码,如401,前端将页面重定向到登录页重新登录
开发流程(使用go web框架和Vue进行示范)
后端
定义一个model
并把Username作为主键
type Login struct {
Username string `json:"username" gorm:"primaryKey"`
Password string `json:"password"`
}
连接数据库,拿到db
db, err := gorm.Open(mysql.Open(path))
初始化数据库
db.AutoMigrate(&Login{})
使用ORM,我们不需要去手动创建表,创建字段
对于golang和ORM框架来说,struct就可以看做是数据库中的表
struct中的属性可以看做是表中的字段
db.AutoMigrate(&Login{}),将会在数据库中自动绑定表,并创建相应的字段
编写service
func TrueLogin(username, password string) (string, error) {
var login Login
//根据前端传来的username,进行查询
err := db.Where("username = ?", username).Find(&login).Error
if err != nil {
//如果没有查询到,则返回用户名或者密码错误
return "", errors.New("The password is incorrect")
}
//判断前端传过来的用户名是否与查询到的用户名是否相同,这一步可有可无,因为肯定是相同的
//判断用户传过来的密码是否与查询到的用户的密码是否相同
if username == login.Username && password == login.Password {
//校验成功之后使用中间件生成token并返回
tokenString, _ := middlewares.GenToken(login.Username, login.Password)
return tokenString, nil
} else {
//否则提示用户名/密码错误
return "", errors.New("The password is incorrect")
}
}
参数为username和password,由controller层进行获取
service只用进行逻辑判断,对传进来的username和password进行校验
检验成功后返回token,检验不成功则返回相关的错误信息
编写controller
func TrueLogin(c *gin.Context) {
//c.PostForm用于POST请求时, 获取表单的值
username := c.PostForm("username")
password := c.PostForm("password")
//将username和password传到service进行校验
tokenString, err := service.TrueLogin(username, password)
if err != nil {
//返回json
// {"code":200, "message":"用户名不存在或者密码不正确"}
//
c.IndentedJSON(200, gin.H{
"code":2002,
"message":err,
})
} else {
c.IndentedJSON(http.StatusOK, gin.H{
//返回json
// {"code":200, "message":"login successfully", "data":tokenString}
"code":2002,
"message":"login successfully",
"data":tokenString,
})
}
}
编写router路由
func LoadLogin(e *gin.Engine) {
e.POST("/api/v3/trueLogin", controllers.TrueLogin)
}
运行并制定端口
err := r.Run(":8080")
此时该服务便可以通过http://localhost:8080/api/v3/tureLogin进行访问
测试
假设表中有一条数据
username = test
password = test
使用Vue
使用axios请求后端
将input输入框的数据提交到后台
后台并返回结果
前端对后端返回的结果进行判断
若为"login successfully"
则登录成功并跳转到hello.html并将后端返回的token保存到localStorage中
否则提示用户名/密码错误
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>login</title>
</head>
<body>
<div id="app">
<input type="text" v-model="loginForm.username" placeholder="用户名"/>
<input type="text" v-model="loginForm.password" placeholder="密码"/>
<button @click="login">登录</button>
</div>
<script src="./js/vue.js"></script>
<script src="./js/axios.min.js"></script>
<script>
var vue = new Vue({
el:"#app",
data: {
loginForm:{
username:'',
password:''
}
},
methods : {
login (){
let param = new URLSearchParams()
param.append('username', this.loginForm.username)
param.append('password', this.loginForm.password)
axios ({
method:'post',
url:"http://nj-jay.com:8080/api/v3/trueLogin",
data:param
}).then(function(response){
console.log(response.data)
//window.location.href = 'http://47.97.44.29:8000'
if (response.data.message=="login successfully"){
alert("登录成功")
//登录成功就跳转
window.location.href = 'hello.html';
var user_token = response.data.data;
// 存token到localStorage中
localStorage.setItem("currentUser_token", user_token);
} else {
alert("用户名/密码错误")
}
})
}
}
})
</script>
</body>
</html>
在hello.html中head标签中嵌入checkLog函数判断localStorage中是否存在token
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<script src="./js/function.js"></script>
<script type="text/javascript">checkLog()</script>
<title>about</title>
</head>
<body>
<h1>welcome</h1>
<script src="./js/vue.js"></script>
<script src="./js/axios.min.js"></script>
</body>
</html>
function.js
判断localStorage中是否存在token
若不存在则跳转到登录页
function checkLog(){
var a = localStorage.getItem('currentUser_token')
if (!a) {
//不存在就跳转到首页
window.location.href = './index.html'
}
}
以上就是登录实现的所有过程
完整代码示例包含在我的github中
链接: https://github.com/nj-jay/mysql-gin-api
欢迎star
1 条评论