wip: 刚刚开始, 探索阶段
This commit is contained in:
commit
eb1744bd0d
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
.idea
|
||||||
|
.vscode
|
||||||
|
.DS_Store
|
19
go.mod
Normal file
19
go.mod
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
module uauth
|
||||||
|
|
||||||
|
go 1.20
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/google/uuid v1.6.0
|
||||||
|
github.com/gorilla/mux v1.8.1
|
||||||
|
github.com/loveuer/nf v0.2.11
|
||||||
|
github.com/spf13/cobra v1.8.1
|
||||||
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/fatih/color v1.17.0 // indirect
|
||||||
|
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||||
|
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||||
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
|
github.com/spf13/pflag v1.0.5 // indirect
|
||||||
|
golang.org/x/sys v0.20.0 // indirect
|
||||||
|
)
|
27
go.sum
Normal file
27
go.sum
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||||
|
github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4=
|
||||||
|
github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI=
|
||||||
|
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
|
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
|
||||||
|
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
|
||||||
|
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||||
|
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||||
|
github.com/loveuer/nf v0.2.11 h1:W775exDO8eNAHT45WDhXekMYCuWahOW9t1aVmGh3u1o=
|
||||||
|
github.com/loveuer/nf v0.2.11/go.mod h1:M6reF17/kJBis30H4DxR5hrtgo/oJL4AV4cBe4HzJLw=
|
||||||
|
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||||
|
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||||
|
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||||
|
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||||
|
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
|
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
|
github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
|
||||||
|
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
|
||||||
|
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||||
|
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||||
|
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
|
||||||
|
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
18
httptest/uauth/auth req.bru
Normal file
18
httptest/uauth/auth req.bru
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
meta {
|
||||||
|
name: auth req
|
||||||
|
type: http
|
||||||
|
seq: 2
|
||||||
|
}
|
||||||
|
|
||||||
|
get {
|
||||||
|
url: http://127.0.0.1:8080/authorize?client_id=12345&response_type=code&redirect_uri=http://localhost:8080/callback&scopde=balaba
|
||||||
|
body: none
|
||||||
|
auth: none
|
||||||
|
}
|
||||||
|
|
||||||
|
params:query {
|
||||||
|
client_id: 12345
|
||||||
|
response_type: code
|
||||||
|
redirect_uri: http://localhost:8080/callback
|
||||||
|
scopde: balaba
|
||||||
|
}
|
9
httptest/uauth/bruno.json
Normal file
9
httptest/uauth/bruno.json
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"version": "1",
|
||||||
|
"name": "uauth",
|
||||||
|
"type": "collection",
|
||||||
|
"ignore": [
|
||||||
|
"node_modules",
|
||||||
|
".git"
|
||||||
|
]
|
||||||
|
}
|
30
internal/cmd/cmd.go
Normal file
30
internal/cmd/cmd.go
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/loveuer/nf/nft/log"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
"uauth/internal/opt"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
Command = &cobra.Command{
|
||||||
|
Use: "uauth",
|
||||||
|
Short: "uauth: oauth v2 server",
|
||||||
|
Example: "",
|
||||||
|
PersistentPreRun: func(cmd *cobra.Command, args []string) {
|
||||||
|
if opt.Cfg.Debug {
|
||||||
|
log.SetLogLevel(log.LogLevelDebug)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
Command.PersistentFlags().BoolVar(&opt.Cfg.Debug, "debug", false, "debug mode")
|
||||||
|
|
||||||
|
initServe()
|
||||||
|
|
||||||
|
Command.AddCommand(
|
||||||
|
initServe(),
|
||||||
|
)
|
||||||
|
}
|
11
internal/cmd/serve.go
Normal file
11
internal/cmd/serve.go
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
package cmd
|
||||||
|
|
||||||
|
import "github.com/spf13/cobra"
|
||||||
|
|
||||||
|
func initServe() *cobra.Command {
|
||||||
|
serve := &cobra.Command{
|
||||||
|
Use: "serve",
|
||||||
|
}
|
||||||
|
|
||||||
|
return serve
|
||||||
|
}
|
9
internal/opt/config.go
Normal file
9
internal/opt/config.go
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
package opt
|
||||||
|
|
||||||
|
type config struct {
|
||||||
|
Debug bool `json:"debug"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
Cfg = config{}
|
||||||
|
)
|
100
main.go
Normal file
100
main.go
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
"github.com/loveuer/nf"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 假设这是你的用户认证函数
|
||||||
|
func authenticateUser(username, password string) (bool, error) {
|
||||||
|
// 这里你应该实现真实的用户认证逻辑
|
||||||
|
// 为了简化,我们这里直接硬编码一个用户名和密码
|
||||||
|
if username == "user" && password == "pass" {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return false, fmt.Errorf("invalid username or password")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理登录请求
|
||||||
|
func handleLogin(c *nf.Ctx) error {
|
||||||
|
username := c.FormValue("username")
|
||||||
|
password := c.FormValue("password")
|
||||||
|
|
||||||
|
// 认证用户
|
||||||
|
ok, err := authenticateUser(username, password)
|
||||||
|
if err != nil || !ok {
|
||||||
|
return c.Status(http.StatusUnauthorized).SendString("Unauthorized")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 用户认证成功,重定向到授权页面
|
||||||
|
http.Redirect(c.Writer, c.Request, "/authorize?client_id=12345&response_type=code&redirect_uri=http%3A%2F%2Flocalhost%3A8080%2Fcallback&scope=read%20write", http.StatusFound)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理授权请求
|
||||||
|
func handleAuthorize(c *nf.Ctx) error {
|
||||||
|
// 解析查询参数
|
||||||
|
clientID := c.Query("client_id")
|
||||||
|
responseType := c.Query("response_type")
|
||||||
|
redirectURI := c.Query("redirect_uri")
|
||||||
|
scope := c.Query("scope")
|
||||||
|
|
||||||
|
// 检查客户端 ID 和其他参数
|
||||||
|
// 在实际应用中,你需要检查这些参数是否合法
|
||||||
|
if clientID != "12345" || responseType != "code" || redirectURI != "http://localhost:8080/callback" {
|
||||||
|
return c.Status(http.StatusBadRequest).SendString("Invalid request")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 显示授权页面给用户
|
||||||
|
_, err := c.Write([]byte(`
|
||||||
|
<html>
|
||||||
|
<head><title>Authorization</title></head>
|
||||||
|
<body>
|
||||||
|
<h1>Do you want to authorize this application?</h1>
|
||||||
|
<form action="/approve" method="post">
|
||||||
|
<input type="hidden" name="client_id" value="` + clientID + `"/>
|
||||||
|
<input type="hidden" name="redirect_uri" value="` + redirectURI + `"/>
|
||||||
|
<input type="hidden" name="scope" value="` + scope + `"/>
|
||||||
|
<button type="submit">Yes, I authorize</button>
|
||||||
|
</form>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
`))
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理用户的授权批准
|
||||||
|
func handleApprove(c *nf.Ctx) error {
|
||||||
|
// 获取表单数据
|
||||||
|
clientID := c.FormValue("client_id")
|
||||||
|
redirectURI := c.FormValue("redirect_uri")
|
||||||
|
scope := c.FormValue("scope")
|
||||||
|
|
||||||
|
// 生成授权码
|
||||||
|
authorizationCode := uuid.New().String()[:8]
|
||||||
|
|
||||||
|
log.Printf("[D] client_id = %s, scope = %s, auth_code = %s", clientID, scope, authorizationCode)
|
||||||
|
|
||||||
|
// 重定向到回调 URL 并附带授权码
|
||||||
|
http.Redirect(c.Writer, c.Request, redirectURI+"?code="+authorizationCode, http.StatusFound)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
app := nf.New()
|
||||||
|
|
||||||
|
// 设置路由
|
||||||
|
app.Get("/login", handleLogin)
|
||||||
|
app.Get("/authorize", handleAuthorize)
|
||||||
|
app.Post("/approve", handleApprove)
|
||||||
|
|
||||||
|
// 启动 HTTP 服务器
|
||||||
|
log.Println("Starting server on :8080")
|
||||||
|
log.Fatal(app.Run(":8080"))
|
||||||
|
}
|
23
model/user.go
Normal file
23
model/user.go
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
type Status int64
|
||||||
|
|
||||||
|
type User struct {
|
||||||
|
Id uint64 `json:"id" gorm:"primaryKey;column:id"`
|
||||||
|
CreatedAt int64 `json:"created_at" gorm:"column:created_at;autoCreateTime:milli"`
|
||||||
|
UpdatedAt int64 `json:"updated_at" gorm:"column:updated_at;autoUpdateTime:milli"`
|
||||||
|
DeletedAt int64 `json:"deleted_at" gorm:"index;column:deleted_at;default:0"`
|
||||||
|
|
||||||
|
Username string `json:"username" gorm:"column:username;type:varchar(64);unique"`
|
||||||
|
Password string `json:"-" gorm:"column:password;type:varchar(256)"`
|
||||||
|
|
||||||
|
Status Status `json:"status" gorm:"column:status;default:0"`
|
||||||
|
|
||||||
|
Nickname string `json:"nickname" gorm:"column:nickname;type:varchar(64)"`
|
||||||
|
Comment string `json:"comment" gorm:"column:comment"`
|
||||||
|
|
||||||
|
CreatedById uint64 `json:"created_by_id" gorm:"column:created_by_id"`
|
||||||
|
CreatedByName string `json:"created_by_name" gorm:"column:created_by_name;type:varchar(64)"`
|
||||||
|
|
||||||
|
LoginAt int64 `json:"login_at" gorm:"-"`
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user