Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/matlab/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在Tomcat中扩展ValveBase总是为request.getRemoteUser()返回null_Java_Tomcat_Logging_Tomcat Valve - Fatal编程技术网

Java 在Tomcat中扩展ValveBase总是为request.getRemoteUser()返回null

Java 在Tomcat中扩展ValveBase总是为request.getRemoteUser()返回null,java,tomcat,logging,tomcat-valve,Java,Tomcat,Logging,Tomcat Valve,我已经在Tomcat 8.0.51和9.0.14中测试了这一点,得到了相同的结果。在Ubuntu Linux 16.04上运行 这个示例代码只是将所有请求记录到控制台(或catalina.out)。主要问题是request.getRemoteUser()始终返回null——即使用户已通过身份验证 我注意到AccessLogValve和JDBCAccessLogValve阀门在用户进行身份验证后正确返回登录名/用户名。我在下面通过显示阀门记录到标准控制台日志的sames代码行的访问日志行来说明这一

我已经在Tomcat 8.0.51和9.0.14中测试了这一点,得到了相同的结果。在Ubuntu Linux 16.04上运行

这个示例代码只是将所有请求记录到控制台(或catalina.out)。主要问题是
request.getRemoteUser()
始终返回
null
——即使用户已通过身份验证

我注意到
AccessLogValve
JDBCAccessLogValve
阀门在用户进行身份验证后正确返回登录名/用户名。我在下面通过显示阀门记录到标准控制台日志的sames代码行的访问日志行来说明这一点

是否需要为我的
LoginValve
扩展或实现一个类,以便在对用户进行身份验证时返回登录名/用户?我还尝试调用
request.getUserPrincipal()
,它也总是返回null

对于
ValveBase
为什么会阻止此操作,但却适用于AccessLogs,非常感谢提供任何帮助

package org.apache.catalina.connector;

import java.io.IOException;
import java.time.LocalDateTime;
import javax.servlet.ServletException;
import javax.servlet.http.HttpSession;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
import org.apache.catalina.valves.ValveBase;

public class LoginValve extends ValveBase {
    public void invoke(Request request, Response response) throws IOException, ServletException {
        String reqlogin=request.getRemoteUser();
        String method=request.getMethod();
        String requestURI=request.getRequestURI();
        HttpSession session = request.getRequest().getSession();
        String sid=session.getId();
        String user_id = (String) session.getAttribute("UserID");
        String sesslogin=(String) session.getAttribute("login");  // put in session by app code
        LocalDateTime now=LocalDateTime.now();
        System.out.println("LoginValve: "+now+" sid: "+sid+" UserID: "+user_id+" method: "+method+" requestURI: "+requestURI+" reqlogin: "+reqlogin+" sesslogin: "+sesslogin);

        getNext().invoke(request, response);
    }
}
如果LoginValve低于此值,则显示输出。请注意,调用
request.getRemoteUser()
提供的字段是reqlogin。sesslogin字段由应用程序填充到会话中,与
getRemoteUser()
调用无关

