mirror of
https://github.com/certd/certd.git
synced 2026-04-24 12:27:25 +08:00
perf: oauth支持github 和google, 修复头像显示问题
This commit is contained in:
@@ -35,7 +35,13 @@ const menus = computed(() => [
|
|||||||
|
|
||||||
const avatar = computed(() => {
|
const avatar = computed(() => {
|
||||||
const avt = userStore.getUserInfo?.avatar;
|
const avt = userStore.getUserInfo?.avatar;
|
||||||
return avt ? `/api/basic/file/download?key=${avt}` : "";
|
if (!avt) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
if (avt.startsWith("http")) {
|
||||||
|
return avt;
|
||||||
|
}
|
||||||
|
return `/api/basic/file/download?key=${avt}`;
|
||||||
});
|
});
|
||||||
|
|
||||||
async function handleLogout() {
|
async function handleLogout() {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
<a-descriptions-item :label="t('authentication.username')">{{ userInfo.username }}</a-descriptions-item>
|
<a-descriptions-item :label="t('authentication.username')">{{ userInfo.username }}</a-descriptions-item>
|
||||||
<a-descriptions-item :label="t('authentication.nickName')">{{ userInfo.nickName }}</a-descriptions-item>
|
<a-descriptions-item :label="t('authentication.nickName')">{{ userInfo.nickName }}</a-descriptions-item>
|
||||||
<a-descriptions-item :label="t('authentication.avatar')">
|
<a-descriptions-item :label="t('authentication.avatar')">
|
||||||
<a-avatar v-if="userInfo.avatar" size="large" :src="'api/basic/file/download?&key=' + userInfo.avatar" style="background-color: #eee"> </a-avatar>
|
<a-avatar v-if="userInfo.avatar" size="large" :src="userAvatar" style="background-color: #eee"> </a-avatar>
|
||||||
<a-avatar v-else size="large" style="background-color: #00b4f5">
|
<a-avatar v-else size="large" style="background-color: #00b4f5">
|
||||||
{{ userInfo.username }}
|
{{ userInfo.username }}
|
||||||
</a-avatar>
|
</a-avatar>
|
||||||
@@ -108,6 +108,17 @@ async function bind(type: string) {
|
|||||||
window.location.href = loginUrl;
|
window.location.href = loginUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const userAvatar = computed(() => {
|
||||||
|
if (isEmpty(userInfo.value.avatar)) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
if (userInfo.value.avatar.startsWith("http")) {
|
||||||
|
return userInfo.value.avatar;
|
||||||
|
}
|
||||||
|
|
||||||
|
return "api/basic/file/download?&key=" + userInfo.value.avatar;
|
||||||
|
});
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
await getUserInfo();
|
await getUserInfo();
|
||||||
await loadOauthBounds();
|
await loadOauthBounds();
|
||||||
|
|||||||
@@ -3,3 +3,5 @@ export * from './oidc/plugin-oidc.js'
|
|||||||
export * from './wx/plugin-wx.js'
|
export * from './wx/plugin-wx.js'
|
||||||
export * from './oauth2/plugin-gitee.js'
|
export * from './oauth2/plugin-gitee.js'
|
||||||
export * from './oauth2/plugin-clogin.js'
|
export * from './oauth2/plugin-clogin.js'
|
||||||
|
export * from './oauth2/plugin-github.js'
|
||||||
|
export * from './oauth2/plugin-google.js'
|
||||||
@@ -0,0 +1,103 @@
|
|||||||
|
import { AddonInput, BaseAddon, IsAddon } from "@certd/lib-server";
|
||||||
|
import { BuildLoginUrlReq, BuildLogoutUrlReq, IOauthProvider, OnCallbackReq } from "../api.js";
|
||||||
|
|
||||||
|
@IsAddon({
|
||||||
|
addonType: "oauth",
|
||||||
|
name: 'github',
|
||||||
|
title: 'GitHub认证',
|
||||||
|
desc: 'GitHub OAuth2登录',
|
||||||
|
icon:"simple-icons:github",
|
||||||
|
showTest: false,
|
||||||
|
})
|
||||||
|
export class GithubOauthProvider extends BaseAddon implements IOauthProvider {
|
||||||
|
|
||||||
|
@AddonInput({
|
||||||
|
title: "ClientId",
|
||||||
|
helper: "[GitHub Developer Settings](https://github.com/settings/developers)创建应用后获取",
|
||||||
|
required: true,
|
||||||
|
})
|
||||||
|
clientId = "";
|
||||||
|
|
||||||
|
@AddonInput({
|
||||||
|
title: "ClientSecretKey",
|
||||||
|
component: {
|
||||||
|
placeholder: "ClientSecretKey / appSecretKey",
|
||||||
|
},
|
||||||
|
required: true,
|
||||||
|
})
|
||||||
|
clientSecretKey = "";
|
||||||
|
|
||||||
|
async buildLoginUrl(params: BuildLoginUrlReq) {
|
||||||
|
|
||||||
|
let scope = "user:email" // Scope of the access request
|
||||||
|
let state:any = {
|
||||||
|
forType: params.forType || 'login',
|
||||||
|
}
|
||||||
|
state = this.ctx.utils.hash.base64(JSON.stringify(state))
|
||||||
|
|
||||||
|
const authorizeEndpoint = "https://github.com/login/oauth/authorize"
|
||||||
|
const redirectUrl = encodeURIComponent(params.redirectUri)
|
||||||
|
const loginUrl = `${authorizeEndpoint}?client_id=${this.clientId}&redirect_uri=${redirectUrl}&response_type=code&scope=${scope}&state=${state}`
|
||||||
|
return {
|
||||||
|
loginUrl,
|
||||||
|
ticketValue: {
|
||||||
|
state,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async onCallback(req: OnCallbackReq) {
|
||||||
|
|
||||||
|
const code = req.code || ""
|
||||||
|
|
||||||
|
const tokenEndpoint = "https://github.com/login/oauth/access_token"
|
||||||
|
|
||||||
|
const uri = new URL(req.currentURL)
|
||||||
|
const redirectUri = `${uri.origin}${uri.pathname}`
|
||||||
|
const res = await this.ctx.utils.http.request( {
|
||||||
|
url: tokenEndpoint,
|
||||||
|
method: "post",
|
||||||
|
headers: {
|
||||||
|
"Accept": "application/json"
|
||||||
|
},
|
||||||
|
data:{
|
||||||
|
client_id: this.clientId,
|
||||||
|
client_secret: this.clientSecretKey,
|
||||||
|
code,
|
||||||
|
redirect_uri: redirectUri
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const tokens = res
|
||||||
|
|
||||||
|
const userInfoEndpoint = "https://api.github.com/user"
|
||||||
|
|
||||||
|
// 获取用户信息
|
||||||
|
const userInfoRes = await this.ctx.utils.http.request( {
|
||||||
|
url: userInfoEndpoint,
|
||||||
|
method: "get",
|
||||||
|
headers: {
|
||||||
|
"Authorization": `Bearer ${tokens.access_token}`,
|
||||||
|
"Accept": "application/json"
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const userInfo = userInfoRes
|
||||||
|
|
||||||
|
return {
|
||||||
|
token:{
|
||||||
|
accessToken: tokens.access_token,
|
||||||
|
refreshToken: tokens.refresh_token,
|
||||||
|
expiresIn: tokens.expires_in,
|
||||||
|
},
|
||||||
|
userInfo: {
|
||||||
|
openId: userInfo.id,
|
||||||
|
nickName: userInfo.login || userInfo.name || "",
|
||||||
|
avatar: userInfo.avatar_url,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
async buildLogoutUrl(params: BuildLogoutUrlReq) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,103 @@
|
|||||||
|
import { AddonInput, BaseAddon, IsAddon } from "@certd/lib-server";
|
||||||
|
import { BuildLoginUrlReq, BuildLogoutUrlReq, IOauthProvider, OnCallbackReq } from "../api.js";
|
||||||
|
|
||||||
|
@IsAddon({
|
||||||
|
addonType: "oauth",
|
||||||
|
name: 'google',
|
||||||
|
title: 'Google认证',
|
||||||
|
desc: 'Google OAuth2登录',
|
||||||
|
icon:"simple-icons:google",
|
||||||
|
showTest: false,
|
||||||
|
})
|
||||||
|
export class GoogleOauthProvider extends BaseAddon implements IOauthProvider {
|
||||||
|
|
||||||
|
@AddonInput({
|
||||||
|
title: "ClientId",
|
||||||
|
helper: "[Google Cloud Console](https://console.cloud.google.com/apis/credentials)创建应用后获取",
|
||||||
|
required: true,
|
||||||
|
})
|
||||||
|
clientId = "";
|
||||||
|
|
||||||
|
@AddonInput({
|
||||||
|
title: "ClientSecretKey",
|
||||||
|
component: {
|
||||||
|
placeholder: "ClientSecretKey / appSecretKey",
|
||||||
|
},
|
||||||
|
required: true,
|
||||||
|
})
|
||||||
|
clientSecretKey = "";
|
||||||
|
|
||||||
|
async buildLoginUrl(params: BuildLoginUrlReq) {
|
||||||
|
|
||||||
|
let scope = "email profile" // Scope of the access request
|
||||||
|
let state:any = {
|
||||||
|
forType: params.forType || 'login',
|
||||||
|
}
|
||||||
|
state = this.ctx.utils.hash.base64(JSON.stringify(state))
|
||||||
|
|
||||||
|
const authorizeEndpoint = "https://accounts.google.com/o/oauth2/auth"
|
||||||
|
const redirectUrl = encodeURIComponent(params.redirectUri)
|
||||||
|
const loginUrl = `${authorizeEndpoint}?client_id=${this.clientId}&redirect_uri=${redirectUrl}&response_type=code&scope=${scope}&state=${state}`
|
||||||
|
return {
|
||||||
|
loginUrl,
|
||||||
|
ticketValue: {
|
||||||
|
state,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async onCallback(req: OnCallbackReq) {
|
||||||
|
|
||||||
|
const code = req.code || ""
|
||||||
|
|
||||||
|
const tokenEndpoint = "https://oauth2.googleapis.com/token"
|
||||||
|
|
||||||
|
const uri = new URL(req.currentURL)
|
||||||
|
const redirectUri = `${uri.origin}${uri.pathname}`
|
||||||
|
const res = await this.ctx.utils.http.request( {
|
||||||
|
url: tokenEndpoint,
|
||||||
|
method: "post",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/x-www-form-urlencoded"
|
||||||
|
},
|
||||||
|
data:{
|
||||||
|
client_id: this.clientId,
|
||||||
|
client_secret: this.clientSecretKey,
|
||||||
|
code,
|
||||||
|
redirect_uri: redirectUri,
|
||||||
|
grant_type: "authorization_code"
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const tokens = res
|
||||||
|
|
||||||
|
const userInfoEndpoint = "https://www.googleapis.com/oauth2/v3/userinfo"
|
||||||
|
|
||||||
|
// 获取用户信息
|
||||||
|
const userInfoRes = await this.ctx.utils.http.request( {
|
||||||
|
url: userInfoEndpoint,
|
||||||
|
method: "get",
|
||||||
|
headers: {
|
||||||
|
"Authorization": `Bearer ${tokens.access_token}`
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const userInfo = userInfoRes
|
||||||
|
|
||||||
|
return {
|
||||||
|
token:{
|
||||||
|
accessToken: tokens.access_token,
|
||||||
|
refreshToken: tokens.refresh_token,
|
||||||
|
expiresIn: tokens.expires_in,
|
||||||
|
},
|
||||||
|
userInfo: {
|
||||||
|
openId: userInfo.sub,
|
||||||
|
nickName: userInfo.name || userInfo.email || "",
|
||||||
|
avatar: userInfo.picture,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
async buildLogoutUrl(params: BuildLogoutUrlReq) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user