实现验证码控件代码验证控件,方便使用验证码(修改)

本文介绍了一种自定义的验证码控件实现方法,该控件继承自BaseValidator,能够为指定的Image控件设置验证码图片,并在验证失败时清空输入框的内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  网站在进行重要操作步骤时,为了防止攻击,一般都采用生成验证码的方法。为了使用方便,我自己写了一个从BaseValidator实现的验证控件,负责给指定的Image控制设置ImageSrc并在验证失败时,清空TextBox控制的值。从BaseValidator继承,是因为服务端只需调用
ExpandedBlockStart.gifContractedBlock.gif if(Page.IsValid)dot.gif{} 
就可以了。

下面主要代码公布如下,希望大家拍砖。
使用代码示例:
None.gif                        <asp:TextBox ID="TextBox1" runat="server" AutoCompleteType="Disabled"  ></asp:TextBox>
None.gif                        
<asp:Image ID="Image1" runat="server" ImageAlign="absMiddle" />
None.gif                        
<asp:ImageValidator runat="server" ID="imagevalidator" 
          ImageControl
="Image1" 
          ControlToValidate
="TextBox1" 
          Display
="Dynamic"
          CharCount
="4" 
          Fonts
="宋体,Gungsuh,仿宋,黑体" 
          BgColor
="White" 
          MaxFontSize
="16" 
          MinFontSizePercent
="50" 
          ErrorMessage
="验证码错误!" 
          SetFocusOnError
="True" />
None.gif
后台编码:
None.gif        protected void OnLogin(object sender, EventArgs e)
ExpandedBlockStart.gifContractedBlock.gif        
dot.gif{
InBlock.gif            
try
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
if (Page.IsValid)
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    
string hashedPwd = Utility.Md5.HashedString(this.tbLoginPassword.Text.Trim());
InBlock.gif                    Manager manager 
= Manager.CreateInstance(this.tbLoginName.Text.Trim(), hashedPwd);
InBlock.gif                    
//登陆成功
InBlock.gif
                    ManagePageBase.SetAuthSession(manager);
InBlock.gif                                                          System.Web.Security.FormsAuthentication.RedirectFromLoginPage(manager.Name, 
false);
ExpandedSubBlockEnd.gif                }

ExpandedSubBlockEnd.gif            }

InBlock.gif            
catch (BusinessException ex)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
this.ShowMessage(ex.Message);
ExpandedSubBlockEnd.gif            }

ExpandedBlockEnd.gif        }

None.gif

实现代码如下:
None.gifusing System;
None.gif
using System.Collections.Generic;
None.gif
using System.Text;
None.gif
using System.Text.RegularExpressions;
None.gif
using System.ComponentModel;
None.gif
using System.Web.Configuration;
None.gif
using System.Drawing.Design;
None.gif
using System.Drawing;
None.gif
using System.Web.SessionState;
None.gif
using System.Web;
None.gif
using System.Web.UI;
None.gif
using System.Web.UI.WebControls;
None.gif
using System.Drawing.Imaging;
None.gif
using System.Drawing.Drawing2D;
None.gif
None.gif
namespace Iyond.Web.UI.WebControls
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
InBlock.gif    
public class ImageValidator : System.Web.UI.WebControls.BaseValidator
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif
InBlock.gif        
private string _chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
InBlock.gif        [Bindable(
false)]
InBlock.gif        [Category(
"Data")]
InBlock.gif        [DefaultValue(
"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")]
InBlock.gif        [Localizable(
true)]
InBlock.gif        [Description(
"用于生成验证码的源字符")]
InBlock.gif        
public string Chars
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
get
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
return _chars;
ExpandedSubBlockEnd.gif            }

InBlock.gif
InBlock.gif            
set
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                _chars 
= value;
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
private int _charCount = 5;
InBlock.gif        [Bindable(
false)]
InBlock.gif        [Category(
"Data")]
InBlock.gif        [DefaultValue(
5)]
InBlock.gif        [Localizable(
true)]
InBlock.gif        [Description(
"验证码中字符的数量")]
InBlock.gif        
public int CharCount
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
get
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
return _charCount;
ExpandedSubBlockEnd.gif            }

