iOS网络请求安全认证(JWT,RSA)

在网络世界中,安全是一个很重要的问题,以往的HTTP请求已经不能承担这个安全任务,抓包工具一抓,你的所有网络请求全都曝光。当然,你可能会采用加密算法来加密数据,但是这仍然不够。

在移动端和服务器的通信过程中,有两种认证方式:token和session。

Session: 每个用户经过我们的应用认证之后,我们的应用都要在服务端做一次记录,以方便用户下次请求的鉴别,通常而言session都是保存在数据库和内存中,而随着认证用户的增多,服务端的开销会明显增大。

扩展性: 用户认证之后,服务端做认证记录,如果认证的记录被保存在内存中的话,这意味着用户下次请求还必须要请求在这台服务器上,这样才能拿到授权的资源,这样在分布式的应用上,相应的限制了负载均衡器的能力。这也意味着限制了应用的扩展能力。

__CSRF: __因为是基于cookie来进行用户识别的, cookie如果被截获,用户就会很容易受到跨站请求伪造的攻击。CSRF攻击是源于WEB的隐式身份验证机制!WEB的身份验证机制虽然可以保证一个请求是来自于某个用户的浏览器,但却无法保证该请求是用户批准发送的!

基于token的鉴权机制
基于token的鉴权机制类似于http协议也是无状态的,它不需要在服务端去保留用户的认证信息或者会话信息。这就意味着基于token认证机制的应用不需要去考虑用户在哪一台服务器登录了,这就为应用的扩展提供了便利。

流程上是这样的:

  • 用户使用用户名密码来请求服务器
  • 服务器进行验证用户的信息
  • 服务器通过验证发送给用户一个token
  • 客户端存储token,并在每次请求时附送上这个token值
  • 服务端验证token值,并返回数据

这个token必须要在每次请求时传递给服务端,它应该保存在请求头里, 另外,服务端要支持CORS(跨来源资源共享)策略,一般我们在服务端这么做就可以了Access-Control-Allow-Origin: *

那么我们现在回到JWT的主题上。

JWT是啥?

Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该token被设计为紧凑且安全的,特别适用于分布式站点的单点登录(SSO)场景。JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密。

JWT长什么样?

JWT是由三段信息构成的,将这三段信息文本用.链接一起就构成了Jwt字符串。就像这样:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHQiOjE0ODg1NTM3OTk5NzIsImlwIjoiMTkyLjE2OC4xMDIuMTk1IiwidGVsIjoiMTMxMjM0NTY3ODkiLCJ0eXBlIjoiMiIsImRldmljZSI6ImVjMGEwOWZhOWRiOTNjNDQ1Mzk1YzcyNmI2OTUyM2YzIiwiaWF0IjoxNDg4NTI0OTk5OTcyfQ.9rl2XwKIMnVCVVKv9GvhTify7P2xhxIITfaSX4tm_78

 

JWT的构成

第一部分我们称它为头部(header),第二部分我们称其为载荷(payload, 类似于飞机上承载的物品),第三部分是签证(signature).

Header

JWT的头部承载两部分信息:

声明类型,这里是JWT
声明加密的算法 通常直接使用 HMAC SHA256
完整的头部就像下面这样的JSON:

{'typ': 'JWT','alg': 'HS256'
}

 

然后将头部进行base64加密(该加密是可以对称解密的),构成了第一部分.

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.

Playload

Token的第二部分是负载,它包含了claim, Claim是一些实体(通常指的用户)的状态和额外的元数据,有三种类型的claim: reserved , public 和 private .

  • Reserved claims: 这些claim是JWT预先定义的,在JWT中并不会强制使用它们,而是推荐使用,常用的有 iss(签发者) , exp(过期时间戳) , sub(面向的用户) , aud(接收方) , iat(签发时间) 。

  • Public claims:根据需要定义自己的字段,注意应该避免冲突

  • Private claims:这些是自定义的字段,可以用来在双方之间交换信息

负载使用的例子:

{"sub": "1234567890","name": "John Doe","admin": true
}

上述的负载需要经过 Base64Url编码后作为JWT结构的第二部分。

Signature

创建签名需要使用编码后的header和payload以及一个秘钥,使用header中指定签名算法进行签名。例如如果希望使用HMAC SHA256算法,那么签名应该使用下列方式创建:

