Struts 2值栈“登录尝试”计数器不持久变量

时间:2013-02-15 15:48:25

标签: struts2 persistent-storage valuestack

我现在正在学习Struts 2并尝试进行登录尝试计数器以在x次失败尝试后阻止任何进一步的登录尝试。

这是我的login.jsp

的正文
<body>

<h1><s:property value="loginAttempts"/></h1>

<s:form action="login">
    <s:textfield name="username" label="Username" />
    <s:password name="password" label="Password"/>
<%-- <s:hidden name="loginAttempts"  value="<s:property value="loginAttempts"/>" /> --%>
    <s:set var="loginAttempts"><s:property value="loginAttempts"/></s:set>
    <s:submit value="login"/>
</s:form>

</body>

我的Action类(我不包括他们的getter和setter的私有var,但他们都在那里)

public String execute() throws Exception{

    if (username.equals("admin")&& password.equals("admin"))
    {   return SUCCESS;}
    else if (Integer.parseInt(getLoginAttempts())>2)
    {
        return "lockout";
    }
    else
    {   setLoginAttempts(String.valueOf(Integer.parseInt(getLoginAttempts())+1));
        return "fail";}
}

在最初调用login.jsp的动作中,我传入了一个初始值

loginAttempts="0";

并且工作正常。当我在login.jsp页面上点击提交时会出现问题。

我得到以下堆栈跟踪

java.lang.NumberFormatException: null 
java.lang.Integer.parseInt(Integer.java:417)
java.lang.Integer.parseInt(Integer.java:499)
com.struts.users.LoginAction.execute(LoginAction.java:17)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

第17行

else if (Integer.parseInt(getLoginAttempts())>2)

每当我点击提交按钮loginAttempt变量时,它会将自身重置为NULL

由于

编辑:我明白这可能不是正确的做法,我应该用会话这样做。但是我试图理解它为什么不起作用。

1 个答案:

答案 0 :(得分:0)

struts2动作不是持久的!每次请求发生时都会重新创建 您需要做的是为操作实现ServletRequestAware界面,以便您访问HttpServletRequest,然后您可以使用您的网络服务器存储的http会话对象,并在其上增加值。要小心,因为这需要线程安全 - 您可能需要在更新值时锁定http会话 另一种方法是在ServletContext中有一个对象,用于存储Map用户名以进行登录尝试。这可能更可靠。

评论中的一点澄清:

您的表单将其上的值(称为POSTing)发送到您的网络服务器,然后struts2接收此“POST数据”并为您解释它 - 使用您操作中的相关设置程序为您提供此数据。
因此,为了发送登录尝试值,您的表单需要将其作为变量,因此需要<s:hidden>。那么你的行动应该有一个loginattempts的setter;即具有签名setLoginAttempts(int loginAttempts)的方法 现在,当您的操作完成并发现请求无效时,您希望增加该变量并在操作中为其提供一个getter。
现在,您的JSP(由尝试失败的操作呈现)可以从操作中读取该值,并将其添加到用户将发送的HTML表单中。因此我提到了一个圆圈 从用户POST数据中读取变量loginAttempts时,此方法无法添加到您网站的安全性 - 用户可以发送任何想要的内容,您的操作将读取该次数作为登录尝试次数。
我希望有帮助......