InBlock.gif            
set
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                _charCount 
= value;
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
private string _pageValidateCode = "~/IyondValidateCode.aspx";
InBlock.gif        [Category(
"Data")]
InBlock.gif        [Localizable(
true)]
InBlock.gif        [Description(
"在Web.config中的HttpHandler节中配置的读取验证码的页面")]
InBlock.gif        
public string ValidateCodePage
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif            
get dot.gifreturn _pageValidateCode; }
ExpandedSubBlockStart.gifContractedSubBlock.gif            
set dot.gif{ _pageValidateCode = value; }
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif
InBlock.gif        
private int _minFontSizePercent = 60;
InBlock.gif        [Category(
"Data")]
InBlock.gif        [Localizable(
true)]
InBlock.gif        [Description(
"字体最小高度占Image控件高度的百分比")]
InBlock.gif        
public int MinFontSizePercent
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
get
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
return _minFontSizePercent;
ExpandedSubBlockEnd.gif            }

InBlock.gif            
set
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
if (value > 100)
InBlock.gif                    
throw new ArgumentOutOfRangeException("MaxFontSize", value, "最大为100(表示100%)");
InBlock.gif                
if (value < 50)
InBlock.gif                    
throw new ArgumentOutOfRangeException("MaxFontSize", value, "最小为50(表示50%)");
InBlock.gif
InBlock.gif                _minFontSizePercent 
= value;
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif
InBlock.gif        
public int MinFontSize
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
get
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
return Convert.ToInt32(this.MaxFontSize * this.MinFontSizePercent / 100 + 1);
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
private int _maxFontSize = 100;
InBlock.gif        [Category(
"Data")]
InBlock.gif        [Localizable(
true)]
InBlock.gif        [Description(
"字体最大高度占Image控件高度的百分比")]
InBlock.gif        
public int MaxFontSize
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
get
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
return _maxFontSize;
ExpandedSubBlockEnd.gif            }

InBlock.gif            
set
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
if (value > 100)
InBlock.gif                    
throw new ArgumentOutOfRangeException("MaxFontSize", value, "最大为100");
InBlock.gif                
if (value < 6)
InBlock.gif                    
throw new ArgumentOutOfRangeException("MaxFontSize", value, "最小为6");
InBlock.gif                _maxFontSize 
= value;
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
private Color _fontColor = Color.Black;
InBlock.gif        [Category(
"Data")]
InBlock.gif        [Localizable(
true)]
InBlock.gif        [Description(
"字体颜色")]
InBlock.gif        
public Color FontColor
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
get
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
return _fontColor;
ExpandedSubBlockEnd.gif            }

InBlock.gif            
set
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                _fontColor 
= value;
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
private Color _bgColor = Color.White;
InBlock.gif        [Category(
"Data")]
InBlock.gif        [Localizable(
true)]
InBlock.gif        [Description(
"字体颜色")]
InBlock.gif        
public Color BgColor
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
get
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
return _bgColor;
ExpandedSubBlockEnd.gif            }

