This commit is contained in:
Sakurasan
2023-04-13 02:49:39 +08:00
parent 08d5bfbf19
commit a9783ae092
3 changed files with 143 additions and 126 deletions

View File

@@ -1,8 +1,7 @@
package main
import (
"crypto/rand"
"encoding/base64"
"chat/services/board"
"fmt"
"log"
"net/http"
@@ -16,29 +15,21 @@ import (
"github.com/golang-jwt/jwt"
"github.com/google/go-github/v50/github"
"github.com/joho/godotenv"
"golang.org/x/oauth2"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
var db *gorm.DB
var jwtSecret = []byte("JWT_SECRET")
var oauthConf *oauth2.Config
func main() {
func init() {
err := godotenv.Load()
if err != nil {
log.Fatal("Error loading .env file")
}
oauthConf = &oauth2.Config{
ClientID: os.Getenv("GITHUB_CLIENT_ID"),
ClientSecret: os.Getenv("GITHUB_CLIENT_SECRET"),
// Scopes: []string{"read:user", "user:email"},
Endpoint: oauth2.Endpoint{
AuthURL: "https://github.com/login/oauth/authorize",
TokenURL: "https://github.com/login/oauth/access_token",
}}
}
func main() {
initDB()
router := gin.Default()
@@ -53,27 +44,12 @@ func main() {
AllowCredentials: true,
}))
router.GET("/", func(ctx *gin.Context) { ctx.Writer.WriteString("hello world") })
router.GET("/auth/github", githubLoginHandler)
// router.POST("/auth/signin/sso", )
router.GET("/auth/idt", board.IdentityHandler)
router.POST("/auth/signin/sso", board.SSOHandler)
router.Run(":8000")
}
func githubLoginHandler(c *gin.Context) {
state := generateState()
session := sessions.Default(c)
session.Set("state", state)
if err := session.Save(); err != nil {
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
url := oauthConf.AuthCodeURL("state")
log.Println(url)
c.Redirect(http.StatusFound, url)
}
func initDB() {
dsn := os.Getenv("MYSQL_DSN")
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
@@ -92,24 +68,6 @@ func initDB() {
log.Println("Database connection established")
}
func generateState() string {
return generateRandomString(20)
}
func generateCode() string {
return generateRandomString(20)
}
func generateRandomString(length int) string {
byteArr := make([]byte, length)
_, err := rand.Read(byteArr)
if err != nil {
log.Fatal("Error generating random string:", err)
}
return base64.URLEncoding.EncodeToString(byteArr)
}
func storeStateToDB(state, code string) error {
query := "INSERT INTO oauth_state (state, code) VALUES (?, ?)"
err := db.Exec(query, state, code).Error

View File

@@ -1,76 +1,88 @@
<template>
<div v-if="!accessToken">
<button @click="">Login with GitHub</button>
</div>
<div v-else>
<p>Access Token: {{ accessToken }}</p>
<button @click="logout">Logout</button>
<div>
<button @click="handleGithubLogin">Login with GitHub</button>
</div>
</template>
<script>
import { reactive } from 'vue';
<script setup>
import { reactive,onMounted } from 'vue';
import axios from 'axios';
export default {
setup() {
const auth = reactive({
type: "github",
redirectUrl: null,
code: null,
state: null,
});
const auth = reactive({
type: "github",
redirectUrl: null,
code: null,
state: null,
});
const handleGithubLogin = async()=> {
try {
const response = await axios.get('http://localhost:8000/auth/idt')
const redirectUrl = response.data.redirectUri
auth.state = response.data.state
auth.redirectUrl = redirectUrl
localStorage.setItem("state",response.data.state)
console.log("state:",response.data.state,"url:",response.data.redirectUri)
window.location.href = redirectUrl
} catch (error) {
console.error(error)
}
}
// Function to handle GitHub login button click
const handleGithubLogin = async () => {
try {
// Send a GET request to /auth/github to get the redirect URL
const response = await axios.get('/auth/github')
auth.redirectUrl = response.data.redirectUrl
auth.state = response.data.state
window.location.href = state.redirectUrl
} catch (error) {
console.error(error)
}
};
const handleCallback = async () => {
// const code = this.$route.query.code
// const status = this.$route.query.status
const urlParams = new URLSearchParams(window.location.search)
const code = urlParams.get('code')
const status = urlParams.get('state')
try {
const response = await axios.post('/auth/signin/sso', {
code,
status
})
const jwt = response.data.jwt
localStorage.setItem('jwt', jwt)
} catch (error) {
console.error(error);
if (error.response.status != 200) {
console.log('授权失败')
}
}
};
const logout = () => {
localStorage.setItem('jwt','');
};
// // 监听 URL 变化,处理从 GitHub 授权页面回调回来的 code 参数
// const handleUrlChange = () => {
// const urlParams = new URLSearchParams(window.location.search);
// const code = urlParams.get('code');
// if (code) {
// handleCallback(code);
// }
// };
// window.addEventListener('load', handleUrlChange);
},
const handleCallback = async () => {
// const code = this.$route.query.code
// const status = this.$route.query.status
const urlParams = new URLSearchParams(window.location.search)
const code = urlParams.get('code')
const status = urlParams.get('state')
try {
const response = await axios.post('/auth/signin/sso', {
code,
status
})
const jwt = response.data.jwt
localStorage.setItem('jwt', jwt)
} catch (error) {
console.error(error);
if (error.response.status != 200) {
console.log('授权失败')
}
}
};
async function getToken() {
try {
const url = new URL(window.location.href)
const code = url.searchParams.get('code')
const state = url.searchParams.get('state')
const postData = new URLSearchParams({
code: code,
state: state
})
const jwtResponse = await axios.post('http://localhost:8000/auth/signin/sso', postData)
const jwt = jwtResponse.data.jwt
localStorage.setItem('jwt', jwt)
console.log("jwt:",jwtResponse)
// window.location.href = '/'
} catch (error) {
console.error(error)
}
}
const logout = () => {
localStorage.setItem('jwt','');
};
// // 监听 URL 变化,处理从 GitHub 授权页面回调回来的 code 参数
// const handleUrlChange = () => {
// const urlParams = new URLSearchParams(window.location.search);
// const code = urlParams.get('code');
// if (code) {
// handleCallback(code);
// }
// };
// window.addEventListener('load', handleUrlChange);
onMounted(() => {
getToken()
})
</script>

View File

@@ -2,6 +2,8 @@ package board
import (
"context"
"crypto/rand"
"encoding/base64"
"fmt"
"log"
"net/http"
@@ -13,16 +15,7 @@ import (
"golang.org/x/oauth2"
)
var (
oauthConf = &oauth2.Config{
ClientID: os.Getenv("GITHUB_CLIENT_ID"),
ClientSecret: os.Getenv("GITHUB_CLIENT_SECRET"),
// Scopes: []string{"read:user", "user:email"},
Endpoint: oauth2.Endpoint{
AuthURL: "https://github.com/login/oauth/authorize",
TokenURL: "https://github.com/login/oauth/access_token",
}}
)
var ()
type SignIn struct {
Username string `json:"username"`
@@ -40,9 +33,55 @@ type SignUp struct {
Password string `json:"password"`
}
func generateState() string {
return generateRandomString(20)
}
func generateCode() string {
return generateRandomString(20)
}
func generateRandomString(length int) string {
byteArr := make([]byte, length)
_, err := rand.Read(byteArr)
if err != nil {
log.Fatal("Error generating random string:", err)
}
return base64.URLEncoding.EncodeToString(byteArr)
}
func IdentityHandler(c *gin.Context) {
state := generateState()
session := sessions.Default(c)
session.Set("state", state)
if err := session.Save(); err != nil {
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
oauthConf := &oauth2.Config{
ClientID: os.Getenv("GITHUB_CLIENT_ID"),
ClientSecret: os.Getenv("GITHUB_CLIENT_SECRET"),
RedirectURL: "http://localhost:5173/",
// Scopes: []string{"read:user", "user:email"},
Endpoint: oauth2.Endpoint{
AuthURL: "https://github.com/login/oauth/authorize",
TokenURL: "https://github.com/login/oauth/access_token",
}}
url := oauthConf.AuthCodeURL(state)
log.Println(url)
c.JSON(http.StatusOK, gin.H{
"state": state,
"redirectUri": url,
})
}
func SSOHandler(c *gin.Context) {
signin := SSOSignIn{}
if err := c.BindQuery(&signin); err != nil {
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "Unmashal request body."})
return
}
session := sessions.Default(c)
savedState := session.Get("state")
if savedState == nil || savedState.(string) != signin.State {
@@ -50,6 +89,14 @@ func SSOHandler(c *gin.Context) {
return
}
oauthConf := &oauth2.Config{
ClientID: os.Getenv("GITHUB_CLIENT_ID"),
ClientSecret: os.Getenv("GITHUB_CLIENT_SECRET"),
// Scopes: []string{"read:user", "user:email"},
Endpoint: oauth2.Endpoint{
AuthURL: "https://github.com/login/oauth/authorize",
TokenURL: "https://github.com/login/oauth/access_token",
}}
// 使用 code 换取 token
token, err := oauthConf.Exchange(context.Background(), signin.Code)
if err != nil {