[
](#restful-api-in-go)GO中的RESTful API
这是一个中级的Go项目,在Go中运行的项目结构优化了RESTful API服务。该项目中的API是基于坚实和通用的原则设计的,并连接到本地MySQL数据库。
这个项目的亮点如下
- RESTful API展示了数据库表的标准CRUD操作。
- 该项目具有干净的架构,并且已经覆盖了测试。
- 数据验证
- 它使用基于JWT的认证和认证中间件。
- 每个令牌在15分钟内过期,以防止系统错误。
- 错误处理是通过清晰的响应完成的。
- 在JWT创建的令牌的帮助下,它提出了用户名和密码的结构化日志,持续15分钟。之后,用户可以创建TODO。
- 该项目在开发过程中使用了以下软件包
[
](#getting-started)开始使用
如果你以前没有接触过Go,你应该访问这个网站。
安装完Go后,你应该运行以下命令来体验这个项目
# download the starter code
git clone https://github.com/Kivanc10/golang-rest-api-with-mysql.git
# open the code
之后,你就有了一个运行在http://127.0.0.1:8080 的RESTful API。它为我们提供了以下端点
GET /users:它为我们提供了所有登录用户的列表。POST /signUp:它允许用户注册。它将用户信息保存在数据库中,并使用JWT创建令牌。它接受这样的附加数据。PersonID可以是任何东西,因为数据库安排了自动增量。-
{
POST /signIn:验证和登录。它用JWT再次创建令牌。它接受附加数据,就像上面所说的。GET /users/me:它允许用户访问他的信息。要做到这一点,用户必须经过认证,否则系统将不会让它发生。PUT /users/update/me: 它用所接受的数据更新当前的认证用户。要做到这一点,用户必须经过认证。它接受的附件数据如下。-
{
-
DELETE /user/me:它删除了当前的认证用户。要做到这一点,用户必须经过认证。GET /users/logout/me:它允许用户注销所有令牌。要做到这一点,用户必须经过认证。该用户将不会从数据库中删除。POST /todo: 它允许用户创建todos。要做到这一点,用户必须经过认证。它接受这样的附件数据。-
{
-
GET /todos: 它列出了所有由认证用户创建的todos。GET /todos/me:它只列出属于当前认证用户的todos。
[
](#if-you-have-api-client-tools-like-postman-you-can-handle-complicated-operations-easily)如果你有API客户端工具,如Postman ,你可以轻松处理复杂的操作。
如果你在Postman中创建一个新的环境,并声明你要使用的变量,你就会使一切都变得清晰。
你还应该在一些请求的测试部分添加一组代码,用请求头的承载令牌自动安排。(signup,login,getme,update,logout )在代码之前,你应该在编辑集合的授权部分定义一个名为authToken 的环境令牌。
然后将代码粘贴到signup,login,getme,update,logout 请求中。
if
之后,你的请求头将自动更新为有效的令牌以进行认证。
你必须确保你选择的环境
[
](#how-to-use-endpoints)如何使用端点
# sign up the user via POST /signUp
curl -X POST -H "Content-Type: application/json" -d `{ "PersonID":0,"UserName":"sample user name","Password":"12312321"}` http://localhost:8080/signUp
# it should return response.header with jwt and token
# sign in with user via POST /signIn
curl -X POST -H "Content-Type: application/json" -d `{ "PersonID":0,"UserName":"sample user name","Password":"12312321"}` http://localhost:8080/signIn
# it should return response.Header with jwt and token
# save token during the loggedin and inherit auth from postman environment,it handles itself
curl -X GET -H "Authorization: Bearer ...JWT token here..." http://localhost:8080/users/me
# to create todos for the user authenticated
curl -X POST -H "Authorization: Bearer ...JWT token here..." -d `{"Context" : "sample todo"}` http://localhost:8080/todo
# it returns the saved todo belong to the user authenticated
[
](#project-layout)项目布局
.
[
](#working-with-jwt-based-authenticaton-and-auth-middleware)与基于JWT的认证和认证中间件一起工作
[
](#jwt)JWT
- JSON Web Token (JWT)是一种独立的方式,以JSON对象的形式在各方之间安全地传输信息。如果你将处理授权和信息交换,你最合理的做法就是使用JWT。
[
](#auth-middleware)认证中间件
- 我们已经有了认证服务和它的适配器以及登录中间件,我们可以创建中间件来检查已认证的用户,如果用户没有被认证,它可以重定向到/登录页面。
在该项目中,如果有必要,我们创建令牌,如signUp,signIn,... ,以进行和保存更改。然后我们使用Auth中间件来访问当前用户,如果其令牌是有效的。auth中间件使我们能够设计一个真正的安全系统。
[
](#to-create-tokens)创建令牌
", atClaims)
return token, nil // return token created and no error if succeed
}
">
func
[
](#to-integrate-auth-middleware)整合认证中间件
%s and len -> %d/n", authHeader, len(authHeader))
if len(authHeader) != 2 || authHeader[0] == "null" { // ["Bearer", "Token..."],如果不是这样,就有一个错误
//fmt.Println("Malformed token")
w.WriteHeader(http.StatusUnauthorized)
w.Write([]byte("Malformed Token"))
log.Fatal("Malformed token")
}
jwtToken := authHeader[1] //获得
令牌
token, err := jwt.
Parse(jwtToken)
Parse(jwtToken, func(token *jwt.Token) (interface{}, error) { // parse the token
if _, ok := token.(*jwt.SigningMethodHMAC); !ok {
return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
}
return []byte(mySignInKey), nil
})
// 用jwt.MapClaims进行类型转换,检查令牌是否有效
if claims, ok := token.(jwt.MapClaims); ok && token.Valid { // 如果该令牌有效
ctx := context.WithValue(r.Context(), "props", claims) // props是上下文关键字
// 在处理程序中访问上下文值
next.ServeHTTP(w, r.WithContext(ctx
))
// 如果成功,就用上下文服务http
} else { // 如果有错误
fmt.Println("token err -> ", err)
//r.Header.Set("ExpiredToken", jwtToken)
//DelTokenIfExpired(jwtToken)
// usernameInter := claims["user_name"]
// if username, ok := usernameInter.Stringer); ok {
// person := dbop.GetPersonToDelToken(username.String())
// dbop.DeleteTokenIfExpired(person
) // }
w.WriteHeader(http.StatusUnauthorized)
w.Write([]byte("you are Unauthorized or your token is expired") ) }
}
">
func
[
](#database-scheme)数据库方案




