最近公司要求调研一键登录业务,如下图所示 。
本文将对比传统登录方式和一键登录,并简单介绍极光认证服务的集成。
传统登录方式
移动互联网发展到现在,账号登录 几乎成为了所有应用的标配功能。说到登录方式,无外乎账号密码登录和验证码登录。可是这两种方式,真的便捷安全吗?
账号密码登录
账号密码登录作为最原始的一种登录方式,也是我最讨厌的一种登录方式。
从便捷性上来说,用户得输入一个满足平台规则的用户名和密码,对于不同的平台,都制定了自己的规则。虽然通常都没什么问题,可总是有一些有损用户体验的地方。
- 我想输入中文,平台只给输入英文、字母、符号,或者反之
- 密码长度限定,最少 6 位,8 位 ......
- 密码输入限定,最常见的,要求包含大小写字母和数字
有的时候想个密码和闯关一样,特别要求包含大小写字母的,用户容易遗忘。早期的 iCloud 就这么设定的,我还真忘记过,无奈之下,只能去找回密码。
从安全性上来说,也是有弊端的。我想很多人都喜欢 Write Once, Run Everywhere ,一个密码通吃所有场景。这本身就是一件极不安全的事情,经常有坊间流传的某某数据库泄露可能就把你的密码给暴露了,一堆黑产在后面天天撞库。另一个方面,对于需要实名认证,或者限定用户认证信息的情况下,同一个用户可以无限制的注册账号。虽然可以通过技术手段来限制,但总归带来一定的不便利。
验证码登录
验证码登录一定程度上解决了上面的问题。用户不需要想一个独特的密码,直接输入手机验证码即可。同时,手机号码的实名信息也在一定程度上防止了用户无限制的注册。即使现在大部分应用仍然会保留账号密码登录接口,但毋庸置疑,验证码登录已经成为主流。
要说验证码登录还有什么缺点?唯一一点就是还不够便利。用户正确输入手机号码,接收验证码,用户体验不好的 ROM 还得自己去填验证码,再碰到网络抽疯,只能倒回去选择账号密码登录。
秉着用户至上的原则,可以让用户什么都不输入,就自动完成登录过程,那就再好不过了。这就是今天要说的一键登录。
一键登录
再回忆一下文章开头的 Gif,用户跳转到登录页面之后,无需输入任何内容,页面自动展示用户的手机号码,只需点击一键登录按钮即可,大大优化了用户体验,避免明文验证码的安全隐患,也没有密码方面的后顾之忧。
上面的登录流程图来自中国移动免密登录服务文档。依托运营商独有网关认证能力,用户一键授权即可获取本机号码完成登录/注册。同样对于中国联通,中国电信,都提供了类似服务。
看到这,是不是有点崩溃。为了一个免密登录,开发者竟然要去对接三家 SDK 。同样作为开发者的我,生平最讨厌的就是集成 SDK ,且不说文档质量,同一个业务,三个 SDK 给应用体积带来的增长也不能接受。
那么有没有一个现成的 SDK ,整合三家运营商的服务呢?
极光认证
我在几年前使用过极光社区的开源 IM 聊天 UI 组件 aurora-imui 。
Aurora IMUI 是个通用的即时通讯(IM)UI 库,不特定于任何 IM SDK。完整的聊天列表和消息输入组件,同时支持 ANDROID/IOS/RN 。我调研过很多 IM 的 UI 组件库,很少有像 IMUI 这么功能完整的,因此对极光社区留下了很好的印象。本次我也调研了极光社区的免密一键登录服务 —— 极光认证 。
准备工作
简单说一下开通流程。
- 注册 极光开发者账号 ,然后完成 开发者认证 。
- 选择要开通极光认证的应用程序,你也可以新建应用 。Android应用需要填写 应用包名 和 应用签名,并提供一个 RSA加密公钥,一键登录的手机号码将用 RSA 公钥加密后返回,开发者需使用对应私钥解密。RSA加密公钥位数是 1024位,密钥格式是 PKCS#8 。公钥对应的私钥,我们要妥善保管,避免泄露。
应用签名直接通过命令行获取。
keytool -list -v -keystore debug.keystore 复制代码
其中 debug.keystore
替换为你自己的签名文件。
RSA 公私钥可以通过 openssl
生成 。
openssl genrsa -out rsa_private.pem 1024 ```ssh 执行后会在当前目录生成名为 **ras_private.pem** 的私钥文件,然后根据私钥文件生成公钥文件。 ```java openssl rsa -in rsa_private.pem -pubout -out rsa_public_key.pem 复制代码
执行后会在当前目录生成名为 ras_public_key.pem 的公钥文件。
集成 SDK
推荐直接使用 jcenter 自动依赖。在 module 的 gradle 文件中添加如下依赖:
android { ...... defaultConfig { applicationId "com.xxx.xxx" // 您应用的包名. ...... ndk { //选择要添加的对应 cpu 类型的 .so 库。 abiFilters 'armeabi', 'armeabi-v7a', 'arm64-v8a' // 还可以添加 'x86', 'x86_64' } manifestPlaceholders = [ JPUSH_PKGNAME : applicationId, JPUSH_APPKEY : "你的 Appkey ", //Portal上注册的包名对应的 appKey. JPUSH_CHANNEL : "developer-default", //暂时填写默认值即可. ] ...... } ...... } dependencies { ...... compile 'cn.jiguang.sdk:jverification:2.3.4' // 此处以2.3.4 版本为例。 compile 'cn.jiguang.sdk:jcore:2.1.2' // 此处以JCore 2.1.2 版本为例。 ...... } 复制代码
Androidmanifest.xml 配置
在清单文件做如下配置。
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="您应用的包名" android:versionCode="100" android:versionName="1.0.0" > <uses-sdk android:minSdkVersion="9" android:targetSdkVersion="23" /> <!-- Required --> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" /> <uses-permission android:name="android.permission.WRITE_SETTINGS"/> <!-- Optional --> <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> <!-- 用于开启 debug 版本的应用在6.0 系统上 层叠窗口权限 --> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> <uses-permission android:name="android.permission.GET_TASKS" /> <uses-permission android:name="android.permission.VIBRATE" /> <uses-permission android:name="android.permission.WAKE_LOCK" /> <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:name="Your Application Name"> <!-- since 2.0.0 optional 可选项,使用一键登录功能必须添加 --> <!-- since 2.1.1 optional 可选项,通过screenOrientation设置授权页面横竖屏展示 --> <activity android:name="com.cmic.sso.sdk.activity.OAuthActivity" android:configChanges="orientation|keyboardHidden|screenSize" android:screenOrientation="portrait" android:launchMode="singleTop"> </activity> <!-- since 2.0.0 optional 可选项,使用一键登录功能必须添加 --> <!-- since 2.1.1 optional 可选项,通过screenOrientation设置授权页面横竖屏展示 --> <activity android:name="com.cmic.sso.sdk.activity.LoginAuthActivity" android:theme="@android:style/Theme.Holo.NoActionBar" android:configChanges="orientation|keyboardHidden|screenSize" android:screenOrientation="portrait" android:launchMode="singleTop"> </activity> <!-- since 2.0.0 optional 可选项,使用一键登录功能必须添加 --> <!-- since 2.1.1 optional 可选项,通过screenOrientation设置授权页面横竖屏展示 --> <activity android:name="cn.jiguang.verifysdk.CtLoginActivity" android:configChanges="orientation|keyboardHidden|screenSize" android:theme="@android:style/Theme.Holo.NoActionBar" android:screenOrientation="portrait" android:launchMode="singleTop"> </activity> <!-- Required --> <meta-data android:name="JPUSH_APPKEY" android:value="您应用的Appkey"/> <meta-data android:name="JPUSH_CHANNEL" android:value="developer-default"/> </application> </manifest> 复制代码
初始化
在 Application 中进行初始化。
JVerificationInterface.init(this, new RequestCallback<String>() { @Override public void onResult(int code, String result) { ...... } }) 复制代码
API 介绍
直接来看一键登录接口。
JVerificationInterface.loginAuth(final Context context, LoginSettings settings, final VerifyListener listener)
使用如下:
LoginSettings settings = new LoginSettings(); settings.setAutoFinish(true);//设置登录完成后是否自动关闭授权页 settings.setTimeout(15 * 1000);//设置超时时间,单位毫秒。 合法范围(0,30000],范围以外默认设置为10000 settings.setAuthPageEventListener(new AuthPageEventListener() { @Override public void onEvent(int cmd, String msg) { //do something... } });//设置授权页事件监听 JVerificationInterface.loginAuth(this, settings, new VerifyListener() { @Override public void onResult(int code, String content, String operator) { if (code == 6000){ Log.d(TAG, "code=" + code + ", token=" + content+" ,operator="+operator); }else{ Log.d(TAG, "code=" + code + ", message=" + content); } } }); 复制代码
6000
代表成功。
但是在实际开发中并不建议直接这样使用。一键登录需要依赖预取号结果,如果没有预取号,一键登录时会自动预取号。建议拉起授权页前,比如在开屏页或者业务入口页预先调用一键登录预取号接口进行预取号,可以提升授权页拉起速度,优化体验。
一键登录预取号接口如下所示。
JVerificationInterface.preLogin(Context context, int timeOut, PreLoginListener listener)
JVerificationInterface.preLogin(this, 5000,new PreLoginListener() { @Override public void onResult(final int code, final String content) { Log.d(TAG,"[" + code + "]message=" + content ); } }); 复制代码
返回的 code 为 7000
表示获取成功。注意,不要在预取号回调中重复调用预取号或者拉起授权页接口。
另外,在使用前记得判断当前网络环境是否支持。
JVerificationInterface.checkVerifyEnable(Context context)
boolean verifyEnable = JVerificationInterface.checkVerifyEnable(this); if(!verifyEnable){ Log.d(TAG,"当前网络环境不支持认证"); return; } 复制代码
经过我的实测,在仅开启 Wifi ,关闭数据流量的情况下,是无法进行一键登录的。此时应提示用户使用账号密码或者验证码登录。
混淆配置
-dontoptimizefankan -dontpreverify -dontwarn cn.jpush.** -keep class cn.jpush.** { *; } -dontwarn cn.jiguang.** -keep class cn.jiguang.** { *; } -dontwarn com.cmic.** -keep class com.cmic.** { *; } -dontwarn com.unicom.** -keep class com.unicom.** { *; } -dontwarn cn.com.chinatelecom.** -keep class cn.com.chinatelecom.** { *; } 复制代码
使用限制
- 支持国内三大运营商,中国移动、中国联通、中国电信。由于运营商限制等原因,对于 Web SDK,目前不支持中国联通
- 网络支持中国移动 2G/3G/4G、中国联通 3G/4G、中国电信 4G 。对于移动端用户来说必须开启数据流量
- 2G网络下认证失败率较高
- 支持双卡手机,但只能以打开数据网络的SIM卡进行认证
以上只是简单介绍了极光认证的使用,新开通用户都会赠送 1000 次体验。更多详细内容可以参见 官方文档 ,也可以直接下载 官方 Demo 。相信对于开发者来说,什么都不如一个 demo 来的实在。
总结
翻看 aurora-imui 时,发现极光还提供了各种服务的插件。
极光认证也提供了 Android,IOS,Web,React Native,Flutter,Cordova 等各种版本,满足开发者的各种需求。掘金上也看到了 Flutter 开发者的推荐, 本机号码一键登录!推荐 Flutter 极光认证插件 。
一键登录一定会是未来的趋势,如果你还没有了解过,那就快来体验吧 !