HMACSHA256(base64UrlEncode(header) + "." +base64UrlEncode(payload),secret)  

签名用于验证消息的发送者以及消息是没有经过篡改的。

完整的JWT

JWT格式的输出是以 . 分隔的三段Base64编码,与SAML等基于XML的标准相比,JWT在HTTP和HTML环境中更容易传递。

下列的JWT展示了一个完整的JWT格式,它拼接了之前的Header, Payload以及秘钥签名:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.
eyJleHQiOjE0ODg1NTM3OTk5NzIsImlwIjoiMTkyLjE2OC4xMDIuMTk1IiwidGVsIjoiMTMxMjM0NTY3ODkiLCJ0eXBlIjoiMiIsImRldmljZSI6ImVjMGEwOWZhOWRiOTNjNDQ1Mzk1YzcyNmI2OTUyM2YzIiwiaWF0IjoxNDg4NTI0OTk5OTcyfQ.
9rl2XwKIMnVCVVKv9GvhTify7P2xhxIITfaSX4tm_78

如何应用

[AFHTTPSessionManager manager].requestSerializer setValue:JWTToken forHTTPHeaderField:@"token"];
在这次demo中我用的是AFN3.0,Xcoede8。AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];manager.responseSerializer = [AFHTTPResponseSerializer serializer];//服务器返回的是字符串NSMutableDictionary *para = [[NSMutableDictionary alloc] init];[para setValue:userPhoneNumber forKey:@"ac_id"];//用户手机号[para setValue:dToken forKey:@"token"];//UUID    
    NSURLSessionDataTask *task =  [self httpRequestWithMethod:@"POST" pathUrl:USER_GET_NEW_SESSION_ID_URL parameters:para success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {NSString *resonseString = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];//服务器给我们的是一个二进制流字符串,先将其转化成NSString
        NSString *decodeStr = [RSACode decryptString:resonseString publicKey:PUBLICKEY];//服务器给我的数据经过了RSA加密,这里用公钥进行解密NSDictionary *dicObject = [RSACode dictionaryWithJsonString:decodeStr];//解密后得到的是一个字符串,将其转换成字典NSMutableArray *resultJson = [dicObject objectForKey:@"result"];[[NSUserDefaults standardUserDefaults] setValue:[[resultJson firstObject]objectForKey:@"jwtToken"] forKey:RME_DEVICE_JWT];//通过NSUserDefaults将token进行永久化存储[self.requestSerializer setValue:[[resultJson firstObject]objectForKey:@"jwtToken"] forHTTPHeaderField:@"token"];//将token放到请求头      
  } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {}];

上面讲完了JWT,接下来就是RSA加密。

RSA算法是目前最流行的公钥密码算法,它使用长度可以变化的密钥。RSA是第一个既能用于数据加密也能用于数字签名的算法。 RSA算法的原理如下: 1.随机选择两个大质数pqp不等于q,计算N=pq; 2.选择一个大于1小于N的自然数ee必须与(p-1)×(q-1)互素。 3.用公式计算出d:d×e = 1 (mod (p-1)×(q-1)) 。 4.销毁pq。 最终得到的Ne就是“公钥”,d就是“私钥”,发送方使用N去加密数据,接收方只有使用d才能解开数据内容。
RSA的安全性依赖于大数分解,小于1024位的N已经被证明是不安全的,而且由于RSA算法进行的都是大数计算,使得RSA最快的情况也比DES慢上好几倍,这也是RSA最大的缺陷,因此它通常只能用于加密少量数据或者加密密钥。需要注意的是,RSA算法的安全性只是一种计算安全性,绝不是无条件的安全性,这是由它的理论基础决定的。因此,在实现RSA算法的过程中,每一步都应尽量从安全性方面考虑。

首先通过Mac终端生成公钥和私钥。

RSA公钥私钥.png

红线部分是需要输入的指令,生成的文件在当前目录下。

openssl
genrsa -out rsa_private_key.pem 1024
pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM -nocrypt
rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem

生成了公钥和私钥之后,我们APP端只要持有公钥即可,私钥放于服务端。这样在和服务器进行通信的时候,敏感信息服务器可以用私钥将其加密,即使他人拿到数据也没有用。而我们传给服务器的数据,也可以通过公钥去加密,由于公钥加密的数据只有对应的私钥才能解开,而私钥只有服务器才持有,这样就保证了只有服务器才能解开加密。这样就会使我们和服务器的通信更加安全可靠。


 SessionToken
