Implement authorization middleware
Change WriteJson function to use only for successful response Implement WriteError function
Showing
3 changed files
with
50 additions
and
12 deletions
... | @@ -10,6 +10,12 @@ import ( | ... | @@ -10,6 +10,12 @@ import ( |
10 | "github.com/jmoiron/sqlx" | 10 | "github.com/jmoiron/sqlx" |
11 | ) | 11 | ) |
12 | 12 | ||
13 | +type Prop int | ||
14 | + | ||
15 | +const ( | ||
16 | + PropUserNo Prop = iota | ||
17 | +) | ||
18 | + | ||
13 | type App struct { | 19 | type App struct { |
14 | Config Config | 20 | Config Config |
15 | db *sqlx.DB | 21 | db *sqlx.DB | ... | ... |
1 | package main | 1 | package main |
2 | 2 | ||
3 | import ( | 3 | import ( |
4 | + "context" | ||
4 | "encoding/json" | 5 | "encoding/json" |
5 | "net/http" | 6 | "net/http" |
7 | + "strings" | ||
6 | "time" | 8 | "time" |
7 | 9 | ||
8 | "github.com/dgrijalva/jwt-go" | 10 | "github.com/dgrijalva/jwt-go" |
... | @@ -22,7 +24,7 @@ func (app *App) PostUsers(w http.ResponseWriter, r *http.Request) { | ... | @@ -22,7 +24,7 @@ func (app *App) PostUsers(w http.ResponseWriter, r *http.Request) { |
22 | body := make(map[string]interface{}) | 24 | body := make(map[string]interface{}) |
23 | err := json.NewDecoder(r.Body).Decode(&body) | 25 | err := json.NewDecoder(r.Body).Decode(&body) |
24 | if err != nil { | 26 | if err != nil { |
25 | - WriteJson(w, http.StatusBadRequest, map[string]interface{}{"msg": "Failed to parse request json"}) | 27 | + WriteError(w, http.StatusBadRequest, "Failed to parse request json") |
26 | return | 28 | return |
27 | } | 29 | } |
28 | 30 | ||
... | @@ -32,48 +34,73 @@ func (app *App) PostUsers(w http.ResponseWriter, r *http.Request) { | ... | @@ -32,48 +34,73 @@ func (app *App) PostUsers(w http.ResponseWriter, r *http.Request) { |
32 | if err != nil { | 34 | if err != nil { |
33 | if merr, ok := err.(*mysql.MySQLError); ok { | 35 | if merr, ok := err.(*mysql.MySQLError); ok { |
34 | if merr.Number == 1062 { | 36 | if merr.Number == 1062 { |
35 | - WriteJson(w, http.StatusConflict, map[string]interface{}{"msg": "Already registered"}) | 37 | + WriteError(w, http.StatusConflict, "Already registered") |
36 | return | 38 | return |
37 | } | 39 | } |
38 | } | 40 | } |
39 | 41 | ||
40 | - WriteJson(w, http.StatusInternalServerError, map[string]interface{}{"msg": "Failed to register"}) | 42 | + WriteError(w, http.StatusInternalServerError, "Failed to register") |
41 | return | 43 | return |
42 | } | 44 | } |
43 | 45 | ||
44 | no, _ := res.LastInsertId() | 46 | no, _ := res.LastInsertId() |
45 | - WriteJson(w, http.StatusOK, map[string]interface{}{"user_no": no}) | 47 | + WriteJson(w, map[string]interface{}{"user_no": no}) |
48 | +} | ||
49 | + | ||
50 | +type AuthClaims struct { | ||
51 | + UserNo uint64 `json:"user_no"` | ||
52 | + jwt.StandardClaims | ||
46 | } | 53 | } |
47 | 54 | ||
48 | func (app *App) PostTokens(w http.ResponseWriter, r *http.Request) { | 55 | func (app *App) PostTokens(w http.ResponseWriter, r *http.Request) { |
49 | body := make(map[string]interface{}) | 56 | body := make(map[string]interface{}) |
50 | err := json.NewDecoder(r.Body).Decode(&body) | 57 | err := json.NewDecoder(r.Body).Decode(&body) |
51 | if err != nil { | 58 | if err != nil { |
52 | - WriteJson(w, http.StatusBadRequest, map[string]interface{}{"msg": "Failed to parse request json"}) | 59 | + WriteError(w, http.StatusBadRequest, "Failed to parse request json") |
53 | return | 60 | return |
54 | } | 61 | } |
55 | 62 | ||
56 | hash := sha3.Sum256([]byte(body["password"].(string))) | 63 | hash := sha3.Sum256([]byte(body["password"].(string))) |
57 | rows, err := app.db.Query("SELECT `no` FROM users WHERE `id`=? AND `password`=?", body["id"], hash[:]) | 64 | rows, err := app.db.Query("SELECT `no` FROM users WHERE `id`=? AND `password`=?", body["id"], hash[:]) |
58 | if err != nil { | 65 | if err != nil { |
59 | - WriteJson(w, http.StatusInternalServerError, map[string]interface{}{"msg": "Failed to register"}) | 66 | + WriteError(w, http.StatusInternalServerError, "Failed to register") |
60 | return | 67 | return |
61 | } | 68 | } |
62 | 69 | ||
63 | if !rows.Next() { | 70 | if !rows.Next() { |
64 | - WriteJson(w, http.StatusUnauthorized, map[string]interface{}{"msg": "Login failed"}) | 71 | + WriteError(w, http.StatusUnauthorized, "Login failed") |
65 | return | 72 | return |
66 | } | 73 | } |
67 | 74 | ||
68 | no := uint64(0) | 75 | no := uint64(0) |
69 | rows.Scan(&no) | 76 | rows.Scan(&no) |
70 | 77 | ||
71 | - token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{"no": no}) | 78 | + token := jwt.NewWithClaims(jwt.SigningMethodHS256, AuthClaims{UserNo: no}) |
72 | auth, err := token.SignedString([]byte(app.Config.TokenSecret)) | 79 | auth, err := token.SignedString([]byte(app.Config.TokenSecret)) |
73 | if err != nil { | 80 | if err != nil { |
74 | - WriteJson(w, http.StatusInternalServerError, map[string]interface{}{"msg": "Login failed"}) | 81 | + WriteError(w, http.StatusInternalServerError, "Login failed") |
75 | return | 82 | return |
76 | } | 83 | } |
77 | 84 | ||
78 | - WriteJson(w, http.StatusOK, map[string]interface{}{"token": auth}) | 85 | + WriteJson(w, map[string]interface{}{"token": auth}) |
86 | +} | ||
87 | + | ||
88 | +func (app *App) WithAuth(next func(http.ResponseWriter, *http.Request)) http.Handler { | ||
89 | + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | ||
90 | + auth := r.Header.Get("Authorization") | ||
91 | + if len(auth) > 6 && strings.Index(auth, "Bearer ") == 0 { | ||
92 | + token, err := jwt.ParseWithClaims(auth[7:], &AuthClaims{}, func(token *jwt.Token) (interface{}, error) { | ||
93 | + return []byte(app.Config.TokenSecret), nil | ||
94 | + }) | ||
95 | + | ||
96 | + if err == nil { | ||
97 | + claims := token.Claims.(*AuthClaims) | ||
98 | + ctx := context.WithValue(r.Context(), PropUserNo, claims.UserNo) | ||
99 | + next(w, r.WithContext(ctx)) | ||
100 | + return | ||
101 | + } | ||
102 | + } | ||
103 | + | ||
104 | + WriteError(w, http.StatusUnauthorized, "Authorization failed") | ||
105 | + }) | ||
79 | } | 106 | } | ... | ... |
... | @@ -5,8 +5,13 @@ import ( | ... | @@ -5,8 +5,13 @@ import ( |
5 | "net/http" | 5 | "net/http" |
6 | ) | 6 | ) |
7 | 7 | ||
8 | -func WriteJson(w http.ResponseWriter, status int, data interface{}) { | 8 | +func WriteJson(w http.ResponseWriter, data interface{}) { |
9 | w.Header().Set("Content-Type", "application/json") | 9 | w.Header().Set("Content-Type", "application/json") |
10 | - w.WriteHeader(status) | ||
11 | json.NewEncoder(w).Encode(data) | 10 | json.NewEncoder(w).Encode(data) |
12 | } | 11 | } |
12 | + | ||
13 | +func WriteError(w http.ResponseWriter, status int, message string) { | ||
14 | + w.Header().Set("Content-Type", "application/json") | ||
15 | + w.WriteHeader(status) | ||
16 | + json.NewEncoder(w).Encode(map[string]interface{}{"msg": message}) | ||
17 | +} | ... | ... |
-
Please register or login to post a comment