详解基于Android App 安全登录认证解决方案

近几年移动互联网的高速发展,智能手机的使用用户呈现爆炸性增长,手机终端上的App 种类繁多,大多数App 都需要与后台系统进行交互,交互的第一步需要进行登录认证,过于简单的认证方式可能被破解从而造成用户信息的泄露甚至威胁着用户的财产安全。为此基于Android 系统,对比现有几种常见的App 登录认证方式,并提出一种采用RSA 非对称加密和加入Token 时效机制的登录认证解决方案。在登录验证阶段采用RSA 非对称加密方式,App 端对服务器端返回的Token 信息加上时间戳,将处理后的Token 信息保存到本地,后面的每次请求都携带该Token 从而实现免登录的登录状态的保持。

1. 登录认证方式

1.1 Web登录认证方式

目前常见的Web认证的方式主要有三种:

(1)HTTP Basic Auth。 这种方式就是每次请求服务器时都携带用户名和密码,优点是使用非常简单,缺点也非常明显,因为每次都需要携带用户名和密码,很有可能造成密码被截获。

(2)OAuth。一种开放的授权标准,允许第三方应用访问用户在某一个服务商服务器上存储的私密数据,其处理流程先是第三方应用通过App Key和App secret换取OAuth_Token进行授权(此时颜色有可能需要输入用户名和密码),授权完成后服务商页面会跳转到第三方应用同时返回Access Token,此后第三方应用就可以通过这个Access Token去服务商服务器中访问相应数据。

(3)Cookie Auth。Cookie认证机制就是浏览器在发起一次登录认证请求时,服务端验证通过后将会在产生一段Cookie信息并返回给浏览器,浏览器会将其保存到本地,以后的每次请求都会使用该    Cookie信息而不再进行登录验证。

1.2 App登录认证方式

由于App客户端无法处理Cookie信息,因此App登录认证无法使用Web认证方式中的Cookie认证方式,为了登录状态的保持,一般会模拟Cookie认证方式,即在App端发起登录认证请求后,得到服务端验证成功的确认之后,App端一般会保存一些状态信息在本地,后面每次请求都是携带该状态信息,根据状态信息的不同,可以分为如下两种:

(1) 保存用户信息表中的某个唯一标识。App端发起登录请求,服务器端在验证成功之后一般会将该登录用户的信息返回给客户端,客户端此时可以将用户信息中的某个唯一标识字段给保存下来,如使用SharedPreference进行保存,后面每次发起网络请求时,先判断本地是否存在该字段,如果不存在说明用户没有进行登录认证,跳转到登录页;如果存在,则直接将这个字段携带进请求信息中,从而实现登录保持状态。这种方式优点是比较简单,缺点就是如果保存的字段容易被别人截获,缺乏安全性。

(2)保存Token信息。App中非常常用的一种登录认证方式,他的实现过程是,由App端发起登录请求,服务器端在验证成功后生成一份Token信息保存到用户表中并设置一定的时效,同时将此Token返回给App端,App端将此Token保存到本地,以后的每次发起请求都是用该Token。与前面一种方式相比,避免了用户表中信息的泄露,相对更加安全。其流程图如下:

这种方式相对于第一种来说更加安全,但还是存在着明显的安全漏洞,需要进行优化。本文将以这种方案为基础,提出一种更加安全的基于Android平台的App登录解决方案。这里我们把现有的这种方案成为Token认证机制,本文提出的方案成为改进的Token认证机制。

2. 改进的Token认证机制详细设计

上述Token认证机制也是存在着一些明显的安全漏洞,本文提出的改进的Token认证机制就是基于对原来Token认证机制中安全漏洞的优化。对于登录认证机制,我们可以把它分为登录验证,状态保持和登出三个阶段,改进的Token认证机制主要是在登录验证和状态保持阶段进行优化。

2.1 登录验证优化