InBlock.gif            
set
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                _bgColor 
= value;
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
private bool _ignoreCase = true;
InBlock.gif        [Category(
"Data")]
InBlock.gif        [Localizable(
true)]
InBlock.gif        [Description(
"是否乎略大小写")]
InBlock.gif        
public bool IgnoreCase
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif            
get dot.gifreturn _ignoreCase; }
ExpandedSubBlockStart.gifContractedSubBlock.gif            
set dot.gif{ _ignoreCase = value; }
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
private bool _enableChangeImage = true;
InBlock.gif        [Category(
"Data")]
InBlock.gif        [Localizable(
true)]
InBlock.gif        [Description(
"是否允许更换图片")]
InBlock.gif        
public bool EnableChangeImage
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif            
get dot.gifreturn _enableChangeImage; }
ExpandedSubBlockStart.gifContractedSubBlock.gif            
set dot.gif{ _enableChangeImage = value; }
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
private int _maxRotate = 45;
InBlock.gif        [Category(
"Data")]
InBlock.gif        [Localizable(
true)]
InBlock.gif        [Description(
"每个字的最大旋转角度")]
InBlock.gif        
public int MaxRotate
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif            
get dot.gifreturn _maxRotate; }
ExpandedSubBlockStart.gifContractedSubBlock.gif            
set dot.gif{ _maxRotate = value; }
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
private List<string> _fonts = new List<string>();
InBlock.gif        [Category(
"Data")]
InBlock.gif        [Localizable(
true)]
InBlock.gif        [Description(
"字体列表,从中随机选择")]
InBlock.gif        [Editor(
"System.Windows.Forms.Design.StringArrayEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
InBlock.gif        
typeof(UITypeEditor)), TypeConverter(typeof(FontNamesConverter)),
InBlock.gif        RefreshProperties(RefreshProperties.Repaint), 
InBlock.gif        NotifyParentProperty(
true)]
InBlock.gif        
public string[] Fonts
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
get
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
return _fonts.ToArray();
ExpandedSubBlockEnd.gif            }

InBlock.gif            
set
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
if (value == null)
InBlock.gif                    
throw new ArgumentNullException("Fonts");
InBlock.gif
InBlock.gif                _fonts.Clear();
InBlock.gif                _fonts.AddRange(value);
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif
InBlock.gif
InBlock.gif        
private static Dictionary<string, ImageValidatorConfig> runtimeConfig = new Dictionary<string, ImageValidatorConfig>();
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// 查询验证码配置
InBlock.gif        
/// </summary>
InBlock.gif        
/// <param name="sign">验证码标识</param>
ExpandedSubBlockEnd.gif        
/// <returns></returns>

InBlock.gif        public static ImageValidatorConfig GetConfig(string sign)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
if (!runtimeConfig.ContainsKey(sign))
InBlock.gif                
throw new ArgumentOutOfRangeException("sign", sign);
InBlock.gif
InBlock.gif            
return runtimeConfig[sign] as ImageValidatorConfig;
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// 计算是不是合法(验证码是不是正确)
InBlock.gif        
/// </summary>
ExpandedSubBlockEnd.gif        
/// <returns></returns>

InBlock.gif        protected override bool EvaluateIsValid()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
bool isValid = false;
InBlock.gif            
string text1 = base.GetControlValidationValue(base.ControlToValidate);
InBlock.gif            
if ((text1 == null|| (text1.Trim().Length == 0))
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                isValid 
= false;
ExpandedSubBlockEnd.gif            }

InBlock.gif            
else
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                isValid 
= this.ValidateChar();
ExpandedSubBlockEnd.gif            }

InBlock.gif
InBlock.gif            
this.IsValid = isValid;
InBlock.gif            
return this.IsValid;
InBlock.gif
InBlock.gif
ExpandedSubBlockEnd.gif        }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// 查看是不是合法
InBlock.gif        
/// </summary>
ExpandedSubBlockEnd.gif        
/// <returns></returns>

InBlock.gif        private bool ValidateChar()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
string validatecode = ValidateCodeHandler.GetAndEmptyValidateCode(this.ValidateSign);
InBlock.gif            
if (string.IsNullOrEmpty(validatecode))
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
return false;
ExpandedSubBlockEnd.gif            }

InBlock.gif            
else
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
return string.Compare(validatecode, this.GetControlValidationValue(this.ControlToValidate), this.IgnoreCase) == 0;
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// 关联的图片控件ID
ExpandedSubBlockEnd.gif        
/// </summary>

InBlock.gif        [DescriptionAttribute("BaseValidator_ImageControl"), IDReferenceProperty, TypeConverter(typeof(ImageControlConverter)), Themeable(false), DefaultValue(""), CategoryAttribute("Behavior")]
InBlock.gif        
public string ImageControl
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
get
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
object obj1 = this.ViewState["ImageControl"];
InBlock.gif                
if (obj1 != null)
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    
return (string)obj1;
ExpandedSubBlockEnd.gif                }

InBlock.gif                
return string.Empty;
ExpandedSubBlockEnd.gif            }

