Fintech 뱅킹 애플리케이션 구축을 통한 Golang- 제2과: 로그인 및 REST API 학습

이 글은 처음에 다음과 같이 발표되었습니다.
https://www.blog.duomly.com/golang-course-with-building-a-fintech-banking-app-lesson-2-login-and-rest-api

소개


Golang 과정의 마지막 회에서 우리는 프로젝트 설정과 첫 번째 데이터베이스 이전을 진행했다.
 
다음은 URL입니다.
https://www.blog.duomly.com/golang-course-with-building-a-fintech-banking-app-lesson-1-start-the-project
 
"Fintech 은행 응용 프로그램 구축을 통해 Tailwind CSS를 배우는 Angular 9"마지막 회에서 제 친구 Anna는 프로젝트 설정과 첫 번째 로그인 UI를 만들었습니다.
 
너는 그것으로 우리의 백엔드를 연결하여 완전한fintech 응용 프로그램을 구축할 수 있다.
다음은 URL입니다.
https://www.blog.duomly.com/angular-course-building-a-banking-application-with-tailwind-css-lesson-1-start-the-project/
 
오늘 방송에서 Golang 과정의 두 번째 부분을 배울 것입니다. 저희는 사용자 인증을 중점적으로 소개할 것입니다.
 
로그인 기능을 구축하는 방법과 RESTAPI의 첫 번째 노드를 만드는 방법을 가르쳐 드리겠습니다.
 
우리는 낡은 코드를 좀 더 깨끗하게 재구성할 것이다.
 
우리 시작합시다!
 
그나저나 동영상을 좋아한다면 유튜브 버전입니다.

 

재구성 인터페이스


우리가 해야 할 첫 번째 단계는 우리가 지난 회에 만든 인터페이스를 재구성하는 것이다.
 
이를 위해, "인터페이스"라는 디렉터리를 만들고, 이 디렉터리에 "인터페이스.go"라는 파일을 만들어야 합니다.
 
 
package interfaces

import "github.com/jinzhu/gorm"

type User struct {
    gorm.Model
  Username string
    Email string
    Password string
}

type Account struct {
    gorm.Model
  Type string
    Name string
    Balance uint
    UserID uint
}

type ResponseAccount struct {
    ID uint
    Name string
    Balance int
}

type ResponseUser struct {
    ID uint
    Username string
    Email string
    Accounts []ResponseAccount
}
 
다음으로 우리는 인터페이스의 구조를 사용해야 한다.마이그레이션된 파일이 아닌 파일로 이동합니다.가다
 
사용자와 계정 구조와 관련된 곳에서 변경해야 합니다.
 
마이그레이션go 파일은 아래의 예시와 같다.
 
package migrations

import (
    "duomly.com/go-bank-backend/helpers"
    "duomly.com/go-bank-backend/interfaces"
    _ "github.com/jinzhu/gorm/dialects/postgres"
)

func connectDB() *gorm.DB {
    db, err := gorm.Open("postgres", "host=127.0.0.1 port=5432 user=postgres dbname=bankapp password=postgres sslmode=disable")
    HandleErr(err)
    return db
}

func createAccounts() {
    db := connectDB()

    users := &[2]interfaces.User{
        {Username: "Martin", Email: "[email protected]"},
        {Username: "Michael", Email: "[email protected]"},
    }

    for i := 0; i < len(users); i++ {
        // Correct one way
        generatedPassword := helpers.HashAndSalt([]byte(users[i].Username))
        user := &interfaces.User{Username: users[i].Username, Email: users[i].Email, Password: generatedPassword}
        db.Create(&user)

        account := &interfaces.Account{Type: "Daily Account", Name: string(users[i].Username + "'s" + " account"), Balance: uint(10000 * int(i+1)), UserID: user.ID}
        db.Create(&account)
    }
    defer db.Close()
}


func Migrate() {
    User := &interfaces.User{}
    Account := &interfaces.Account{}
    db := connectDB()
    db.AutoMigrate(&User, &Account)
    defer db.Close()

    createAccounts()
}

 

