介绍

文件权限检查由NameNode执行,而不是DataNode执行。 默认情况下,任何客户端都可以访问只有其块ID的任何块。 为了解决这个问题,Hadoop引入了块访问令牌的概念。 块访问令牌由NameNode生成,并在DataNode端进行合法性验证。块访问令牌作为Hadoop数据传输协议的一部分或通过HTTP查询参数来呈现。一个典型的应用场景如下:一个客户端向NameNode发送文件读请求,NameNode验证该用户具有文件读权限后,将文件对应的所有数据块的ID、位置以及数据块访问令牌发送给客户端;当客户端需要读取某个数据块时,将数据块ID和数据块访问令牌发送给对应的DataNode。由于NameNode已经通过心跳将密钥发送给各个DataNode,因此DataNode可以对数据块进行安全验证,而只有通过安全验证的访问请求才可以获取数据块。

Block Token产生和验证的过程如下:

(1)Namenode经过对客户的身份验证和访问权限验证之后,返回块位置以及块访问令牌。

(2)客户端给Datanode发送块ID以及块访问令牌请求数据。

(3)Datanode经过验证块访问令牌之后返回给客户端请求的数据。

源码分析

用户使用Block Token访问数据的流程图如下:

Block Token的产生

由代码追踪可知Block Token是调用BlockPoolTokenSecretManager类产生的,但实际产生Block Token的操作是由BlockTokenSecretManager类执行的,该类与BlockPoolTokenSecretManager类的关系如下:

BlockPoolTokenSecretManager包含BlockTokenSecretManager,并且每一个blockPool对应一个BlockTokenSecretManager

  实际用map存储对应关系:

1 private final Map<String, BlockTokenSecretManager> map =
2     new HashMap<String, BlockTokenSecretManager>();

所以先调用BlockPoolTokenSecretManager类的方法获取BlockPoolId找到对应的BlockTokenSecretManager。

/*** See {@link BlockTokenSecretManager#generateToken(ExtendedBlock, EnumSet)}*/public Token<BlockTokenIdentifier> generateToken(ExtendedBlock b,EnumSet<AccessMode> of) throws IOException {return get(b.getBlockPoolId()).generateToken(b, of);}

进入实际产生BlockToken的方法:

 1  /** Generate an block token for current user */
 2   public Token<BlockTokenIdentifier> generateToken(ExtendedBlock block,
 3       EnumSet<AccessMode> modes) throws IOException {
 4     UserGroupInformation ugi = UserGroupInformation.getCurrentUser();
 5     String userID = (ugi == null ? null : ugi.getShortUserName());
 6     LOG.info("sqy test!"+"ugi="+ugi+",userID="+userID);
 7     return generateToken(userID, block, modes);
 8   }
 9
10   /** Generate a block token for a specified user */
11   public Token<BlockTokenIdentifier> generateToken(String userId,
12       ExtendedBlock block, EnumSet<AccessMode> modes) throws IOException {
13     BlockTokenIdentifier id = new BlockTokenIdentifier(userId, block
14         .getBlockPoolId(), block.getBlockId(), modes);
15     return new Token<BlockTokenIdentifier>(id, this);
16   }

经过Kerberos和权限检查之后,Namenode就需要返回给用户块信息了。下面只讲主要的实现方法,调用BlockManager#createLocatedBlock(),该方法主要做了两件事:创建LocatedBlock和产生BlockToken。

(1)进入BlockManager类

 1  private LocatedBlock createLocatedBlock(final BlockInfoContiguous blk, final long pos,
 2     final BlockTokenSecretManager.AccessMode mode) throws IOException {
 3     //获取BlockID、BlockPoolID、userID、位置pos
 4     final LocatedBlock lb = createLocatedBlock(blk, pos);
 5     if (mode != null) {
 6       //设置块令牌
 7       setBlockToken(lb, mode);
 8     }
 9     return lb;
10   }

由于我们这里主要讲块访问令牌的建立使用过程,创建LocatedBlock获取块信息这部分就不展开讲了。mode=AccessMode.READ,进入到setBlockToken方法中。

 1  public void setBlockToken(final LocatedBlock b,
 2       final BlockTokenSecretManager.AccessMode mode) throws IOException {
 3     // 如果开启BlockToken认证功能,这里是在hdfs-site.xml文件中配置的。
 4     if (isBlockTokenEnabled()) {
 5       // Use cached UGI if serving RPC calls.
 6       b.setBlockToken(blockTokenSecretManager.generateToken(
 7           NameNode.getRemoteUser().getShortUserName(),
 8           b.getBlock(), EnumSet.of(mode)));
 9     }
10   }