InBlock.gif            
set
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
this.ViewState["ImageControl"= value;
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
protected System.Web.UI.WebControls.Image Image
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
get 
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
if (string.IsNullOrEmpty(this.ImageControl))
InBlock.gif                    
throw new ArgumentNullException("ImageControl");
InBlock.gif
InBlock.gif                
return this.NamingContainer.FindControl(this.ImageControl) as System.Web.UI.WebControls.Image;
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
protected string ValidateSign
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
get
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
if (ViewState["imagevalidate::validatesign"== null)
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    ViewState[
"imagevalidate::validatesign"= Utility.HashedString(string.Format("{0}::{1}",Page.Request.Url.AbsolutePath,this.UniqueID));
ExpandedSubBlockEnd.gif                }

InBlock.gif
InBlock.gif                
return Convert.ToString(ViewState["imagevalidate::validatesign"]);
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
protected override void OnPreRender(EventArgs e)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
this.Image.ImageUrl = "#";
InBlock.gif            
this.Image.Attributes["onload"= "this.style.display=''";
InBlock.gif
InBlock.gif            
if (this.EnableChangeImage)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                Image.ToolTip 
= "看不清楚吗?双击换一张";
InBlock.gif                Image.Attributes[
"ondblclick"= "if(!this.orgsrc)this.orgsrc=this.src;this.src=this.orgsrc + '&t=' + new Date().valueOf()";
ExpandedSubBlockEnd.gif            }

InBlock.gif            
this.Image.Style.Add(HtmlTextWriterStyle.Display, "none");
InBlock.gif            StringBuilder sbjs 
= new StringBuilder();
InBlock.gif            sbjs.AppendFormat(
"javascript:this.onerror=null;this.src='{0}?sign={1}';", Page.ResolveClientUrl(this.ValidateCodePage), this.ValidateSign);
InBlock.gif
InBlock.gif            
this.Image.Attributes.Add("onerror", sbjs.ToString());
InBlock.gif
InBlock.gif            runtimeConfig[
this.ValidateSign] = new ImageValidatorConfig(this.Chars, this.CharCount,this.FontColor, 
InBlock.gif                
this.Fonts,this.MinFontSize, this.MaxFontSize);
InBlock.gif
InBlock.gif            
if (!this.IsValid)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                ITextControl textInput 
= this.NamingContainer.FindControl(this.ControlToValidate) as ITextControl;
InBlock.gif                
if (textInput != null)
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    textInput.Text 
= "";
ExpandedSubBlockEnd.gif                }

InBlock.gif
ExpandedSubBlockEnd.gif            }

InBlock.gif
InBlock.gif
InBlock.gif            
base.OnPreRender(e);
ExpandedSubBlockEnd.gif        }

InBlock.gif            
InBlock.gif
InBlock.gif
ExpandedSubBlockEnd.gif    }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
/**//// <summary>
InBlock.gif    
/// 查找Image控件ID列表
ExpandedSubBlockEnd.gif    
/// </summary>

InBlock.gif    public class ImageControlConverter : ControlIDConverter
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
protected override bool FilterControl(Control control)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
if (control is System.Web.UI.WebControls.Image)
InBlock.gif                
return true;
InBlock.gif            
else
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
return false;
ExpandedSubBlockEnd.gif            }

InBlock.gif            
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
/**//// <summary>
InBlock.gif    
/// 控制配置类
ExpandedSubBlockEnd.gif    
/// </summary>

InBlock.gif    public class ImageValidatorConfig
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
private string _chars = string.Empty;
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// 可用字符列表构成的串
InBlock.gif        
/// </summary>
InBlock.gif        
/// <example>
InBlock.gif        
/// 123456789
ExpandedSubBlockEnd.gif        
/// </example>

InBlock.gif        public string Chars
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
get
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
return _chars;
ExpandedSubBlockEnd.gif            }

InBlock.gif
InBlock.gif            
set
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                _chars 
= value;
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
private int _charCount = 5;
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// 验证图片上字符数量
ExpandedSubBlockEnd.gif        
/// </summary>

