图片 5

认证鉴权那点事,类加载机制

目录

类加载机制

JVM把class文件加载的内存,并对数据进行校验、转换解析和初始化,最终形成JVM可以直接使用的Java类型的过程就是加载机制。

类从被加载到虚拟机内存中开始,到卸载出内存为止,它的生命周期包括了:加载(Loading)、验证(Verification)、准备(Preparation)、解析(Resolution)、初始化(Initialization)、使用(Using)、卸载(Unloading)七个阶段,其中验证、准备、解析三个部分统称链接。

图片 1

加载(装载)、验证、准备、初始化和卸载这五个阶段顺序是固定的,类的加载过程必须按照这种顺序开始,而解析阶段不一定;它在某些情况下可以在初始化之后再开始,这是为了运行时动态绑定特性。值得注意的是:这些阶段通常都是互相交叉的混合式进行的,通常会在一个阶段执行的过程中调用或激活另外一个阶段。

 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
 <head>
  <title>习题(向指定表格中写数据)</title>
  <meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
  <style type="text/css">

  </style>
  <script  type="text/javascript" src="jquery-1.7.1.min.js"></script>
  <script type="text/javascript">
        window.onload=function(){
        $('td').html('test');
        $('#btnOk').click(function(){
            //取得行数
            var hang=$('#hang').val() -1;
            //取得列数
            var lie=$('#lie').val() -1;
            //取得内容
            var content=$('#content').val();
            //向指定表格中写数据
            $('tr:eq('+hang+')> td:eq('+lie+')').html(content);
            });
        };
  </script>
 </head>
 <body>
    <input type='text' id='hang' />
    <hr />
    <input type='text' id='lie' />
    <hr />
    <input type='text' id='content' />
    <hr />
  <table border='1' width='500'>
        <tr>
            <td></td>
            <td></td>
            <td></td>
            <td></td>
            <td></td>
        </tr>
            <tr>
            <td></td>
            <td></td>
            <td></td>
            <td></td>
            <td></td>
        </tr>
            <tr>
            <td></td>
            <td></td>
            <td></td>
            <td></td>
            <td></td>
        </tr>
  </table>
  <input type="button" id='btnOk' value='确定'  />
 </body>
</html>
  • 一、Mongodb
    的权限管理
  • 二、鉴权方式
  • 三、内部鉴权
  • 四、数据库角色
  • 五、相关操作
  • 六、常见问题
  • 七、扩展阅读

加载:

加载阶段是“类加载机制”中的一个阶段,这个阶段通常也被称作“装载”,主要完成:

1.通过“类全名”来获取定义此类的二进制字节流

2.将字节流所代表的静态存储结构转换为方法区的运行时数据结构

3.在java堆中生成一个代表这个类的java.lang.Class对象,作为方法区这些数据的访问入口

虚拟机规范对于“通过“类全名”来获取定义此类的二进制字节流”并没有指明二进制流必须要从一个本地class文件中获取,准确地说是根本没有指明要从哪里获取及怎样获取。例如:

从Zip包中读取,这很常见,最终成为日后JAR、EAR、WAR格式的基础。

从网络获取,常见应用Applet。

运行时计算生成,这种场景使用的最多的就是动态代理技术,在java.lang.reflect.Proxy中,就是用ProxyGenerator.generateProxyClass来为特定接口生成$Prxoy的代理类的二进制字节流。

由其他格式文件生成,典型场景:JSP应用

从数据库中读取,这种场景相对少见,有些中间件服务器(如SAP
Netweaver)可以选择把程序安装到数据库中来完成程序代码在集群间的分发。

相对于类加载过程的其他阶段,加载阶段(准备地说,是加载阶段中获取类的二进制字节流的动作)是开发期可控性最强的阶段,因为加载阶段可以使用系统提供的类加载器(ClassLoader)来完成,也可以由用户自定义的类加载器完成,开发人员可以通过定义自己的类加载器去控制字节流的获取方式。

