一步一步实现MVC5+EF6+Bootstarp+Autofac+NoSql实现OADemo 之登陆(一) 验证码 Captcha 之大插件小用
不知何年何月才能完成OADemo啊,总之还是一步一步来吧,这段时间开始着手了,先做登陆。 前段时间研究了一下在CentOS7下安装Mysql和Memcached服务,并测试了用C#操作,结果还行。
今天做一个简单的基于Bootstarp的响应式登陆页面(其实是在网上下的模板),不管是登陆还是注册吧,都会用到验证码,以前是用GDI绘出来的,觉得太丑了,百度的关于.net的验证码绝大多数也是用的这种方法,最后试了一下captcha,觉得还挺好看的,所以就试着用用。
nugit控制台install-package captcha到项目就行了,下载好了有个readme.txt文件,照着搞了一下,挺方便的
后台代码这样写的
[HttpPost] [CaptchaValidation("CaCode", "ExampleCaptcha", "Incorrect CAPTCHA code!")] public ActionResult ExampleAction(bool captchaValid) { if (!captchaValid) { return Content("no"); } else { return Content("ok"); } }
前台这样子的
<form action="/Example/ExampleAction" method="post"> @{ MvcCaptcha exampleCaptcha = new MvcCaptcha("ExampleCaptcha"); exampleCaptcha.UserInputID = "CaCode"; exampleCaptcha.ImageStyle = BotDetect.ImageStyle.CaughtInTheNet2; @Html.Captcha(exampleCaptcha) @*@Html.TextBox("CaCode")*@ <input type="text" id="CaCode" name="CaCode"/> } <input type="submit" value="GO" /> </form>
这都是照着readme搞的,当然还有注册路由的
public class RouteConfig { public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.IgnoreRoute("{*botdetect}", new { botdetect = @"(.*)BotDetectCaptcha\.ashx" }); routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } ); } }
就这三步就行了,然后测试一下,先输个错的试试,点GO,输出no,很好,再搞个对的,输出ok相当可以,再然后,不小心输错了还是ok,再然后空的还是ok???
把浏览器关了,重新生成再打开试,哪怕第一次是错的也是输出ok。另外还有一个问题点图片就会转到https://captcha.org/captcha.html?asp.net这个地址。
问题一
出现这个问题按理说应该是好事,说明插件帮我们做了缓存验证码的事,并且还设置了过期时间,将部分属性打印到页面看看情况
<form action="/Example/ExampleAction" method="post"> @{ MvcCaptcha exampleCaptcha = new MvcCaptcha("ExampleCaptcha"); exampleCaptcha.UserInputID = "CaCode"; exampleCaptcha.ImageStyle = BotDetect.ImageStyle.CaughtInTheNet2; @Html.Captcha(exampleCaptcha) @*@Html.TextBox("CaCode")*@ <input type="text" id="CaCode" name="CaCode"/> <ul> <li>HelpLinkUrl: @exampleCaptcha.HelpLinkUrl</li> <li>AddInitScript: @exampleCaptcha.AddInitScript</li> <li>AdditionalCssClasses: @exampleCaptcha.AdditionalCssClasses</li> <li>AdditionalInlineCss: @exampleCaptcha.AdditionalInlineCss</li> <li>AddScriptInclude: @exampleCaptcha.AddScriptInclude</li> <li>AutoClearInput: @exampleCaptcha.AutoClearInput</li> <li>AutoFocusInput: @exampleCaptcha.AutoFocusInput</li> <li>AutoReloadTimeout: @exampleCaptcha.AutoReloadTimeout</li> <li>CodeLength: @exampleCaptcha.CodeLength</li> <li>CodeStyle: @exampleCaptcha.CodeStyle</li> <li>CodeTimeout: @exampleCaptcha.CodeTimeout</li> <li>HelpLinkEnabled: @exampleCaptcha.HelpLinkEnabled</li> <li>HelpLinkText: @exampleCaptcha.HelpLinkText</li> <li>IconsDivWidth: @exampleCaptcha.IconsDivWidth</li> <li>ReloadIconUrl: @exampleCaptcha.ReloadIconUrl</li> <li>SoundIconUrl: @exampleCaptcha.SoundIconUrl</li> <li>ImageStyle: @exampleCaptcha.ImageStyle</li> <li>Locale: @exampleCaptcha.Locale</li> <li> @exampleCaptcha.HelpLinkMode</li> <li> @exampleCaptcha.WebCaptcha.CaptchaImageUrl</li> <li> @exampleCaptcha.WebCaptcha.CaptchaBase.GetCode("ExampleCaptcha", BotDetect.CodeGenerationPurpose.ImageGeneration).CaptchaCode</li> </ul> } <input type="submit" value="GO" /> </form>
从第一个属性来看应该是解决问题二的办法,但是很不幸,设置exampleCaptcha.HelpLinkUrl和HelpLinkText的值无效,结果还是回到了默认值。
还有就是CodeTimeout也是设置无效。在webconfig中
<sessionState mode=" sessionIDManagerType="BotDetect.Web.CustomSessionIdManager, BotDetect" />
设置timeout小于20的值也无效,可能是有个最小值限定吧,这里我还没有试过超过20的值,晕!
其它的还好吧。
最后一个属性是我企图找出当前的验证码,依然很不幸,并不是,到现在我还没办法得到。之所以想得当验证码,其一是我觉得它帮我做的就是在session中缓存了验证码,可我并不想用session,如果只是保存在cookie中,那敢情好,我也无需得到验证码。
看看点击刷新按钮的请求
可以看出有三个GET请求,前两个是请求刷新和声音的按钮,后面一个是请求图片的。主要看后面一个,看来是有请求cookie的,并且有两个key。虽然如此,可我还并不肯定到底有没有用session缓存,关于这个,希望路过的大牛给予指导。
再看看参数,有四个参数,每次请求只有d的值是变化的,这就是跟我们以前用的验证码刷新是一个意思啦。这个请求地址正是exampleCaptcha.WebCaptcha.CaptchaImageUrl的属性值。
看看刷新按钮最终生成的html是什么样子的,如下图,最关键的是a标签的onclick(红框框起部分),虽然看不到具体方法,但能知道方法的最终结果就是为了完成上面的请求。能理解这个,其它的都可以理解了。
其二我并不喜欢在前端写过多的C#代码。观察了一下后端代码
[CaptchaValidation("CaCode", "ExampleCaptcha", "Incorrect CAPTCHA code!")]
public ActionResult ExampleAction(bool captchaValid)...
对于Action的参数captchaValid我很不解,当我改变参数名称后就会报错,想想应该是CaptchaValidationAttribute中得来的吧,觉得用这个Attribute限制太多,不够灵活。最终我去掉了Attribute,用MvcCaptcha类的静态方法 MvcCaptcha.Validate(string,string,string),这个重载需要三个参数一个是captcha的Id,一个是用户输入值,另一个是validtingInstanceId
对于最后一个参数我开始摸不着北,后面在html源码中找到个hidden的input,只是感觉像是它,因为它有name属性,凭着感觉试了,没想还真行
那么就把后台给改了试试,其实最后个参数的值就是exampleCaptcha.CurrentInstanceId这个属性值(有时我自己觉得我有点傻的可爱),这样一来问题一就解决了部分问题,可以不用在前端写那么多C#代码了,并且每次登陆页面都要输入对的验证码才能ok。
public ActionResult ExampleAction(string CaCode, string BDC_VCID_ExampleCaptcha) { string instaneId = CustomCaptcha.CurrentInstanceId; bool captchaValid= MvcCaptcha.Validate("ExampleCaptcha", CaCode,BDC_VCID_ExampleCaptcha); if (captchaValid) return Content("ok"); return Content("no"); }
问题二
解决问题二我用的办法很粗暴,我后来重做了一个MVC项目,做了一个完整的登陆页面,那个刷新和声音按钮我不好布局,直接给隐藏了,既然它粗暴的让改属性值不能改变验证图片的点击链接,我又不能说让用户点图片进入一个外国网站,那么我也只能粗暴通过jquery来解决问题,我想的办法就是把前面关于刷新按钮的a标签的onclick给图片中a标签的onclick,简单粗暴。
虽然两个问题并没有完美解决,但感觉自己还在挺努力的。所以最后把修改的全部代码贴上吧
最终效果
前端
@{ Layout = null; } @using BotDetect.Web.Mvc; <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1.0" /> <title>登录</title> <link href="~/Content/bootstrap.min.css" rel="stylesheet" /> <link href="~/Content/LoginStyle.css" rel="stylesheet" /> <script src="~/scripts/jquery-1.9.1.min.js"></script> <script src="~/scripts/bootstrap.min.js"></script> <script type="text/javascript"> $(function () { $("#ExampleCaptcha_CaptchaImageDiv a").attr("onclick", "ExampleCaptcha.ReloadImage(); this.blur(); return false;") .attr("href", "#").attr("title", "点击刷新验证码"); }) </script> </head> <body> <div class="box"> <div class="login-box"> <div class="login-title text-center"> <h1><small>登录</small></h1> </div> <div class="login-content "> <div class="form form-horizontal" > <form action="/Login/Account" method="post"> <div class="form-group"> <div class="col-xs-12 "> <div class="input-group"> <span class="input-group-addon"><span class="glyphicon glyphicon-user"></span></span> <input type="text" id="username" name="username" class="form-control" placeholder="用户名"> </div> </div> </div> <div class="form-group"> <div class="col-xs-12 "> <div class="input-group"> <span class="input-group-addon"><span class="glyphicon glyphicon-lock"></span></span> <input type="text" id="password" name="password" class="form-control" placeholder="密码"> </div> </div> </div> <div class="form-group"> <div class="col-xs-12"> <div class="input-group"> <div class="col-xs-6" style="margin-left:0" > <input type="text" id="CaptchaCode" style="width:200px" class="form-control" placeholder="输入验证码(点图可刷新)" name="CaptchaCode"/> </div> <div class="col-xs-6" style="margin-left:0"> @Html.Captcha(CustomCaptcha.GetCaptcha(,,)) </div> </div> </div> </div> <div class="form-group form-actions"> <div class="col-xs-4 col-xs-offset-4 "> <button type="submit" class="btn btn-sm btn-info"><span class="glyphicon glyphicon-off"></span> 登录</button> </div> </div> <div class="form-group"> <div class="col-xs-6 link"> <p class="text-center remove-margin"> <small>忘记密码?</small> <a href="javascript:void(0)"><small>找回</small></a> </p> </div> <div class="col-xs-6 link"> <p class="text-center remove-margin"> <small>还没注册?</small> <a href="javascript:void(0)"><small>注册</small></a> </p> </div> </div> </form> </div> </div> </div> </div> </body> </html>
后端专门写了一个类,有一个静态属性,用于指定当前验证码的实例Id,一个静态方法,用于自定义captcha
using BotDetect.Web.Mvc; namespace OADemo.MVCApp { public class CustomCaptcha { /// <summary> /// 当前验证码的实例Id /// </summary> public static string CurrentInstanceId { get { return currentInstanceId; } } private static string currentInstanceId; public static MvcCaptcha GetCaptcha(string captchaId) { MvcCaptcha exampleCaptcha = new MvcCaptcha(captchaId); exampleCaptcha.ImageStyle = BotDetect.ImageStyle.CaughtInTheNet2; exampleCaptcha.ReloadEnabled = false; exampleCaptcha.SoundEnabled = false; currentInstanceId = exampleCaptcha.CurrentInstanceId; return exampleCaptcha; } /// <summary> /// 获取自定义的验证码样式 /// </summary> /// <param name="captchaId"></param> /// <param name="width">指定验证码图片的宽度</param> /// <param name="height">指定验证码图片的高度</param> /// <param name="codeLength">指定验证码的个数</param> /// <returns></returns> public static MvcCaptcha GetCaptcha(string captchaId,int width,int height,int codeLength) { MvcCaptcha exampleCaptcha = new MvcCaptcha(captchaId); exampleCaptcha.ImageStyle = BotDetect.ImageStyle.CaughtInTheNet2;//我个人喜欢的风格 exampleCaptcha.ReloadEnabled = false;//去掉刷新的按钮 exampleCaptcha.SoundEnabled = false;//去掉声音播放按钮 exampleCaptcha.CodeLength = codeLength;//指定验证码的长度 exampleCaptcha.ImageSize = new System.Drawing.Size(width,height);//指定图片的大小 currentInstanceId = exampleCaptcha.CurrentInstanceId;//当前实例的id return exampleCaptcha; } } }
后端控制器代码
using System.Web.Mvc; namespace OADemo.MVCApp.Controllers { public class LoginController : Controller { // GET: Login public ActionResult Index() { return View(); } public ActionResult Account(string CaptchaCode, string name, string pwd,string BDC_VCID_ExampleCaptcha) { string instaneId = CustomCaptcha.CurrentInstanceId; bool captchaValid= MvcCaptcha.Validate("ExampleCaptcha", CaptchaCode,instaneId); if (captchaValid) return Content("ok"); return Content("no"); } } }
Controller Code
好吧,后端控制器代码应该是这样才对的
using System.Web.Mvc; namespace OADemo.MVCApp.Controllers { public class LoginController : Controller { // GET: Login public ActionResult Index() { return View(); } public ActionResult Account(string CaptchaCode, string username, string password) { string instaneId = CustomCaptcha.CurrentInstanceId; bool captchaValid= MvcCaptcha.Validate("ExampleCaptcha", CaptchaCode,instaneId); if (captchaValid) return Content("ok"); return Content("no"); } } }
目前就写到这里了,当然后面的验证还没写,还只是在测试captcha阶段,所以想说要源码的同志,就不要费力了,因为这里忘记密码和注册都没有写的。这一篇完全只是写的我目前对captcha的研究,也许在众多的MvcCaptcha类的事件中,才是真正有效解决问题的办法,只是我没有英文水平,加上现在时间太晚,眼睛和脑袋受不了,暂告一段落,事件这么多呢,搞懂了,webconfig配置都可以自定义
public static event EventHandler<GeneratedCaptchaCodeEventArgs> GeneratedCaptchaCode; public static event EventHandler<GeneratedCaptchaImageEventArgs> GeneratedCaptchaImage; public static event EventHandler<GeneratedCaptchaSoundEventArgs> GeneratedCaptchaSound; public static event EventHandler<GeneratingCaptchaCodeEventArgs> GeneratingCaptchaCode; public static event EventHandler<GeneratingCaptchaImageEventArgs> GeneratingCaptchaImage; public static event EventHandler<GeneratingCaptchaSoundEventArgs> GeneratingCaptchaSound; public static event EventHandler<InitializedWebCaptchaEventArgs> InitializedWebCaptcha; public static event EventHandler<ValidatedUserInputEventArgs> ValidatedUserInput; public static event EventHandler<ValidatingUserInputEventArgs> ValidatingUserInput;
一步一步实现MVC5+EF6+Bootstarp+Autofac+NoSql实现OADemo 之登陆(一) 验证码 Captcha 之大插件小用的更多相关文章
- 一步一步创建ASP.NET MVC5程序[Repository+Autofac+Automapper+SqlSugar](一)
前言 大家好,我是Rector 从今天开始,Rector将为大家推出一个关于创建ASP.NET MVC5程序[Repository+Autofac+Automapper+SqlSugar]的文章系列, ...
- 一步一步创建ASP.NET MVC5程序[Repository+Autofac+Automapper+SqlSugar](五)
前言 Hi,大家好,我是Rector 时间飞逝,一个星期又过去了,今天还是星期五,Rector在图享网继续跟大家分享系列文本:一步一步创建ASP.NET MVC5程序[Repository+Autof ...
- 一步一步创建ASP.NET MVC5程序[Repository+Autofac+Automapper+SqlSugar](四)
前言 上一篇<一步一步创建ASP.NET MVC5程序[Repository+Autofac+Automapper+SqlSugar](三)>,我们完成了: * 引用SqlSugar * ...
- 一步一步创建ASP.NET MVC5程序[Repository+Autofac+Automapper+SqlSugar](三)
前言 上一篇<一步一步创建ASP.NET MVC5程序[Repository+Autofac+Automapper+SqlSugar](二)>我们通过如下操作: 创建实体及工具类 创建Re ...
- 一步一步创建ASP.NET MVC5程序[Repository+Autofac+Automapper+SqlSugar](二)
前言: 在本系列第一篇<一步一步创建ASP.NET MVC5程序[Repository+Autofac+Automapper+SqlSugar](一)>中,我为大家介绍了搭建空白解决方案以 ...
- 一步一步创建ASP.NET MVC5程序[Repository+Autofac+Automapper+SqlSugar](六)
前言 大家好,我是Rector 又是星期五,很兴奋,很高兴,很high...啦啦啦... Rector在图享网又和大家见面啦!!!上一篇<一步一步创建ASP.NET MVC5程序[Reposit ...
- 一步一步创建ASP.NET MVC5程序[Repository+Autofac+Automapper+SqlSugar](七)
前言 大家好,我依旧是你们的老朋友Rector,很高兴又在周五的时候准时和大家见面. Rector的系列文章[一步一步创建ASP.NET MVC5程序[Repository+Autofac+Autom ...
- 一步一步创建ASP.NET MVC5程序[Repository+Autofac+Automapper+SqlSugar](八)
前言 Hi, 大家好,还是星期五,还是Rector,又在图享网准时和大家见面了. 今天给大家带来系列教程<一步一步创建ASP.NET MVC5程序[Repository+Autofac+Auto ...
- 一步一步创建ASP.NET MVC5程序[Repository+Autofac+Automapper+SqlSugar](九)
前言 童鞋们,大家好 我是专注.NET开发者社区建设的实践者Rector. 首先,为自己间隔了两个星期五再更新本系列文章找个不充分的理由:Rector最近工作,家庭的各种事务所致,希望大家谅解. 本文 ...
随机推荐
- nginx资源定向 css js路径问题
今天玩玩项目,学学nginx发现还不错,速度还可以,但是CSS JS确无法使用,原来Iginx配置时需要对不同类型的文件配置规则,真是很郁闷,不过想想也还是很有道理.闲暇之际,把配置贴上来.#user ...
- House Robber
You are a professional robber planning to rob houses along a street. Each house has a certain amount ...
- IE hack中主要的几个
_: IE6; #*+.: IE6 IE7; black\0: IE8; black\9: IE所有; @media screen\9 { … }: IE6 IE7; @media \0screen\ ...
- Server Tomcat v7.0 Server at localhost was unable to start within 45 seconds 解决方法
Server Tomcat v6.0 Server at localhost was unable to start within 45 seconds. If the server requires ...
- Linux下安装PHP
从php官网下载好需要php的压缩包,我下的是5.5.37版, 解压:# tar -xvf php-5.5.37.tar.gz 移至解压出的文件夹:# cd php-5.5.37 检查安装环境:# . ...
- bzoj1222: [HNOI2001]产品加工--DP
DP神题orz dp[i]表示机器1工作i小时,机器2工作dp[i]小时 那么对于每个任务: 选1:dp[i]=dp[i-a]; 选2:dp[i]=dp[i]+b; 选1+2:dp[i]=dp[i-c ...
- 火狐的调试利器-----Firebug
什么是Firebug 从事了数年的Web开发工作,越来越觉得现在对WEB开发有了更高的要求.要写出漂亮的HTML代码:要编写精致的CSS样式表展示每个页面模块:要调试javascript给页面增加一些 ...
- 一个链接直接打开APP
http://www.cnblogs.com/jzm17173/p/4569574.html 这是IOS http://www.jianshu.com/p/af211f2a990e
- Mongodb数据库加密存储(python)
需求: 不知道大家有没有遇到过这样的需求:自己的服务器出于对数据库安全的保护,需要对存储的数据进行加密保护.这样万一数据库被人拿到,别人也不能拿到数据库里面的内容.这里还有一个前提:前端的展示页面是 ...
- IOS彩票第三天界面
******ios6 和ios7的适配 ILBaseTableViewController.m - (void)viewDidLoad { [super viewDidLoad]; // 244 24 ...