보조 대상에 연결 데이터베이스 재구성


다음 단계는 이전과 관련이 있을 것이다.파일로 이동한 다음 조수로 이동합니다.가다
 
"connectDB"함수를 helpers로 옮겨야 합니다.가다
이제 ConnectDB라는 이름을 지정해야 합니다.
마지막 단계는 이전에서 그것을 다시 사용하는 것이다.하지만 가져오는 형식으로
당신의 조수.go는 다음 예제와 같습니다.
package helpers

import (
    "github.com/jinzhu/gorm"
    _ "github.com/lib/pq"
    "golang.org/x/crypto/bcrypt"
)


func HandleErr(err error) {
    if err != nil {
        panic(err.Error())
    }
}

func HashAndSalt(pass []byte) string {
    hashed, err := bcrypt.GenerateFromPassword(pass, bcrypt.MinCost)
    HandleErr(err)

    return string(hashed)
}

func ConnectDB() *gorm.DB {
    db, err := gorm.Open("postgres", "host=127.0.0.1 port=5432 user=postgres dbname=bankapp password=postgres sslmode=disable")
    HandleErr(err)
    return db
}
 
마이그레이션go는 다음 예제와 같습니다.
 
package migrations

import (
    "duomly.com/go-bank-backend/helpers"
    "duomly.com/go-bank-backend/interfaces"
    _ "github.com/jinzhu/gorm/dialects/postgres"
)

func createAccounts() {
    db := helpers.ConnectDB()

    users := &[2]interfaces.User{
        {Username: "Martin", Email: "[email protected]"},
        {Username: "Michael", Email: "[email protected]"},
    }

    for i := 0; i < len(users); i++ {
        // Correct one way
        generatedPassword := helpers.HashAndSalt([]byte(users[i].Username))
        user := &interfaces.User{Username: users[i].Username, Email: users[i].Email, Password: generatedPassword}
        db.Create(&user)

        account := &interfaces.Account{Type: "Daily Account", Name: string(users[i].Username + "'s" + " account"), Balance: uint(10000 * int(i+1)), UserID: user.ID}
        db.Create(&account)
    }
    defer db.Close()
}


func Migrate() {
    User := &interfaces.User{}
    Account := &interfaces.Account{}
    db := helpers.ConnectDB()
    db.AutoMigrate(&User, &Account)
    defer db.Close()

    createAccounts()
}
 

로그인 기능 만들기


이제 우리는 로그인 논리에 들어갈 수 있다.
 
우리가 해야 할 첫 번째 일은'users'라는 디렉터리와'users.go'라는 파일을 만드는 것이다.
 
"users.go"에서 "users"라는 패키지와 "Login"이라는 빈 함수를 만들어야 합니다.
 
함수 "login"은 "username"과 "pass"를 문자열로 해야 합니다.
우리는'어떤'유형의 키가 있는 지도를 되돌릴 수 있어야 한다.
 
DEP도 가져와야 하지만 다음 예제에서 복사할 수 있습니다.
 
package users

import (
    "time"

    "duomly.com/go-bank-backend/helpers"
    "duomly.com/go-bank-backend/interfaces"
    "github.com/dgrijalva/jwt-go"
    "golang.org/x/crypto/bcrypt"
)

func Login(username string, pass string) map[string]interface{} {
}
 
로그인 시 데이터베이스 연결
다음 중요한 일은db 연결을 만들고 함수params에서 사용자 이름을 가진 사용자를 찾는 것입니다.
 
사용자 상태가 "not found"일 때 알려 주는 "if"문구를 기억해야 합니다.
 
db := helpers.ConnectDB()
user := &interfaces.User{}
if db.Where("username = ? ", username).First(&user).RecordNotFound() {
    return map[string]interface{}{"message": "User not found"}
}
 

암호 확인


사용자가 있을 때, 우리는 우리가 보낸 비밀번호가 정확한지 확인해야 한다.
 
"Login"이라는 같은 함수에서 "bcrypt.CompareHash AndPassword"방법으로 간단한 암호 검증을 만들어야 합니다.
 