加载阶段完成后,虚拟机外部的二进制字节流就按照虚拟机所需的格式存储在方法区之中,方法区中的数据存储格式有虚拟机实现自行定义,虚拟机并未规定此区域的具体数据结构。然后在java堆中实例化一个java.lang.Class类的对象,这个对象作为程序访问方法区中的这些类型数据的外部接口。加载阶段与链接阶段的部分内容(如一部分字节码文件格式验证动作)是交叉进行的,加载阶段尚未完成,链接阶段可能已经开始,但这些夹在加载阶段之中进行的动作,仍然属于链接阶段的内容,这两个阶段的开始时间仍然保持着固定的先后顺序。

 

 

 

 

图片 2

一、Mongodb 的权限管理

认识权限管理,说明主要概念及关系

与大多数数据库一样,Mongodb同样提供了一套权限管理机制。
为了体验Mongodb
的权限管理,我们找一台已经安装好的Mongodb,可以参照这里搭建一个单节点的Mongodb。

直接打开mongo shell:

./bin/mongo --port=27017

尝试执行stats命令以查看appdb数据库的状态:

MongoDB Enterprise > use appdb
MongoDB Enterprise > db.stats()
{
    "ok" : 0,
    "errmsg" : "not authorized on nscl to execute command { dbstats: 1.0, scale: undefined }",
    "code" : 13
}

此时的提示正是说明你当前的操作没有获得许可,使用appdb预创建的用户进行鉴权:

> db.auth('appuser','yourpassword')
1
> db.stats()
{
    "db" : "appdb",
    "collections" : 0,
    "views" : 0,
    "objects" : 0,
    "avgObjSize" : 0,
    "dataSize" : 0,
    "storageSize" : 0,
    "numExtents" : 0,
    "indexes" : 0,
    "indexSize" : 0,
    "fileSize" : 0,
    "ok" : 1
}

可以发现,在通过验明身份之后,stats操作的鉴权获得了许可。


以上例子可能让你对数据库鉴权有了点浅显认识,那么接下来开始说点概念了,大致是叫基于角色的权限控制

图片 3

[图-角色权限控制]

先解释下图中的几个实体:

  • Resource,资源
    一个资源可以是一个数据库、集合、或者一个集群..往大了说,任何可能被操作的事物都可以被当做资源。
  • Action,动作
    动作是指对资源的一个执行行为,比如读取表、读取数据库,其中读取便是一个动作。
  • Privilege,权限
    权限指的是对某类或某一些资源执行某些动作的允许,与Permission的意义一致。
  • Role,角色
    系统中的角色,通常是代表了一种权力等级的象征,比如论坛中的管理员、版主、游客等等,就是角色;
    系统定义中,角色往往代表一组权限的集合。
  • User,用户
    可登录系统的实体,一个用户通常可被赋予多个角色。

噢,关于图的简单解释:
权限定义了对某些资源的某些操作,角色则可以拥有多个权限;
用户User可以被赋予多个角色,从而获得这些角色所拥有的权限以操作某些资源。

对于Mongodb来说,只要开启鉴权,所有的DB访问操作都需要通过权限检查。而大致的操作流程跟下图类似

图片 4

[图-mongo鉴权]

  1. Mongodb 的用户归属于某个数据库,用户需要在所属的数据库中进行鉴权;
  2. 一旦通过鉴权,当前的会话(连接)中所有操作将按照用户被赋予的角色权限执行检查。

验证:

验证是链接阶段的第一步,这一步主要的目的是确保class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身安全。

验证阶段主要包括四个检验过程:文件格式验证、元数据验证、字节码验证和符号引用验证。

1.文件格式验证 

 验证class文件格式规范,例如: class文件是否已魔术0xCAFEBABE开头
, 主、次版本号是否在当前虚拟机处理范围之内等

2.元数据验证

这个阶段是对字节码描述的信息进行语义分析,以保证起描述的信息符合java语言规范要求。验证点可能包括:这个类是否有父类(除了java.lang.Object之外,所有的类都应当有父类)、这个类是否继承了不允许被继承的类(被final修饰的)、如果这个类的父类是抽象类,是否实现了起父类或接口中要求实现的所有方法。

3.字节码验证

 进行数据流和控制流分析,这个阶段对类的方法体进行校验分析,这个阶段的任务是保证被校验类的方法在运行时不会做出危害虚拟机安全的行为。如:保证访法体中的类型转换有效,例如可以把一个子类对象赋值给父类数据类型,这是安全的,但不能把一个父类对象赋值给子类数据类型、保证跳转命令不会跳转到方法体以外的字节码命令上。

