Block Token 原理分析
介绍
文件权限检查由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 原理分析相关推荐
- android 实例源码解释,Android Handler 原理分析及实例代码
Android Handler 原理分析 Handler一个让无数android开发者头疼的东西,希望我今天这边文章能为您彻底根治这个问题 今天就为大家详细剖析下Handler的原理 Handler使 ...
- Select函数实现原理分析
转载自 http://blog.chinaunix.net/uid-20643761-id-1594860.html select需要驱动程序的支持,驱动程序实现fops内的poll函数.select ...
- Redis数据持久化机制AOF原理分析一---转
http://blog.csdn.net/acceptedxukai/article/details/18136903 http://blog.csdn.net/acceptedxukai/artic ...
- Java NIO使用及原理分析
http://blog.csdn.net/wuxianglong/article/details/6604817 转载自:李会军•宁静致远 最近由于工作关系要做一些Java方面的开发,其中最重要的一块 ...
- Elasticsearch实现原理分析
介绍 本文是分析Elasticsearch系列文章中的一篇,是一个译文.共有三个部分,每部分讲解部分Elasticsearch的实现原理. 在翻译的过程中,也需要查看对应部分的源码,来加深对实 ...
- airflow mysql_Airflow 使用及原理分析
Airflow 入门及使用 什么是 Airflow?Airflow 是一个使用 Python 语言编写的 Data Pipeline 调度和监控工作流的平台. Airflow 是通过 DAG(Dire ...
- Android--Handler使用应运及消息机制处理原理分析
最近开通了一个小微博,欢迎大家关注,每天分享一些上班路上看的小知识点 点击打开链接 一.Handler是什么 ? handler是android给我们提供的一套用来更新UI的一套机制,也是一套消息处理 ...
- 原理剖析(第 009 篇)ReentrantReadWriteLock工作原理分析
2019独角兽企业重金招聘Python工程师标准>>> 原理剖析(第 009 篇)ReentrantReadWriteLock工作原理分析 一.大致介绍 1.在前面章节了解了AQS和 ...
- 编译原理语义分析代码_Pix2Pix原理分析与代码解读
原理分析: 图像.视觉中很多问题都涉及到将一副图像转换为另一幅图像(Image-to-Image Translation Problem),这些问题通常都使用特定的方法来解决,不存在一个通用的方法.但 ...
最新文章
- Android ViewGroup事件分发机制
- 理解js中this的指向
- 博弈论笔记:不完全信息与声誉
- 数据结构和算法 —— 时间复杂度+空间复杂度
- js备忘录模式——实现分页点击已经请求过上一页的数据(读js设计模式)
- node.js 爬虫入门总结
- 【java】java 协程
- linux查看tomcat日志_Linux 查看指定时间段的日志
- vue 实现文件下载
- Oracle行转列、列转行的Sql语句总结
- 设置组策略的应用条件-----Windows 管理规范 (WMI)过虑器
- CVS常用命令速查手册
- 客户端 API 开发总结
- mac下报 504 Gateway Time-out
- GaN制备Micro-led(二)——光子晶体倒装 Micro-LED 制备的关键工艺(纳米压印光刻、干法刻蚀、介质薄膜沉积、物理气相沉积)
- 浅析三点SEO理论到底带给了我们什么
- ERROR: Removing unused resources requires unused code shrinking to be turned on.
- svchost.exe 占用网络资源
- 计算机工作区如何删除,Windows Ink工作区是什么,怎么打开/关闭Windows Ink?
- sparksql内写linux脚本,shell脚本调用spark-sql
热门文章
- UVA 10746 Crime Wave - The Sequel
- WinCE 和Win Mobile的关系
- linux mysql详解,Linux 下mysql安装使用详解
- java 音乐api接口_关于网易云音乐爬虫的api接口?
- 5.QML动画——分组动画
- php制作本地程序,PHP安装程序制作
- arraylist从大到小排序_初学Python最简易入门之十四排序算法10对字典排序
- Eclipse安装SVN最新版插件
- JSR-303 Bean Validation 介绍及 Spring MVC 服务端验证最佳实践
- 选择HttpHandler还是HttpModule?