状态存储位置服务器存储所有的Session状态信息每个客户端存储自己的token状态
扩展性即使是分布式的布局方式,也需要到存储当前Session的服务器获取数据任意一台服务器均可解析Token
分享无法分享和授权给其他应用可以很方便的分享和授权给其他应用,而且很安全,无法伪造
依赖性通常需要借助Cookie来实现没有依赖,加密方式安全就安全


链接:http://www.jianshu.com/p/08b85f749c86

转载于:https://www.cnblogs.com/weiming4219/p/8026225.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/281640.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

微信小程序黑客马拉松即将开始,来做最酷的 Mini Program Creators!

微信小程序黑客马拉松正式启动 近日,小程序斩获一项世界级殊荣——作为一项全新的技术和应用创新,小程序首次获选世界互联网领先科技成果。目前小程序应用数量已超过 100 万,覆盖了 200 多个细分行业,日活用户达到 2 亿。 微信小程…

oracle 文件写 n r,[oracle]log_archive_dest_n与DB_RECOVERY_FILE_DEST

DB_RECOVERY_FILE_DEST参数是默认的flashrecovery area的路径,里面存放有归档日志、闪回日志以及rman的备份文件等文件。LOG_ARCHIVE_DEST_n参数是存放归档日志的路径,n表示1~10的一个整数,由于归档日志在recovery的时候担当了重要的角色&…

记一次 .NET 某娱乐聊天流平台 CPU 爆高分析

一:背景 1.讲故事前段时间有位朋友加微信,说他的程序直接 CPU100%,每次只能手工介入重启,让我帮忙看下到底怎么回事,哈哈,这种CPU打满的事故,程序员压力会非常大, 我让朋友在 CPU 高的时候抓 2 …

linux下mariadb大小写敏感

2019独角兽企业重金招聘Python工程师标准>>> Linux下安装好mariadb后,在使用时会发现mariadb对大小写敏感,这对开发带来一定的不利,这时只要在配置文件中配置一下,取消大小写敏感即可: sudo vi /etc/MySQL/…

评论列表显示及排序,个人中心显示

1.显示所有评论{% for foo in ques.comments %} 2.所有评论排序uquestion db.relationship(Question, backrefdb.backref(comments, order_bycreat_time.desc)) 3.显示评论条数{{ ques.comments|length }} 1题代码如下&#xff1a; <h3>评论区:({{ ques.comments|length…

软件工程现行国标汇集

GB/T 8566-2007 《信息技术 软件生存周期过程》GB/T 8567-2006 《计算机软件文档编制规范》 GB/T 9385-2008《计算机软件需求规格说明规范》GB/T 9386-2008 《计算机软件测试文档编制规范》 GB/T 11457-2006《信息技术 软件工程术语》GB/T 14394-2008《计算机软件可靠性和可维护…

oracle listagg方法,Oracle实现字符串拼接和分离功能的方法(LISTAGG函数),oraclelistagg...

Oracle实现字符串拼接和分离功能的方法(LISTAGG函数)&#xff0c;oraclelistagg字符串拼接(String Aggregation Techniques)是数据处理时经常需要用到一个技术&#xff0c;比如需要按时间顺序拼装一个快递的运输记录&#xff0c;或者将流程中各个环节的处理人拼装为一个字符串。…

他俩都曾是技术大牛,创业这些年来有怎样的苦与乐?

这是头哥侃码的第263篇原创国庆假期回来&#xff0c;「头哥唠 B 唠」的直播仍在继续。这次我邀请了我工作上的老板和朋友&#xff0c;一起聊了聊关于 “技术创业路上的苦与乐”。熟悉他们两位的都知道&#xff0c;可以说是技术出身&#xff0c;然后创业当老板的代表。大家都知道…

maven,gradle本地缓存位置

gradle: 配置系统环境变量GRADLE_USER_HOME即可&#xff0c;值为缓存位置。 maven: 修改settings文件&#xff1a;maven的home路径下的conf文件夹下的settings.xml 对于有些IDEA&#xff0c;还需要配置。但是不要再打开项目后的FILE-->settings配置&#xff0c;而是需要在选…