4.符号引用验证

符号引用中通过字符串描述的全限定名是否能找到对应的类、符号引用类中的类,字段和方法的访问性(private、protected、public、default)是否可被当前类访问。

 

二、鉴权方式

阐述Mongodb支持的几种鉴权方式
鉴权方式是指Mongodb如何识别接入用户,如何检查权限是否合法的一系列校验机制。

  • SCRAM-SHA-1
    SCRAM-SHA-1
    是默认的鉴权机制,定义于 IETF standard, RFC 5802
    是一种安全性较高的”挑战-应答”鉴权机制。关于”挑战-应答”可以参考维基百科

  • MongoDB Challenge and Response (MONGODB-CR)
    3.0 以前采用的机制,已经废弃

  • x.509 Certificate Authentication.
    基于证书的鉴权,采用该方式可建立 SSL/TLS 加密连接

  • LDAP proxy authentication
    基于LDAP 系统的鉴权,仅企业版支持

  • Kerberos authentication
    基于Kerberos
    的鉴权,仅企业版支持

SCRAM-SHA-1 是当前推荐使用的鉴权方式,既然如此,有必要上图继续解释:

图片 5

步骤解读

  1. 客户端发起一个SCRAM鉴权请求;
    鉴权参数中带上用户名、客户端随机字符串(防止重放攻击);
  2. 服务端发出一个挑战响应;
    服务侧先检查用户名,通过后生成一个salt因子、迭代数、合并字符串(包含客户端随机串和服务端随机串)
  3. 客户端响应一个proof(证明数据)和合并字符串;
    响应的
    proof数据根据服务所给的随机参数以及客户端密钥生成,是一个客户端签名与密钥异或计算后的结果;
  4. 服务端将存储的密钥结合随机参数,使用同样的算法生成签名并校验客户端
    proof数据;
    若校验通过,服务端采用类似方式发送自己的签名;
  5. 客户端校验服务端签名数据。

可以看到,SCRAM鉴权时也类似SSL/TLS
的握手过程,但相比之下简单许多,同时在性能方面也要具备优势;
然后我们看看安全性的部分:

  • 信息窃听,传输过程中全部采用动态签名,保证密码不会被传输;
  • 重放攻击,由于使用了随机数,每次生成的数据都不一样,可避免重复数据攻击;
  • 服务假冒,鉴权过程是双向的,即客户端会校验服务端身份,而服务端密钥也根据密码生成,中间人无法仿造;
  • 存储安全,密码在数据库中均没有明文存储,都通过不可逆的算法加密存储。

另外SCRAM-SHA-1 相比MONGODB-CR的优势还有:

A tunable work factor (iterationCount),
可灵活调整的安全系数
Per-user random salts rather than server-wide salts
每个用户有独立的随机系数
A cryptographically stronger hash function (SHA-1 rather than MD5),
更安全的hash函数
Authentication of the server to the client as well as the client to the
server.
支持双向认证


SCRAM-SHA-1的实现感兴趣?戳这里

准备:

准备阶段是正式为类变量分配内存并设置类变量初始值的阶段,这些内存都将在方法区中进行分配。这个阶段中有两个容易产生混淆的知识点,首先是这时候进行内存分配的仅包括类变量(static
修饰的变量),而不包括实例变量,实例变量将会在对象实例化时随着对象一起分配在java堆中。其次是这里所说的初始值“通常情况”下是数据类型的零值,假设一个类变量定义为:

public static int value  = 12;

那么变量value在准备阶段过后的初始值为0而不是12,因为这时候尚未开始执行任何java方法,而把value赋值为123的putstatic指令是程序被编译后,存放于类构造器<clinit>()方法之中,所以把value赋值为12的动作将在初始化阶段才会被执行。

上面所说的“通常情况”下初始值是零值,那相对于一些特殊的情况,如果类字段的字段属性表中存在ConstantValue属性,那在准备阶段变量value就会被初始化为ConstantValue属性所指定的值,建设上面类变量value定义为:

public static final int value = 123;

编译时javac将会为value生成ConstantValue属性,在准备阶段虚拟机就会根据ConstantValue的设置将value设置为123。

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注

标签:
网站地图xml地图