ASP:当密码框有值时,文本框的值在回发时消失

11

我有一个像这样的 asp.net 文本框:

 <asp:TextBox ID="PINPad" runat="server" Columns="6" MaxLength="4" 
      CssClass="PINTextClass"></asp:TextBox>

正如你所猜测的那样,这是来自屏幕上PIN键盘的文本框。Javascript填充数值。页面每五秒钟提交一次(如果有update panel会影响此操作),以更新屏幕上的其他不相关项目。这个操作完全没有问题。

但是,当我将它转换为密码文本框,像这样:

  <asp:TextBox ID="PINPad" runat="server" Columns="6" MaxLength="4" 
       CssClass="PINTextClass" TextMode="Password"></asp:TextBox>

每当页面回发时,文本框在屏幕上被清空且为空(尽管在计时器事件期间,该值确实会传回服务器)。

有什么建议可以修复这个问题,以便在回发期间保留其值?


3
这里有一篇文章,介绍如何更加安全地解决这个问题(即使不是完美的解决方法),网址为:http://www.codeproject.com/Articles/18927/How-to-safely-keep-a-password-field-during-postbac。 - Mark
5个回答

16

ASP.NET为了安全起见,试图防止您将密码值发送回客户端。如果您接受安全问题(即它既不是真正的安全信息,或者您确定连接是安全的),则可以手动设置控件的"value"属性,而不是使用其Text属性。它可能看起来像这样:

this.PINPad.Attributes.Add("value", this.PINPad.Text);

5
protected void Page_Load(object sender, EventArgs e)
{
    if (IsPostBack)
  {
        if (!(String.IsNullOrEmpty(txtPwd.Text.Trim())))
        {
             txtPwd.Attributes["value"]= txtPwd.Text;              
        }
        if (!(String.IsNullOrEmpty(txtConfirmPwd.Text.Trim())))
        {
            txtConfirmPwd.Attributes["value"] = txtConfirmPwd.Text;
        }
  }
}

0

这里有另一种方法来实现它:

using System;
using System.Text;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace WebControlLibrary
{
    public class PWDTextBox : TextBox
    {
        public PWDTextBox()
        {
            this.TextMode = TextBoxMode.Password;
        }

        public string Password
        {
            get
            {
                string val = (string)ViewState["pwd"];
                if (string.IsNullOrEmpty(val))
                {
                    return "";
                }
                else
                {
                    return val;
                }
            }
            set
            {
                ViewState["pwd"] = value;
            }
        }

        public override string Text
        {
            get
            {
                return Password;
            }
            set
            {
                Password = value;
            }
        }

        protected override void OnPreRender(EventArgs e)
        {
            base.OnPreRender(e);
            this.Text = Password;
        }

        protected override void AddAttributesToRender(HtmlTextWriter writer)
        {
            base.AddAttributesToRender(writer);
            writer.AddAttribute(HtmlTextWriterAttribute.Value, this.Password);
        }
    }
}

0
在后台回发中丢失密码的问题可以通过使用异步JavaScript调用来避免,让我们描述一个登录页面的典型场景:
假设我们有一个登录页面,允许用户在下拉列表中选择语言以更改其标签的语言。

enter image description here

一个解决方案是调用下拉列表的 selectedIndexChanged 事件,进行一个回传到服务器并选择所选语言中的标签。
在这种情况下,密码字段将因 ASP.NET 的安全功能而丢失,该功能使得密码字段在回传之间不会被保存。
如果使用异步 JavaScript 技术和 XML(Ajax)调用来避免回传,则可以解决此问题。
添加一个 JavaScript 函数,该函数将从下拉列表控件中调用,在此情况下,此函数在代码后端被分配给下拉列表的 Command 属性。
function ValueChanged(div) 
            {
                var table = div.getElementsByTagName("table");
                if (table && table.length > 0) 
                {
                    var t = table[0].getAttribute('type'); 
                    if (t != null && (t == "DropDown"))
                    {
                        var inputs = div.getElementsByTagName("input");
                        if (inputs && inputs.length == 2) 
                        {

                            {
                                Translate(inputs[1].value);
                            }
                        }
                    }
                }
            }

