溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

詳解基于Android App 安全登錄認(rèn)證解決方案

發(fā)布時(shí)間:2020-09-28 05:54:43 來源:腳本之家 閱讀:170 作者:趙小賤1213 欄目:移動開發(fā)

近幾年移動互聯(lián)網(wǎng)的高速發(fā)展,智能手機(jī)的使用用戶呈現(xiàn)爆炸性增長,手機(jī)終端上的App 種類繁多,大多數(shù)App 都需要與后臺系統(tǒng)進(jìn)行交互,交互的第一步需要進(jìn)行登錄認(rèn)證,過于簡單的認(rèn)證方式可能被破解從而造成用戶信息的泄露甚至威脅著用戶的財(cái)產(chǎn)安全。為此基于Android 系統(tǒng),對比現(xiàn)有幾種常見的App 登錄認(rèn)證方式,并提出一種采用RSA 非對稱加密和加入Token 時(shí)效機(jī)制的登錄認(rèn)證解決方案。在登錄驗(yàn)證階段采用RSA 非對稱加密方式,App 端對服務(wù)器端返回的Token 信息加上時(shí)間戳,將處理后的Token 信息保存到本地,后面的每次請求都攜帶該Token 從而實(shí)現(xiàn)免登錄的登錄狀態(tài)的保持。

1. 登錄認(rèn)證方式

1.1 Web登錄認(rèn)證方式

目前常見的Web認(rèn)證的方式主要有三種:

(1)HTTP Basic Auth。 這種方式就是每次請求服務(wù)器時(shí)都攜帶用戶名和密碼,優(yōu)點(diǎn)是使用非常簡單,缺點(diǎn)也非常明顯,因?yàn)槊看味夹枰獢y帶用戶名和密碼,很有可能造成密碼被截獲。

(2)OAuth。一種開放的授權(quán)標(biāo)準(zhǔn),允許第三方應(yīng)用訪問用戶在某一個(gè)服務(wù)商服務(wù)器上存儲的私密數(shù)據(jù),其處理流程先是第三方應(yīng)用通過App Key和App secret換取OAuth_Token進(jìn)行授權(quán)(此時(shí)顏色有可能需要輸入用戶名和密碼),授權(quán)完成后服務(wù)商頁面會跳轉(zhuǎn)到第三方應(yīng)用同時(shí)返回Access Token,此后第三方應(yīng)用就可以通過這個(gè)Access Token去服務(wù)商服務(wù)器中訪問相應(yīng)數(shù)據(jù)。

(3)Cookie Auth。Cookie認(rèn)證機(jī)制就是瀏覽器在發(fā)起一次登錄認(rèn)證請求時(shí),服務(wù)端驗(yàn)證通過后將會在產(chǎn)生一段Cookie信息并返回給瀏覽器,瀏覽器會將其保存到本地,以后的每次請求都會使用該    Cookie信息而不再進(jìn)行登錄驗(yàn)證。

1.2 App登錄認(rèn)證方式

由于App客戶端無法處理Cookie信息,因此App登錄認(rèn)證無法使用Web認(rèn)證方式中的Cookie認(rèn)證方式,為了登錄狀態(tài)的保持,一般會模擬Cookie認(rèn)證方式,即在App端發(fā)起登錄認(rèn)證請求后,得到服務(wù)端驗(yàn)證成功的確認(rèn)之后,App端一般會保存一些狀態(tài)信息在本地,后面每次請求都是攜帶該狀態(tài)信息,根據(jù)狀態(tài)信息的不同,可以分為如下兩種:

(1) 保存用戶信息表中的某個(gè)唯一標(biāo)識。App端發(fā)起登錄請求,服務(wù)器端在驗(yàn)證成功之后一般會將該登錄用戶的信息返回給客戶端,客戶端此時(shí)可以將用戶信息中的某個(gè)唯一標(biāo)識字段給保存下來,如使用SharedPreference進(jìn)行保存,后面每次發(fā)起網(wǎng)絡(luò)請求時(shí),先判斷本地是否存在該字段,如果不存在說明用戶沒有進(jìn)行登錄認(rèn)證,跳轉(zhuǎn)到登錄頁;如果存在,則直接將這個(gè)字段攜帶進(jìn)請求信息中,從而實(shí)現(xiàn)登錄保持狀態(tài)。這種方式優(yōu)點(diǎn)是比較簡單,缺點(diǎn)就是如果保存的字段容易被別人截獲,缺乏安全性。

 (2)保存Token信息。App中非常常用的一種登錄認(rèn)證方式,他的實(shí)現(xiàn)過程是,由App端發(fā)起登錄請求,服務(wù)器端在驗(yàn)證成功后生成一份Token信息保存到用戶表中并設(shè)置一定的時(shí)效,同時(shí)將此Token返回給App端,App端將此Token保存到本地,以后的每次發(fā)起請求都是用該Token。與前面一種方式相比,避免了用戶表中信息的泄露,相對更加安全。其流程圖如下:

   詳解基于Android App 安全登錄認(rèn)證解決方案