InBlock.gif        public int CharCount
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
get
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
return _charCount;
ExpandedSubBlockEnd.gif            }

InBlock.gif            
set
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                _charCount 
= value;
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif        
private int _minFontSize = 60;
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// 字体最小高度占Image控件高度的百分比
ExpandedSubBlockEnd.gif        
/// </summary>

InBlock.gif        public int MinFontSize
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
get
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
return _minFontSize;
ExpandedSubBlockEnd.gif            }

InBlock.gif            
set
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                _minFontSize 
= value;
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif        
private int _maxFontSize = 100;
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// 字体最大高度占Image控件高度的百分比
ExpandedSubBlockEnd.gif        
/// </summary>

InBlock.gif        public int MaxFontSize
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
get
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
return _maxFontSize;
ExpandedSubBlockEnd.gif            }

InBlock.gif            
set
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                _maxFontSize 
= value;
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
private Color _fontColor = Color.Black;
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// 字符颜色
ExpandedSubBlockEnd.gif        
/// </summary>

InBlock.gif        public Color FontColor
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
get
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
return _fontColor;
ExpandedSubBlockEnd.gif            }

InBlock.gif            
set
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                _fontColor 
= value;
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
private Color _bgColor = Color.White;
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// 背景颜色
ExpandedSubBlockEnd.gif        
/// </summary>

InBlock.gif        public Color BgColor
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
get
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
return _bgColor;
ExpandedSubBlockEnd.gif            }

InBlock.gif            
set
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                _bgColor 
= value;
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
private string[] _fonts = null;
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// 可用字体列表,生成时,会随机选择
ExpandedSubBlockEnd.gif        
/// </summary>

InBlock.gif        public string[] Fonts
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
get
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
return _fonts;
ExpandedSubBlockEnd.gif            }

InBlock.gif            
set
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
if (value == null)
InBlock.gif                    
throw new ArgumentNullException("Fonts");
InBlock.gif
InBlock.gif                
if(value.Length == 0)
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    
throw new ArgumentException("至少指定一种字体");
ExpandedSubBlockEnd.gif                }

InBlock.gif                _fonts 
= value;
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
private int _maxRotate = 45;
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// 每个字符最大旋转角度
ExpandedSubBlockEnd.gif        
/// </summary>

InBlock.gif        public int MaxRotate
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif            
get dot.gifreturn _maxRotate; }
ExpandedSubBlockStart.gifContractedSubBlock.gif            
set dot.gif{ _maxRotate = value; }
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif
InBlock.gif
InBlock.gif
InBlock.gif        
public ImageValidatorConfig(string chars, int charCount, Color fontColor, string[] fonts, int minFontSise, int maxFontSize)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
this.Chars = chars;
InBlock.gif            
this.CharCount = charCount;
InBlock.gif            
this.FontColor = fontColor;
InBlock.gif            
this.MinFontSize = minFontSise;
InBlock.gif            
this.MaxFontSize = maxFontSize;
InBlock.gif            
this.Fonts = fonts;
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif
InBlock.gif    
public class ValidateCodeHandler : System.Web.IHttpHandler, IRequiresSessionState
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
ContractedSubBlock.gifExpandedSubBlockStart.gif        
IHttpHandler 成员#region IHttpHandler 成员
InBlock.gif
InBlock.gif        
public bool IsReusable
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif            
get dot.gifreturn false; }
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
public void ProcessRequest(HttpContext context)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
try
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
string sign = context.Request.QueryString["sign"];
InBlock.gif
InBlock.gif                
//生成一个验证码图片
InBlock.gif
                using (System.Drawing.Image bmp = BuildValidateImage(sign))// images[sign];
ExpandedSubBlockStart.gifContractedSubBlock.gif
                dot.gif{
InBlock.gif                    
//输出到浏览器
InBlock.gif
                    context.Response.Clear();
InBlock.gif                    context.Response.ContentType 
= "image/Png";
InBlock.gif                    bmp.Save(context.Response.OutputStream, ImageFormat.Jpeg);
InBlock.gif                    context.Response.End();
InBlock.gif
ExpandedSubBlockEnd.gif                }

