feat: 增加oauth2的认证

--story=1016294 --user=王孝刚 【东区】希望可以支持Oauth2【X-Pack】 https://www.tapd.cn/57709429/s/1610096
This commit is contained in:
wxg0103 2024-11-14 18:33:06 +08:00 committed by wxg
parent 8b707272ca
commit b406a8954e
6 changed files with 364 additions and 127 deletions

View File

@ -1,66 +1,90 @@
import en from 'element-plus/es/locale/lang/en'; import en from 'element-plus/es/locale/lang/en'
import components from './components'; import components from './components'
import layout from './layout'; import layout from './layout'
import views from './views'; import views from './views'
export default { export default {
lang: 'English', lang: 'English',
layout, layout,
views, views,
components, components,
en, en,
login: { login: {
authentication: 'Login Authentication', authentication: 'Login Authentication',
ldap: { ldap: {
title: 'LDAP Settings', title: 'LDAP Settings',
address: 'LDAP Address', address: 'LDAP Address',
serverPlaceholder: 'Please enter LDAP address', serverPlaceholder: 'Please enter LDAP address',
bindDN: 'Bind DN', bindDN: 'Bind DN',
bindDNPlaceholder: 'Please enter Bind DN', bindDNPlaceholder: 'Please enter Bind DN',
password: 'Password', password: 'Password',
passwordPlaceholder: 'Please enter password', passwordPlaceholder: 'Please enter password',
ou: 'User OU', ou: 'User OU',
ouPlaceholder: 'Please enter User OU', ouPlaceholder: 'Please enter User OU',
ldap_filter: 'User Filter', ldap_filter: 'User Filter',
ldap_filterPlaceholder: 'Please enter User Filter', ldap_filterPlaceholder: 'Please enter User Filter',
ldap_mapping: 'LDAP Attribute Mapping', ldap_mapping: 'LDAP Attribute Mapping',
ldap_mappingPlaceholder: 'Please enter LDAP Attribute Mapping', ldap_mappingPlaceholder: 'Please enter LDAP Attribute Mapping',
test: 'Test Connection', test: 'Test Connection',
enableAuthentication: 'Enable LDAP Authentication', enableAuthentication: 'Enable LDAP Authentication',
save: 'Save', save: 'Save',
testConnectionSuccess: 'Test Connection Success', testConnectionSuccess: 'Test Connection Success',
testConnectionFailed: 'Test Connection Failed', testConnectionFailed: 'Test Connection Failed',
saveSuccess: 'Save Success', saveSuccess: 'Save Success'
},
cas: {
title: 'CAS Settings',
ldpUri: 'ldpUri',
ldpUriPlaceholder: 'Please enter ldpUri',
redirectUrl: 'Callback Address',
redirectUrlPlaceholder: 'Please enter Callback Address',
enableAuthentication: 'Enable CAS Authentication',
saveSuccess: 'Save Success',
save: 'Save',
},
oidc: {
title: 'OIDC Settings',
authEndpoint: 'Auth Endpoint',
authEndpointPlaceholder: 'Please enter Auth Endpoint',
tokenEndpoint: 'Token Endpoint',
tokenEndpointPlaceholder: 'Please enter Token Endpoint',
userInfoEndpoint: 'User Info Endpoint',
userInfoEndpointPlaceholder: 'Please enter User Info Endpoint',
clientId: 'Client ID',
clientIdPlaceholder: 'Please enter Client ID',
clientSecret: 'Client Secret',
clientSecretPlaceholder: 'Please enter Client Secret',
logoutEndpoint: 'Logout Endpoint',
logoutEndpointPlaceholder: 'Please enter Logout Endpoint',
redirectUrl: 'Redirect URL',
redirectUrlPlaceholder: 'Please enter Redirect URL',
enableAuthentication: 'Enable OIDC Authentication',
},
jump_tip: 'Jumping to the authentication source page for authentication',
jump: 'Jump',
}, },
}; cas: {
title: 'CAS Settings',
ldpUri: 'ldpUri',
ldpUriPlaceholder: 'Please enter ldpUri',
validateUrl: 'Validation Address',
validateUrlPlaceholder: 'Please enter Validation Address',
redirectUrl: 'Callback Address',
redirectUrlPlaceholder: 'Please enter Callback Address',
enableAuthentication: 'Enable CAS Authentication',
saveSuccess: 'Save Success',
save: 'Save'
},
oidc: {
title: 'OIDC Settings',
authEndpoint: 'Auth Endpoint',
authEndpointPlaceholder: 'Please enter Auth Endpoint',
tokenEndpoint: 'Token Endpoint',
tokenEndpointPlaceholder: 'Please enter Token Endpoint',
userInfoEndpoint: 'User Info Endpoint',
userInfoEndpointPlaceholder: 'Please enter User Info Endpoint',
clientId: 'Client ID',
clientIdPlaceholder: 'Please enter Client ID',
clientSecret: 'Client Secret',
clientSecretPlaceholder: 'Please enter Client Secret',
logoutEndpoint: 'Logout Endpoint',
logoutEndpointPlaceholder: 'Please enter Logout Endpoint',
redirectUrl: 'Redirect URL',
redirectUrlPlaceholder: 'Please enter Redirect URL',
enableAuthentication: 'Enable OIDC Authentication'
},
jump_tip: 'Jumping to the authentication source page for authentication',
jump: 'Jump',
oauth2: {
title: 'OAUTH2 Settings',
authEndpoint: 'Auth Endpoint',
authEndpointPlaceholder: 'Please enter Auth Endpoint',
tokenEndpoint: 'Token Endpoint',
tokenEndpointPlaceholder: 'Please enter Token Endpoint',
userInfoEndpoint: 'User Info Endpoint',
userInfoEndpointPlaceholder: 'Please enter User Info Endpoint',
scope: 'Scope',
scopePlaceholder: 'Please enter Scope',
clientId: 'Client ID',
clientIdPlaceholder: 'Please enter Client ID',
clientSecret: 'Client Secret',
clientSecretPlaceholder: 'Please enter Client Secret',
redirectUrl: 'Redirect URL',
redirectUrlPlaceholder: 'Please enter Redirect URL',
filedMapping: 'Field Mapping',
filedMappingPlaceholder: 'Please enter Field Mapping',
enableAuthentication: 'Enable OAUTH2 Authentication',
save: 'Save',
saveSuccess: 'Save Success'
}
}
}

View File

@ -1,66 +1,90 @@
import zhCn from 'element-plus/es/locale/lang/zh-cn'; import zhCn from 'element-plus/es/locale/lang/zh-cn'
import components from './components'; import components from './components'
import layout from './layout'; import layout from './layout'
import views from './views'; import views from './views'
export default { export default {
lang: '简体中文', lang: '简体中文',
layout, layout,
views, views,
components, components,
zhCn, zhCn,
login: { login: {
authentication: '登录认证', authentication: '登录认证',
ldap: { ldap: {
title: 'LDAP 设置', title: 'LDAP 设置',
address: 'LDAP 地址', address: 'LDAP 地址',
serverPlaceholder: '请输入LDAP 地址', serverPlaceholder: '请输入LDAP 地址',
bindDN: '绑定DN', bindDN: '绑定DN',
bindDNPlaceholder: '请输入绑定 DN', bindDNPlaceholder: '请输入绑定 DN',
password: '密码', password: '密码',
passwordPlaceholder: '请输入密码', passwordPlaceholder: '请输入密码',
ou: '用户OU', ou: '用户OU',
ouPlaceholder: '请输入用户 OU', ouPlaceholder: '请输入用户 OU',
ldap_filter: '用户过滤器', ldap_filter: '用户过滤器',
ldap_filterPlaceholder: '请输入用户过滤器', ldap_filterPlaceholder: '请输入用户过滤器',
ldap_mapping: 'LDAP 属性映射', ldap_mapping: 'LDAP 属性映射',
ldap_mappingPlaceholder: '请输入 LDAP 属性映射', ldap_mappingPlaceholder: '请输入 LDAP 属性映射',
test: '测试连接', test: '测试连接',
enableAuthentication: '启用 LDAP 认证', enableAuthentication: '启用 LDAP 认证',
save: '保存', save: '保存',
testConnectionSuccess: '测试连接成功', testConnectionSuccess: '测试连接成功',
testConnectionFailed: '测试连接失败', testConnectionFailed: '测试连接失败',
saveSuccess: '保存成功', saveSuccess: '保存成功'
},
cas: {
title: 'CAS 设置',
ldpUri: 'ldpUri',
ldpUriPlaceholder: '请输入ldpUri',
redirectUrl: '回调地址',
redirectUrlPlaceholder: '请输入回调地址',
enableAuthentication: '启用CAS认证',
saveSuccess: '保存成功',
save: '保存',
},
oidc: {
title: 'OIDC 设置',
authEndpoint: '授权端地址',
authEndpointPlaceholder: '请输入授权端地址',
tokenEndpoint: 'Token端地址',
tokenEndpointPlaceholder: '请输入Token端地址',
userInfoEndpoint: '用户信息端地址',
userInfoEndpointPlaceholder: '请输入用户信息端地址',
clientId: '客户端ID',
clientIdPlaceholder: '请输入客户端ID',
clientSecret: '客户端密钥',
clientSecretPlaceholder: '请输入客户端密钥',
logoutEndpoint: '注销端地址',
logoutEndpointPlaceholder: '请输入注销端地址',
redirectUrl: '回调地址',
redirectUrlPlaceholder: '请输入回调地址',
enableAuthentication: '启用OIDC认证',
},
jump_tip: '即将跳转至认证源页面进行认证',
jump: '跳转',
}, },
}; cas: {
title: 'CAS 设置',
ldpUri: 'ldpUri',
ldpUriPlaceholder: '请输入ldpUri',
validateUrl: '验证地址',
validateUrlPlaceholder: '请输入验证地址',
redirectUrl: '回调地址',
redirectUrlPlaceholder: '请输入回调地址',
enableAuthentication: '启用CAS认证',
saveSuccess: '保存成功',
save: '保存'
},
oidc: {
title: 'OIDC 设置',
authEndpoint: '授权端地址',
authEndpointPlaceholder: '请输入授权端地址',
tokenEndpoint: 'Token端地址',
tokenEndpointPlaceholder: '请输入Token端地址',
userInfoEndpoint: '用户信息端地址',
userInfoEndpointPlaceholder: '请输入用户信息端地址',
clientId: '客户端ID',
clientIdPlaceholder: '请输入客户端ID',
clientSecret: '客户端密钥',
clientSecretPlaceholder: '请输入客户端密钥',
logoutEndpoint: '注销端地址',
logoutEndpointPlaceholder: '请输入注销端地址',
redirectUrl: '回调地址',
redirectUrlPlaceholder: '请输入回调地址',
enableAuthentication: '启用OIDC认证'
},
jump_tip: '即将跳转至认证源页面进行认证',
jump: '跳转',
oauth2: {
title: 'OAUTH2 设置',
authEndpoint: '授权端地址',
authEndpointPlaceholder: '请输入授权端地址',
tokenEndpoint: 'Token端地址',
tokenEndpointPlaceholder: '请输入Token端地址',
userInfoEndpoint: '用户信息端地址',
userInfoEndpointPlaceholder: '请输入用户信息端地址',
scope: '连接范围',
scopePlaceholder: '请输入连接范围',
clientId: '客户端ID',
clientIdPlaceholder: '请输入客户端ID',
clientSecret: '客户端密钥',
clientSecretPlaceholder: '请输入客户端密钥',
redirectUrl: '回调地址',
redirectUrlPlaceholder: '请输入回调地址',
filedMapping: '字段映射',
filedMappingPlaceholder: '请输入字段映射',
enableAuthentication: '启用OAUTH2认证',
save: '保存',
saveSuccess: '保存成功'
}
}
}

View File

@ -15,6 +15,12 @@
:placeholder="$t('login.cas.ldpUriPlaceholder')" :placeholder="$t('login.cas.ldpUriPlaceholder')"
/> />
</el-form-item> </el-form-item>
<el-form-item :label="$t('login.cas.validateUrl')" prop="config_data.validateUrl">
<el-input
v-model="form.config_data.validateUrl"
:placeholder="$t('login.cas.validateUrlPlaceholder')"
/>
</el-form-item>
<el-form-item :label="$t('login.cas.redirectUrl')" prop="config_data.redirectUrl"> <el-form-item :label="$t('login.cas.redirectUrl')" prop="config_data.redirectUrl">
<el-input <el-input
v-model="form.config_data.redirectUrl" v-model="form.config_data.redirectUrl"
@ -49,6 +55,7 @@ const form = ref<any>({
auth_type: 'CAS', auth_type: 'CAS',
config_data: { config_data: {
ldpUri: '', ldpUri: '',
validateUrl: '',
redirectUrl: '' redirectUrl: ''
}, },
is_active: true is_active: true
@ -62,6 +69,9 @@ const rules = reactive<FormRules<any>>({
'config_data.ldpUri': [ 'config_data.ldpUri': [
{ required: true, message: t('login.cas.ldpUriPlaceholder'), trigger: 'blur' } { required: true, message: t('login.cas.ldpUriPlaceholder'), trigger: 'blur' }
], ],
'config_data.validateUrl': [
{ required: true, message: t('login.cas.validateUrlPlaceholder'), trigger: 'blur' }
],
'config_data.redirectUrl': [ 'config_data.redirectUrl': [
{ {
required: true, required: true,
@ -85,6 +95,9 @@ const submit = async (formEl: FormInstance | undefined) => {
function getDetail() { function getDetail() {
authApi.getAuthSetting(form.value.auth_type, loading).then((res: any) => { authApi.getAuthSetting(form.value.auth_type, loading).then((res: any) => {
if (res.data && JSON.stringify(res.data) !== '{}') { if (res.data && JSON.stringify(res.data) !== '{}') {
if (!res.data.config_data.validateUrl) {
res.data.config_data.validateUrl = res.data.config_data.ldpUri
}
form.value = res.data form.value = res.data
} }
}) })

View File

@ -0,0 +1,161 @@
<template>
<div class="authentication-setting__main main-calc-height">
<el-scrollbar>
<div class="form-container p-24" v-loading="loading">
<el-form
ref="authFormRef"
:rules="rules"
:model="form"
label-position="top"
require-asterisk-position="right"
>
<el-form-item :label="$t('login.oauth2.authEndpoint')" prop="config_data.authEndpoint">
<el-input
v-model="form.config_data.authEndpoint"
:placeholder="$t('login.oauth2.authEndpointPlaceholder')"
/>
</el-form-item>
<el-form-item :label="$t('login.oauth2.tokenEndpoint')" prop="config_data.tokenEndpoint">
<el-input
v-model="form.config_data.tokenEndpoint"
:placeholder="$t('login.oauth2.tokenEndpointPlaceholder')"
/>
</el-form-item>
<el-form-item
:label="$t('login.oauth2.userInfoEndpoint')"
prop="config_data.userInfoEndpoint"
>
<el-input
v-model="form.config_data.userInfoEndpoint"
:placeholder="$t('login.oauth2.userInfoEndpointPlaceholder')"
/>
</el-form-item>
<el-form-item :label="$t('login.oauth2.scope')" prop="config_data.scope">
<el-input
v-model="form.config_data.scope"
:placeholder="$t('login.oauth2.scopePlaceholder')"
/>
</el-form-item>
<el-form-item :label="$t('login.oauth2.clientId')" prop="config_data.clientId">
<el-input
v-model="form.config_data.clientId"
:placeholder="$t('login.oauth2.clientIdPlaceholder')"
/>
</el-form-item>
<el-form-item :label="$t('login.oauth2.clientSecret')" prop="config_data.clientSecret">
<el-input
v-model="form.config_data.clientSecret"
:placeholder="$t('login.oauth2.clientSecretPlaceholder')"
show-password
/>
</el-form-item>
<el-form-item :label="$t('login.oauth2.redirectUrl')" prop="config_data.redirectUrl">
<el-input
v-model="form.config_data.redirectUrl"
:placeholder="$t('login.oauth2.redirectUrlPlaceholder')"
/>
</el-form-item>
<el-form-item :label="$t('login.oauth2.filedMapping')" prop="config_data.fieldMapping">
<el-input
v-model="form.config_data.fieldMapping"
:placeholder="$t('login.oauth2.filedMappingPlaceholder')"
/>
</el-form-item>
<el-form-item>
<el-checkbox v-model="form.is_active"
>{{ $t('login.oauth2.enableAuthentication') }}
</el-checkbox>
</el-form-item>
</el-form>
<div class="text-right">
<el-button @click="submit(authFormRef)" type="primary" :disabled="loading">
{{ $t('login.ldap.save') }}
</el-button>
</div>
</div>
</el-scrollbar>
</div>
</template>
<script setup lang="ts">
import { reactive, ref, watch, onMounted } from 'vue'
import authApi from '@/api/auth-setting'
import type { FormInstance, FormRules } from 'element-plus'
import { t } from '@/locales'
import { MsgSuccess } from '@/utils/message'
const form = ref<any>({
id: '',
auth_type: 'OAUTH2',
config_data: {
authEndpoint: '',
tokenEndpoint: '',
userInfoEndpoint: '',
scope: '',
clientId: '',
clientSecret: '',
redirectUrl: '',
fieldMapping: ''
},
is_active: true
})
const authFormRef = ref()
const loading = ref(false)
const rules = reactive<FormRules<any>>({
'config_data.authEndpoint': [
{ required: true, message: t('login.oauth2.authEndpointPlaceholder'), trigger: 'blur' }
],
'config_data.tokenEndpoint': [
{ required: true, message: t('login.oauth2.tokenEndpointPlaceholder'), trigger: 'blur' }
],
'config_data.userInfoEndpoint': [
{
required: true,
message: t('login.oauth2.userInfoEndpointPlaceholder'),
trigger: 'blur'
}
],
'config_data.scope': [
{ required: true, message: t('login.oauth2.scopePlaceholder'), trigger: 'blur' }
],
'config_data.clientId': [
{ required: true, message: t('login.oauth2.clientIdPlaceholder'), trigger: 'blur' }
],
'config_data.clientSecret': [
{ required: true, message: t('login.oauth2.clientSecretPlaceholder'), trigger: 'blur' }
],
'config_data.redirectUrl': [
{ required: true, message: t('login.oauth2.redirectUrlPlaceholder'), trigger: 'blur' }
],
'config_data.fieldMapping': [
{ required: true, message: t('login.oauth2.filedMappingPlaceholder'), trigger: 'blur' }
]
})
const submit = async (formEl: FormInstance | undefined, test?: string) => {
if (!formEl) return
await formEl.validate((valid, fields) => {
if (valid) {
authApi.putAuthSetting(form.value.auth_type, form.value, loading).then((res) => {
MsgSuccess(t('login.ldap.saveSuccess'))
})
}
})
}
function getDetail() {
authApi.getAuthSetting(form.value.auth_type, loading).then((res: any) => {
if (res.data && JSON.stringify(res.data) !== '{}') {
form.value = res.data
}
})
}
onMounted(() => {
getDetail()
})
</script>
<style lang="scss" scoped></style>

View File

@ -19,6 +19,7 @@ import OIDC from './component/OIDC.vue'
import SCAN from './component/SCAN.vue' import SCAN from './component/SCAN.vue'
import { t } from '@/locales' import { t } from '@/locales'
import useStore from '@/stores' import useStore from '@/stores'
import OAUTH2 from '@/views/authentication/component/OAUTH2.vue'
const { user } = useStore() const { user } = useStore()
const router = useRouter() const router = useRouter()
@ -40,6 +41,11 @@ const tabList = [
name: 'OIDC', name: 'OIDC',
component: OIDC component: OIDC
}, },
{
label: t('login.oauth2.title'),
name: 'OAUTH2',
component: OAUTH2
},
{ {
label: '扫码登录', label: '扫码登录',
name: 'SCAN', name: 'SCAN',

View File

@ -66,7 +66,8 @@
:key="item" :key="item"
class="login-button-circle color-secondary" class="login-button-circle color-secondary"
@click="changeMode(item)" @click="changeMode(item)"
>{{ item }} >
<span style="font-size: 10px">{{ item }}</span>
</el-button> </el-button>
<el-button <el-button
v-if="item === 'QR_CODE' && loginMode !== item" v-if="item === 'QR_CODE' && loginMode !== item"
@ -162,6 +163,14 @@ function redirectAuth(authType: string) {
if (authType === 'OIDC') { if (authType === 'OIDC') {
url = `${config.authEndpoint}?client_id=${config.clientId}&redirect_uri=${redirectUrl}&response_type=code&scope=openid+profile+email` url = `${config.authEndpoint}?client_id=${config.clientId}&redirect_uri=${redirectUrl}&response_type=code&scope=openid+profile+email`
} }
if (authType === 'OAUTH2') {
url =
`${config.authEndpoint}?client_id=${config.clientId}&response_type=code` +
`&redirect_uri=${redirectUrl}&state=${res.data.id}`
if (config.scope) {
url += `&scope=${config.scope}`
}
}
if (url) { if (url) {
window.location.href = url window.location.href = url
} }