更新记录

1.0.0(2026-06-18)

首次发布


平台兼容性

uni-app(4.0)

Vue2 Vue3 Chrome Safari app-vue app-nvue Android iOS 鸿蒙
× × × × × × 5.0 15 12
微信小程序 支付宝小程序 抖音小程序 百度小程序 快手小程序 京东小程序 鸿蒙元服务 QQ小程序 飞书小程序 小红书小程序 快应用-华为 快应用-联盟
× × × × × × × × × × × ×

其他

多语言 暗黑模式 宽屏模式
× ×

sangfor-vpn-sdk

本uts插件支持 uni-app 和 uni-app x 项目,推荐先下载示例项目(uni-app)进行试用。

本地调试、开发、试用时,安卓端和iOS端都需要打包自定义基座。

深信服SDK仅支持armeabi-v7a、 arm64-v8a架构模拟器, 不支持X86架构模拟器。

推荐使用真机进行调试、开发、试用。

uniappx工程的鸿蒙端只支持源码授权。

深信服SDK鸿蒙端的getAuthStatus与安卓端、iOS端调用方式和返回值都不一样,具体getAuthStatus使用方式请看示例代码

插件使用示例

uniapp demo

vue3 界面

<template>
    <view class="main-page-wrapper" style="padding: 5px 10px;">
        <view class="main-auth-wrapper">
            <view class="row-item">
                <text class="title">服务器:</text>
                <input type="url" class="input-wrapper" placeholder="请输入服务器地址" v-model="vpnAddress" />
            </view>
            <view class="row-item">
                <text class="title">账  号:</text>
                <input class="input-wrapper" placeholder="请输入账号" v-model="vpnUserName" />
            </view>
            <view class="row-item">
                <text class="title">密   码:</text>
                <input class="input-wrapper" placeholder="请输入密码" v-model="vpnUserPassword" />
            </view>
            <view>
                <button type="default" @click="loginVPNMianAuth()" plain="true">开始账号密码主认证</button>
            </view>
        </view>

        <!-- 图形辅助认证 -->
        <view v-if="showRandCode" class="rand-code-wrapper">
            <view class="rand-code-img-wrapper">
                <input v-model="userRandCode" style="width: 400rpx; height: 80rpx; border: solid 1px #ddd;" placeholder="请输入图形验证码" />
                <view @click="getRandCode()" style="width: 80px; background-color: black; height: 40px; border: solid 1px #ddd;">
                    <image :src="randCodeBase64" style="width: 100%; height: 100%; "></image>
                </view>
            </view>
            <view>
                <button type="default" @click="doRandCodeAuth()" plain="true">图形辅助认证</button>
            </view>
        </view>

        <!-- 主动修改密码 -->
        <view v-if="activelyModifyPwdShow" class="modify-password-wrapper">
            <view class="row-item">
                <text class="title">旧密码:</text>
                <input class="input-wrapper" placeholder="请输入旧密码" v-model="oldPwd" />
            </view>
            <view class="row-item">
                <text class="title">新密码:</text>
                <input class="input-wrapper" placeholder="请输入新密码" v-model="newPwd" />
            </view>
            <view>
                <button type="default" @click="activelyResetPasswordHandle()" plain="true">主动修改密码</button>
            </view>
        </view>

        <!-- 修改初始密码 -->
        <view v-if="modifyInitialPwdShow" class="modify-password-wrapper">
            <view>
                <text v-text="pwsRules"></text>
            </view>

            <view class="row-item">
                <text class="title">初始密码:</text>
                <input class="input-wrapper" placeholder="请输入初始密码" v-model="initialOldPwd" />
            </view>
            <view class="row-item">
                <text class="title">新密码:</text>
                <input class="input-wrapper" placeholder="请输入新密码" v-model="initialNewPwd" />
            </view>
            <view>
                <button type="default" @click="modifyInitialPasswordHandle()" plain="true">修改初始密码</button>
            </view>
        </view>

        <view class="uni-btn-wrapper">
            <button style="margin-bottom: 20rpx;" type="default" @click="getAuthStatusAndShow()" plain="true">获取认证状态</button>
            <button style="margin-bottom: 20rpx;" type="default" @click="loginAutoTicketAndShow()" plain="true">免密认证</button>
            <button style="margin-bottom: 20rpx;" type="default" @click="allowactivelyResetPasswordHandle()" plain="true">是否支持主动修改密码</button>
            <button style="margin-bottom: 20rpx;" type="default" @click="getPswStrategyHandle()" plain="true">获取密码规则</button>
            <button style="margin-bottom: 20rpx;" type="default" @click="logoutHandle()" plain="true">注销登录</button>
        </view>
    </view>