ExpandedSubBlockEnd.gif            }

InBlock.gif            
catch
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                context.Response.End();
InBlock.gif
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif
ExpandedSubBlockEnd.gif        
#endregion

InBlock.gif
InBlock.gif        
protected static string SESSIONKEY = "iyond::imagevalidator";
InBlock.gif
InBlock.gif        
protected static Dictionary<doubledouble> _cacheSqrt = new Dictionary<doubledouble>();
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// 为了加快开方,自己写一个开方函数
InBlock.gif        
/// </summary>
InBlock.gif        
/// <param name="d"></param>
ExpandedSubBlockEnd.gif        
/// <returns></returns>

InBlock.gif        public static double Sqrt(double d)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
if (_cacheSqrt.ContainsKey(d))
InBlock.gif                
return _cacheSqrt[d];
InBlock.gif            
else
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
lock (_cacheSqrt)
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    
double ret = Math.Sqrt(d);
InBlock.gif                    _cacheSqrt[d] 
= ret;
InBlock.gif                    
return ret;
ExpandedSubBlockEnd.gif                }

ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// 取验证码图片的字串形式,取出时清空。以防止漏洞
InBlock.gif        
/// </summary>
InBlock.gif        
/// <param name="sign">验证码配置标识</param>
ExpandedSubBlockEnd.gif        
/// <returns></returns>

InBlock.gif        public static string GetAndEmptyValidateCode(string sign)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
if (ValidateCodeDictionary.ContainsKey(sign))
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
string validatecode = ValidateCodeDictionary[sign];
InBlock.gif                ValidateCodeDictionary[sign] 
= string.Empty;
InBlock.gif                
return validatecode;
ExpandedSubBlockEnd.gif            }

InBlock.gif            
else
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
return string.Empty;
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// 依配置生成验证码图片
InBlock.gif        
/// </summary>
InBlock.gif        
/// <param name="sign">验证码配置标识</param>
ExpandedSubBlockEnd.gif        
/// <returns></returns>

InBlock.gif        public static System.Drawing.Image BuildValidateImage(string sign)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
//得到验证吗生成配置
InBlock.gif
            ImageValidatorConfig config = ImageValidator.GetConfig(sign);
InBlock.gif
InBlock.gif            
//生成新验证码
InBlock.gif
            string validatecode = Utility.GetRandomChar(config.Chars, config.CharCount);
InBlock.gif            ValidateCodeDictionary[sign] 
= validatecode;
InBlock.gif
InBlock.gif            Random random 
= new Random();
InBlock.gif
InBlock.gif            
//随机生成每个字要使用的字体和大小
InBlock.gif
            List<DrawCharInfo> draws = new List<DrawCharInfo>();
InBlock.gif            
using (Bitmap bmpTemp = new Bitmap(11))
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
using (Graphics gm = Graphics.FromImage(bmpTemp))
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    
using (SolidBrush brush = new SolidBrush(config.FontColor))
ExpandedSubBlockStart.gifContractedSubBlock.gif                    
dot.gif{
InBlock.gif                        
char[] chars = validatecode.ToCharArray();
InBlock.gif                        
foreach (char ch in chars)
ExpandedSubBlockStart.gifContractedSubBlock.gif                        
dot.gif{
InBlock.gif                            
string fontName = config.Fonts[random.Next(0, config.Fonts.Length - 1)];
InBlock.gif                            
float fontSize = Convert.ToSingle(random.Next(config.MinFontSize, config.MaxFontSize));
InBlock.gif                            Font font 
= new Font(fontName, fontSize , FontStyle.Regular, GraphicsUnit.Pixel);
InBlock.gif
InBlock.gif                            SizeF size 
= gm.MeasureString(ch.ToString(), font);
InBlock.gif
InBlock.gif                            draws.Add(
new DrawCharInfo(ch, font, size));
ExpandedSubBlockEnd.gif                        }

ExpandedSubBlockEnd.gif                    }

ExpandedSubBlockEnd.gif                }

ExpandedSubBlockEnd.gif            }