다음에if문장을 만들어야 합니다. 여기서 비밀번호가 일치하지 않는지, 오류가 없는지 확인하겠습니다.
 
만약 그렇다면, 우리는 암호 오류 메시지를 되돌려야 한다.
 
passErr := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(pass))

if passErr == bcrypt.ErrMismatchedHashAndPassword && passErr != nil {
    return map[string]interface{}{"message": "Wrong password"}
}
 

사용자 계정 찾기


현재 우리는 사용자와 비밀번호를 가지고 있으며, 모든 것이 검증을 거쳤지만, 우리의 사용자는 아직 완성하지 못했다.
 
우리는 사용자 대상의 은행 계좌가 필요하다.
 
이를 실현하기 위해서는 ResponseAccount 형식의 슬라이스를 사용하여 var 계정을 정의해야 합니다.
우리는 이 그룹 내의 데이터베이스에서 데이터를 분배할 것이다.
 
다음으로, 데이터베이스는 표'accounts'의 모든 기록으로 필드'id','name','balance'를 되돌려 달라고 요구해야 합니다. 그 중에서'user\u id'는 사용자 id와 같습니다.
 
accounts := []interfaces.ResponseAccount{}
db.Table("accounts").Select("id, name, balance").Where("user_id = ? ", user.ID).Scan(&accounts)

응답기 설정


다음 단계에서responseUser의 구조를 설정하고 키에 값을 부여해야 합니다.
responseUser 구조 이후에 DB 연결을 닫을 수 있습니다.
 
responseUser := &interfaces.ResponseUser{
    ID: user.ID,
    Username: user.Username,
    Email: user.Email,
    Accounts: accounts,
}

defer db.Close()
 

서명 영패


"Login"함수의 마지막이자 가장 중요한 부분 중 하나는 우리가 설정하고 서명해야 하는 JWT 영패입니다.
이를 위해 우리는 JWT 패키지를 사용할 것이다.
아래의 예에서 어떻게 해야 하는지 봅시다.
 
tokenContent := jwt.MapClaims{
    "user_id": user.ID,
    "expiry": time.Now().Add(time.Minute * 60).Unix(),
}
jwtToken := jwt.NewWithClaims(jwt.GetSigningMethod("HS256"), tokenContent)
token, err := jwtToken.SignedString([]byte("TokenPassword"))
helpers.HandleErr(err)
 

응답 준비


마지막이것은 Login 함수의 마지막 부분입니다. API로 돌아갑니다.
"jwt"키에 영패를 전달하고responseUser를 "data"매개 변수로 전달하는 메시지를 "모든 정상"으로 설정해야 합니다.
 
var response = map[string]interface{}{"message": "all is fine"}
response["jwt"] = token
response["data"] = responseUser

return response
 

API 패키지 만들기


이제 API를 사용할 수 있습니다.

우리가 완성해야 할 첫 번째 단계는 "api"라는 새 디렉터리를 만들고 같은 이름의 파일을 만드는 것입니다. 확장자는 "go"입니다.
파일에서 "api"라는 패키지를 설명하고 의존 항목을 가져와야 합니다.
 
package api

import (
    "encoding/json"
    "fmt"
    "io/ioutil"
    "log"
    "net/http"

    "duomly.com/go-bank-backend/helpers"
    "duomly.com/go-bank-backend/users"

    "github.com/gorilla/mux"
)

API에서 구조 생성하기


두 번째 단계는 구조 성명이다.
"Login"이라는 두 가지 구조를 만들어야 합니다. "Username"은 문자열이고, "Password"는 문자열입니다.
마지막 구조는 문자열인 "ErrResponse"로 선언되어야 합니다.
 
type Login struct {
    Username string
    Password string
}


type ErrResponse struct {
    Message string
}
 

API에서 로그인 함수 생성하기


이 단계에서 API에 대한 첫 번째 함수를 만듭니다.
"login"이라고 명명하고 "w http. ResponseWriter"와 "r*http. Request"를 매개 변수로 해야 합니다.
 