</template>

vue3 js代码

import { onMounted, ref } from 'vue'
import * as sangforVpnSdk from '@/uni_modules/sangfor-vpn-sdk'

const vpnAddress = ref('https://**.**.**.**/')
const vpnUserName = ref('')
const vpnUserPassword = ref('')
const showRandCode = ref(false)
const userRandCode = ref('') // 用户输入的图像验证码
const randCodeBase64 = ref('') // 图像验证码的src
const oldPwd = ref('')
const newPwd = ref('')
const activelyModifyPwdShow = ref(false)
const initialOldPwd = ref('')
const initialNewPwd = ref('')
const modifyInitialPwdShow = ref(false)
const pwsRules = ref('') // 修改初始密码时的密码规则

// 获取认证状态
async function getAuthStatusAndShow() {
    uni.showLoading({
        title: '请求中'
    })

    // #ifdef APP-HARMONY
    console.log("仅鸿蒙会编译")
    const res = await sangforVpnSdk.getAuthStatus()
    uni.hideLoading()
    if (res) {
        uni.showModal({
            title: '当前的登录状态为:已认证成功',
            showCancel: false
        })
    } else {
        uni.showModal({
            title: '当前的登录状态为:未认证成功',
            showCancel: false
        })
    }
    // #endif

    // #ifndef APP-HARMONY
    console.log("仅非鸿蒙会编译")
    const res = sangforVpnSdk.getAuthStatus()
    uni.hideLoading()
    uni.showModal({
        title: '当前的登录状态为:' + res,
        showCancel: false
    })
    // #endif
}

// 免密登录
function loginAutoTicketAndShow() {
    const res = sangforVpnSdk.startAutoTicket()
    if (res) {
        uni.showModal({
            title: '当前已登录过且支持免密',
            showCancel: false
        })
    } else {
        uni.showModal({
            title: '当前未登录过或不支持免密',
            showCancel: false
        })
    }
}

// 处理登录结果
function dealAuthResult(result) {
    console.log(result)
    if (result.message.startsWith("AUTH_")) {
        if (result.message === "AUTH_SUCCESS") {
            uni.showModal({
                title: '账号:' + vpnUserName.value + ',认证成功!',
                showCancel: false
            });
            return
        }
        if (result.message === 'AUTH_TYPE_RAND') {
            // 图像验证码
            showRandCode.value = true
            getRandCode()
            return
        }
        if (result.message === 'AUTH_TYPE_RENEW_PASSWORD') {
            // 修改初始密码
            modifyInitialPwdShow.value = true
            console.log("result.data.changePwdData is ", result.data.changePwdData)
            pwsRules.value = result.data.changePwdData.policyMsg
            console.log('pwsRules.value is ', pwsRules.value)
            return
        }
        if (result.message === 'AUTH_TYPE_NOT_SUPPORT') {
            // 未支持的AUTH_TYPE
            uni.showModal({
                title: 'uts插件暂不支持此认证类型,可联系uts插件作者增加',
                showCancel: false
            });
            return
        }
    } else {
        uni.showModal({
            title: '认证失败,失败原因是:' + result.message,
            showCancel: false
        });
        return
    }
}

// 用户名密码登录
function loginVPNMianAuth() {
    console.log('vpnAddress is', vpnAddress.value)
    console.log('vpnUserName is', vpnUserName.value)
    console.log('vpnUserPassword is', vpnUserPassword.value)
    uni.showLoading({
        title: '请求中'
    })
    sangforVpnSdk.startPasswordAuth(vpnAddress.value, vpnUserName.value, vpnUserPassword.value, (result) => {
        uni.hideLoading()
        dealAuthResult(result)
    })
}

// 获取图形验证码
function getRandCode() {
    console.log('vue 中 开始 获取 uts regetRandCode')
    sangforVpnSdk.regetRandCode((result) => {
        console.log('得到的验证码是:', result)
        if (result.success) {
            randCodeBase64.value = 'data:image/png;base64,' + result.message
        } else {
            uni.showModal({
                title: '获取图形验证码失败',
                content: result.message,
                showCancel: false
            })
        }
    })
}

// 图形验证
function doRandCodeAuth() {
    console.log('vue 中 开始调用 uts doSecondaryAuth')
    // 图形验证码验证
    sangforVpnSdk.doSecondaryAuth({
        u: vpnUserName.value,
        p: vpnUserPassword.value,
        randCode: userRandCode.value
    }, result => {
        console.log(result)
        if (result.message) {
            uni.showModal({
                title: '提示',
                content: result.message,
                showCancel: false
            })
        } else {
            uni.showModal({
                title: '提示',
                content: result,
                showCancel: false
            })
        }
    })
}

