Guns框架学习记录-9-事务管理+JWT签名认证机制

14.事务管理

1.事务的四个特性:ACID

原子性(Atomicity):事务中的操作,要么全做成,要么都不做。事务是不可拆分的,事务必须以Commit/Rollback结束。
一致性(Consistency):单独运行的事务,必须保证保持数据库的一致状态,从一个一致状态迁移到另一个一致状态,与原子性相关。
隔离性(Isolation):多个并发事务之间不能相互干扰,并发不影响事务的执行。
持久性(Durability):一旦事务成功完成(Commit),它对数据库的更新应该是持久的。即使在写入磁盘之前,系统发生故障,在下次启动之后,也应保障数据更新的有效。

2.不考虑事务隔离性会产生的三种后果

1.脏读:在一个事务中,读取了另一个未提交事务中的数据
2.不可重复读:一个事务范围内多次查询,返回了不同数据值(由于在查询间隔被另一个事务修改了)
3.幻读:一个事务批量修改表中的所有数据,这时另一个事务往表里新增了一条记录,导致第一个事务发现修改完之后落了一条,就跟产生幻觉一样

3.事务隔离级别:隔离级别越高,执行效率越低。

隔离级别从上往下依次降低:
Serializable (串行化):可避免脏读、不可重复读、幻读的发生。
Repeatable read (可重复读):可避免脏读、不可重复读的发生(默认的隔离级别) 。
Read committed (读已提交):可避免脏读的发生。
Read uncommitted (读未提交):最低级别,任何情况都无法保证。

补充:大多数数据库默认的事务隔离级别是Read committed,比如Sql Server,Oracle。但是,Mysql的默认隔离级别是Repeatable read。

4.事务传播行为:当事务方法被另一个事务方法调用时,须指定事务应该如何传播。

事务的传播行为:
PROPAGATION_REQUIRED--表示当前方法必须运行在事务中。如果当前事务存在,方法将会在该事务中运行。否则,会启动一个新的事务
PROPAGATION_SUPPORTS--表示当前方法不需要事务,但是如果存在当前事务的话,那么该方法会在这个事务中运行,如果当前没有事务,就以非事务方式执行
PROPAGATION_MANDATORY--表示该方法必须在事务中运行,如果当前事务不存在,则会抛出一个异常
PROPAGATION_REQUIRES_NEW--表示当前方法必须运行在它自己的事务中。一个新的事务将被启动。如果存在当前事务,在该方法执行期间,当前事务会被挂起
PROPAGATION_NOT_SUPPORTED--表示该方法不应该运行在事务中。如果存在当前事务,在该方法运行期间,当前事务将被挂起
PROPAGATION_NEVER--表示当前方法不应该运行在事务上下文中。如果当前正有一个事务在运行,则会抛出异常
PROPAGATION_NESTED--一个事务内部嵌套事务的执行不会影响外部事务,但外部事务的执行要影响内部

5.参考博客:

关于上述理论讲解我已经在博客中进行总结了,详情见:

事务管理:https://blog.csdn.net/Nerver_77/article/details/79876040

Spring中的事务管理:https://blog.csdn.net/Nerver_77/article/details/79896351

Spring中事务管理的传播行为测试:https://blog.csdn.net/Nerver_77/article/details/81556968

15.JWT签名机制

这里只对JWT进行简单介绍,具体应用中的使用后续会进行补充。

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

Session认证:

http协议本身是一种无状态的协议,如果客户端向服务端提供了用户名和密码来进行用户认证,下一次请求时,用户还要再一次进行用户认证。
通过http协议并不能知道是哪个客户端发出的请求,所以为了让服务端能识别是哪个客户端发出的请求,我们只能在服务端存储一份用户登录的信息,这份登录信息会在响应时传递给浏览器,并保存为cookie,以便下次请求时发送给我们的服务端,这样服务端就能进行识别。

Session的问题:

1. 服务器开销较大,客户端的用户数据session都保存在内存中,当数据量加大时,服务器开销会增加。
2. 拓展性差,客户端认证记录将保存在服务端内存中,分布式搭建服务,限制负载均衡能力,影响拓展能力。
3. 容易受到CSRF攻击,session基于cookie进行认证,cookie被截获后,有较大风险受到跨站请求伪造的攻击。

JWT应用场景:

常用于身份认证,一旦用户完成了认证,在接下来的每个请求中包含JWT,可以用来验证用户身份以及对路由,服务和资源的访问权限进行验证。
由于它的开销非常小,可以轻松的在不同域名的系统中传递,所有目前在单点登录(SSO)中比较广泛的使用了该技术。
信息交换在通信的双方之间使用JWT对数据进行编码是一种非常安全的方式,由于它的信息是经过签名的,可以确保发送者发送的信息是没有经过伪造的。

JWT结构:
头部(header) + 载荷(payload) + 签证(signature) 以下内容来自:https://jwt.io/introduction/

1. header:声明类型 + 声明加密算法,类似以下格式的header。
    {
      'typ': 'JWT',
      'alg': 'HS256'
    }
    将其经过base64加密后构成了第一部分header:eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9
2. payload:标准中注册的声明(可选) + 公有声明 + 私有声明
    标准中注册的声明(可选) :
        iss: jwt签发者
        sub: jwt所面向的用户
        aud: 接收jwt的一方
        exp: jwt的过期时间,这个过期时间必须要大于签发时间
        nbf: 定义在什么时间之前,该jwt都是不可用的
        iat: jwt的签发时间
        jti: jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击
    公共的声明 :公共的声明可以添加任何的信息,一般添加用户的相关信息或其他业务需要的必要信息.但不建议添加敏感信息,因为该部分在客户端可解密。
    私有的声明 :私有声明是提供者和消费者所共同定义的声明,一般不建议存放敏感信息。
    {
      "sub": "1234567890",
      "name": "John Doe",
      "admin": true
    }
    将其经过base64加密后构成第二部分payload:eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9
3. signature:签证信息(header base64 + payload base64 + secret)
    这个部分需要base64加密后的header和base64加密后的payload使用.连接组成的字符串,
    然后通过header中声明的加密方式进行加盐secret组合加密,然后就构成了jwt的第三部分signature。
将header + payload + signature 用.分隔连接起来就构成了jwt token。
注意:secret是保存在服务器端的,jwt的签发生成也是在服务器端的,secret就是用来进行jwt的签发和jwt的验证。
所以,它就是你服务端的私钥,在任何场景都不应该暴露出去。若客户端获取secret, 那就意味着客户端是可以自我签发jwt。

应用:

在请求头中加入Authorization,并加上Bearer作为验证首部,jwt token连接在后面传输即可。
服务端解析的时候获取Authorization中的除去Bearer部分requestHeader.substring(7)获取jwt中的token进行校验即可。

基于token的鉴权认证机制流程:

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

8/10/2018 2:51:00 PM

猜你喜欢

转载自blog.csdn.net/Nerver_77/article/details/81564525