Skip to content

Commit 82e5495

Browse files
committed
Add example
1 parent 432c315 commit 82e5495

File tree

7 files changed

+273
-13
lines changed

7 files changed

+273
-13
lines changed

README.md

Lines changed: 71 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
Golang OAuth2 Server
2-
=====================
1+
OAuth2服务端
2+
===========
3+
4+
> 基于Golang实现的OAuth2协议,具有简单化、模块化的特点
35
46
[![GoDoc](https://godoc.org/gopkg.in/oauth2.v2?status.svg)](https://godoc.org/gopkg.in/oauth2.v2)
57
[![Go Report Card](https://goreportcard.com/badge/gopkg.in/oauth2.v2)](https://goreportcard.com/report/gopkg.in/oauth2.v2)
@@ -8,9 +10,75 @@ Golang OAuth2 Server
810
----
911

1012
```bash
11-
$ go get -v gopkg.in/oauth2.v2
13+
$ go get -u gopkg.in/oauth2.v2/...
14+
```
15+
16+
使用
17+
----
18+
19+
``` go
20+
package main
21+
22+
import (
23+
"log"
24+
"net/http"
25+
26+
"gopkg.in/oauth2.v2/manage"
27+
"gopkg.in/oauth2.v2/models"
28+
"gopkg.in/oauth2.v2/server"
29+
"gopkg.in/oauth2.v2/store/client"
30+
"gopkg.in/oauth2.v2/store/token"
31+
)
32+
33+
func main() {
34+
manager := manage.NewRedisManager(
35+
&token.RedisConfig{Addr: "192.168.33.70:6379"},
36+
)
37+
manager.MapClientStorage(client.NewTempStore())
38+
srv := server.NewServer(server.NewConfig(), manager)
39+
40+
http.HandleFunc("/authorize", func(w http.ResponseWriter, r *http.Request) {
41+
authReq, err := srv.GetAuthorizeRequest(r)
42+
if err != nil {
43+
http.Error(w, err.Error(), http.StatusBadRequest)
44+
return
45+
}
46+
// TODO: 登录验证、授权处理
47+
authReq.UserID = "000000"
48+
49+
err = srv.HandleAuthorizeRequest(w, authReq)
50+
if err != nil {
51+
http.Error(w, err.Error(), http.StatusBadRequest)
52+
}
53+
})
54+
55+
http.HandleFunc("/token", func(w http.ResponseWriter, r *http.Request) {
56+
err := srv.HandleTokenRequest(w, r)
57+
if err != nil {
58+
http.Error(w, err.Error(), http.StatusBadRequest)
59+
}
60+
})
61+
62+
log.Fatal(http.ListenAndServe(":9096", nil))
63+
}
64+
65+
```
66+
67+
测试
68+
----
69+
70+
``` bash
71+
$ goconvey -port=9092
1272
```
1373

74+
> goconvey使用明细[https://github.com/smartystreets/goconvey](https://github.com/smartystreets/goconvey)
75+
76+
范例
77+
----
78+
79+
模拟授权码模式的测试范例,请查看[example](/example)
80+
81+
1482
License
1583
-------
1684

example/README.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
OAuth2 服务端/客户端模拟
2+
=====================
3+
4+
运行服务端
5+
--------
6+
7+
```
8+
$ cd example/server
9+
$ go run main.go
10+
```
11+
12+
运行客户端
13+
--------
14+
15+
```
16+
$ cd example/client
17+
$ go run main.go
18+
```
19+
20+
打开浏览器
21+
--------
22+
23+
[http://localhost:9094](http://localhost:9094)
24+
25+
``` json
26+
{
27+
"access_token": "143C1A45CFF9E0922F9DC68F7EBC81DC",
28+
"expires_in": 7200,
29+
"refresh_token": "5BD7453B8E7C5A3A308166F1675AD57216811391",
30+
"scope": "all",
31+
"token_type": "Bearer"
32+
}
33+
```

example/client/main.go

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package main
2+
3+
import (
4+
"io"
5+
"log"
6+
"net/http"
7+
"net/url"
8+
)
9+
10+
const (
11+
redirectURI = "http://localhost:9094/oauth2"
12+
serverURI = "http://localhost:9096"
13+
)
14+
15+
func main() {
16+
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
17+
u, err := url.Parse(serverURI + "/authorize")
18+
if err != nil {
19+
panic(err)
20+
}
21+
q := u.Query()
22+
q.Add("response_type", "code")
23+
q.Add("client_id", "222222")
24+
q.Add("scope", "all")
25+
q.Add("state", "xyz")
26+
q.Add("redirect_uri", url.QueryEscape(redirectURI))
27+
u.RawQuery = q.Encode()
28+
http.Redirect(w, r, u.String(), http.StatusFound)
29+
})
30+
31+
http.HandleFunc("/oauth2", func(w http.ResponseWriter, r *http.Request) {
32+
r.ParseForm()
33+
state := r.Form.Get("state")
34+
if state != "xyz" {
35+
http.Error(w, "State invalid", http.StatusBadRequest)
36+
return
37+
}
38+
code := r.Form.Get("code")
39+
if code == "" {
40+
http.Error(w, "Code not found", http.StatusBadRequest)
41+
return
42+
}
43+
uv := url.Values{}
44+
uv.Add("code", code)
45+
uv.Add("redirect_uri", redirectURI)
46+
uv.Add("grant_type", "authorization_code")
47+
uv.Add("client_id", "222222")
48+
uv.Add("client_secret", "22222222")
49+
resp, err := http.PostForm(serverURI+"/token", uv)
50+
if err != nil {
51+
http.Error(w, err.Error(), http.StatusInternalServerError)
52+
return
53+
}
54+
io.Copy(w, resp.Body)
55+
})
56+
57+
log.Println("OAuth2 client is running at 9094 port.")
58+
log.Fatal(http.ListenAndServe(":9094", nil))
59+
}

example/server/main.go

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package main
2+
3+
import (
4+
"log"
5+
"net/http"
6+
7+
"gopkg.in/oauth2.v2/manage"
8+
"gopkg.in/oauth2.v2/models"
9+
"gopkg.in/oauth2.v2/server"
10+
"gopkg.in/oauth2.v2/store/client"
11+
"gopkg.in/oauth2.v2/store/token"
12+
)
13+
14+
func main() {
15+
// 创建基于redis的oauth2管理实例
16+
manager := manage.NewRedisManager(
17+
&token.RedisConfig{Addr: "192.168.33.70:6379"},
18+
)
19+
// 使用临时客户端存储
20+
manager.MapClientStorage(client.NewTempStore(&models.Client{
21+
ID: "222222",
22+
Secret: "22222222",
23+
Domain: "http://localhost:9094",
24+
}))
25+
26+
srv := server.NewServer(server.NewConfig(), manager)
27+
28+
http.HandleFunc("/authorize", func(w http.ResponseWriter, r *http.Request) {
29+
authReq, err := srv.GetAuthorizeRequest(r)
30+
if err != nil {
31+
http.Error(w, err.Error(), http.StatusBadRequest)
32+
return
33+
}
34+
authReq.UserID = "000000"
35+
// TODO: 登录验证、授权处理
36+
err = srv.HandleAuthorizeRequest(w, authReq)
37+
if err != nil {
38+
http.Error(w, err.Error(), http.StatusBadRequest)
39+
}
40+
})
41+
42+
http.HandleFunc("/token", func(w http.ResponseWriter, r *http.Request) {
43+
err := srv.HandleTokenRequest(w, r)
44+
if err != nil {
45+
http.Error(w, err.Error(), http.StatusBadRequest)
46+
}
47+
})
48+
49+
log.Println("OAuth2 server is running at 9096 port.")
50+
log.Fatal(http.ListenAndServe(":9096", nil))
51+
}

manage/manager.go

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,39 @@ import (
55

66
"github.com/LyricTian/inject"
77
"gopkg.in/oauth2.v2"
8+
"gopkg.in/oauth2.v2/generates"
9+
"gopkg.in/oauth2.v2/models"
10+
"gopkg.in/oauth2.v2/store/token"
811
)
912

1013
// Config 授权配置参数
1114
type Config struct {
1215
TokenExp time.Duration // 令牌有效期
13-
RefreshExp time.Duration // g令牌有效期
16+
RefreshExp time.Duration // 更新令牌有效期
17+
}
18+
19+
// NewRedisManager 创建基于redis存储的管理实例
20+
func NewRedisManager(redisCfg *token.RedisConfig) *Manager {
21+
m := NewManager()
22+
m.MapClientModel(models.NewClient())
23+
m.MapTokenModel(models.NewToken())
24+
m.MapAuthorizeGenerate(generates.NewAuthorizeGenerate())
25+
m.MapAccessGenerate(generates.NewAccessGenerate())
26+
m.MustTokenStorage(token.NewRedisStore(redisCfg))
27+
28+
return m
29+
}
30+
31+
// NewMongoManager 创建基于mongodb存储的管理实例
32+
func NewMongoManager(mongoCfg *token.MongoConfig) *Manager {
33+
m := NewManager()
34+
m.MapClientModel(models.NewClient())
35+
m.MapTokenModel(models.NewToken())
36+
m.MapAuthorizeGenerate(generates.NewAuthorizeGenerate())
37+
m.MapAccessGenerate(generates.NewAccessGenerate())
38+
m.MustTokenStorage(token.NewMongoStore(mongoCfg))
39+
40+
return m
1441
}
1542

1643
// NewManager 创建Manager的实例
@@ -32,6 +59,7 @@ func NewManager() *Manager {
3259
m.SetGTConfig(oauth2.PasswordCredentials, &Config{TokenExp: time.Hour * 2, RefreshExp: time.Hour * 24 * 7})
3360
// 设定客户端模式令牌的有效期为1小时
3461
m.SetGTConfig(oauth2.ClientCredentials, &Config{TokenExp: time.Hour * 2})
62+
3563
return m
3664
}
3765

server/server.go

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,12 @@ import (
1212

1313
// NewServer 创建OAuth2服务实例
1414
func NewServer(cfg *Config, manager oauth2.Manager) *Server {
15-
return &Server{
15+
srv := &Server{
1616
cfg: cfg,
1717
manager: manager,
1818
}
19+
srv.SetClientHandler(ClientFormHandler)
20+
return srv
1921
}
2022

2123
// Server OAuth2服务处理
@@ -24,6 +26,21 @@ type Server struct {
2426
manager oauth2.Manager
2527
}
2628

29+
// SetTokenType 设置令牌类型
30+
func (s *Server) SetTokenType(tokenType string) {
31+
s.cfg.TokenType = tokenType
32+
}
33+
34+
// SetAllowedResponseType 设置允许的授权类型
35+
func (s *Server) SetAllowedResponseType(allowedTypes ...oauth2.ResponseType) {
36+
s.cfg.AllowedResponseType = allowedTypes
37+
}
38+
39+
// SetAllowedGrantType 允许的授权模式
40+
func (s *Server) SetAllowedGrantType(allowedTypes ...oauth2.GrantType) {
41+
s.cfg.AllowedGrantType = allowedTypes
42+
}
43+
2744
// SetClientHandler 设置客户端处理
2845
func (s *Server) SetClientHandler(handler ClientHandler) {
2946
s.cfg.Handler.ClientHandler = handler

store/client/temp.go

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,20 @@ import (
88
)
99

1010
// NewTempStore 创建客户端临时存储实例
11-
func NewTempStore() oauth2.ClientStore {
12-
return &TempStore{
13-
data: map[string]*models.Client{
14-
"1": &models.Client{
15-
ID: "1",
16-
Secret: "11",
17-
Domain: "http://localhost",
18-
},
11+
func NewTempStore(clients ...*models.Client) oauth2.ClientStore {
12+
data := map[string]*models.Client{
13+
"1": &models.Client{
14+
ID: "1",
15+
Secret: "11",
16+
Domain: "http://localhost",
1917
},
2018
}
19+
for _, cli := range clients {
20+
data[cli.ID] = cli
21+
}
22+
return &TempStore{
23+
data: data,
24+
}
2125
}
2226

2327
// TempStore 客户端信息的临时存储

0 commit comments

Comments
 (0)