這種方式相對于第一種來說更加安全,但還是存在著明顯的安全漏洞,需要進(jìn)行優(yōu)化。本文將以這種方案為基礎(chǔ),提出一種更加安全的基于Android平臺的App登錄解決方案。這里我們把現(xiàn)有的這種方案成為Token認(rèn)證機(jī)制,本文提出的方案成為改進(jìn)的Token認(rèn)證機(jī)制。

2. 改進(jìn)的Token認(rèn)證機(jī)制詳細(xì)設(shè)計(jì)

上述Token認(rèn)證機(jī)制也是存在著一些明顯的安全漏洞,本文提出的改進(jìn)的Token認(rèn)證機(jī)制就是基于對原來Token認(rèn)證機(jī)制中安全漏洞的優(yōu)化。對于登錄認(rèn)證機(jī)制,我們可以把它分為登錄驗(yàn)證,狀態(tài)保持和登出三個(gè)階段,改進(jìn)的Token認(rèn)證機(jī)制主要是在登錄驗(yàn)證和狀態(tài)保持階段進(jìn)行優(yōu)化。

2.1 登錄驗(yàn)證優(yōu)化

登錄驗(yàn)證階段是指App客戶端向服務(wù)器端發(fā)起登錄認(rèn)證請求,并攜帶用戶名和密碼,服務(wù)器端收到請求后獲取用戶名和密碼,并向數(shù)據(jù)庫進(jìn)行查詢驗(yàn)證的階段。由于這一階段需要密碼的傳輸,很多情況下可能都是明文或者簡單的MD5加密后直接傳輸,一旦被黑客截獲可能造成密碼的泄露風(fēng)險(xiǎn)。因此這一階段的優(yōu)化就是加強(qiáng)密碼加密功能,這里我們采用RSA非對稱加密方式。

RSA是一種非對稱加密,它是對稱加密的一種加強(qiáng)版,使用對稱加密的服務(wù)器端和客戶端都使用同一種加密規(guī)則,因此在服務(wù)器端生成加密密鑰之后需要傳遞給客戶端,客戶端也需要保存這個(gè)密鑰,而傳遞密鑰的過程和保存密鑰在客戶端后都有可能發(fā)生密鑰的截獲造成安全漏洞。而非對稱加密方式會在服務(wù)器端生成兩套密鑰,生成的公鑰是公開的并傳給客戶端,私鑰保存在服務(wù)器端,客戶端用公鑰加密信息后傳遞到服務(wù)器端,服務(wù)器端再用私鑰進(jìn)行解密,因此只要私鑰不泄露,通信就是安全的。

由上面的分析可以知道,要使用RSA加密方式先要讓服務(wù)器生成公鑰和私鑰,并將公鑰返回給客戶端,因此,在圖1 的登錄驗(yàn)證階段需要額外進(jìn)行一次請求獲取公鑰(這個(gè)過程只需要一次,只要獲得了公鑰以后登錄認(rèn)證就不再需要該過程),其流程如圖2所示。

詳解基于Android App 安全登錄認(rèn)證解決方案

根據(jù)上面的分析, 可以看到這一階段最核心的是服務(wù)器端公鑰和密鑰的生成過程以及利用公鑰加密和利用私鑰解密的過程。其核心代碼如下:

 /**
  * 初始化密鑰
  *
  * @return
  * @throws Exception
  */
 public static Map<String, Object> initKey() throws Exception {
  KeyPairGenerator keyPairGen = KeyPairGenerator
    .getInstance(KEY_ALGORITHM);
  keyPairGen.initialize(1024);
  KeyPair keyPair = keyPairGen.generateKeyPair();
  // 公鑰
  RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
  // 私鑰
  RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
  Map<String, Object> keyMap = new HashMap<String, Object>(2);
  keyMap.put(PUBLIC_KEY, publicKey);
  keyMap.put(PRIVATE_KEY, privateKey);
  return keyMap;
 }
 /**
  * 取得公鑰
  *
  * @param keyMap
  * @return
  * @throws Exception
  */
 public static String getPublicKey(Map<String, Object> keyMap)
   throws Exception {
  Key key = (Key) keyMap.get(PUBLIC_KEY);
  return encryptBASE64(key.getEncoded());
 }