登录验证阶段是指App客户端向服务器端发起登录认证请求,并携带用户名和密码,服务器端收到请求后获取用户名和密码,并向数据库进行查询验证的阶段。由于这一阶段需要密码的传输,很多情况下可能都是明文或者简单的MD5加密后直接传输,一旦被黑客截获可能造成密码的泄露风险。因此这一阶段的优化就是加强密码加密功能,这里我们采用RSA非对称加密方式。

RSA是一种非对称加密,它是对称加密的一种加强版,使用对称加密的服务器端和客户端都使用同一种加密规则,因此在服务器端生成加密密钥之后需要传递给客户端,客户端也需要保存这个密钥,而传递密钥的过程和保存密钥在客户端后都有可能发生密钥的截获造成安全漏洞。而非对称加密方式会在服务器端生成两套密钥,生成的公钥是公开的并传给客户端,私钥保存在服务器端,客户端用公钥加密信息后传递到服务器端,服务器端再用私钥进行解密,因此只要私钥不泄露,通信就是安全的。

由上面的分析可以知道,要使用RSA加密方式先要让服务器生成公钥和私钥,并将公钥返回给客户端,因此,在图1 的登录验证阶段需要额外进行一次请求获取公钥(这个过程只需要一次,只要获得了公钥以后登录认证就不再需要该过程),其流程如图2所示。