LoginValve: 2019-02-02T15:58:06.034 sid: 79D54B40DB8131E2A74375A67CE72ECD UserID: 3776559 method: GET requestURI: /app/auth/logoff.jsp reqlogin: null sesslogin: joe_user
LoginValve: 2019-02-02T15:58:06.050 sid: 41D1AD1DBBE5FA1D6EE4CB7A350D7DD6 UserID: null method: GET requestURI: /app/index.jsp reqlogin: null sesslogin: null
LoginValve: 2019-02-02T15:58:07.958 sid: 41D1AD1DBBE5FA1D6EE4CB7A350D7DD6 UserID: null method: GET requestURI: /app/user/index.jsp reqlogin: null sesslogin: null
LoginValve: 2019-02-02T15:58:10.006 sid: F75895CAE2521849902CF9894E39A039 UserID: null method: POST requestURI: /app/user/j_security_check reqlogin: null sesslogin: null
LoginValve: 2019-02-02T15:58:10.020 sid: F75895CAE2521849902CF9894E39A039 UserID: null method: GET requestURI: /app/user/index.jsp reqlogin: null sesslogin: null
LoginValve: 2019-02-02T15:58:13.743 sid: 0BBD2544A3C117E32FEE0A03840EAEAE UserID: 3776559 method: GET requestURI: /app/user/transactions.jsp reqlogin: null sesslogin: joe_user
LoginValve: 2019-02-02T15:58:18.127 sid: 0BBD2544A3C117E32FEE0A03840EAEAE UserID: 3776559 method: GET requestURI: /app/user/profile.jsp reqlogin: null sesslogin: joe_user
LoginValve: 2019-02-02T15:58:20.961 sid: 0BBD2544A3C117E32FEE0A03840EAEAE UserID: 3776559 method: GET requestURI: /app/user/feedback.jsp reqlogin: null sesslogin: joe_user
LoginValve: 2019-02-02T15:58:22.930 sid: 0BBD2544A3C117E32FEE0A03840EAEAE UserID: 3776559 method: GET requestURI: /app/user/ reqlogin: null sesslogin: joe_user
LoginValve: 2019-02-02T15:58:24.849 sid: 0BBD2544A3C117E32FEE0A03840EAEAE UserID: 3776559 method: GET requestURI: /app/auth/logoff.jsp reqlogin: null sesslogin: joe_user
LoginValve: 2019-02-02T15:58:24.872 sid: 879B16BB6831D4E07B486C7C0712AE5D UserID: null method: GET requestURI: /app/index.jsp reqlogin: null sesslogin: null
以下是localhost\u access\u日志文件的输出(该文件记录用户joe\u用户对
请求.getRemoteUser()的调用)

同样,问题是,如何获得对
request.getRemoteUser()
的调用,以便在对登录用户进行身份验证时返回该用户

当用户通过身份验证时,我的LoginValve是否需要扩展或实现一个类来返回登录名/用户

是的,您需要实现其文档中的“拟由阀门使用,以指示阀门提供访问日志记录”中的说明

这就是我们正在做的
JDBCAccessLogValve
AccessLogValve

以下是示例代码:

package org.stack;

import java.io.IOException;
import java.time.LocalDateTime;
import javax.servlet.ServletException;
import javax.servlet.http.HttpSession;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
import org.apache.catalina.valves.ValveBase;
import org.apache.catalina.AccessLog;

public class LoginValve extends ValveBase implements AccessLog {

    // Should this valve set request attributes for IP address, hostname, protocol and port used for the request?
    boolean requestAttributesEnabled = false;

    @Override
    public void invoke(Request request, Response response) throws IOException, ServletException {
        // null 
        System.out.println("LoginValve-invoke: " + request.getRemoteUser());
        getNext().invoke(request, response);
    }

    @Override
    public void log(Request request, Response response, long time) {
        // remote user
        System.out.println("LoginValve-log: " + request.getRemoteUser());
    }

    @Override
    public void setRequestAttributesEnabled(boolean requestAttributesEnabled) {
        this.requestAttributesEnabled = requestAttributesEnabled;
    }

    @Override
    public boolean getRequestAttributesEnabled() {
        return requestAttributesEnabled;
    }
}
当启用
tomcat users.xml
文件以允许在manager webapp上进行身份验证时,我得到了一个肯定的结果:

curl -u stack:stack 'http://localhost:8080/manager/html'
..
$ grep 'LoginValve' catalina.out
LoginValve-invoke: null
LoginValve-log: stack

我还没有找到正确的答案,但在Tomcat的理念中,可以通过过滤器来完成的事情应该通过过滤器来完成,阀门应该会改变内部行为。使用过滤器也会使应用程序更易于移植到另一个平台。嗨,Eugene。我想通过Tomcat安全容器来记录请求(在我的帖子中没有提到这一点)。Tomcat专门阻止来自过滤器和侦听器的j_安全检查。我发现的信息说,将安全性放入Tomcat安全容器的方法是使用一个阀门来查看这些。我看到j_安全检查被记录(一个小胜利)-但是我在任何请求上都看不到经过身份验证的用户。Eugene-再次感谢你!你的专业知识太棒了。非常感谢。TedWell,检查文档、Tomcat源代码和构建测试场景花了1小时。StackOverflow是一个学习的好地方,特别是对于故障排除策略。敬请。
curl -u stack:stack 'http://localhost:8080/manager/html'
..
$ grep 'LoginValve' catalina.out
LoginValve-invoke: null
LoginValve-log: stack