نحوه ایجاد یک تصویر امنیتی (Captcha) با حروف فارسی در ASP.Net MVC
نویسنده: پژمان پارسائی
تاریخ: ۱۳۹۲/۰۳/۰۳ ۱۷:۵
آدرس: www.dntips.ir
| مطالب | ۳۶۹۴ |
| نویسندگان | ۲۷۶ |
| گروههای مطالب | ۱۰۲۴ |
| نقشههای راه | ۱۱۹ |
| دورهها | ۱۴ |
| اشتراکها | ۱۷۹۱۴ |
using System;
using System.Web.Mvc;
namespace MVCPersianCaptcha.Models
{
public class CaptchaImageResult : ActionResult
{
public override void ExecuteResult(ControllerContext context)
{
throw new NotImplementedException();
}
}
} // Create a new 32-bit bitmap image. Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb);
// Create a graphics object for drawing. Graphics gfxCaptchaImage = Graphics.FromImage(bitmap);
gfxCaptchaImage.PageUnit = GraphicsUnit.Pixel; gfxCaptchaImage.SmoothingMode = SmoothingMode.HighQuality; gfxCaptchaImage.Clear(Color.White);
// Create a Random Number from 1000 to 9999 int salt = CaptchaHelpers.CreateSalt();
public int CreateSalt()
{
Random random = new Random();
return random.Next(1000, 9999);
} HttpContext.Current.Session["captchastring"] = salt;
string randomString = (salt).NumberToText(Language.Persian);
// Set up the text format.
var format = new StringFormat();
int faLCID = new System.Globalization.CultureInfo("fa-IR").LCID;
format.SetDigitSubstitution(faLCID, StringDigitSubstitute.National);
format.Alignment = StringAlignment.Near;
format.LineAlignment = StringAlignment.Near;
format.FormatFlags = StringFormatFlags.DirectionRightToLeft; // Font of Captcha and its size
Font font = new Font("Tahoma", 10); // Create a path for text GraphicsPath path = new GraphicsPath();
path.AddString(randomString,
font.FontFamily,
(int)font.Style,
(gfxCaptchaImage.DpiY * font.SizeInPoints / 72),
new Rectangle(0, 0, width, height), format); gfxCaptchaImage.DrawPath(Pens.Navy, path);
//-- using a sin ware distort the image
int distortion = random.Next(-10, 10);
using (Bitmap copy = (Bitmap)bitmap.Clone())
{
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
int newX = (int)(x + (distortion * Math.Sin(Math.PI * y / 64.0)));
int newY = (int)(y + (distortion * Math.Cos(Math.PI * x / 64.0)));
if (newX < 0 || newX >= width) newX = 0;
if (newY < 0 || newY >= height) newY = 0;
bitmap.SetPixel(x, y, copy.GetPixel(newX, newY));
}
}
} //-- Draw the graphic to the bitmap gfxCaptchaImage.DrawImage(bitmap, new Point(0, 0)); gfxCaptchaImage.Flush();
HttpResponseBase response = context.HttpContext.Response; response.ContentType = "image/jpeg"; bitmap.Save(response.OutputStream, ImageFormat.Jpeg);
// Clean up. font.Dispose(); gfxCaptchaImage.Dispose(); bitmap.Dispose();
public CaptchaImageResult CaptchaImage()
{
return new CaptchaImageResult();
} <img src="@Url.Action("CaptchaImage")"/> [HttpPost]
public ActionResult Index(LogOnModel model)
{
if (!ModelState.IsValid) return View(model);
if (model.CaptchaInputText == Session["captchastring"].ToString())
TempData["message"] = "تصویر امنتی را صحیح وارد کرده اید";
else
TempData["message"] = "تصویر امنیتی را اشتباه وارد کرده اید";
return View();
} [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public sealed class ValidateCaptchaAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var controllerBase = filterContext.Controller;
var captchaInputTextProvider = controllerBase.ValueProvider.GetValue("CaptchaInputText");
if (captchaInputTextProvider == null)
{
controllerBase.ViewData.ModelState.AddModelError("CaptchaInputText", "لطفا تصویر امنیتی را وارد کنید");
base.OnActionExecuting(filterContext);
return;
}
var inputText = captchaInputTextProvider.AttemptedValue;
if (inputText != Session["captchastring"].ToString())
controllerBase.ViewData.ModelState.AddModelError("CaptchaInputText", "تصویر امنیتی را اشتباه وارد کرده اید");
}
}سلام
اگر کد شما را گسترش دهیم و به جای پیغامهای خطای ارسال شده، مقادیر Attributeها یا متادیتاهایی مثل Required را خواند و مستقیم پیغامی به کنترل و ModelState پاس نداد، فکر میکنم کاملتر باشه .
ممنون - مطلب کاربردی و مفیدی بود
شخصا این Captcha را به انواع دیگر ترجیح میدم چرا که:
1- شخصی سازی شده
2- ارجاع به سایت واسطی نداره
3- هیچ گونه سرباری نداره
4- اعمال هر گونه تغییر و اصلاح مناسب با فرهنگ و کشور و یا حتی نوع سایت قابل انجام است
بازهم تشکر میکنم
WebApiConfig.Register(GlobalConfiguration.Configuration);
public ValidateCaptchaAttribute()
{
ErrorWasHappened = "خطایی اتفاق افتاده است";
CaptchaCodeIsRequired = "لطفا کد امنیتی را وارد کنید";
CaptchaCodeIsIncorrect = "کد امنیتی را اشتباه وارد کرده اید";
CookieMustEnabled = "باید ابتدا قابلیت کوکیها را در مرورگر خود فعال کنید";
ExpireTimeCaptchaCodeBySeconds = 60;
TimeIsExpired = string.Format("حداکثر مهلت وارد کردن کد امنیتی {0} ثانیه است",ExpireTimeCaptchaCodeBySeconds.ToString());
}The system cannot find the file specified " source="mscorlib" detail="System.Security.Cryptography.CryptographicException: The system cannot find the file specified.
<system.web> <trust level="Medium" originUrl=".*" />
شاید هاست شما مدیوم تراست هست. برای تست روی لوکال این تنظیم بالا رو به وب کانفیگ اضافه کنید تا خطا رو بتونید لوکال دیباگ کنید.
The application attempted to perform an operation not allowed by the security policy. To grant this application the required permission please contact your system administrator or change the application's trust level in the configuration file
<trust level="Full" originUrl=".*" />
[System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Assert, Unrestricted = true)]
var cspp = new CspParameters { KeyContainerName = key };var cspp = new CspParameters { KeyContainerName = key, Flags = CspProviderFlags.UseMachineKeyStore };پیغام:
The system cannot find the file specified " source=" mscorlib "
< trust level = "Medium" originUrl = ".*" />
System.Security.Cryptography.CryptographicException: Object already exists
Resource interpreted as Image but transferred with MIME type text/html: "http://site:8080/Error/Index?aspxerrorpath=/Shared/CaptchaImage"
اگر به سرور دسترسی دارید این دستور را اجرا کنید:
aspnet_regiis -pa "SampleKeys" "NT AUTHORITY\NETWORK SERVICE"
[OutputCache(Location = OutputCacheLocation.None, NoStore = true)]
// در فایل CaptchaImageResult.cs HttpResponseBase response = context.HttpContext.Response; response.ContentType = "image/jpeg"; context.HttpContext.DisableBrowserCache(); // این سطر جدید است bitmap.Save(response.OutputStream, ImageFormat.Jpeg);
public class HomeController : Controller
{
[NoBrowserCache]
public ActionResult Index() [NoBrowserCache] [OutputCache(Location = OutputCacheLocation.None, NoStore = true, Duration = 0, VaryByParam = "None")] public CaptchaImageResult CaptchaImage(string rndDate)
<img src="@Url.Action("CaptchaImage", "Home", routeValues: new{ rdnDate = DateTime.Now.Ticks })"/> {"Error occurred while decoding OAEP padding."} if (context.RequestContext.HttpContext.Request.UrlReferrer.AbsolutePath ==
context.RequestContext.HttpContext.Request.Url.AbsolutePath)
throw new InvalidOperationException(); System.Security.Cryptography.CryptographicException: Object already exists at System.Security.Cryptography.CryptographicException.ThrowCryptographicException(Int32 hr) at System.Security.Cryptography.Utils._CreateCSP(CspParameters param, Boolean randomKeyContainer, SafeProvHandle& hProv)
C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys
aspnet_regiis -pa "SampleKeys" "NT AUTHORITY\NETWORK SERVICE"
public class SignInAndSignUpViewModel
{
public SignInViewModel SignIn { get; set; }
public SignUpViewModel SignUp { get; set; }
} controllerBase.ValueProvider.GetValue("CaptchaInputText");
controllerBase.ViewData.ModelState.AddModelError("CaptchaInputText", Error.....); controllerBase.ValueProvider.GetValue("SignIn.CaptchaInputText");
controllerBase.ViewData.ModelState.AddModelError("SignIn.CaptchaInputText", Error.....); CryptographicException was unhandled: System cannot find the specified file
cspParams.Flags = CspProviderFlags.UseMachineKeyStore;