git和php的区别,Git与Github的有什么区别

Git是一款免费&#xff0c;开源的分布是版本&#xff0c;用于敏捷高效的处理任何或小或大的项目。分布式相对于集中式的最大区别在于开发者可以提到本地&#xff0c;每个开发者通过克隆&#xff0c;在本地磁盘内拷贝一个完整的GIt仓库。Git的功能特性&#xff1a;1.从服务器上克…

E20171214-sl

well-grounded  地基打的好 relevent adj. 有关的&#xff0c;中肯的; 相关联的proposal n. 建议; 提议; 求婚; 〈美〉投标;转载于:https://www.cnblogs.com/lancgg/p/8281675.html

客户端嵌套 Web 页面如何选择

客户端嵌套 Web 页面如何选择客户端嵌套 Web 页面如何选择作者&#xff1a;驚鏵在使用客户端嵌套WEB页面有一下几种方案&#xff1a;WebView2[1]Electron[2]NW.js[3]sciter[4]miniblink[5]现在国内众多桌面程序都是用了以下五种&#xff0c;因为它跨平台更为方便&#x1f447;。…

每天练习50个shell

1、统计日志每天IP访问量前十 awk {print $1} 1.log | sort -n | uniq -c | sort -n 解释&#xff1a;&#xff08;1&#xff09;awk 命令在分段方面比较有优势&#xff0c;这里的{print $1}将第一段打印出来&#xff0c;awk可以用-F指定分隔符&#xff0c;如果不指定分隔符&am…

【Tomcat】Tomcat配置与优化(内存、并发、管理)【自己配置】

一、JVM内存配置优化 主要通过以下的几个jvm参数来设置堆内存的&#xff1a; -Xmx512m 最大总堆内存&#xff0c;一般设置为物理内存的1/4 -Xms512m 初始总堆内存&#xff0c;一般将它设置的和最大堆内存一样大&#xff0c;这样就不需要根据当前堆使用情况而调整堆的大…

oracle 网关下载,oracle透明网关访问sqlserver2000

oracle透明网关访问sqlserver2000介绍oracle 10g透明网关访问sqlserver2000一、环境如下:ORACLE 10g 安装在:192.168.0.250 的window2003 server(版本&#xff1a;Oracle Database 10g Enterprise Edition Release 10.2.0.3.0 - 64bit Production) SqlServer 2000安装在:192.16…

C++和C#的指针小解

昨天和赵崇说了一下工作的事情&#xff0c;说起了性能问题就讨论起了数据结果和指针对性能的影响。曾经一直没有想到这方面的事情&#xff0c;这几天专门抽时间回想一下这方面的知识&#xff0c;然后一点一点的总结一下&#xff0c;看看数据结构和指针在咱们代码中是怎样实现效…

使用RoleBasedAuthorization实现基于用户角色的访问权限控制

本文将介绍如何通过 Sang.AspNetCore.RoleBasedAuthorization[1] 库实现 RBAC 权限管理。使用介绍Step 1添加库 Sang.AspNetCore.RoleBasedAuthorizationInstall-Package Sang.AspNetCore.RoleBasedAuthorizationStep 2在 Program.cs 中添加builder.Services.AddSangRoleBasedA…

【2018-11-15】中证1000指数的估值详情

中证1000指数选取中证500和沪深300指数样本股以外的&#xff0c;流动性好的1000只股票组成&#xff0c;与沪深300 和中证500 等形成互补。 中证1000的个股大多数是由市场上流通市值排名在 800 到 1800 名之间的个股组成&#xff0c;是一个适用范围较广的小盘指数。 中证1000的…

[Leetcode Week15]Populating Next Right Pointers in Each Node

Populating Next Right Pointers in Each Node 题解 原创文章&#xff0c;拒绝转载 题目来源&#xff1a;https://leetcode.com/problems/populating-next-right-pointers-in-each-node/description/ Description Given a binary tree struct TreeLinkNode {TreeLinkNode *left…

php 数组 1 开始,php数组使用1

1、array_values($arr) 将数组转换成索引数组$arr1 [id>10,name>杨过,sex>male,salary>8900];echo .var_export(array_values($arr1),true).;2、array_column($arr,$col,$boll); 获取多维数组的列表组成的数组。$arr2 [];$arr2 [[id>10,name>杨过,sex>…