我是靠谱客的博主 奋斗砖头,最近开发中收集的这篇文章主要介绍spring、springboot整合hadoop的时候出现的权限问题,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

相信大家在使用spring、springboot整合hadoop的时候,操作权限的时候可能会遇到下面这样一个权限异常。不过解决的方式有多种,我这里列出两种比较好的解决问题的方案。

Caused by: org.apache.hadoop.ipc.RemoteException(org.apache.hadoop.security.AccessControlException): Permission denied: user=hwf, access=WRITE, inode="/mydir3":hdfs:hdfs:drwxr-xr-x

意思其实就是我们在本机操作的时候,默认是本机用户去我们HDFS系统操作,比如上传,这个时候我们本机用户在HDFS系统上面是没有权限的,这个时候就会报出上面那个错误。

经过对源码一步一步跟踪,发现在org.apache.hadoop.security.UserGroupInformation这个类中看出了端倪。在这个类的commit方法中,核心代码为下面这个

//If we don't have a kerberos user and security is disabled, check
//if user is specified in the environment or properties
if (!isSecurityEnabled() && (user == null)) {
  String envUser = System.getenv(HADOOP_USER_NAME);
  if (envUser == null) {
    envUser = System.getProperty(HADOOP_USER_NAME);
  }
  user = envUser == null ? null : new User(envUser);
}
// use the OS user
if (user == null) {
  user = getCanonicalUser(OS_PRINCIPAL_CLASS);
  if (LOG.isDebugEnabled()) {
    LOG.debug("using local user:"+user);
  }
}
// if we found the user, add our principal
if (user != null) {
  if (LOG.isDebugEnabled()) {
    LOG.debug("Using user: "" + user + "" with name " + user.getName());
  }

  User userEntry = null;
  try {
    userEntry = new User(user.getName());
  } catch (Exception e) {
    throw (LoginException)(new LoginException(e.toString()).initCause(e));
  }
  if (LOG.isDebugEnabled()) {
    LOG.debug("User entry: "" + userEntry.toString() + """ );
  }

  subject.getPrincipals().add(userEntry);

大致意思就是,如果没有设置kerberos用户就获取系统环境用户,最后伪装成User进行登录,而且new User(envUser)我们只需要一个用户名即可,可以设置在HADOOP_USER_NAME这个里面。那么设想一下,如果我们在程序获取系统环境变量HADOOP_USER_NAME之前给他设置成我们HDFS的那个有权限的用户,是不是这样就可以了呢。

然后进行设计,那么我们就写一个BeanFactoryPostProcessor吧,在这个类里面注入这个属性的值。这样直接

System.setProperty("HADOOP_USER_NAME" , "hdfs");可以解决问题。但是问题来了,我们需要把这两个值配置起来,于是有了下面的代码:
@Value("${HADOOP_USER_NAME_KEY}")
private String HADOOP_USER_NAME_KEY;

@Value("${HADOOP_USER_NAME}")
private String HADOOP_USER_NAME;

但是在程序里面拿不到这个值,System.setProperty(HADOOP_USER_NAME_KEY , HADOOP_USER_NAME);

确实BeanFactoryPostProcessor是在所有初始化bean之前,执行的,这个时候spring并没有帮我们把xml装配成一个一个bean,属性文件也没有解析,那么怎么办呢?

这个时候我们可以实现InitializingBean,问题轻松解决,代码也变得足够优雅了。

其实,如果仔细看过hadoop官网的小伙伴,应该知道另外一种解决方案!

Proxy user - Superusers Acting On Behalf Of Other Users

没错,就是通过动态创建代理的方式!但是这种方式需要在hadoop的core-site.xml中配置一点东西,比如我这里的用户是

hwf,那么,可以按照下面这样配置。下面的配置权限相对比较宽松,这样我本地的用户hwf就能够在任何域名下或者在任何组里面都能够扮演想要成为的角色。

   <property>
     <name>hadoop.proxyuser.hwf.hosts</name>
     <value>*</value>
   </property>
   <property>
     <name>hadoop.proxyuser.hwf.groups</name>
     <value>*</value>
   </property>

比如我这里扮演的还是用户hdfs,这个时候可以在程序里面设置。

UserGroupInformation ugi =
        UserGroupInformation.createProxyUser("hdfs", UserGroupInformation.getLoginUser());
ugi.doAs(new PrivilegedExceptionAction<Void>() {
             public Void run() throws Exception {
                 //写你的逻辑
             }
});

同样,这种方式也能解决问题!

最后,欢迎热爱技术的小伙伴加入我们的聊天群qq:852278138

最后

以上就是奋斗砖头为你收集整理的spring、springboot整合hadoop的时候出现的权限问题的全部内容,希望文章能够帮你解决spring、springboot整合hadoop的时候出现的权限问题所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(57)

评论列表共有 0 条评论

立即
投稿
返回
顶部