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 可重复生成且插入
3. 登录后重定向回首页
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
...
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) {
...
</code></pre><p>如果都不行,那就是这个js链接的问题。。。<br><img src="https://img2022.cnblogs.com/blog/2357964/202207/2357964-20220719211805806-1683536289.png"><br>兄弟们可以从<a href="http://www.htmleaf.com/js/jquery/jquery-2.0.0.html" rel="noopener">这里</a>找个能用的替换掉</p><h2 id="验证token的拦截器">验证token的拦截器</h2><p><code>handler/auth.go</code></p><pre><code class="language-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)
})
}
</code></pre><ol><li>是针对HTTP请求的</li><li>好处:以后所有要进行安全验证的接口都可以通过浏览器来实现,这样就可以实现统一认证,避免每个接口都要实现验证方法,节省时间和资源。</li></ol>
Original: https://www.cnblogs.com/cenjw/p/16490891.html
Author: micromatrix
Title: Golang仿云盘项目-4账号系统与鉴权(1)-解决:登录404notfound
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/712526/
转载文章受原作者版权保护。转载请注明原作者出处!