why hadoop web not control
By
yuanxiaolong
更新日期:
hadoop 的web界面 user.name=xxx 为什么不能控制访问呢?我们一探究竟
起因是因为有人问到,hadoop的web界面为什么不能控制访问人员呢?
例如 http://localhost:50070/dfshealth.jsp?user.name=xxx ,其中这个xxx可以随便写均可以跳过权限控制?
PS:关于hadoop的web安全添加 这里有一篇文章 hadoop添加web安全
分析过程
1.先 开启远程调试hadoop的debug模式
2.在core-site.xml中找到给hadoop添加权限的类
core-site.xml1 2 3 4
| <property> <name>hadoop.http.filter.initializers</name> <value>org.apache.hadoop.security.AuthenticationFilterInitializer</value> </property>
|
看样子是个类似servlet的过滤器,先看一下这个类
AuthenticationFilterInitializer.java1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| static final String PREFIX = "hadoop.http.authentication.";
static final String SIGNATURE_SECRET_FILE = AuthenticationFilter.SIGNATURE_SECRET + ".file";
@Override public void initFilter(FilterContainer container, Configuration conf) { Map<String, String> filterConfig = new HashMap<String, String>(); ... String signatureSecretFile = filterConfig.get(SIGNATURE_SECRET_FILE); ... try { StringBuilder secret = new StringBuilder(); Reader reader = new FileReader(signatureSecretFile); int c = reader.read(); while (c > -1) { secret.append((char)c); c = reader.read(); } reader.close(); filterConfig.put(AuthenticationFilter.SIGNATURE_SECRET, secret.toString()); } catch (IOException ex) { throw new RuntimeException("Could not read HTTP signature secret file: " + signatureSecretFile); } ... container.addFilter("authentication", AuthenticationFilter.class.getName(), filterConfig);
|
做了3件事情:
- 获取指定的权限文件
- 将权限文件放到filterConfig这个map里
- 将这个map传递给了AuthenticationFilter这个类,作为初始参数
3.再看一下AuthenticationFilter,继承了servlet的fitler接口,那么直奔doFilter方法吧!
AuthenticationFilter.java1
| public class AuthenticationFilter implements Filter
|
我们在doFilter里打个断点,刷新界面,果然进入断点处。
里面就1个行比较可疑
AuthenticationFilter.java1 2 3
| ... token = authHandler.authenticate(httpRequest, httpResponse); ...
|
这个authHander是个接口,实现类有2个 KerberosAuthenticationHandler.java 和 PseudoAuthenticationHandler.java 到底哪个呢?
4.一般这种对接口的实例化,spring的IOC是一种,但是hadoop不可能依赖spring,那么它的实例化,十有八九在初始化的时候做的。看一下init方法
AuthenticationFilter.java1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| @Override public void init(FilterConfig filterConfig) throws ServletException { String configPrefix = filterConfig.getInitParameter(CONFIG_PREFIX); configPrefix = (configPrefix != null) ? configPrefix + "." : ""; Properties config = getConfiguration(configPrefix, filterConfig); String authHandlerName = config.getProperty(AUTH_TYPE, null); String authHandlerClassName; if (authHandlerName == null) { throw new ServletException("Authentication type must be specified: simple|kerberos|<class>"); } if (authHandlerName.equals("simple")) { authHandlerClassName = PseudoAuthenticationHandler.class.getName(); } else if (authHandlerName.equals("kerberos")) { authHandlerClassName = KerberosAuthenticationHandler.class.getName(); } else { authHandlerClassName = authHandlerName; } ...
|
这里我们看到,用哪个类是根据 authHandlerName 是 simple还是kerberos,而且有configPrefix,说明是统一前缀的,就是 AuthenticationFilterInitializer.PREFIX
因此这个 authHandlerName 就是 core-site.xml 的 hadoop.http.authentication.type (验证方式,默认为简单simple,也可自己定义class,需配置所有节点)
结论
由此可见,这里只判断了userName是否为空的情况,并没有严格校验内容。