InBlock.gif
InBlock.gif            
//找出最大高度,找出图片宽度
InBlock.gif
            int bmpWidth = 0, bmpHeight = 0;
InBlock.gif            
foreach (DrawCharInfo dci in draws)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                bmpWidth 
+= Convert.ToInt32(dci.Size.Width) + 1;
InBlock.gif                bmpHeight 
= Math.Max(bmpHeight, Convert.ToInt32(dci.Size.Height) + 1);
ExpandedSubBlockEnd.gif            }

InBlock.gif
InBlock.gif
InBlock.gif            
//依每个字符的配置,生成图片
InBlock.gif
            Bitmap bmp = new Bitmap(bmpWidth, bmpHeight);
InBlock.gif            
using (Graphics g = Graphics.FromImage(bmp))
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                g.SmoothingMode 
= System.Drawing.Drawing2D.SmoothingMode.HighQuality;
InBlock.gif                
using (SolidBrush brush = new SolidBrush(config.FontColor))
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    
//用背景清空,将来可以考虑生成背景
InBlock.gif
                    g.Clear(config.BgColor);
InBlock.gif
InBlock.gif                    
//宽度计数
InBlock.gif
                    float x = 0;
InBlock.gif
InBlock.gif                    
foreach (DrawCharInfo dci in draws)
ExpandedSubBlockStart.gifContractedSubBlock.gif                    
dot.gif{
InBlock.gif                        
//保存场景配置
InBlock.gif
                        GraphicsState gs = g.Save();
InBlock.gif
InBlock.gif                        
//随机Y坐标
InBlock.gif
                        float y = random.Next(Math.Max(0, bmpHeight - Convert.ToInt32(dci.Size.Height))) / 2;
InBlock.gif
InBlock.gif                        
//随机旋转角度
InBlock.gif
                        float rotate = random.Next(-config.MaxRotate, config.MaxRotate);
InBlock.gif
InBlock.gif                        
//计算宽高
InBlock.gif
                        float halfWidth = dci.Size.Width / 2;
InBlock.gif                        
float halfHeight = dci.Size.Height / 2;
InBlock.gif
InBlock.gif                        
//变换坐标
InBlock.gif
                        g.TranslateTransform(x + halfWidth, y + halfHeight);
InBlock.gif                        g.RotateTransform(rotate);
InBlock.gif
InBlock.gif                        
//打印字符
InBlock.gif
                        g.DrawString(dci.Char.ToString(), dci.Font, brush, -halfWidth, -halfHeight);
InBlock.gif
InBlock.gif                        
//原来场景
InBlock.gif
                        g.Restore(gs);
InBlock.gif
InBlock.gif                        
//增加宽度计数
InBlock.gif
                        x += dci.Size.Width;
ExpandedSubBlockEnd.gif                    }

ExpandedSubBlockEnd.gif                }

ExpandedSubBlockEnd.gif            }

InBlock.gif
InBlock.gif            
//返回图片
InBlock.gif
            return bmp;
InBlock.gif
ExpandedSubBlockEnd.gif        }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// 保存每个标识的验证码字串
ExpandedSubBlockEnd.gif        
/// </summary>

InBlock.gif        protected static Dictionary<stringstring> ValidateCodeDictionary
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
get
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
if (HttpContext.Current.Session[SESSIONKEY] == null)
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    HttpContext.Current.Session[SESSIONKEY] 
= new Dictionary<stringstring>();
ExpandedSubBlockEnd.gif                }

InBlock.gif
InBlock.gif                
return HttpContext.Current.Session[SESSIONKEY] as Dictionary<stringstring>;
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
/**//// <summary>
InBlock.gif    
/// 每个字符的在验证吗图片的字体,大小信息
ExpandedSubBlockEnd.gif    
/// </summary>

InBlock.gif    internal class DrawCharInfo
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
private char _char;
InBlock.gif        
private Font _font;
InBlock.gif        
private SizeF _size;
InBlock.gif
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// 字符
ExpandedSubBlockEnd.gif        
/// </summary>

