一鍵登陸完全簡化了用戶的操做流程,傳統要輸入手機號,而後點擊發送驗證碼,再點擊登陸,使用一鍵登陸就不用輸入手機號,直接用本機號碼登陸。php
這裏咱們使用極光的一鍵登陸【我沒收極光的錢哈】html
進入開發者蘋果平臺,申請開發者,一年須要688人民幣,而後申請bundle id,也叫應用id,具體根據提示來,不知道的就搜一下,而後把bundle ID複製下來,粘貼到xcode裏面。java
進入開發者平臺極光開發者平臺 申請帳號後建立應用 node
pubspec.yamlpython
dependencies:
jverify: 0.4.0
複製代碼
\android\app\build.gradle
android
defaultConfig下面添加以下代碼ios
ndk {
//選擇要添加的對應 cpu 類型的 .so 庫。
abiFilters 'armeabi', 'armeabi-v7a', 'x86', 'x86_64', 'mips', 'mips64', 'arm64-v8a'
}
manifestPlaceholders = [
JPUSH_PKGNAME : applicationId,
JPUSH_APPKEY : "e579470dae40f090f92c1f3f", // NOTE: JPush 上註冊的包名對應的 Appkey.
JPUSH_CHANNEL : "developer-default", //暫時填寫默認值便可.
]
複製代碼
無需配置git
import 'package:jverify/jverify.dart';
複製代碼
jverify.setDebugMode(true);
jverify.setup(
appKey: "申請的appkey",
channel: "devloper-default"
);
複製代碼
jverify.checkVerifyEnable().then((map){
bool result = map["result"];
if(result){
// 當前網絡環境支持認證
print('當前網絡環境支持認證');
}else{
// 當前網絡環境不支持認證
print('no~~當前網絡環境不支持認證');
}
});
複製代碼
JVUIConfig uiConfig = JVUIConfig();
jverify.setCustomAuthorizationView(false, uiConfig, landscapeConfig: uiConfig, widgets: widgetList);
/// 步驟 2: 添加 loginAuth 接口回調的監聽 (若是想經過 loginAuth 接口異步返回獲取接口數據,則忽略此步驟)
jverify.addLoginAuthCallBackListener((event){
print("經過添加監聽,獲取到 loginAuth 接口返回數據,code=${event.code},message = ${event.message},operator = ${event.operator}");
});
/// 步驟 3:開始調用一鍵登陸接口
jverify.loginAuth(true).then((map){
/// 步驟 4:獲取 loginAuth 接口異步返回數據(若是是經過添加 JVLoginAuthCallBackListener 監聽來獲取返回數據,則忽略此步驟)
// print("經過接口異步返回,獲取到 loginAuth 接口返回數據,code=$code,message = $content,operator = $operator");
print("經過接口異步返回,獲取到 loginAuth");
print(map);
});
複製代碼
(上面widgets,不是必傳參數)
在這裏,步驟三的數據纔是咱們須要的。github
jverify.getToken().then((map){
int _code = map["code"]; // 返回碼,2000表明獲取成功,其餘爲失敗,詳見錯誤碼描述
String _token = map["content"]; // 成功時爲token,可用於調用驗證手機號接口。token有效期爲1分鐘,超過期效須要從新獲取才能使用。失敗時爲失敗信息
String _operator = map["operator"]; // 成功時爲對應運營商,CM表明中國移動,CU表明中國聯通,CT表明中國電信。失敗時可能爲null
print("一鍵登陸 token code: ${_code} 運營商: ${_operator} _token: ${_token}");
if(_code == 2000){
// 請求後臺校驗
}else{
print('沒有手機卡,或者異常');
}
});
複製代碼
運行邏輯web
Jverify jverify = new Jverify();
// 是否調試模式
jverify.setDebugMode(true);
// ios使用的參數
jverify.setup(
appKey: "e57947打碼c1f3f",
channel: "devloper-default",
useIDFA: false
);
jverify.checkVerifyEnable().then((map){
bool result = map["result"];
if(result){
// 獲取loginAuth
loginAuth() // 這部分的代碼就是上面 獲取loginAuth 的代碼
}
})
複製代碼
會有一個界面彈出來
點擊登陸的按鈕,就會執行
jverify.loginAuth(true)
複製代碼
這個的異步回調,數據打印出來是以下所示
調用後會自動全屏,不須要引入view到flutter界面裏面渲染
有一個安卓手機跑起來後是這樣,出問題了,QAQ
信號太差了,會有失敗的可能性,請在4G+網絡下測試。
2010
緣由: takget sdk 版本>22須要動態申請權限。
不過,咱們先申請下靜態權限 在Android/app/src/main/AndroidManifest.xml
加以下代碼。(manifest裏面,application以前)
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
複製代碼
最好加下基本的權限
<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"/>
<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" />
複製代碼
而後修改Android/app/src/build.gradle
(這是不能保證徹底沒問題,最好是使用動態申請權限,不過測試的時候能夠這樣作)
targetSdkVersion 22
複製代碼
動態申請權限須要寫安卓和iOS兩個權限的代碼而後封裝給flutter使用,不過有現成的插件flutter動態申請權限插件
4033
I/flutter (11895): {code: 4033, message: appkey is not support login, operator: null}
複製代碼
沒有權限,有點奇怪,我什麼都明明申請了啊
這裏忽略了一個細節,在[應用設置] -> [認證設置] -> [一鍵登錄], 如圖,申請RSA加密,把公鑰複製上去,以前咱們講了支付寶支付,裏面也是同樣的邏輯。
而後提交審覈,經過以後再試。
ios跑的時候須要先在xcode輸入bundle ID,不過可能會出現以下錯誤
區別就是,第一個是校驗身份,目前不在咱們的使用範圍呢,也就是安全認證,好比作支付功能,教程目前使用的是是否是本人,就不能發生驗證碼,直接校驗當前使用的手機是否是登陸的帳號便可。
第二個就是咱們要用的 文檔上有一個curl
curl --insecure -X POST -v https://api.verification.jpush.cn/v1/web/loginTokenVerify -H "Content-Type: application/json" -u "7d431e42dfa6a6d693ac2d04:5e987ac6d2e04d95a9d8f0d1" -d '{"loginToken":"STsid0000001542695429579Ob28vB7b0cYTI9w0GGZrv8ujUu05qZvw","exID":"1234566"}'
複製代碼
看不懂curl沒關係,有一個文章能夠學習下。 curl教程
還有一個是吧,curl轉成語言的網址,直接生成代碼 curl轉各個語言代碼, 目前支持蠻多的,nodejs 、java、go、dart、php等
只有根據上面的獲取到了phone的密文才能解析,直接解析loginToken(就是flutter獲取到的token),是不行滴,這個要注意,我卡這裏很久了QAQ
根據點擊一鍵登錄獲取到的token,使用CURL執行,會返回9210(提示參數錯誤),能夠用語言代碼解析,我放個nodejs換取手機號密文成功的代碼
var request = require('request');
var headers = {
'Content-Type': 'application/json'
};
var loginToken = "tg9Z2evKEO/rD7naE1JnCYTbMLirZZgn45FrbAynCA0aukCbC8dzjuWAHI+d9ZjB4vs1ac25U8cJxkGbsBZGXssXpn7aR0vQ0M977qIbkDz/e9DsD+ueQFt/iWHV+ZR4YoDYf9+lMrePqLzTyOx4RiDakHQrLUlUC6G7kznJCSI="
var params = {
loginToken: loginToken,
exID:""
}
var dataString = JSON.stringify(params)
var options = {
url: 'https://api.verification.jpush.cn/v1/web/loginTokenVerify',
method: 'POST',
headers: headers,
body: dataString,
auth: {
'user': '這個是應用的key',
'pass': '這個是應用服務端的密碼'
}
};
function callback(error, response, body) {
if (!error && response.statusCode == 200) {
console.log(body);
}
}
request(options, callback);
複製代碼
import javax.crypto.Cipher;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;
public class RSADecrypt {
public static void main(String[] args) throws Exception {
String encrypted = "iZT省略20字veq0=";
String prikey = "MII省略20字Kqw==";
String publicKey = "省略20字";
System.out.println("解密 result 111");
String result = decrypt(encrypted, prikey);
System.out.println(result);
}
public static String decrypt(String cryptograph, String prikey) throws Exception {
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(prikey));
PrivateKey privateKey = KeyFactory.getInstance("RSA").generatePrivate(keySpec);
Cipher cipher=Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte [] b = Base64.getDecoder().decode(cryptograph);
return new String(cipher.doFinal(b));
}
}
複製代碼
親測能夠,若是報錯,應該是密文問題。
若有須要能夠下方評論找我要加密的方法,pkcs8 java加解密由皮皮鼠(oops)提供。
(若是用本身的解密方法,報錯,若是方法沒有問題,那麼就是少了一個步驟,解密傳入的密文須要base64解碼,代碼: Base64.getDecoder().decode
)
有一個很重要的一點,pkcs8適合java,其餘語言能夠用工具把pkcs8轉pkcs1,支付寶開放平臺有一個轉換的地方
python安裝pycryptodome
報錯了。
<?php
$prefix = '-----BEGIN RSA PRIVATE KEY-----';
$suffix = '-----END RSA PRIVATE KEY-----';
$result = '';
$encrypted = null;
$prikey = null;
$key = $prefix . "\n" . $prikey . "\n" . $suffix;
$r = openssl_private_decrypt(base64_decode($encrypted), $result, openssl_pkey_get_private($key));
echo $result . "\n";
複製代碼
const crypto = require('crypto')
var privateStr = `MIIXXXXXXXXXXXXXXKqw==`
var publicStr = `MxxxxXXXXXXXXXXXXXxxxQAB`
var 公鑰pem = `-----BEGIN PUBLIC KEY-----\n${publicStr.replace(/(.{64})/g, '$1\n')}\n-----END PUBLIC KEY-----`.toString('ascii')
var 私鑰pem = `-----BEGIN PRIVATE KEY-----\n${privateStr}\n-----END PRIVATE KEY-----`
var 一鍵登錄密文 = "";
//私鑰解密
const decodeData = crypto.privateDecrypt({key: 私鑰pem, padding: crypto.constants.RSA_PKCS1_PADDING}, Buffer.from(一鍵登錄密文, 'base64'));
console.log("手機號: ", decodeData.toString())
複製代碼
這裏有一個須要注意的地方
Buffer.from(密文, 'base64') 不等於 new Buffer(
new Buffer(密文.toString('base64'), 'base64').toString(),
'utf-8'
)
複製代碼
(若是密鑰公鑰沒有換行的話,請直接用上面的代碼,若是已經下載就是pem文件,那麼直接替換[私鑰/公鑰]pem)
nodejs這一塊我摸索了很久,若是有幫助,請點個贊,謝謝~~
github.com/jpush/jveri…
docs.jiguang.cn/jverificati…
github.com/jpush/jveri…
github.com/BaseflowIT/…