【问题标题】:Can't catch the value entered via form in another .jsp file. Why?无法在另一个 .jsp 文件中捕获通过表单输入的值。为什么?
【发布时间】:2021-03-04 16:06:34
【问题描述】:

我在 index.jsp 文件中有一个表单,它允许登录我的应用程序。我需要捕获插入的登录信息,以便使用 Java 代码在另一个名为 mainPage.jsp 的文件中使用它。当我这样做时:

String login = request.getParameter("login");

这个字符串有空值。如何捕捉插入的值?

这是我来自 index.jsp 的代码,其中包含可用于登录我的应用程序的表单:

<body>
<form id="log" method="post" onsubmit="return check()" action="mainPage.jsp">
        <div align="center">
            
            Login: <input type="text" id="login" name="login"/>
            <br/></br>
            
            Password: <input type="password" id="password"/>   
            <br/></br>
            
            <button name="login" type="submit">Log in!</button>
        </div> 
    </form> 

        <script type="text/javascript">
        function check() {
            var login = document.getElementById("login").value;
            var password = document.getElementById("password").value;
            var flag = false;
            
            var _users = JSON.parse(users);
            
            for (var i = 0; i < _users.length; i++) {
                if (_users[i].login == login && _users[i].password == password) {
                    flag = true;
                }
            }
            
            if (flag == false) {   
                document.getElementById('info').innerHTML = "Wrong login or password!";
            }
            
            return flag;
        }        
    </script>
</body>

【问题讨论】:

  • 你想在你的检查方法中做什么?如果要检查登录名和密码,则必须在服务器端进行。在您的代码中,您似乎将所有用户加载到客户端大小并检查它。在这种情况下,您只需将所有未加密的数据提供给用户,任何人都可以找到任何密码。关于您问题的要点 - 为什么 get 参数不起作用。简而言之 - 此方法用于获取查询(如 google.com/search?q=abc 和 getParameter("q") 返回 abc。您发送 POST 方法 - 这意味着您的参数在 request.getBody() 中。您可以使用 spring 之类的库更简单地解析它
  • 好的,但是没有 Spring 怎么办呢?你能帮我做这件事吗,@DmitryNazarenko?

标签: javascript java html jsp


【解决方案1】:

第一个问题是使用了错误的方法: HttpRequest.getParameter。此方法在 URL 中查找参数。例如在这个网址中

https://google.com/search?q=java

request.getParameter("q") 返回 java。

在您的示例中,您使用了 POST 查询。这意味着参数将以 www-form-urlencoded 格式出现在您的请求正文中。请求看起来像

login=login&password=password

第二个问题是使用 id 而不是名称。要在标签中传输参数,您需要使用名称,而不是 id。带有名称参数的按钮也将发送空输入。按下按钮后,您将在服务器上看到下一个结果

login=login&login=

这是我们没有预料到的。在下面的示例中,我使用名称正确发送参数。如果您需要 css 样式 - 使用 classes 或 id 参数而不是 html 标签名称


要在没有外部库的情况下解析它,我们必须

  1. 解析请求正文
  2. 提取参数
  3. 向客户端发送响应

这个简单的例子:

login.jsp

<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<!DOCTYPE html>
<html>
<head>
    <title>Login page</title>
    <style>
        /* TODO: use classes of method to make styles */
        label, input {
            display: block;
        }
    </style>
</head>
<body>
    <form method="post">
        <label>Login: 
            <input type="text" name="login" />
        </label>
        <label>Password:
            <input label="password" type="password" name="password"/>
        </label>

        <button type="submit">Log in!</button>
    </form>
</body>
</html>

小服务程序

@WebServlet(name = "login", value = "/login")
public class LoginServlet extends HttpServlet {

    public static final String IS_AUTHENTICATED_PARAM = "isAuthenticated";

    public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
        this.getServletContext().getRequestDispatcher("/login.jsp").include(request, response);
    }


    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //Parse body
        String requestBody = request.getReader().lines().collect(Collectors.joining(System.lineSeparator()));
        //System.out.println(requestBody); - uncomment to view what is in body
        String login = getParamFromBodyUrlEncoded(requestBody, "login");
        String password = getParamFromBodyUrlEncoded(requestBody, "password");
        //In future you can setup secret cookie and check it in other pages
        if(login == null || password == null) {
            request.setAttribute(IS_AUTHENTICATED_PARAM, false);
        } else {
            request.setAttribute("isAuthenticated", isCredentialsCorrect(login, password));
        }
        this.getServletContext().getRequestDispatcher("/loginResult.jsp").include(request, response);
    }

    private String getParamFromBodyUrlEncoded(String requestBody, String paramName) {
        String paramUrlEncoded = paramName + "=";//param format is like login=. We expect paramname like login
        //Search for param
        int paramWithNameStart = requestBody.indexOf(paramUrlEncoded);
        if(paramWithNameStart == -1) {
            return null;
        }
        //Set pointer after param name
        int paramStart = paramWithNameStart + paramUrlEncoded.length();
        //Param should end with & or end of string
        int paramEnd = requestBody.indexOf("&", paramStart);
        if(paramEnd == -1) {
            paramEnd = requestBody.length();
        }

        return requestBody.substring(paramStart, paramEnd);
    }

    private boolean isCredentialsCorrect(String login, String password) {
        if("admin".equals(login) && "password".equals(password)) {
            return true;
        } else {
            return false;
        }
    }
}

loginResult.jsp

<%@ page import="com.example.demo_jsp.LoginServlet" %>
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<!DOCTYPE html>
<html>
<head>
    <title>Login result</title>
</head>
<body>

<h1><%=(boolean)request.getAttribute(LoginServlet.IS_AUTHENTICATED_PARAM) ? 
        "Success authentication" : "Wrong login or password"%></h1>
</body>
</html>

【讨论】:

  • 非常感谢 @Dmitry Nazarenko 的全面回答 :-) 但是,我设法做到这一点要简单得多,并将其发布为我的问题的答案 ;-)
【解决方案2】:

所以,我终于设法以一种非常简单的方式做到了这一点。 当我登录时,我将登录名存储在会话中,然后在我的程序中提取它。

我通过在登录我的应用程序后调用这部分代码来做到这一点:

   if (request.getParameter("login") != null) {    
        session.setAttribute("_login", request.getParameter("login"));
   }

然后,我通过以下方式获取登录人员的姓名:

   String login = session.getAttribute("_login").toString();

效果很好! :-D

【讨论】:

  • 但问题是关于其他主题 - 你得到 request.getParameter("smth") - null 值。如果你从这个请求中获取参数,你已经将你的表单方法更改为get,并且传递密码抛出get方法是不正确的 - 这不是常见的做法。所以,我的回答解决了这个问题,而你发现不是解决问题的最佳方法
  • 大声笑我没有更改表单方法来获取
  • 我认为使用具有解析功能的小型库更简单。例如,您可以查看sparkjava.com - 它非常简单。 Java servlet api 是低级的,在 java 项目中通常与框架一起使用
  • 我明白了,你在会话中存储登录名!它解决了问题,但它不是解决这个问题的常用方法,另一个程序员会和我一样感到惊讶。无论如何,问题是关于为什么我得到空值,以及解决问题的简单方法,它不是您问题的答案。另外 - 我知道您想以您的学习方式解决您的问题,但通常开发人员使用某种标准身份验证方法,如基本、jwt 或令牌身份验证等。
  • 我明白了。感谢您的帮助和有用的建议:-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-02-06
  • 1970-01-01
  • 2020-10-30
  • 2018-08-26
  • 2014-12-22
  • 2021-05-02
  • 1970-01-01
相关资源
最近更新 更多