func login(w http.ResponseWriter, r *http.Request) {

}
 

API 호출된 바디 읽기


"login"함수의 첫 번째 논리는 API 요청의 주체를 읽는 코드입니다.

"body"와 "err"변수를 지정하고 "ioutil. ReadAll"을 분배해야 합니다. 요청의 주체를 포함합니다.

다음은 "helpers"패키지의 "HandleErr"를 사용하고 내부에서 "err"를 전달함으로써 모든 것이 정상인지 확인해야 합니다.
body, err := ioutil.ReadAll(r.Body)
helpers.HandleErr(err)
 

로그인 처리


이 기능의 가장 중요한 부분은 정확한 로그인이다.
"Login"유형의 변수를 정의하고 서명되지 않은 요청체를 할당해야 합니다.
다음은 포맷된 사용자 이름과 비밀번호를 "users. Login"으로 전달해야 합니다.
우리는 이 논리를 "login"이라는 변수에 분배해야 한다.
 
var formattedBody Login
err = json.Unmarshal(body, &formattedBody)
helpers.HandleErr(err)
login := users.Login(formattedBody.Username, formattedBody.Password)
 

API 호출을 위한 응답 준비


로그인을 호출한 후, 우리는 로그인 메시지가 모든 것이 정상인지 확인해야 한다.
만약 그렇다면, "resp"라는 변수를 설명하고 로그인 이름을 지정해야 합니다.
다음은 "json.NewEncoder"를 사용하고resp를 인코딩해야 합니다.
 
if login["message"] == "all is fine" {
    resp := login
    json.NewEncoder(w).Encode(resp)
} else {

}
 

else의 처리 오류


지금, 우리가'if'문구를 처리할 때, 우리도'error'를 처리해야 한다.
이를 위해, 우리는'else'문구를 만들고 응답을 포맷해야 합니다.

'오류 사용자 이름 또는 암호'문자열이 있는'메시지'를 값으로 되돌려야 합니다.
이 반응의 인코딩은 양성 병례와 같아야 한다.
 
if login["message"] == "all is fine" {
    resp := login
    json.NewEncoder(w).Encode(resp)
} else {
    resp := ErrResponse{Message: "Wrong username or password"}
    json.NewEncoder(w).Encode(resp)
}
 

startApi 함수 만들기


API 논리의 마지막 단계에서 우리는 적당한 공유기를 만들고 API 단점을 처리해야 한다.
Gorilla mux를 사용하여 라우터를 만들 것입니다. 첫 번째 라우터로서 "POST"방법을 받아들이는 "/로그인"단점을 정의합니다.
다음은 8888 포트에 HTTP 탐지기를 설치해야 합니다.
 
func StartApi() {
    router := mux.NewRouter()
    router.HandleFunc("/login", login).Methods("POST")
    fmt.Println("App is working on port :8888")
    log.Fatal(http.ListenAndServe(":8888", router))

}
 

주 함수에서 API 구현


API 준비 완료!
작업을 수행하려면 "main.go"파일의 "main"함수에서 API를 구현해야 합니다.
다음 예제를 확인하십시오.
 
package main

import "duomly.com/go-bank-backend/api"

func main() {
    // migrations.Migrate()
    api.StartApi()
}

 

API 실행


우후!
이제 응용 프로그램을 실행하고 테스트를 시작할 수 있습니다.

프로젝트 디렉토리에서 터미널을 열고 다음을 입력합니다.
go run main.go
 

결론


축하합니다. 프로젝트에 로그인 이름과firstrest API가 있습니다.
 
과정부터 프런트엔드에 연결할 수 있습니다.
 
Learn Angular 9 with Tailwind CSS by building fintech banking app
 
여기서 코드를 비교하려면 URL을 참조하십시오.
 
https://github.com/Duomly/go-bank-backend 
 
이 과정의 지점은 "Golang-course-lesson-2"입니다. 
 
다음 시간에 우리는 사용자 등록을 세울 것입니다. 안녕히 계세요.
 
 
 
Thanks for reading,
Radek from Duomly

좋은 웹페이지 즐겨찾기