更新记录

1.0.0(2025-08-01)

支持 android passkey 通行密钥


平台兼容性

云端兼容性

阿里云 腾讯云 支付宝云
×

uni-app(4.63)

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

uni-app x(4.62)

Chrome Safari Android iOS 鸿蒙 微信小程序
- - 11.0 - - -

示例使用

点击右边“使用HBuilderX导入示例项目”,导入示例后免费试用插件或者购买后导入,然后打包自定义android基座。再运行到设备

效果视频(可在抖音或者直接复制链接浏览器打开看)

演示视频链接,点击观看

平台兼容性

目前支持Android,CPU类型支持arm64-v8a,armeabi-v7a android 需要支持iOS请合作,支援我下付费的开发者账号

插件功能

  • 账号密码使用passkey方式保存在本机
  • public key本地保存

在线使用插件通用流程

  1. 购买此插件,选择该插件绑定的项目(使用者项目)。
  2. 购买页面导入到相应项目。
  3. 根据插件作者的提供的文档开发代码,在代码中引用插件,调用插件功能。
  4. 打包自定义基座,得到自定义基座,然后运行时选择自定义基座,进行log输出测试。
  5. 开发完毕后正式云打包。

插件API的使用

引入插件

import {PassKeyOptions,saveUserAndPassword,getUserAndPassword,savePublicKeyCredential,getPublicKeyCredential } from "@/uni_modules/xt-passkey-plugin"

API使用 (api30以上的境外版本机器支持,大陆机器部分支持,看厂商的支持情况。)

账号密码 (实际完成测试)

//保存账号密码,一般在用户输入后登录成功保存。当然其他参数,你可以放到里面,自己做解析即可
function saveUserAndPassword(userId:string, password:string,options : PassKeyOptions)
参数3个,参考下面
使用方式:
saveUserAndPassword(this.username, this.password, {
      complete: (res) => {
         console.log("saveUserAndPassword callback:" + res);
         try {
             const result = typeof res === 'string' ? JSON.parse(res) : res;
             this.callbackText = `保存结果: ${JSON.stringify(result)}`;
         } catch (e) {
             console.error('Error parsing save result:', e);
             this.callbackText = `保存出错: ${e.message}`;
         }
      },
});
返回值:成功如下,其他均为失败
{
    "status": "success",
    "type": "save"
}

//获取已保存的密码,一般在点击输入框或者进入登录页面时调用
export function getUserAndPassword(options : PassKeyOptions)
参数1个,参考下面
getUserAndPassword({
    complete: (res) => {
        console.log("getUserAndPassword callback:" + res);
        try {
            // Parse the JSON string if it's a string
            const result = typeof res === 'string' ? JSON.parse(res) : res;
            this.callbackText = `获取结果: ${JSON.stringify(result)}`;

            if (result.status === 'success' && result.type === 'get') {
                this.username = result.userId || '';
                this.password = result.password || '';
            }
        } catch (e) {
            console.error('Error parsing user data:', e);
            this.callbackText = `获取出错: ${e.message}`;
        }
    },
});

返回值:成功如下,其他均为失败
{
    "status": "success",
    "type": "get",
    "userId": "Hfhdj",
    "password": "jdjjfjf"
}

public key (由于环境限制,我这边无法完成测试,需要自己的域名和相对应的签名)

//保存publickey
function savePublicKeyCredential(registrationJson:string,options : PassKeyOptions)
registrationJson格式如下:
{
    "attestation": "none",
    "authenticatorSelection": {
        "authenticatorAttachment": "platform",
        "requireResidentKey": false,
        "residentKey": "required",
        "userVerification": "required"
    },
    "challenge": "5_1HW194lz90hxhZ_L-Dc2eCl21fawKf6XmT6gXIOn0",
    "excludeCredentials": [],
    "pubKeyCredParams": [
        {
            "alg": -7,
            "type": "public-key"
        }
    ],
    "rp": {
        "id": "dashlane-passkey-demo.glitch.me",
        "name": "Dashlane Passkey Demo"
    },
    "timeout": 1800000,
    "user": {
        "displayName": "hfhdj@jdjdj.com",
        "id": "e656e3e0-cb19-44d3-98c4-9a8a3f50be2e",
        "name": "hfhdj@jdjdj.com"
    }
}
返回结果和前面类似

//获取publickey
function getPublicKeyCredential(authJson :string, options : PassKeyOptions)
authJson 参数如下:
{
    "challenge": "<challenge_string>",
    "allowCredentials": [
        {
            "id": "<credential_id>",
            "transports": ["internal", "hybrid"],
            "type": "public-key"
        }
    ],
    "timeout": 1800000,
    "userVerification": "required",
    "rpId": "dashlane-passkey-demo.glitch.me"
}
返回结果和前面类似