Translate函数接受下拉控件中选择的语言选项作为参数,并执行如下所示的异步调用。

function Translate(lang)
            {
                var request = null;
                if (window.XMLHttpRequest) 
                {
                    request = new XMLHttpRequest();
                    if (request.overrideMimeType)
                    {                        
                        request.overrideMimeType('text/xml');
                    }
                }
                else if (window.ActiveXObject)
                {
                    request = new ActiveXObject("Msxml2.XMLHTTP");
                }
                if (request == null)
                {
                    return;
                }
                var url = "GetLoginTranslations.aspx";               
                request.open('GET', url +'?lang=' + lang, true);
                request.setRequestHeader("Cache-Control", "no-cache");
                request.setRequestHeader("Pragma", "no-cache");
                request.setRequestHeader("If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT");
                request.onreadystatechange = function () { TranslateLabels(request); };
                request.send(null);
            }

上面显示的Translate函数执行调用并在指定的.aspx页面(在本例中为“GetLoginTranslations.aspx”)中获取结果

当请求完成且request.onreadystatechange设置为TranslateLabels函数时,将执行此函数。

这样,与下拉列表控件的onSelectedIndexChanged事件之前不同,不会执行postback。

TranslateLabels函数可能如下所示:

function TranslateLabels(request) 
            {                
                if (request.readyState == 4) 
                {
                    if (request.status == 200) 
                    {
                        if (request.responseXML)
                        {
                            var objRoot = request.responseXML.documentElement;
                            if (objRoot)
                            {
                                if (objRoot.nodeName == "strings")
                                {
                                    for (var i = 0; i < objRoot.childNodes.length; i++) 
                                    {
                                        var node = objRoot.childNodes[i];
                                        var elem;
                                        switch (node.getAttribute("id"))
                                        {
                                            case "lbl_login": 
                                                elem = document.getElementById("lbl_login");
                                                if (elem)
                                                    elem.innerHTML = node.firstChild.nodeValue;
                                                break;
                                         }
///....
}
}
}
}
}
}

请求.responseXML 包含在页面 GetLoginTranslations.aspx 中构建的 XML,并且该 XML 的结构在那里定义。

GetLoginTranslations.aspx 中的 Page_Load() 事件应该如下所示:

protected void Page_Load(object sender, EventArgs e)
        {
  if (Request["lang"] != null)
                strLang = Request["lang"];

            //init response
            Response.Clear();
            Response.Cache.SetExpires(DateTime.Now);
            Response.Cache.SetCacheability(HttpCacheability.NoCache);
            Response.Cache.SetValidUntilExpires(true);
            Response.ContentType = "application/xml";
            Response.Charset = "utf-8";


            XmlTextWriter xml = new XmlTextWriter(Response.OutputStream, System.Text.Encoding.UTF8)
            {
                Formatting = Formatting.None
            };
            xml.WriteStartDocument();
            xml.WriteStartElement("strings");

            xml.WriteStartElement("string");
            xml.WriteAttributeString("id", "lbl_login");
            xml.WriteString(GetTranslation("label_login", strLang));
            xml.WriteEndElement();

            // ... the other labels


            xml.WriteEndElement(); //</strings>
            xml.Close();

        }

其他考虑因素:

  • 将下拉列表的AutoPostback属性设置为false。

0

发生在视图模型属性名为“Password”和“PIN”的情况下。您可以通过将它们定义为以下内容来绕过此行为:

string Password ;

... 而不是:

string Password { get; set; }

如果这样做,像“LabelFor”宏显示的“DisplayAttribute.Name”等功能将不再起作用,因此您必须直接在HTML中定义这些内容。
或者,您可以简单地将字段命名为除“Password”或“PIN”之外的其他名称。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接