// 是否支持主动修改密码
function allowactivelyResetPasswordHandle() {
    let res = sangforVpnSdk.allowResetPassword()
    console.log(' vue 中 allowactivelyResetPasswordHandle res is ', res)
    if (res) {
        activelyModifyPwdShow.value = true
        uni.showModal({
            title: '提示',
            content: '当前用户支持主动修改密码',
            showCancel: false
        })
    } else {
        uni.showModal({
            title: '提示',
            content: '当前用户不支持主动修改密码',
            showCancel: false
        })
    }

    console.log('支持主动修改密码', res)
}

// 获取密码规则
function getPswStrategyHandle() {
    sangforVpnSdk.getPswStrategy(result => {
        uni.showModal({
            title: '密码规则是:',
            content: result.message,
            showCancel: false
        })
        console.log(result)
    })
}

// 主动修改密码
function activelyResetPasswordHandle() {
    sangforVpnSdk.resetPassword(oldPwd.value, newPwd.value, result => {
        console.log(result)
        if (result.message) {
            uni.showModal({
                title: '提示',
                content: result.message,
                showCancel: false
            })
        } else {
            uni.showModal({
                title: '提示',
                content: String(result),
                showCancel: false
            })
        }
    })
}

// 修改初始密码
function modifyInitialPasswordHandle() {
    // 修改初始密码验证
    sangforVpnSdk.doSecondaryAuth({
        oldPw: initialOldPwd.value,
        newPw: initialNewPwd.value,
    }, result => {
        console.log('modifyInitialPasswordHandle 中 result is ', result)
        if (result.message) {
            uni.showModal({
                title: '提示',
                content: result.message,
                showCancel: false
            })
        } else {
            console.log('modifyInitialPasswordHandle 中 result is ', result)
            uni.showModal({
                title: '提示',
                content: result,
                showCancel: false
            })
        }
    })
}

// 注销登录
function logoutHandle() {
    sangforVpnSdk.logout(result => {
        uni.showModal({
            title: '提示',
            content: result.message,
            showCancel: false
        })
        console.log(result)
    })
}

onMounted(() => {
    console.log("onMounted")
    sangforVpnSdk.initSDK()
})

uniappx demo

vue3 界面

<template>
<!-- #ifdef APP -->
<scroll-view style="flex:1">
<!-- #endif -->
    <view class="main-page-wrapper" style="padding: 5px 10px;">
        <view class="main-auth-wrapper">
            <view class="row-item">
                <text class="title">服务器:</text>
                <input type="url" class="input-wrapper" placeholder="请输入服务器地址" v-model="vpnAddress" />
            </view>
            <view class="row-item">
                <text class="title">账  号:</text>
                <input class="input-wrapper" placeholder="请输入账号" v-model="vpnUserName" />
            </view>
            <view class="row-item">
                <text class="title">密   码:</text>
                <input class="input-wrapper" placeholder="请输入密码" v-model="vpnUserPassword" />
            </view>
            <view>
                <button type="default" @click="loginVPNMianAuth()" plain="true">开始账号密码主认证</button>
            </view>
        </view>

        <!-- 图形辅助认证 -->
        <view v-if="showRandCode" class="rand-code-wrapper">
            <view class="rand-code-img-wrapper">
                <input v-model="userRandCode" style="width: 400rpx; height: 80rpx; border: solid 1px #ddd;" placeholder="请输入图形验证码" />
                <view @click="getRandCode()" style="width: 80px; background-color: black; height: 40px; border: solid 1px #ddd;">
                    <image :src="randCodeBase64" style="width: 100%; height: 100%; "></image>
                </view>
            </view>
            <view>
                <button type="default" @click="doRandCodeAuth()" plain="true">图形辅助认证</button>
            </view>
        </view>

        <!-- 主动修改密码 -->
        <view v-if="activelyModifyPwdShow" class="modify-password-wrapper">
            <view class="row-item">
                <text class="title">旧密码:</text>
                <input class="input-wrapper" placeholder="请输入旧密码" v-model="oldPwd" />
            </view>
            <view class="row-item">
                <text class="title">新密码:</text>
                <input class="input-wrapper" placeholder="请输入新密码" v-model="newPwd" />
            </view>
            <view>
                <button type="default" @click="activelyResetPasswordHandle()" plain="true">主动修改密码</button>
            </view>
        </view>

        <!-- 修改初始密码 -->
        <view v-if="modifyInitialPwdShow" class="modify-password-wrapper">
            <view>
                <text>{{ pwsRules }}</text>
            </view>
            <view class="row-item">
                <text class="title">初始密码:</text>
                <input class="input-wrapper" placeholder="请输入初始密码" v-model="initialOldPwd" />
            </view>
            <view class="row-item">
                <text class="title">新密码:</text>
                <input class="input-wrapper" placeholder="请输入新密码" v-model="initialNewPwd" />
            </view>
            <view>
                <button type="default" @click="modifyInitialPasswordHandle()" plain="true">修改初始密码</button>
            </view>
        </view>

        <view class="uni-btn-wrapper">
            <button style="margin-bottom: 20rpx;" type="default" @click="getAuthStatusAndShow()" plain="true">获取认证状态</button>
            <button style="margin-bottom: 20rpx;" type="default" @click="loginAutoTicketAndShow()" plain="true">免密认证</button>
            <button style="margin-bottom: 20rpx;" type="default" @click="allowResetPasswordHandle()" plain="true">是否支持主动修改密码</button>
            <button style="margin-bottom: 20rpx;" type="default" @click="getPswStrategyHandle()" plain="true">获取密码规则</button>
            <button style="margin-bottom: 20rpx;" type="default" @click="logoutHandle()" plain="true">注销登录</button>
        </view>
    </view>
