概述
相信大家在使用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的时候出现的权限问题所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复