InBlock.gif        public Char Char
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif            
get dot.gifreturn _char; }
ExpandedSubBlockEnd.gif        }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// 字体
ExpandedSubBlockEnd.gif        
/// </summary>

InBlock.gif        public Font Font
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif            
get dot.gifreturn _font; }
ExpandedSubBlockEnd.gif        }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// 字体所占区域
ExpandedSubBlockEnd.gif        
/// </summary>

InBlock.gif        public SizeF Size
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif            
get dot.gifreturn _size; }
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
public DrawCharInfo(char ch, Font font, SizeF size)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
this._char = ch;
InBlock.gif            
this._font = font;
InBlock.gif            
this._size = size;
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

None.gif

.Net 验证码控件 操作简单,使用方便参数使用有详细介绍 拖入即可应用!!!!!! 添加到工具箱的步骤 1.将 Vincent.AutoAuthCode.dll 添加到项目的 Bin文件目录下 2.右键点击 Bin 目录 选择添加引用 找到添加的 Bin文件目录下 Vincent.AutoAuthCode.dll 3.在工具栏中,右键点击 常规 选项卡 再点击 选择项 4.在弹出的对话框中的右下方 点击 浏览 找到 Bin文件目录下 Vincent.AutoAuthCode.dll 打开 点击 确定 在 工具箱 的 常规选项 看到 AutcCode 控件 直接拖到要使用验证码的页面位置 即可。 页面的点击事件会触发验证,无需后台代码验证 一、控件特点: 1、使用方便,只需要从工具栏直接拖到页面即可自动验证,零代码使用。 2、自动完成客户端以及服务器的验证码验证,Ajax验证,随用户输入即时 验证并友好提示。 3、可自定义验证码图片外观。 4、有水平方向垂直方向两种方式选择。 5、有数字、小写字母、大写字母三种及任意两种组合、三种组合字符选择。 6、兼容IE及FireFox。 二、使用说明。 1、属性。 IsMatch:指示用户输入的验证码是否正确 TextControlWidth:文本框控件宽度 NextImgText:提示更换图片信息,该提示信息同时显示于图片上面及图片左边 IsShowNextImgText:是否在图片左边显示提示更换图片信息 EnableNextImgText:是否充许换一张图片 ErrorShowType:验证码错误显示方式 CodeStringType:验证码字符类型,组合枚举值,例如CodeStringTypes.Number|CodeStringTypes.LowerLetter CodeStringLength:验证码字符长度,最少为4 ImageType:验证码图像类型 IsMatchCase:验证码验证时是否区分大小写 LayoutDirection":控件各部分排列方向,排列的部分包括文本框、图片、"换一张图片"文本 EnableClientValidate:是否使用客户端脚本验证验证内容包括是否为空、长度是否正确 ImageStyle:验证码图像样式 如: TextControlWidth="90px" 设置 输入验证码的文本框宽度 其中ImageStyle为复类属性,其公开属性如下: ImageStyle-ImgBgColor:图片背景色 ImageStyle-ImgNoiseColor:图片噪声颜色 ImageStyle-ImgBorderColor"图片边框颜色 ImageStyle-TextColor1:文本颜色 ImageStyle-TextColor2:文本颜色2(如果文本为单色则无效) ImageStyle-TextFontSize:文本字体大小,以像素(pix)为单位,验证码图像大小根据此而变化,如果ImgSize大于由该值指定的大小,则图像大小为ImgSize ImageStyle-ImgSize:验证码图像大小,以像素(pix)为单位,如果TextFontSize指定的大小大于该值,则图像大小为TextFontSize指定的大小 ImageStyle-Width:验证码图像大小的宽度,以像素(pix)为单位,如果TextFontSize指定的大小大于该值,则图像大小为TextFontSize指定的大小 ImageStyle-Height:验证码图像大小的高度,以像素(pix)为单位,如果TextFontSize指定的大小大于该值,则图像大小为TextFontSize指定的大小 如: ImageStyle-Width=70 设置验证码图像大小的宽度 (值必须是整数) ImageStyle-ImgBgColor=#1D3647 图片背景色 (值不要添加单、双引号 [''," "])
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值