根据上面的分析, 可以看到这一阶段最核心的是服务器端公钥和密钥的生成过程以及利用公钥加密和利用私钥解密的过程。其核心代码如下:

 /**
  * 初始化密钥
  *
  * @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);
  // 对数据加密
  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);

  // 对数据解密
  Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
  cipher.init(Cipher.DECRYPT_MODE, privateKey);

  return cipher.doFinal(data);
 }

2.2 状态保持优化

App 客户端在上一步登录验证阶段会得到服务器返回的Token 信息,并将该Token 保存到本地,以后的每次请求都直接携带该Token 而不是再次使用用户名和密码进行验证,这一阶段称为状态保持或登录保持阶段。前面介绍的Token 认证机制中的Token 会一直保存在App 客户端本地直至用户主动点击退出按钮,如果该Token 被截获,截获者同样可以使用该Token直接访问服务器中的敏感数据。针对Token 这一长时间保存的特点,我们的优化就是为这个Token 设置一个生效时效,具体来说就是在从服务器获得该Token后,在保存的时候在Token 后加上一个当前的时间戳,后面每次发起网络请求时,先取出该Token 后面的时间戳判断有没有超过生效时间,如果没有则将处理后的Token 放入到请求信息中,如果超时了,则重新进行登录认证过程。这种优化过程是以牺牲了一点用户体验为代价。其流程图如下:

本文章详细探讨了常见的Web 登录认证方式和App登录认证方式, 对现在比较常用的App 登录认证方式Token 认证机制的安全漏洞进行了讨论,在这个基础上提出了改进的Token 认证登录机制, 通过采用RSA 非对称加密优化登录验证阶段, 使用Token 时效机制优化状态保持阶段, 该优化方案在实际生产中得到了检验。同时,该方案还有进一步优化的空间,例如在优化状态保持阶段时采用的是Token 时效机制, 但这样牺牲了App 的使用体验, 因此在以后的研究中可以针对这一阶段做进一步的优化过程。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Android登录注册功能 数据库SQLite验证

    本文实例为大家分享了Android登录注册功能的具体代码,供大家参考,具体内容如下 展示效果 代码区 MainActivity(登录方法) public class MainActivity extends AppCompatActivity { @BindView(R.id.editText) EditText editText; @BindView(R.id.editText2) EditText editText2; @BindView(R.id.button) Button button

  • Android开发中通过手机号+短信验证码登录的实例代码

    首先,需要一个电话号码,目前很多账户都是将账户名设置成手机号,然后点击按钮获取手机验证码. 其次,你需要后台给你手机短信的验证接口,各个公司用的不一样,这个身为前端,不需要你来考虑,你只要让你后台给你写好接口,你直接调用就好了. activity_login.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.andr

  • Android注册登录实时自动获取短信验证码

    android应用的自动化测试必然会涉及到注册登录功能,而许多的注册登录或修改密码功能常常需要输入短信验证码,因此有必要能够自动获得下发的短信验证码. 主要就是实时获取短信信息. android上获取短信信息主要有BroadcastReceiver方式与数据库方式,要实时的话就BroadcastReceiver比较方便,分享一篇文章大家可以查看一下,点击. public class SMSReceiver extends BroadcastReceiver{ private String ver

  • Android开发之登录验证实例教程

    本文所述实例源自一个项目开发中的登录验证功能,具体的要求就是,在Android端输入用户名和密码,在服务器端验证MySQL数据库中是否有此用户,实现之前当然首要的是,如何使Android端的数据发送到服务器端,具体的实现方法如下: 服务器端:ManageServlet.java代码如下: public class ManageServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServle

  • Android手机注册登录时获取验证码之后倒计时功能(知识点总结)

    app注册界面经常会遇到一个场景:手机注册,点击获取验证码,验证码发送成功之后,开始倒计时 具体代码如下所示: private TimerTask timerTask; private Timer timer; private int time = 5000;//五秒 private int timess; /** * 开始倒计时 */ private void startTimer() { timess = time/1000; tvTime.setText(timess+"S");

  • Android本地验证码的简易实现方法(防止暴力登录)

    0.  前言  验证码无处不在,有人问我,你知道达芬奇密码下面是什么吗,对,答案就是达芬奇验证码. 验证码一个最主要的作用就是防止恶意暴力破解登录,防止不间断的登录尝试,有人说其实可以在服务器端对该终端进行登录间隔检测,如果间隔太短可以展示拒绝的姿态.但是还是本地验证码作用更加实在,可以减轻服务器端的压力.这篇将使用自定义View来实现一个如下效果的简易本地验证码.算是对自定义View知识的复习吧. 1.  布局结构  <RelativeLayout xmlns:android="http

  • 详解基于Android App 安全登录认证解决方案

    近几年移动互联网的高速发展,智能手机的使用用户呈现爆炸性增长,手机终端上的App 种类繁多,大多数App 都需要与后台系统进行交互,交互的第一步需要进行登录认证,过于简单的认证方式可能被破解从而造成用户信息的泄露甚至威胁着用户的财产安全.为此基于Android 系统,对比现有几种常见的App 登录认证方式,并提出一种采用RSA 非对称加密和加入Token 时效机制的登录认证解决方案.在登录验证阶段采用RSA 非对称加密方式,App 端对服务器端返回的Token 信息加上时间戳,将处理后的Toke

  • 详解基于Android的Appium+Python自动化脚本编写

    1.Appium Appium是一个开源测试自动化框架,可用于原生,混合和移动Web应用程序测试, 它使用WebDriver协议驱动iOS,Android和Windows应用程序. 通过Appium,我们可以模拟点击和屏幕的滑动,可以获取元素的id和classname,还可以根据操作生成相关的脚本代码. 下面开始Appium的配置. appPackage和APPActivity的获取 任意下载一个app 解压 但是解压出来的xml文件可能是乱码,所以我们需要反编译文件. 逆向AndroidMan

  • 详解Spring Security的formLogin登录认证模式

    一.formLogin的应用场景 在本专栏之前的文章中,已经给大家介绍过Spring Security的HttpBasic模式,该模式比较简单,只是进行了通过携带Http的Header进行简单的登录验证,而且没有定制的登录页面,所以使用场景比较窄. 对于一个完整的应用系统,与登录验证相关的页面都是高度定制化的,非常美观而且提供多种登录方式.这就需要Spring Security支持我们自己定制登录页面,也就是本文给大家介绍的formLogin模式登录认证模式. 准备工作 新建一个Spring B

  • Java 添加、删除、格式化Word中的图片步骤详解( 基于Spire.Cloud.SDK for Java )

    本文介绍使用Spire.Cloud.SDK for Java提供的ImagesApi接口来操作Word中的图片.具体可通过addImage()方法添加图片.deleteImage()方法删除图片.updateImageFormat()格式化Word中的图片以及getImageFormat()获取Word中的图片格式等.操作方法和代码示例可参考下文中的步骤. 步骤1:导入jar文件 创建Maven项目程序,通过maven仓库下载导入.以IDEA为例,新建Maven项目,在pom.xml文件中配置m

  • 详解Node.js使用token进行认证的简单示例

    本文只介绍简单的应用,关于json web token的具体介绍以及原理请参考阮一峰老师的JSON Web Token 入门教程. 使用的Node框架是koa2,前端发送ajax请求使用axios 首先创建工程目录: static中存放静态资源,views存放前端模板,server.js为后端代码. 安装必要的依赖项: "dependencies": { "@koa/router": "^8.0.8", "jsonwebtoken&qu

  • 详解Kotlin Android开发中的环境配置

    详解Kotlin Android开发中的环境配置 在Android Studio上面进行安装插件 在Settings ->Plugins ->Browse repositores.. ->kotlin 安装完成后重启Android Studio就生效了 如图所示: 在Android Studio中做Kotlin相关配置 (1)在根目录 的build.gradle中进行配置使用,代码如下: buildscript { ext.kotlin_version = '1.1.2-4' repos

  • 详解Xamarin.Android 利用Fragment实现底部菜单

    本篇文章主要介绍了详解Xamarin.Android 利用Fragment实现底部菜单,分享给大家,具体如下: 效果图: 第一步:添加引用 引用 Crosslight.Xamarin.Android.Support.v7.AppCompat 这个包. 第二步:绘制Main和Fragment界面 fg_home.axml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:androi

  • 详解基于django实现的webssh简单例子

    本文介绍了详解基于django实现的webssh简单例子,分享给大家,具体如下: 说明 新建一个 django 程序,本文为 chain. 以下仅为简单例子,实际应用 可根据自己平台情况 进行修改. 打开首页后,需要输入1,后台去登录主机,然后返回登录结果. 正常项目 可以post 主机和登录账户,进行权限判断,然后去后台读取账户密码,进行登录. djang后台 需要安装以下模块 安装后会有一个版本号报错,不影响 channels==2.0.2 channels-redis==2.1.0 amq

  • 详解基于JWT的springboot权限验证技术实现

    JWT简介 Json Web Token(JWT):JSON网络令牌,是为了在网络应用环境间传递声明而制定的一种基于JSON的开放标准((RFC 7519).JWT是一个轻便的安全跨平台传输格式,定义了一个紧凑的自包含的方式用于通信双方之间以 JSON 对象行使安全的传递信息.因为数字签名的存在,这些信息是可信的. 实现步骤: 环境spring boot 1.添加jwt依赖 <dependency> <groupId>com.auth0</groupId> <ar

  • 详解基于Facecognition+Opencv快速搭建人脸识别及跟踪应用

    人脸识别技术已经相当成熟,面对满大街的人脸识别应用,像单位门禁.刷脸打卡.App解锁.刷脸支付.口罩检测........ 作为一个图像处理的爱好者,怎能放过人脸识别这一环呢!调研开搞,发现了超实用的Facecognition!现在和大家分享下~~ Facecognition人脸识别原理大体可分为: 1.通过hog算子定位人脸,也可以用cnn模型,但本文没试过: 2.Dlib有专门的函数和模型,实现人脸68个特征点的定位.通过图像的几何变换(仿射.旋转.缩放),使各个特征点对齐(将眼睛.嘴等部位移

随机推荐