<!-- #ifdef APP -->
</scroll-view>
<!-- #endif -->
</template>

vue3 uts代码

import { onMounted } from 'vue'
import * as sangforVpnSdk from '@/uni_modules/sangfor-vpn-sdk' // 引入插件对象

const vpnAddress = ref<string>('https://**.**.**.**/')
const vpnUserName = ref('')
const vpnUserPassword = ref('')
const showRandCode = ref(false)
const userRandCode = ref('') // 用户输入的图像验证码
const randCodeBase64 = ref('') // 图像验证码的src
const oldPwd = ref('')
const newPwd = ref('')
const activelyModifyPwdShow = ref(false)
const initialOldPwd = ref('')
const initialNewPwd = ref('')
const modifyInitialPwdShow = ref(false)
const pwsRules = ref('') // 修改初始密码时的密码规则

// 获取认证状态
async function getAuthStatusAndShow() {
    // #ifdef APP-HARMONY
    console.log("仅鸿蒙会编译")
    const res = await sangforVpnSdk.getAuthStatus()
    uni.hideLoading()
    if (res) {
        uni.showModal({
            title: '当前的登录状态为:已认证成功',
            showCancel: false
        })
    } else {
        uni.showModal({
            title: '当前的登录状态为:未认证成功',
            showCancel: false
        })
    }
    // #endif

    // #ifndef APP-HARMONY
    console.log("仅非鸿蒙会编译")
    const res = sangforVpnSdk.getAuthStatus()
    uni.showModal({
        title: '当前的登录状态为:' + res,
        showCancel: false
    })
    // #endif
}

// 免密登录
function loginAutoTicketAndShow() {
    const res = sangforVpnSdk.startAutoTicket()
    if (res) {
        uni.showModal({
            title: '当前已登录过且支持免密',
            showCancel: false
        })
    } else {
        uni.showModal({
            title: '当前未登录过或不支持免密',
            showCancel: false
        })
    }
}

// 获取图形验证码
function getRandCode() {
    console.log('vue 中 开始 获取 uts regetRandCode')
    sangforVpnSdk.regetRandCode((result: UTSJSONObject) => {
        console.log('得到的验证码是:', result)
        if ((result["success"] as boolean) == true) {
            randCodeBase64.value = 'data:image/png;base64,' + result.message
        } else {
            uni.showModal({
                title: '获取图形验证码失败',
                content: result["message"] as string,
                showCancel: false
            })
        }
    })
}

// 处理登录结果
function dealAuthResult(result: UTSJSONObject) {
    console.log(result)
    const message = result["message"] as string
    if (message.startsWith("AUTH_")) {
        if (message === "AUTH_SUCCESS") {
            uni.showModal({
                title: '账号:' + vpnUserName.value + ',认证成功!',
                showCancel: false
            });
            return
        }
        if (message === 'AUTH_TYPE_RAND') {
            // 图像验证码
            showRandCode.value = true
            getRandCode()
            return
        }
        if (result.message === 'AUTH_TYPE_RENEW_PASSWORD') {
            // 修改初始密码
            modifyInitialPwdShow.value = true
            const data = result.data as UTSJSONObject
            const changePwdData = data["changePwdData"] as UTSJSONObject
            pwsRules.value = changePwdData["policyMsg"] as string
            console.log('pwsRules.value is ', pwsRules.value)
            return
        }
        if (result.message === 'AUTH_TYPE_NOT_SUPPORT') {
            // 未支持的AUTH_TYPE
            uni.showModal({
                title: 'uts插件暂不支持此认证类型,可联系uts插件作者增加',
                showCancel: false
            });
            return
        }
    } else {
        uni.showModal({
            title: '认证失败,失败原因是:' + message,
            showCancel: false
        });
        return
    }
}

// 用户名密码登录
function loginVPNMianAuth() {
    console.log('vpnAddress is', vpnAddress.value)
    console.log('vpnUserName is', vpnUserName.value)
    console.log('vpnUserPassword is', vpnUserPassword.value)
    uni.showLoading({
        title: '请求中'
    })
    sangforVpnSdk.startPasswordAuth(vpnAddress.value, vpnUserName.value, vpnUserPassword.value, (result: UTSJSONObject) => {
        uni.hideLoading()
        dealAuthResult(result)
    })
}

// 图形验证
function doRandCodeAuth() {
    console.log('vue 中 开始调用 uts doSecondaryAuth')
    //图形验证码验证
    sangforVpnSdk.doSecondaryAuth({
        u: vpnUserName.value,
        p: vpnUserPassword.value,
        randCode: userRandCode.value
    }, (result: UTSJSONObject) => {
        console.log(result)
        if (result["success"] as boolean) {
            uni.showModal({
                title: '提示',
                content: result["message"] as string,
                showCancel: false
            })
        } else {
            uni.showModal({
                title: '提示',
                content: result["message"] as string,
                showCancel: false
            })
        }
    })
}

// 是否支持主动修改密码
function allowResetPasswordHandle() {
    let res = sangforVpnSdk.allowResetPassword()

    if (res) {
        activelyModifyPwdShow.value = true
        uni.showModal({
            title: '提示',
            content: '当前用户支持主动修改密码',
            showCancel: false
        })
    } else {
        uni.showModal({
            title: '提示',
            content: '当前用户不支持主动修改密码',
            showCancel: false
        })
    }

    console.log('支持主动修改密码', res)
}

// 获取密码规则
function getPswStrategyHandle() {
    sangforVpnSdk.getPswStrategy((result: UTSJSONObject) => {
        uni.showModal({
            title: '密码规则是:',
            content: result["message"] as string,
            showCancel: false
        })
        console.log(result)
    })
}

// 修改密码
function activelyResetPasswordHandle() {
    sangforVpnSdk.resetPassword(oldPwd.value, newPwd.value, (result: UTSJSONObject) => {
        console.log(result)
        if (result["success"] as boolean) {
            uni.showModal({
                title: '提示',
                content: result["message"] as string,
                showCancel: false
            })
        } else {
            uni.showModal({
                title: '提示',
                content: result["message"] as string,
                showCancel: false
            })
        }
    })
}

// 修改初始密码
function modifyInitialPasswordHandle() {
    // 修改初始密码验证
    sangforVpnSdk.doSecondaryAuth({
        oldPw: initialOldPwd.value,
        newPw: initialNewPwd.value,
    }, (result: UTSJSONObject) => {
        console.log('modifyInitialPasswordHandle 中 result is ', result)
        if (result["success"] as boolean) {
            uni.showModal({
                title: '提示',
                content: result["message"] as string,
                showCancel: false
            })
        } else {
            uni.showModal({
                title: '提示',
                content: result["message"] as string,
                showCancel: false
            })
        }
    })
}

// 注销登录
function logoutHandle() {
    sangforVpnSdk.logout((result: UTSJSONObject) => {
        uni.showModal({
            title: '提示',
            content: result["message"] as string,
            showCancel: false
        })
        console.log(result)
    })
}

onMounted(() => {
    console.log("onMounted")
    sangforVpnSdk.initSDK()
})

插件功能说明

本插件未包含深信服SDK全部功能。目前插件实现的功能全部在上面demo中展示了。

鸿蒙端支持uniappx项目的特别说明

购买源码后,如需支持uniappx项目,可将SangforManager.ets文件中如下代码:

import {UTSJSONObject} from '@dcloudio/uni-app-runtime'
// import {UTSJSONObject} from '@dcloudio/uni-app-x-runtime'

修改为如下:

// import {UTSJSONObject} from '@dcloudio/uni-app-runtime'
import {UTSJSONObject} from '@dcloudio/uni-app-x-runtime'

即可支持uniapp项目

隐私、权限声明

1. 本插件需要申请的系统权限列表:

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

无,本插件只调用深信服零信任SDK

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

暂无用户评论。