(2)进入BlockTokenSecretManager类

在BlockManager类中调用generateToken方法创建令牌之前,会先创建BlockTokenSecretManager类的实例对象blockTokenSecretManager,设置块访问密钥更新间隔时间、块访问令牌的生命周期、加密算法以及生成了密钥。

/** Generate a block token for a specified user */public Token<BlockTokenIdentifier> generateToken(String userId,ExtendedBlock block, EnumSet<AccessMode> modes) throws IOException {//生成TokenIDBlockTokenIdentifier id = new BlockTokenIdentifier(userId, block.getBlockPoolId(), block.getBlockId(), modes);//返回块访问令牌return new Token<BlockTokenIdentifier>(id, this);}

产生返回的块令牌信息的实现:

 1  /**
 2    * Construct a token given a token identifier and a secret manager for the
 3    * type of the token identifier.
 4    * @param id the token identifier
 5    * @param mgr the secret manager
 6    */
 7   public Token(T id, SecretManager<T> mgr) {
 8     password = mgr.createPassword(id); // 设置令牌过期时间和keyId
 9     identifier = id.getBytes();
10     kind = id.getKind();
11     service = new Text();
12   }

Block Token的验证

由之前的理论知识可知,namenode返回给用户块访问令牌,用户根据块信息和块访问令牌去datanode请求文件信息。因此块访问令牌的验证是在datanode发生的,根据代码追踪可知是在DataXceiver类,该类执行了各种block操作处理方法,而在readBlock、writeBlock中就包含了Block Token的验证操作。下面以readBlock方法为例来就行说明。

(1)进入DataXceiver类

 1 public void readBlock(final ExtendedBlock block,
 2       final Token<BlockTokenIdentifier> blockToken,
 3       final String clientName,
 4       final long blockOffset,
 5       final long length,
 6       final boolean sendChecksum,
 7       final CachingStrategy cachingStrategy) throws IOException {
 8     previousOpClientName = clientName;
 9     long read = 0;
10     updateCurrentThreadName("Sending block " + block);
11     OutputStream baseStream = getOutputStream();
12     DataOutputStream out = getBufferedOutputStream();
13     //进行Token READ访问模式的验证
14     checkAccess(out, true, block, blockToken,
15         Op.READ_BLOCK, BlockTokenSecretManager.AccessMode.READ);
16   ......

进入到checkAccess方法中。

 1 private void checkAccess(OutputStream out, final boolean reply,
 2       final ExtendedBlock blk,
 3       final Token<BlockTokenIdentifier> t,
 4       final Op op,
 5       final BlockTokenSecretManager.AccessMode mode) throws IOException {
 6     checkAndWaitForBP(blk);
 7     //判断是否启用BlockToken验证
 8     if (datanode.isBlockTokenEnabled) {
 9       if (LOG.isDebugEnabled()) {
10         LOG.debug("Checking block access token for block '" + blk.getBlockId()
11             + "' with mode '" + mode + "'");
12       }
13       try {
14         //进行BlockToken验证
15         datanode.blockPoolTokenSecretManager.checkAccess(t, null, blk, mode);
16       } catch(InvalidToken e) {
17       .....

(2)进入BlockPoolTokenSecretManager类

1  public Token<BlockTokenIdentifier> generateToken(ExtendedBlock b,
2       EnumSet<AccessMode> of) throws IOException {
3     return get(b.getBlockPoolId()).generateToken(b, of);
4   }

(3)进入BlockTokenSecretManager类

 1 public void checkAccess(Token<BlockTokenIdentifier> token, String userId,
 2       ExtendedBlock block, AccessMode mode) throws InvalidToken {
 3     BlockTokenIdentifier id = new BlockTokenIdentifier();
 4     try {
 5       //从输入流读取参数到tokenID,对其反序列化
 6       id.readFields(new DataInputStream(new ByteArrayInputStream(token
 7           .getIdentifier())));
 8     } catch (IOException e) {
 9       throw new InvalidToken(
10           "Unable to de-serialize block token identifier for user=" + userId
11               + ", block=" + block + ", access mode=" + mode);
12     }
13     //验证块令牌中的相关信息(userID、blockID、BlockPoolID、ExpiryDate、mode) 14     checkAccess(id, userId, block, mode); 15    .....

结论

以上就是Block Token产生、验证的整个过程。不过是否开启Block Token验证是需要在hdfs-site.xml文件中配置的,默认是false。

    dfs.block.access.token.enable

  

转载于:https://www.cnblogs.com/qiuyuesu/p/6724441.html

Block Token 原理分析相关推荐

  1. android 实例源码解释,Android Handler 原理分析及实例代码

    Android Handler 原理分析 Handler一个让无数android开发者头疼的东西,希望我今天这边文章能为您彻底根治这个问题 今天就为大家详细剖析下Handler的原理 Handler使 ...

  2. Select函数实现原理分析

    转载自 http://blog.chinaunix.net/uid-20643761-id-1594860.html select需要驱动程序的支持,驱动程序实现fops内的poll函数.select ...

  3. Redis数据持久化机制AOF原理分析一---转

    http://blog.csdn.net/acceptedxukai/article/details/18136903 http://blog.csdn.net/acceptedxukai/artic ...

  4. Java NIO使用及原理分析

    http://blog.csdn.net/wuxianglong/article/details/6604817 转载自:李会军•宁静致远 最近由于工作关系要做一些Java方面的开发,其中最重要的一块 ...

  5. Elasticsearch实现原理分析

    介绍 本文是分析Elasticsearch系列文章中的一篇,是一个译文.共有三个部分,每部分讲解部分Elasticsearch的实现原理.     在翻译的过程中,也需要查看对应部分的源码,来加深对实 ...

  6. airflow mysql_Airflow 使用及原理分析

    Airflow 入门及使用 什么是 Airflow?Airflow 是一个使用 Python 语言编写的 Data Pipeline 调度和监控工作流的平台. Airflow 是通过 DAG(Dire ...

  7. Android--Handler使用应运及消息机制处理原理分析

    最近开通了一个小微博,欢迎大家关注,每天分享一些上班路上看的小知识点 点击打开链接 一.Handler是什么 ? handler是android给我们提供的一套用来更新UI的一套机制,也是一套消息处理 ...

  8. 原理剖析(第 009 篇)ReentrantReadWriteLock工作原理分析

    2019独角兽企业重金招聘Python工程师标准>>> 原理剖析(第 009 篇)ReentrantReadWriteLock工作原理分析 一.大致介绍 1.在前面章节了解了AQS和 ...

  9. 编译原理语义分析代码_Pix2Pix原理分析与代码解读

    原理分析: 图像.视觉中很多问题都涉及到将一副图像转换为另一幅图像(Image-to-Image Translation Problem),这些问题通常都使用特定的方法来解决,不存在一个通用的方法.但 ...

最新文章

  1. 跳来跳去,到底去大公司还是小公司?
  2. .NET Compact Framework下的蓝牙开发
  3. CloudStack4.1.1升级CloudPlatForm4.2.0实践手册
  4. 南邮 AAencode
  5. 用启明云端支持ESP32的GUI做了一个测温HMI交互界面
  6. spark中local模式与cluster模式使用场景_Spark 知识点 ( 架构 RDD Task )
  7. Spring Boot——基于spring-boot-starter-mail发送邮件的 Service 服务类DEMO
  8. 结构设计模式 - 适配器设计模式
  9. python selenium 获取元素下的元素个数_Python + Selenium,分分钟搭建 Web 自动化框架!(送自动化测试书籍)...
  10. apk签名的重要性和方法
  11. Python 命令的参数
  12. mysql.net连接器_关于mysql-connector-net在C#中的用法
  13. systemctl的使用
  14. java ResourceBundle
  15. python实现屏幕截图_Python实现计算机屏幕任意区域截图
  16. Win11遇到无法删除的文件怎么办?Win11如何强制删除文件?
  17. 计算机复制操作的方法,怎么用键盘复制粘贴?电脑使用键盘复制粘贴的方法
  18. 链表---给定一个排序链表,删除所有重复的元素每个元素只留下一个
  19. linux自带的LED灯驱动实验
  20. 移动端上下滑动事件之--坑爹的touch.js

热门文章

  1. 整数行hdu 1244 Max Sum Plus Plus Plus(dp)
  2. c#_委托事件的理解
  3. 剑灵总显示服务器断开连接,求解一分钟“与服务器断开连接”问题
  4. 2021高考成绩一分段查询陕西省,2021年陕西高考一分一段表查询排名方法 成绩排名位次什么时候公布...
  5. during怎么念_during是什么意思_during的翻译_音标_读音_用法_例句_爱词霸在线词典...
  6. java按钮监听休眠_java-休眠监控解决方案
  7. fastjson 循环json字符串_FastJson拒绝服务漏洞分析
  8. pycharm安装numpy
  9. 冒泡排序汇总(整数,实数,字符,字符串)
  10. pytest测试实战 电子书_pytest实战APL测试框架