/**
  * 取得私鑰
  *
  * @param keyMap
  * @return
  * @throws Exception
  */
 public static String getPrivateKey(Map<String, Object> keyMap)
   throws Exception {
  Key key = (Key) keyMap.get(PRIVATE_KEY);
 
  return encryptBASE64(key.getEncoded());
 }
/**
  * 加密<br>
  * 用公鑰加密
  *
  * @param data
  * @param key
  * @return
  * @throws Exception
  */
 public static byte[] encryptByPublicKey(byte[] data, String key)
   throws Exception {
  // 對公鑰解密
  byte[] keyBytes = decryptBASE64(key);
  // 取得公鑰
  X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
  KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
  Key publicKey = keyFactory.generatePublic(x509KeySpec);
  // 對數(shù)據(jù)加密
  Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
  cipher.init(Cipher.ENCRYPT_MODE, publicKey);
 
  return cipher.doFinal(data);
 }
/**
  * 解密<br>
  * 用私鑰解密
  *
  * @param data
  * @param key
  * @return
  * @throws Exception
  */
 public static byte[] decryptByPrivateKey(byte[] data, String key)
   throws Exception {
  // 對密鑰解密
  byte[] keyBytes = decryptBASE64(key);
 
  // 取得私鑰
  PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
  KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
  Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
 
  // 對數(shù)據(jù)解密
  Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
  cipher.init(Cipher.DECRYPT_MODE, privateKey);
 
  return cipher.doFinal(data);
 }

2.2 狀態(tài)保持優(yōu)化

App 客戶端在上一步登錄驗(yàn)證階段會得到服務(wù)器返回的Token 信息,并將該Token 保存到本地,以后的每次請求都直接攜帶該Token 而不是再次使用用戶名和密碼進(jìn)行驗(yàn)證,這一階段稱為狀態(tài)保持或登錄保持階段。前面介紹的Token 認(rèn)證機(jī)制中的Token 會一直保存在App 客戶端本地直至用戶主動點(diǎn)擊退出按鈕,如果該Token 被截獲,截獲者同樣可以使用該Token直接訪問服務(wù)器中的敏感數(shù)據(jù)。針對Token 這一長時(shí)間保存的特點(diǎn),我們的優(yōu)化就是為這個(gè)Token 設(shè)置一個(gè)生效時(shí)效,具體來說就是在從服務(wù)器獲得該Token后,在保存的時(shí)候在Token 后加上一個(gè)當(dāng)前的時(shí)間戳,后面每次發(fā)起網(wǎng)絡(luò)請求時(shí),先取出該Token 后面的時(shí)間戳判斷有沒有超過生效時(shí)間,如果沒有則將處理后的Token 放入到請求信息中,如果超時(shí)了,則重新進(jìn)行登錄認(rèn)證過程。這種優(yōu)化過程是以犧牲了一點(diǎn)用戶體驗(yàn)為代價(jià)。其流程圖如下:

詳解基于Android App 安全登錄認(rèn)證解決方案

本文章詳細(xì)探討了常見的Web 登錄認(rèn)證方式和App登錄認(rèn)證方式, 對現(xiàn)在比較常用的App 登錄認(rèn)證方式Token 認(rèn)證機(jī)制的安全漏洞進(jìn)行了討論,在這個(gè)基礎(chǔ)上提出了改進(jìn)的Token 認(rèn)證登錄機(jī)制, 通過采用RSA 非對稱加密優(yōu)化登錄驗(yàn)證階段, 使用Token 時(shí)效機(jī)制優(yōu)化狀態(tài)保持階段, 該優(yōu)化方案在實(shí)際生產(chǎn)中得到了檢驗(yàn)。同時(shí),該方案還有進(jìn)一步優(yōu)化的空間,例如在優(yōu)化狀態(tài)保持階段時(shí)采用的是Token 時(shí)效機(jī)制, 但這樣犧牲了App 的使用體驗(yàn), 因此在以后的研究中可以針對這一階段做進(jìn)一步的優(yōu)化過程。

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持億速云。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI