import ( "net/http" "net/url" ) func reqPost() { postUrl := "http://example.com/test" values := make(url.Values) values.Set("name", "HongGilDong") values.Set("age", 31) req, _ := http.PostForm(postUrl, values) defer req.Body.Close() }
2015-11-18
(Go) 웹서비스에 POST 요청으로 값 넘겨서 처리하기
(beego) JSON Response 작성하기
- 샘플 코드
func (c *HappeningController) Get() { data := map[string]interface{}{ "test": "test", "num": 23, "array": []string{"one", "two"}, } c.Data["json"] = &data c.ServeJson() }
- 결과
{ "test":"test", "number": 23, "array":["one", "two"] }
- 참고
2015-11-13
(beego) router 작성시 주의할 점
- router 작성시에 하나의 컨트롤러에 여러 URL 을 매핑하는 경우,
urlfor
가 예측할 수 없을 정도로 비정상적으로 작동한다. 예를 들어, 다음과 같이 router 를 작성했다고 하자.
... beego.Router("/mgmt/user", &c_mgmt.UserController{}, "get:Index") beego.Router("/mgmt/user/:page", &c_mgmt.UserController{}, "get,post:Index") beego.Router("/mgmt/user/:page/:s_item/:val", &c_mgmt.UserController{}, "get:Index") ...
- View 의 템플릿에서
{{urlfor ""mgmt.UserController.Index" "1"}}
를 작성한 경우,/mgmt/user/1
이 호출되어야 겠지만, 실제로는 전혀 다른 값이 호출된다는 것이다. 반면, URL을 호출한 경우에는 매핑된 컨트롤러가 제대로 실행된다. 그러므로, 정상적인 동작을 위해서는 URL 과 컨트롤러는 1:1 로 매핑해야 한다.
2015-11-03
(Go) Get local IP addresses
- 참고
- Sample Code
- myip.go
package main import ( "fmt" "net" ) func main() { addrs, _ := net.InterfaceAddrs() for _, addr := range addrs { if addr.Network() == "ip+net" { if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback() { if ipnet.IP.To4() != nil { fmt.Println(ipnet.IP.String()) } } } else if addr.Network() == "ip" { if addr.String() != "0.0.0.0" { fmt.Println(addr.String()) } } } }
2015-10-22
beego Tutorial
beego 를 공부해보다가, 삽질을 조금 줄여보고자 튜토리얼을 급하게 만들어보았습니다. 개인 위키에 있던 것을 그대로 복사해 놓아서 설명도 적고, 내용도 부족하지만, 그래도 초짜에게는 도움이 될 것 같아요. *^^*
- beego Tutorial 1 : 시작
- beego Tutorial 2 : 첫페이지 만들어보기
- beego Tutorial 3 : 모델 생성
- beego Tutorial 4 : 관리자 목록 보여주기
- beego Tutorial 5 : 관리자 추가하기
- beego Tutorial 6 : 관리자 비밀번호 변경하기
- beego Tutorial 7 : 관리자 수정하기
- beego Tutorial 8 : 관리자 삭제하기
- beego Tutorial 9 : 비밀번호 단방향암호화(SHA512) 하기
- beego Tutorial 10 : 개인정보 양방향암호화(AES256) 하기
- beego Tutorial 11 : 로그인/로그아웃 처리하기
beego Tutorial 11 : 로그인/로그아웃 처리하기
- 명색이 관리자 화면인데, 아무나 들어와서 조작하면 안되겠지요? 이제는 마지막으로 로그인/로그아웃 처리를 해보겠습니다. 로그인/로그아웃은 세션을 이용해서 구현합니다.
- 로그인 화면을 구성합니다.
xyz/views/index.html
을 작성합니다.<!DOCTYPE html> <html lang="ko"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="_xsrf" content="{{.xsrf_token}}" /> <title>Login</title> <link rel="stylesheet" href="/static/b/css/bootstrap.min.css"> </head> <body> <div class="container" style="margin-top: 20px"> <form action="/login" method="post" class="form-horizontal" style="margin: 0 auto; max-width: 360px;"> {{ .xsrfdata }} <div class="form-group"> <label for="userid" class="col-sm-3 control-label">아이디</label> <div class="col-sm-9"> <input type="text" id="userid" name="userid" class="form-control" placeholder="당신의 ID를 입력하세요..." required autofocus> </div> </div> <div class="form-group"> <label for="passwd" class="col-sm-3 control-label">비밀번호</label> <div class="col-sm-9"> <input type="password" id="passwd" name="passwd" class="form-control" placeholder="비밀번호를 입력하세요..." required> </div> </div> <input type="submit" class="btn btn-primary btn-block" value="로그인" /> </form> </div> <!-- jQuery (necessary for Bootstrap's JavaScript plugins) --> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script> <!-- Include all compiled plugins (below), or include individual files as needed --> <script src="/static/b/js/bootstrap.min.js"></script> </body> </html>
xyz/controllers/main.go
를 다음처럼 수정합니다.package controllers import ( "github.com/astaxie/beego" "html/template" ) type MainController struct { beego.Controller } // 메인 로그인 화면 func (c *MainController) Index() { c.Data["xsrfdata"] = template.HTML(c.XsrfFormHtml()) c.TplNames = "index.html" }
- http://localhost:8080/ 에 접속하면 로그인화면이 나올 것입니다.
- xyz/conf/app.conf 에 다음을 추가합니다.
... sessionon = true ...
xyz/models/admin.go
에 다음을 추가합니다.... func (this *Admin) IsMember(userid string, passwd string) bool { sha := sha512.New() sha.Write([]byte(passwd)) hashed_passwd := hex.EncodeToString(sha.Sum(nil)) o := orm.NewOrm() o.Using("default") cnt, _ := o.QueryTable(this).Filter("userid", userid).Filter("password", hashed_passwd).Count() if cnt == 0 { return false } return true } ...
xyz/controllers/main.go
에xyz/models
를import
하고, 다음을 추가한다.... // 로그인 func (c *MainController) Login() { userid := c.GetString("userid") passwd := c.GetString("passwd") admin := new(models.Admin) if is_member := admin.IsMember(userid, passwd); is_member == true { c.SetSession("login", true) // 로그인세션 등록 c.Redirect(c.UrlFor("AdminController.Index"), 302) return } c.Redirect(c.UrlFor(".Index"), 302) } ...
xyz/routers/router.go
에 다음을 추가한다.... beego.Router("/login", &c.MainController{}, "post:Login") ...
xyz/main.go
에github.com/astaxie/beego/context
를 import 하고 다음을 Init() 안의 마지막에 추가한다.... // Authetication var FilterUser = func(ctx *context.Context) { _, login := ctx.Input.Session("login").(bool) if login != true { ctx.Redirect(302, "/") } } beego.InsertFilter("/admin", beego.BeforeRouter, FilterUser) beego.InsertFilter("/admin/*", beego.BeforeRouter, FilterUser) ...
여기까지 작성하면, 로그인해야만 http://localhost:8080/admin 을 접근할 수 있게 된다.
xyz/controllers/main.go
에 다음을 추가한다.... // 로그아웃 func (c *MainController) Logout() { c.DestroySession() c.Redirect(c.UrlFor(".Index"), 302) } ...
xyz/routers/router.go
에 다음을 추가한다.... beego.Router("/logout", &c.MainController{}, "get:Logout") ...
이제, 로그인도 해보고, 로그아웃도 해보세요. ^^
beego Tutorial 10 : 개인정보 양방향암호화(AES256) 하기
- 이 예제에는 개인정보 데이터가 없긴 하지만, 별명(Nick)을 개인정보라 간주하고 암호화를 진행해보겠습니다.
- 데이터를 암호화하고 다시 풀려면, Key 가 있어야 합니다. 이 Key 를
xyz/conf/app.conf
에 기록해 놓습니다.... enckey = oei0oiejhdsa7AS6dkjSk3l5dkwHG659 ...
xyz/models/common.go
를 수정합니다.package models import ( "crypto/aes" "crypto/cipher" "crypto/rand" "encoding/base64" "fmt" "github.com/astaxie/beego" "github.com/astaxie/beego/orm" "io" ) var key []byte func init() { key = []byte(beego.AppConfig.String("enckey")) orm.RegisterModelWithPrefix("tb_", new(Admin)) } func encodeBase64(b []byte) []byte { return []byte(base64.StdEncoding.EncodeToString(b)) } func decodeBase64(b []byte) []byte { data, err := base64.StdEncoding.DecodeString(string(b)) if err != nil { fmt.Printf("Error: Bad Key!\n") return nil } return data } func encrypt(text []byte) []byte { // The key argument should be the AES key, // either 16, 24, or 32 bytes to select AES-128, AES-192, or AES-256. block, err := aes.NewCipher(key) if err != nil { panic(err) } b := encodeBase64(text) ciphertext := make([]byte, aes.BlockSize+len(b)) iv := ciphertext[:aes.BlockSize] if _, err := io.ReadFull(rand.Reader, iv); err != nil { panic(err) } cfb := cipher.NewCFBEncrypter(block, iv) cfb.XORKeyStream(ciphertext[aes.BlockSize:], b) return ciphertext } func decrypt(text []byte) []byte { block, err := aes.NewCipher(key) if err != nil { panic(err) } if len(text) < aes.BlockSize { fmt.Printf("Error!\n") return nil } iv := text[:aes.BlockSize] text = text[aes.BlockSize:] cfb := cipher.NewCFBDecrypter(block, iv) cfb.XORKeyStream(text, text) return decodeBase64(text) }
xyz/models/admin.go
에 다음을 추가한다.func (this *Admin) SetNick(nick string) { ciphertext := encrypt([]byte(nick)) this.Nick = hex.EncodeToString(ciphertext) } func (this *Admin) GetNick() string { ciphertext, _ := hex.DecodeString(this.Nick) plaintext := decrypt(ciphertext) return string(plaintext) }
Insert()
,Update()
에서this.Nick = nick
이라고 되어 있는 부분을this.SetNick(nick)
으로 변경한다.
xyz/views/admin
밑에 있는index.html
과update_form.html
파일에서 Nick 이라고 되어 있는 부분을 모두 GetNick 으로 변경한다.
- DB의 내용을 모두 삭제한 후에, 관리자를 추가해봅니다. 그리고, DB에서 Nick 이 암호화되어 있는지도 봅시다.
$ sqlite3 xyz.db SQLite version 3.7.9 2011-11-01 00:52:41 Enter ".help" for instructions Enter SQL statements terminated with a ";" sqlite> select nick from tb_admin; 2e4cccdfe968a2b127bff7eac978df2354c0bb7c25e8534d sqlite> .quit
제대로 암호화되어서 무슨 내용인지 알아볼 수 없네요. ^^;
beego Tutorial 9 : 비밀번호 단방향암호화(SHA512) 하기
- 정보통신망법, 개인정보보호법 등에 의하면 비밀번호는 단방향암호화(SHA256 등), 개인정보는 양방향암호화(AES256 등)를 하도록 되어 있습니다. 지금까지 작성한 예제는 이런 법에 맞지 않아서 서비스할 수 없겠네요. 여기에서는 비밀번호의 단방향 암호화를 구현해보도록 하겠습니다.
- 먼저, 기존 DB에 들어있던 사용자 정보를 모두 삭제합시다.
$ cd $GOPATH/src/xyz $ sqlite xyz.db SQLite version 3.7.9 2011-11-01 00:52:41 Enter ".help" for instructions Enter SQL statements terminated with a ";" sqlite> select * from tb_admin; 1|testid1|passwd1|nick1 2|testid2|passwd2|nick2 3|testid3|passwd3|nick3 4|testid4|passwd4|nick4 6|admin|dpeltms3|ADMIN sqlite> delete from tb_admin; sqlite> select * from tb_admin; sqlite> .quit
xyz/models/admin.go
에 다음을 추가합니다. 이 부분이 실제로 SHA512 로 단방향암호화를 하는 부분입니다.... import ( "github.com/astaxie/beego/orm" "crypto/sha512" "encoding/hex" ) ... func (this *Admin) SetPassword(passwd string) { sha := sha512.New() sha.Write([]byte(passwd)) this.Password = hex.EncodeToString(sha.Sum(nil)) } ...
그리고,this.password = passwd
라고 되어 있는 부분도this.SetPassword(passwd)
로 변경해줍니다. Insert() 와 Chg_password() 에 있습니다.
- 이제, 관리자를 추가해보고, DB에서 비밀번호가 어떻게 들어가 있는지 확인해봅니다.
$ sqlite3 xyz.db SQLite version 3.7.9 2011-11-01 00:52:41 Enter ".help" for instructions Enter SQL statements terminated with a ";" sqlite> select * from tb_admin; 8|myid|d49434a7e6f3220b6ec15bff84429934d519d0443d20ff46ff3a36e1fc50fc2d43c939d259042987162202dcbbc8788752ea79c02379064ab64363b069278c32|마이이이디 sqlite> .quit
비밀번호가 사람이 알아볼 수 없는 형태로 되어 있지요? 그러면 잘 된 것입니다. *^^*
beego Tutorial 8 : 관리자 삭제하기
xyz/views/admin/index.html
에 다음을 추가한다.... <button onclick="delete_admin('/admin/delete/{{$admins.Id}}')" class="btn btn-default btn-xs">삭제</button> ... <script> function delete_admin(url) { var result = confirm("관리자를 정말로 삭제하시겠습니까?"); if( result == false ) return; location.href = url; } </script> ...
xyz/models/admin.go
에 다음을 추가한다.... func (this *Admin) Delete(id int) { o := orm.NewOrm() o.Using("default") this.Id = id o.Delete(this) } ...
xyz/controllers/admin.go
에 다음을 추가한다.// 관리자 삭제 func (c *AdminController) Delete() { id, _ := strconv.Atoi(c.Ctx.Input.Param(":id")) admin := new(models.Admin) admin.Delete(id) c.Redirect(c.UrlFor(".Index"), 302) }
xyz/routers/router.go
에 다음을 추가하고, 관리자 삭제를 해봅니다.beego.Router("/admin/delete/:id", &c.AdminController{}, "get:Delete")
- 여기까지 하면, 기본적인 CRUD 기능을 모두 작성할 수 있게 됩니다. *^^*
피드 구독하기:
글 (Atom)