Skip to content

Commit 97df1e5

Browse files
authored
Merge pull request #7 from LyricTian/develop
Add fasthttp server handle
2 parents 41a3f22 + da5af9b commit 97df1e5

File tree

6 files changed

+365
-76
lines changed

6 files changed

+365
-76
lines changed

README.md

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
1-
OAuth2服务端
2-
===========
1+
基于Golang的OAuth2服务实现
2+
=======================
33

4-
> 基于Golang实现的OAuth2协议,具有简单化、模块化的特点
4+
> 完全模块化、支持http/fasthttp的服务端处理、令牌存储支持redis/mongodb
55
66
[![GoDoc](https://godoc.org/gopkg.in/oauth2.v2?status.svg)](https://godoc.org/gopkg.in/oauth2.v2)
77
[![Go Report Card](https://goreportcard.com/badge/gopkg.in/oauth2.v2)](https://goreportcard.com/report/gopkg.in/oauth2.v2)
88

99
获取
1010
----
1111

12-
```bash
12+
``` bash
1313
$ go get -u gopkg.in/oauth2.v2/...
1414
```
1515

16-
使用
17-
----
16+
HTTP服务端
17+
--------
1818

1919
``` go
2020
package main
@@ -64,15 +64,43 @@ func main() {
6464

6565
```
6666

67+
FastHTTP服务端
68+
-------------
69+
70+
``` go
71+
srv := server.NewFastServer(server.NewConfig(), manager)
72+
73+
fasthttp.ListenAndServe(":9096", func(ctx *fasthttp.RequestCtx) {
74+
switch string(ctx.Request.URI().Path()) {
75+
case "/authorize":
76+
authReq, err := srv.GetAuthorizeRequest(ctx)
77+
if err != nil {
78+
ctx.Error(err.Error(), 400)
79+
return
80+
}
81+
authReq.UserID = "000000"
82+
// TODO: 登录验证、授权处理
83+
err = srv.HandleAuthorizeRequest(ctx, authReq)
84+
if err != nil {
85+
ctx.Error(err.Error(), 400)
86+
}
87+
case "/token":
88+
err := srv.HandleTokenRequest(ctx)
89+
if err != nil {
90+
ctx.Error(err.Error(), 400)
91+
}
92+
}
93+
})
94+
```
95+
6796
测试
6897
----
98+
> [goconvey](https://github.com/smartystreets/goconvey)
6999
70100
``` bash
71101
$ goconvey -port=9092
72102
```
73103

74-
> goconvey使用明细[https://github.com/smartystreets/goconvey](https://github.com/smartystreets/goconvey)
75-
76104
范例
77105
----
78106

example/README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
OAuth2 服务端/客户端模拟
2-
=====================
1+
OAuth2授权码模式模拟
2+
=================
33

44
运行服务端
55
--------
6+
> 运行fasthttp服务端,请使用`cd example/fastserver`
67
78
```
89
$ cd example/server

example/fastserver/main.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package main
2+
3+
import (
4+
"log"
5+
6+
"github.com/valyala/fasthttp"
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.NewFastServer(server.NewConfig(), manager)
27+
28+
log.Println("OAuth2 server is running at 9096 port.")
29+
fasthttp.ListenAndServe(":9096", func(ctx *fasthttp.RequestCtx) {
30+
switch string(ctx.Request.URI().Path()) {
31+
case "/authorize":
32+
authReq, err := srv.GetAuthorizeRequest(ctx)
33+
if err != nil {
34+
ctx.Error(err.Error(), 400)
35+
return
36+
}
37+
authReq.UserID = "000000"
38+
// TODO: 登录验证、授权处理
39+
err = srv.HandleAuthorizeRequest(ctx, authReq)
40+
if err != nil {
41+
ctx.Error(err.Error(), 400)
42+
}
43+
case "/token":
44+
err := srv.HandleTokenRequest(ctx)
45+
if err != nil {
46+
ctx.Error(err.Error(), 400)
47+
}
48+
}
49+
})
50+
}

server/authorize.go

Lines changed: 61 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,39 @@
11
package server
22

33
import (
4+
"encoding/base64"
45
"net/http"
6+
"strings"
57

8+
"github.com/valyala/fasthttp"
69
"gopkg.in/oauth2.v2"
710
)
811

912
// AuthorizeRequest 授权请求
1013
type AuthorizeRequest struct {
11-
Type oauth2.ResponseType
12-
ClientID string
13-
Scope string
14-
RedirectURI string
15-
State string
16-
UserID string
14+
Type oauth2.ResponseType // 授权类型
15+
ClientID string // 客户端标识
16+
Scope string // 授权范围
17+
RedirectURI string // 重定向URI
18+
State string // 状态
19+
UserID string // 用户标识
1720
}
1821

19-
// ClientHandler 客户端处理(获取请求的客户端认证信息)
20-
type ClientHandler func(r *http.Request) (clientID, clientSecret string, err error)
21-
22-
// UserHandler 用户处理(密码模式,根据用户名、密码获取用户标识)
23-
type UserHandler func(username, password string) (userID string, err error)
24-
25-
// ScopeHandler 授权范围处理(更新令牌时的授权范围检查)
26-
type ScopeHandler func(new, old string) (err error)
27-
2822
// TokenRequestHandler 令牌请求处理
2923
type TokenRequestHandler struct {
24+
// 客户端信息处理
3025
ClientHandler ClientHandler
31-
UserHandler UserHandler
32-
ScopeHandler ScopeHandler
26+
// 客户端信息处理(基于fasthttp)
27+
ClientFastHandler ClientFastHandler
28+
// 用户信息处理
29+
UserHandler UserHandler
30+
// 授权范围处理
31+
ScopeHandler ScopeHandler
3332
}
3433

34+
// ClientHandler 获取请求的客户端认证信息
35+
type ClientHandler func(r *http.Request) (clientID, clientSecret string, err error)
36+
3537
// ClientFormHandler 客户端表单信息
3638
func ClientFormHandler(r *http.Request) (clientID, clientSecret string, err error) {
3739
clientID = r.Form.Get("client_id")
@@ -53,3 +55,45 @@ func ClientBasicHandler(r *http.Request) (clientID, clientSecret string, err err
5355
clientSecret = password
5456
return
5557
}
58+
59+
// ClientFastHandler 基于fasthttp获取客户端认证信息
60+
type ClientFastHandler func(ctx *fasthttp.RequestCtx) (clientID, clientSecret string, err error)
61+
62+
// ClientFormFastHandler 客户端表单信息(基于fasthttp)
63+
func ClientFormFastHandler(ctx *fasthttp.RequestCtx) (clientID, clientSecret string, err error) {
64+
clientID = string(ctx.FormValue("client_id"))
65+
clientSecret = string(ctx.FormValue("client_secret"))
66+
if clientID == "" || clientSecret == "" {
67+
err = ErrAuthorizationFormInvalid
68+
}
69+
return
70+
}
71+
72+
// ClientBasicFastHandler 客户端基础认证信息(基于fasthttp)
73+
func ClientBasicFastHandler(ctx *fasthttp.RequestCtx) (clientID, clientSecret string, err error) {
74+
auth := string(ctx.Request.Header.Peek("Authorization"))
75+
const prefix = "Basic "
76+
if auth == "" || !strings.HasPrefix(auth, prefix) {
77+
err = ErrAuthorizationHeaderInvalid
78+
return
79+
}
80+
c, err := base64.StdEncoding.DecodeString(auth[len(prefix):])
81+
if err != nil {
82+
return
83+
}
84+
cs := string(c)
85+
s := strings.IndexByte(cs, ':')
86+
if s < 0 {
87+
err = ErrAuthorizationHeaderInvalid
88+
return
89+
}
90+
clientID = cs[:s]
91+
clientSecret = cs[s+1:]
92+
return
93+
}
94+
95+
// UserHandler 密码模式下,根据用户名、密码获取用户标识
96+
type UserHandler func(username, password string) (userID string, err error)
97+
98+
// ScopeHandler 更新令牌时的授权范围检查
99+
type ScopeHandler func(new, old string) (err error)

0 commit comments

Comments
 (0)