uniapp主页代码

<template>
    <view class="content">
        <image class="logo" src="/static/logo.png"></image>
        <view class="text-area">
            <text class="title">{{title}}</text>
        </view>

        <!-- 用户名输入框 -->
        <view class="input-group">
            <text class="input-label">用户名:</text>
            <input class="input" v-model="username" placeholder="请输入用户名" />
        </view>

        <!-- 密码输入框 -->
        <view class="input-group"> 
            <text class="input-label">密码:</text>
            <input class="input" v-model="password" password placeholder="请输入密码" />
        </view>

        <!-- 登录按钮 -->
        <button class="login-btn" @click="handleLogin">登录</button>

        <!-- 新增的简单文本显示框 -->
        <text style="width:80%; margin-top:20rpx; display:block; text-align:center; word-wrap:break-word; white-space:pre-wrap;">{{callbackText}}</text>
    </view>
</template>

<script>
    import {PassKeyOptions,saveUserAndPassword,getUserAndPassword,savePublicKeyCredential,getPublicKeyCredential } from "@/uni_modules/xt-passkey-plugin"
    export default {
        data() {
            return {
                title: '登录页面',
                username: '',
                password: '',
                callbackText: ''
            }
        },
        onLoad() {
            getUserAndPassword({
                    complete: (res) => {
                        console.log("getUserAndPassword callback:" + res);
                        try {
                            // Parse the JSON string if it's a string
                            const result = typeof res === 'string' ? JSON.parse(res) : res;
                            this.callbackText = `获取结果: ${JSON.stringify(result)}`;

                            if (result.status === 'success' && result.type === 'get') {
                                this.username = result.userId || '';
                                this.password = result.password || '';
                            }
                        } catch (e) {
                            console.error('Error parsing user data:', e);
                            this.callbackText = `获取出错: ${e.message}`;
                        }
                    },
                });
        },
        methods: {
            handleLogin() {
                // 获取用户名和密码
                console.log('用户名:', this.username);
                console.log('密码:', this.password);
                // 判空处理
                    if (!this.username || !this.password) {
                        uni.showToast({
                            title: '用户名和密码不能为空',
                            icon: 'none',
                            duration: 2000
                        });
                        return;
                    }

                saveUserAndPassword(this.username, this.password, {
                      complete: (res) => {
                         console.log("saveUserAndPassword callback:" + res);
                         try {
                             const result = typeof res === 'string' ? JSON.parse(res) : res;
                             this.callbackText = `保存结果: ${JSON.stringify(result)}`;
                         } catch (e) {
                             console.error('Error parsing save result:', e);
                             this.callbackText = `保存出错: ${e.message}`;
                         }
                      },
                });

                // 这里可以添加登录逻辑,比如调用API
                uni.showToast({
                    title: `登录中: ${this.username}`,
                    icon: 'loading'
                });

                // 模拟登录请求
                setTimeout(() => {
                    uni.showToast({
                        title: '登录成功',
                        icon: 'success'
                    });
                    // 实际开发中可以在这里跳转到首页
                }, 1500);
            }
        }
    }
</script>

<style>
    .content {
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
    }

    .logo {
        height: 200rpx;
        width: 200rpx;
        margin-top: 200rpx;
        margin-left: auto;
        margin-right: auto;
        margin-bottom: 50rpx;
    }

    .text-area {
        display: flex;
        justify-content: center;
        margin-bottom: 50rpx;
    }

    .title {
        font-size: 36rpx;
        color: #8f8f94;
    }

    /* 输入框组样式 */
    .input-group {
        width: 80%;
        margin-bottom: 30rpx;
        display: flex;
        align-items: center;
    }

    .input-label {
        width: 150rpx;
        font-size: 30rpx;
        color: #333;
    }

    .input {
        flex: 1;
        height: 80rpx;
        padding: 0 20rpx;
        border: 1rpx solid #ddd;
        border-radius: 8rpx;
        font-size: 28rpx;
    }

    /* 登录按钮样式 */
    .login-btn {
        width: 80%;
        height: 90rpx;
        line-height: 90rpx;
        margin-top: 50rpx;
        background-color: #007AFF;
        color: white;
        font-size: 32rpx;
        border-radius: 45rpx;
    }

    .login-btn:active {
        background-color: #0062CC;
    }
</style>

隐私、权限声明

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

<uses-permission android:name="android.permission.USE_CREDENTIALS" /> <uses-permission android:name="android.permission.USE_BIOMETRIC" />

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

不采集数据,不发送服务器,系统本地存储

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

没有广告

暂无用户评论。