Golang仿云盘项目-4 账号系统与鉴权(1)-解决:登录 404 not found
4.1 账号系统功能
解决:登录 404 not found
本文来自博客园,作者:Arway,转载请注明原文链接:https://www.cnblogs.com/cenjw/p/16490891.html
- 支持用户注册、登录
- 支持用户Session鉴权
- 用户数据资源隔离
用户表设计
CREATE TABLE `tbl_user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_name` varchar(64) NOT NULL DEFAULT '' COMMENT '用户名',
`user_pwd` varchar(256) NOT NULL DEFAULT '' COMMENT '用户encoded密码',
`email` varchar(64) DEFAULT '' COMMENT '邮箱',
`phone` varchar(128) DEFAULT '' COMMENT '手机号',
`email_validated` tinyint(1) DEFAULT 0 COMMENT '邮箱是否已验证',
`phone_validated` tinyint(1) DEFAULT 0 COMMENT '手机号是否已验证',
`signup_at` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '注册日期',
`last_active` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后活跃时间戳',
`profile` text COMMENT '用户属性',
`status` int(11) NOT NULL DEFAULT '0' COMMENT '账户状态(启用/禁用/锁定/标记删除等)',
PRIMARY KEY (`id`),
UNIQUE KEY `idx_username` (`user_name`),
KEY `idx_status` (`status`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4;
4.2 用户注册/登录接口
注册接口
db/user.go
点击查看代码
// UserSignup: 通过用户名和密码完成user表的注册
func UserSignup(username, password string) bool {
// 插入一条用户数据
stmt, err := mydb.DBConn().Prepare("INSERT ignore INTO tbl_user(user_name, user_pwd)" +
"VALUES(?,?)")
if err != nil {
fmt.Println("Failed to insert, err: " + err.Error())
return false
}
defer stmt.Close()
ret, err := stmt.Exec(username, password)
if err != nil {
fmt.Println("Failed to insert, err: " + err.Error())
return false
}
// 校验是否注册成功(重复注册也当做注册失败)
if rows, err := ret.RowsAffected(); nil == err && rows > 0 {
return true
}
return false
}
// 用于处理用户请求的一些handler
handler/user.go
点击查看代码
// SignupHandler : 处理用户注册请求
func SignupHandler(w http.ResponseWriter, r *http.Request) {
if r.Method == "GET" {
data, err := ioutil.ReadFile("./static/view/signup.html")
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
}
w.Write(data)
return
}
r.ParseForm()
username := r.Form.Get("username")
passwd := r.Form.Get("password")
if len(username) < 3 || len(passwd) < 5 {
w.Write([]byte("Invalid parameter"))
return
}
// 对密码进行加盐及取Sha1值加密
encPasswd := util.Sha1([]byte(passwd + pwdSalt))
// 将用户信息注册到用户表中
suc := dblayer.UserSignup(username, encPasswd)
if suc {
w.Write([]byte("SUCCESS"))
} else {
w.Write([]byte("FAILED"))
}
}
登录接口
-
校验用户名和密码
比较请求上传参数中的数据和从数据库查出来的数据 -
生成访问凭证(token)
-- 创建用户token表 CREATE TABLE `tbl_user_token` ( `id` int(11) NOT NULL AUTO_INCREMENT, `user_name` varchar(64) NOT NULL DEFAULT '' COMMENT '用户名', `user_token` char(40) NOT NULL DEFAULT '' COMMENT '用户登录token', PRIMARY KEY (`id`), UNIQUE KEY `idx_username` (`user_name`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
replace: token 可重复生成且插入
-
登录后重定向回首页
handler/user.go
处理登录请求点击查看代码
// SignInHandler : 登录接口 func SignInHandler(w http.ResponseWriter, r *http.Request) { if r.Method == "GET" { http.Redirect(w, r, "/static/view/signin.html", http.StatusFound) return } r.ParseForm() username := r.Form.Get("username") password := r.Form.Get("password") encPasswd := util.Sha1([]byte(password + pwdSalt)) // 1. 校验用户名及密码 pwdChecked := dblayer.UserSignin(username, encPasswd) if !pwdChecked { w.Write([]byte("FAILED")) return } // 2. 生成访问凭证(token) token := GenToken(username) upRes := dblayer.UpdateToken(username, token) if !upRes { w.Write([]byte("FAILED")) return } // 3. 登录成功后重定向到首页 // w.Write([]byte("http://" + r.Host + "/static/view/home.html")) resp := util.RespMsg{ Code: 0, Msg: "OK", Data: struct{ Location string Username string Token string }{ Location: "http://" + r.Host + "/static/view/home.html", Username: username, Token: token, }, } w.Write(resp.JSONBytes()) }
用户信息查询接口
handler/user.go
点击查看代码
func UserInfoHandler(w http.ResponseWriter, r *http.Request) {
// 1. 解析参数
r.ParseForm()
username := r.Form.Get("username")
token := r.Form.Get("token")
fmt.Printf("username: %v\n", username)
// 2.验证token是否有效
if !isTokenValid(token) {
w.WriteHeader(http.StatusForbidden)
return
}
// 3. 查询用户信息
user, err := dblayer.GetUserInfo(username)
fmt.Printf("user: %v", user)
if err != nil {
w.WriteHeader(http.StatusForbidden)
return
}
// 4. 组装并且响应用户数据
resp := util.RespMsg{
Code: 0,
Msg: "OK",
Data: user,
}
w.Write(resp.JSONBytes())
}
本文来自博客园,作者:Arway,转载请注明原文链接:https://www.cnblogs.com/cenjw/p/16490891.html
解决:登录 404 not found
问题1:视频缺少了加载静态文件的部分内容,搜索了一波,go的http库有这么几个方法:
http.StripPrefix()
方法配合http.Handle()
或http.HandleFunc()
可以实现带路由前缀的文件服务。
参考 https://cloud.tencent.com/developer/article/1351492
解决方法
在main.go文件的main方法中加上下面的代码
func main() {
// static configure
http.Handle("/static/",
http.StripPrefix("/static/", http.FileServer(http.Dir("./static/"))))
...
问题2: 跳转home.html, 前端没有加载数据
解决
查看了home.html文件发现没有传数据。。。
home.html
...
<script lang="javascript">
window.onload = function () {
var username = document.getElementById('username');
$.ajax({
// url: "/user/info?" + queryParams(), 注释掉这句
url: "/user/info",
type: "POST",
// 加上data
data: {username: localStorage.getItem("username"),
token: localStorage.getItem("token")},
error: function (jqXHR, textStatus, errorThrown) {
...
如果都不行,那就是这个js链接的问题。。。
兄弟们可以从这里找个能用的替换掉
验证token的拦截器
handler/auth.go
// HTTPInterceptor: HTTP请求拦截器(函数类似Python的装饰器)
func HTTPInterceptor(h http.HandlerFunc) http.HandlerFunc {
return http.HandlerFunc(
func(w http.ResponseWriter, r *http.Request) {
r.ParseForm()
username := r.Form.Get("username")
token := r.Form.Get("token")
if len(username) < 3 || !isTokenValid(token) {
w.WriteHeader(http.StatusForbidden)
return
}
h(w, r)
})
}
- 是针对HTTP请求的
- 好处:以后所有要进行安全验证的接口都可以通过浏览器来实现,这样就可以实现统一认证,避免每个接口都要实现验证方法,节省时间和资源。
本文来自博客园,作者:micromatrix,转载请注明原文链接:https://www.cnblogs.com/cenjw/p/16490891.html
posted on 2022-07-19 18:50 micromatrix 阅读(207) 评论(0) 编辑 收藏 举报