OAuth를 사용하여 Golang 애플리케이션 보호

이 강좌에서 우리는 OAuth 보호 golang 프로그램을 어떻게 사용하는지, 그리고 FusionAuth를 인증 제공 프로그램으로 사용하는지 배울 것이다.인증과 권한 수여는 모든 응용 프로그램에 매우 중요하며, Golang 응용 프로그램도 예외가 아니다.
우선 FusionAuth 서버를 설정합니다.그리고 Golang 프로그램을 설정하여 URL을 구성하고 사용자를 FusionAuth에서 생성한 로그인 폼으로 안내합니다.마지막으로 OIDC를 사용하여 사용자 데이터를 얻을 수 있도록 액세스 토큰을 사용하는 방법을 배울 것입니다.
당신은 개념적으로 이 점을 따르거나 먼저 완전하게 실현된 GitHub repo을 볼 수 있습니다.이제 시작합시다!

요구 사항


본 강좌의 요구에 따라 다음과 같다.
  • Go SDK
  • VScode 또는 기타 텍스트 편집기
  • FusionAuth
  • 자체 제작(옵션)
  • FusionAuth를 인증 공급자로 설정


    FusionAuth를 사용하면 pick your installation method그러나 본고에서 우리는 자체 제작 소프트웨어를 사용하여 설치할 것이다.이 과정은 매우 간단하다.먼저 터미널에서 다음 명령을 실행하여 tap을 설치합니다.
    brew tap fusionauth/homebrew-fusionauth
    
    이 설치 절차는 한 번만 수행할 수 있습니다.다음 명령을 실행하여 FusionAuth 마스터 서비스를 설치해야 합니다.
    brew install fusionauth-app
    
    마지막으로 프로젝트 터미널에서 다음 명령을 실행하여 FusionAuth 서비스를 시작해야 합니다.
    brew services start fusionauth-app
    
    시작하려면 브라우저를 열고 http://localhost:9011 로 이동해야 합니다.그리고 우리는 유지 보수 모드와 설치 마법사를 완성해야 한다.

    설치 마법사를 사용하여 FusionAuth 설치


    유지보수 모드 창에는 데이터베이스의 수퍼유저 인증서가 필요합니다.

    이 자격 증명을 사용하여 FusionAuth를 연결할 데이터베이스 사용자를 만듭니다.유지보수 모드 페이지의 다음 단계에서 다음 옵션을 선택하면 사용자의 사용자 이름과 비밀번호를 지정할 수 있습니다.

    유지보수 모드가 아닌 다른 도구를 사용하여 FusionAuth 사용자와 데이터베이스를 만들려면 할 수 있습니다.이 옵션에 대한 자세한 내용은 silent mode documentation 을 참조하십시오.
    FusionAuth의 데이터베이스를 만들려면 라이센스를 수락하고 초기 FusionAuth 계정을 만들어야 합니다.

    그리고 이 새 FusionAuth 계정에 로그인해야 합니다.이 사용자는 FusionAuth 인스턴스에서 관리 권한을 갖습니다.

    새 애플리케이션 생성 및 구성


    처음에는 FusionAuth 자체의 응용 프로그램만 있었습니다.따라서 응용 프로그램 탭으로 이동하여 녹색 + 기호를 클릭하여 새 응용 프로그램을 만들어야 합니다.
    그리고 이 프로그램을 설정해야 합니다.우선, http://localhost:8080/callback 의 권한 리셋을 추가합니다.인증에 성공하면 인증 코드를 처리하는 URL입니다.
    또한 권한 부여 코드 확인란을 선택해야 합니다.이것은 우리가 사용할 권한 수여이자 대부분의 용례가 추천하는 권한 수여이다.
    성공적으로 설치한 후 녹색 돋보기를 눌러 프로그램을 보십시오.OAuthClient IDClient Secret 값은 같은 화면의 OAuth 구성 섹션에서도 찾을 수 있습니다.너는 반드시 이 두 방면에 주의해야 한다.

    우리는 기본 임대인에 이 프로그램을 설치했다.FusionAuth는 다중 세입자 설정을 지원하지만, 본고에서, 우리는 모든 사용자 데이터를 한 세입자에 저장할 것이다. 왜냐하면 이것은 일을 좀 간단하게 하기 때문이다.이제 FusionAuth 설정이 완료되었습니다.우리 골랑 부분으로 넘어가자.

    고란을 위해 발전 환경을 만들다


    우리는 고란을 위해 발전 환경을 창조할 것이다.만약 네가 이미 그것을 가지고 있다면, 너는 그것을 뛰어넘을 수 있다.우선 itsofficial website에서 Go를 다운로드해야 합니다.
    우리 먼저 가서 뛰자.이것은 가장 간단한 바둑 종목이다.조금도 이상하지 않다. 이것이 바로 전형적인'안녕한 세상'프로그램이다.그것은 보기에 이렇다.
    package main
    import "fmt"
    func main() {
      fmt.Println("Hello, Golang")
    }
    
    main.go라는 파일에 저장합니다.터미널에서 코드가 있는 디렉토리에서 다음을 실행합니다.
    go run main.go
    
    다음 출력이 표시됩니다.
    Hello, Golang
    
    성공신분 검증을 좀 추가해 주시겠습니까?

    Golang 응용 프로그램에서 초기 처리 프로그램과 OAuth2 설정을 설정합니다


    프로세서와 OAuth2 설정을 설정합니다.이를 위해서는 OAuth 및 HTTP 패키지와 같은 필수 구성 요소를 먼저 가져와야 합니다.
    package main
    import (
      "fmt"
      "io/ioutil"
      "net/http"
      "golang.org/x/oauth2"
      "github.com/thanhpk/randstr"
    )
    //...
    
    Golang 설정에 따라 비표준 패키지get가 필요할 수 있습니다.
    go get github.com/thanhpk/randstr
    go get golang.org/x/oauth2  
    
    다음 코드 세그먼트와 같이 구성을 포함하는 변수를 정의해야 합니다.
    //...
    var (
      FusionAuthConfig *oauth2.Config
      oauthStateString = randstr.Hex(16)
    )
    //...
    
    다음에 새로운 OAuth 실례를 만들고 init 함수에서 설정해야 합니다.여기에는 FusionAuth 응용 프로그램 OAuth 구성 부분에서 얻은 ClientIDClientSecret 이 필요합니다.또한 OAuth2 끝점FusionAuth docs에서 추출할 수 있는 URL과 리셋 URL(예: 위의 FusionAuth 구성에서 입력한 것)을 정의해야 합니다.
    //...
    func init() {
      FusionAuthConfig = &oauth2.Config{
        RedirectURL: "http://localhost:8080/callback",
        ClientID: "7d2b4cb4-ccd5-42ac-8469-f802393c8f98",
        ClientSecret:"6x9GI_FUs5TBt_ql0m1CxNy962L7SEf0Kx2KxsY7WYw",
        Scopes: []string{"openid"},
        Endpoint: oauth2.Endpoint{
          AuthURL: "http://localhost:9011/oauth2/authorize",
          TokenURL: "http://localhost:9011/oauth2/token",
          AuthStyle: oauth2.AuthStyleInHeader,
        },
      }
    }
    //...
    
    여기에서 우리는 init 함수에 OAuth 연결을 설정했다.프로그램을 시작할 때마다 이 함수를 실행합니다.생산 응용 프로그램에서 이 값들은 하드코딩이 아니라 프로필이나 데이터베이스 테이블에서 추출해야 한다.

    모니터 추가


    현재, 우리는 페이지를 표시해야 한다.handleMain 함수에 대해 다음과 같이 HTML을 하드 인코딩하고 있지만 더 큰 응용 프로그램에 대해서는 템플릿 언어를 봐야 할 수도 있습니다.
    //...
    func handleMain(w http.ResponseWriter, r *http.Request) {
      var htmlIndex = `<html>
        <body>
           <a href="/login">FusionAuth Log In</a>
        </body>
        </html>`
       fmt.Fprintf(w, htmlIndex)
    }
    //...
    
    그리고 우리는 handleMain 함수에서 main 함수를 호출해야 한다.이렇게 하면 8080 포트를 청취할 수 있습니다.
    //...
    func main() {
      http.HandleFunc("/", handleMain)
      fmt.Println(http.ListenAndServe(":8080", nil))
    }
    //...
    
    "Hello world"예시의 코드를 변경했기 때문에 Golang 프로그램을 다시 시작해야 합니다.기존 서버를 중지해야 합니다.그런 다음 다음 다음 명령을 사용하여 다시 시작합니다.
    go run main.go
    
    으로 이동http://localhost:8080/.웹 브라우저에서 다음 화면을 볼 수 있습니다.

    좋지만, 우리는 실제로 어떻게 로그인합니까?물어봐서 반갑습니다.

    로그인 기능


    로그인 함수에 대해 handleFusionAuthLogin 라는 새 함수를 만들어야 합니다.그런 다음 URL을 생성하고 HTTP 패키지를 사용하여 사용자를 해당 URL로 다시 지정합니다.올바르게 구성된 OAuth 라이브러리를 사용하기 때문에 URL을 생성합니다.
    //...
    func handleFusionAuthLogin(w http.ResponseWriter, r *http.Request) {
      url := FusionAuthConfig.AuthCodeURL(oauthStateString)
      http.Redirect(w, r, url, http.StatusTemporaryRedirect)
    }
    //...
    

    리셋 처리

    code 파라미터를 포함하고 권한 수여 코드에 대한 중요한 리셋을 처리하기 위해 codestate 변수를 getUserInfo 함수에 전달합니다.아래에서 이 함수 뒤에 있는 코드를 볼 수 있지만, FusionAuth에서 사용자 데이터를 가져옵니다.콜백 처리 코드는 다음과 같습니다.
    //...
    func handleFusionAuthCallback(w http.ResponseWriter, r *http.Request) {
      content, err := getUserInfo(r.FormValue("state"), r.FormValue("code"))
      if err != nil {
        fmt.Println(err.Error())
        http.Redirect(w, r, "/", http.StatusTemporaryRedirect)
        return
      }
      fmt.Fprintf(w, "Content: %s\n", content)
    }
    //...
    
    또한 브라우저가 액세스할 수 있는 경로에 상기 두 프로세서를 등록할 수 있도록 기본 기능을 업데이트해야 합니다.
    func main() {
      http.HandleFunc("/", handleMain)
      http.HandleFunc("/login", handleFusionAuthLogin)
      http.HandleFunc("/callback", handleFusionAuthCallback)
      fmt.Println(http.ListenAndServe(":8080", nil))
    }
    

    사용자 데이터 표시


    사용자 정보를 얻고 표시하기 위해서는 위에서 말한 바와 같이 getUserInfo 함수를 만들어야 합니다.
    //...
    func getUserInfo(state string, code string) ([]byte, error) {
      if state != oauthStateString {
        return nil, fmt.Errorf("invalid oauth state")
      }
      token, err := FusionAuthConfig.Exchange(oauth2.NoContext, code)
      if err != nil {
        return nil, fmt.Errorf("code exchange failed: %s", err.Error())
      }
      url := "http://localhost:9011/oauth2/userinfo"
      var bearer = "Bearer " + token.AccessToken
      req, err := http.NewRequest("GET", url, nil)
      req.Header.Add("Authorization", bearer)
      client := &http.Client{}
      response, err := client.Do(req)
      if err != nil {
        return nil, fmt.Errorf("failed getting user info: %s", err.Error())
      }
      defer response.Body.Close()
      contents, err := ioutil.ReadAll(response.Body)
      if err != nil {
       return nil, fmt.Errorf("failed reading response body: %s", err.Error())
      }
      return contents, nil
    }
    //...
    
    이것은 우리가 그것을 분해할 수 있는 상당히 많은 코드이다.
  • 우선, 우리는 서버에서 받은 state 파라미터가 우리가 보낸 것과 일치하는지 검사합니다.CSRF 공격을 방지하기 위해서입니다.
  • 그리고 우리는 code 파라미터를 교환하고 방문 영패를 검색합니다.
  • 다음에 우리는 접속 영패를 탑재 영패로 사용하여 Authorization 헤더를 가진 모두가 알고 있는 사용자 정보 단점에 대한 요청을 구성한다.
  • 마지막으로 서버의 응답을 인쇄합니다.
  • 로컬에서 실행 중인 경우 이 비디오와 유사한 내용을 볼 수 있습니다.

    다음 단계


    분명히 실제 응용 프로그램에서 JSON 데이터 구조를 인쇄하는 것만은 아닙니다.사용자의 데이터를 표시하거나, 환영하거나, 또는 그들이 누구인지에 따라 기능을 표시하거나 숨기기를 원합니다.
    액세스 토큰을 자격 증명으로 표시하도록 다른 API에 요청할 수도 있습니다.

    결론


    Golang의 권한 수여 코드를 사용하면 OAuth와 호환되는 모든 신분 제공 프로그램을 사용하여 응용 프로그램을 보호할 수 있습니다.너는 GitHub에서 검토하고 신청을 제출할 수 있다.
    즐거운 인코딩!
    Renee French에서 수정한 golang gopher 이미지는 aCCAv3 license에 따라 제공됩니다.

    좋은 웹페이지 즐겨찾기