PDA

View Full Version : ایجاد تصویر امنیتی در asp.net core



EBRAHIMIEKOKDARAGHI
شنبه 30 آذر 1398, 09:30 صبح
با سلام و خسته نباشید خدمت تمامی اساتید و برنامه نویس های محترم
من قبلا برای تولید تصویر امنیتی تو asp.net mvs از یک CaptchaController که به درستی و بدون اشکال کار می کرد بعد از مهاجرت به .net core با یه کمی تغییرات تبدیل به کد زیر کردم مشکلی که هست اینه که وقتی وب سایت لود میشه عبارت امنیتی رو null میده در حالی که تصویر امنیتی درست هستش و حتما باید رفرش کنی که درست بشه لطفا کمک کنید

{
// GET: Captcha
public IActionResult CaptchaImage(string prefix, bool noisy = true)
{
var rand = new Random((int)DateTime.Now.Ticks);
//generate new question
int a = rand.Next(10, 99);
int b = rand.Next(0, 9);
var captcha = string.Format("{0} + {1} = ?", a, b);
HttpContext.Session.SetString("Captcha" + prefix, (a + b).ToString());
FileContentResult img = null;
using (var mem = new MemoryStream())
using (var bmp = new Bitmap(130, 30))
using (var gfx = Graphics.FromImage((Image)bmp))
{
gfx.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
gfx.SmoothingMode = SmoothingMode.AntiAlias;
gfx.FillRectangle(Brushes.White, new Rectangle(0, 0, bmp.Width, bmp.Height));


//add noise
if (noisy)
{
int i, r, x, y;
var pen = new Pen(Color.Yellow);
for (i = 1; i < 10; i++)
{
pen.Color = Color.FromArgb(
(rand.Next(0, 255)),
(rand.Next(0, 255)),
(rand.Next(0, 255)));


r = rand.Next(0, (130 / 3));
x = rand.Next(0, 130);
y = rand.Next(0, 30);


gfx.DrawEllipse(pen, x - r, y - r, r, r);
}
}


//add question
gfx.DrawString(captcha, new Font("Tahoma", 15), Brushes.Gray, 2, 3);


//render as Jpeg
bmp.Save(mem, System.Drawing.Imaging.ImageFormat.Jpeg);
img = this.File(mem.GetBuffer(), "image/Jpeg");
}


return img;
}
}

کد رفرش


<script>
$('.refreshCaptcha').click(function () {
var d = new Date();
$(".imgcpatcha").attr("src", "/Captcha/CaptchaImage?" + d.getTime());


})
</script>


کد Register.cshtml


<div class="modal fade" id="myModal" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content modal-info">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
</div>
<div class="modal-body real-spa">
<div class="login-grids">
<div class="login">
<div class="login-left">
<form asp-controller="Home" asp-action="LogIn">
<h3>ورود</h3>
<input type="text" name="UserId2" placeholder="کلمه کاربری" />
<input type="password" name="Password2" placeholder="کلمه عبور" />
<div>
<div style="float:right">
<img alt="Captcha" class="imgcpatcha" src="@Url.Action("CaptchaImage", "Captcha")" style="" />
</div>
<div style="float:right">
<img src="~/images/refresh.png" class="img-responsive refreshCaptcha" width="30" height="30" />
</div>
<div style="clear:both"></div>
</div>
<input type="text" name="Captcha" placeholder="جواب سوال؟" />
<h4><a href="#">رمز فراموش شده</a> </h4>
<div class="single-bottom">
@Html.CheckBox("Remember", false, new { @style = "margin :0px" })

<label for="brand"><span></span>مرا به خاطر بسپار</label>
</div>
<input type="submit" value="ورود">
</form>

</div>
</div>

</div>
</div>
</div>
</div>
</div>


کد اکشن login

public async Task<IActionResult> LogIn(string UserId2, string Password2, bool Remember, string Captcha)
{
if (Password2 == null || UserId2==null)
{
TempData["Message_Login"] = "نام کاربری یا کلمه عبور راوارد نکرده اید";
return RedirectToAction(nameof(Index));
}
string coderPass = Encript_Decript.codare(Password2).Trim();
if (HttpContext.Session.GetString("Captcha").Trim() == null || HttpContext.Session.GetString("Captcha").ToString() != Captcha.Trim())
{
TempData["Message_Login"] = "جواب سوال امنیتی اشتباه است";
return RedirectToAction(nameof(Index));
}
try
{
rdb = new RegisterRepository(db);
var regData = await rdb.Find(UserId2.Trim());
if (regData == null)
{
TempData["Message_Login"] = "کلمه کاربری وجود ندارد";
return RedirectToAction(nameof(Index));
}


if (regData.Password == coderPass.Trim())
{
var claims = new List<Claim>
{
new Claim(ClaimTypes.Name, regData.UserId.Trim()),
new Claim(ClaimTypes.Role, regData.Roles.Trim()),
};


var claimsIdentity = new ClaimsIdentity(
claims, CookieAuthenticationDefaults.AuthenticationScheme) ;


var authProperties = new AuthenticationProperties
{
IsPersistent = Remember,

};


await HttpContext.SignInAsync(
CookieAuthenticationDefaults.AuthenticationScheme,
new ClaimsPrincipal(claimsIdentity),
authProperties);


return RedirectToAction(nameof(Index));


}
else
{
TempData["Message_Login"] = "کلمه عبور نادرست است";
return RedirectToAction(nameof(Index));
}


}
catch (Exception)
{
return RedirectToAction(nameof(Error));
}
}

EBRAHIMIEKOKDARAGHI
دوشنبه 14 بهمن 1398, 21:42 عصر
با سلام مجدد خدمت اساتید وخسته نباشید
اگه امکان داره این مشکل رو راهنمایی کنید خیلی گیرم
منون

magicmilkom
سه شنبه 29 بهمن 1398, 23:26 عصر
سلام دوست عزیز. چرا از ریکپچای گوگل استفاده نمی کنید؟
پیشنهاد اول: استفاده از ریکپچای گوگل: چون callbackurl داره و از لحاظ security خیلی بهتره.

راه حل شما در صورت عدم استفاده از ریکپچای گوگل:

روی پوشه کنترلر خود کلیک کنید تا کنترلری با نام CaptachaController به منظور درج Action Method در آن ایجاد کنید و کد زیر را برای ایجاد این اکشن متود درون کنترلر خود درج کنید:



public class CaptchaController : Controller
{
public ActionResult CaptchaImage(string prefix, bool noisy = true)
{
var rand = new Random((int)DateTime.Now.Ticks);
//generate new question
int a = rand.Next(10, 99);
int b = rand.Next(0, 9);
var captcha = string.Format("{0} + {1} = ?", a, b);

//store answer
Session["Captcha" + prefix] = a + b;

//image stream
FileContentResult img = null;

using (var mem = new MemoryStream())
using (var bmp = new Bitmap(130, 30))
using (var gfx = Graphics.FromImage((Image)bmp))
{
gfx.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
gfx.SmoothingMode = SmoothingMode.AntiAlias;
gfx.FillRectangle(Brushes.White, new Rectangle(0, 0, bmp.Width, bmp.Height));

//add noise
if (noisy)
{
int i, r, x, y;
var pen = new Pen(Color.Yellow);
for (i = 1; i < 10; i++)
{
pen.Color = Color.FromArgb(
(rand.Next(0, 255)),
(rand.Next(0, 255)),
(rand.Next(0, 255)));

r = rand.Next(0, (130 / 3));
x = rand.Next(0, 130);
y = rand.Next(0, 30);

gfx.DrawEllipse(pen, x - r, y - r, r, r);
}
}

//add question
gfx.DrawString(captcha, new Font("Tahoma", 15), Brushes.Gray, 2, 3);

//render as Jpeg
bmp.Save(mem, System.Drawing.Imaging.ImageFormat.Jpeg);
img = this.File(mem.GetBuffer(), "image/Jpeg");
}

return img;
}

توضیج: بر اساس کد بالا دو مقدار a و b به صورت رندوم بر اساس کد بالا ایجاد میشه و حاصل جمع آنها در یک session نگهداری میشه که تصویری به صورت a+b ایجاد میکنه (مثلا 8+9). همانطور که می بینید در آخر این تصویر را return می کنه.

magicmilkom
سه شنبه 29 بهمن 1398, 23:32 عصر
به فرض مثال می خواهیم یک کپچایی ایجاد کنیم در صفحه ی ریجیستر.
اگر مدلی برای صفحات اکانت خود مثلا AccountViewModel تعریف کرده باشید (بر اساس عرف) در این صورت در کلاس RegisterViewModel خاصیت زیر را اضافه کنید:



[Required(ErrorMessage = "لطفا {0} را وارد کنید")]
[Display(Name = "حاصل جمع")]
public string Captcha { get; set; }

magicmilkom
سه شنبه 29 بهمن 1398, 23:35 عصر
حالا در فایل مربوطه به View خودتون که اینجا باید در پوشه View در فولدر Account و فایل Register.cshtml باشه رفته و کد زیر را قرار دهید:



<img alt="Captcha" id="imgcpatcha" src="@Url.Action("CaptchaImage","Captcha")" style="" />


همانطور که می دونید که این کدcaptcha را نمایش می دهد. ولی برای برقراری ارتباط و آنالیز ورودی input و ارتباط با اکشن متود ایجاد شده از کد ajax زیر در بخش script خودتون استفاده کنید.

یادت نره که ajax رو اول باید فعال کنی...

magicmilkom
سه شنبه 29 بهمن 1398, 23:40 عصر
<script type="text/javascript"> $(function () {
$('#refresh').click(function () {


$.ajax({
url: '@Url.Action("CaptchaImage","Captcha")',
type: "GET",
data: null
})
.done(function (functionResult) {
$("#imgcpatcha").attr("src", "/Captcha/CaptchaImage?" + functionResult);
});

});
}); </script>

magicmilkom
سه شنبه 29 بهمن 1398, 23:41 عصر
در کد ajax بالا اکشن متود بر میگرده به همان اکشن متودی که در اول کار ایجاد کردیم و نوع آن از نوع GET خواهد بود چرا که داده ای را به سمت سرور ارسال نمی کنه بلکه فقط خروجی اکشن متود را دریافت می کنه و با کمک FunctionResult موجود در کد ajax خروجی را در تصویر ادرس دهی شده با id با نام imgcaptach قرار میده.

در نهایت فقط کد زیر را نیز در اکشن متود Register در AccountController را در ابتدای آن قرار دهید تا برابری session را با مقدار ورودی مورد ارزیابی قرار دهد.


if (Session["Captcha"] == null || Session["Captcha"].ToString() != model.Captcha) {
ModelState.AddModelError("Captcha", "مجموع اشتباه است"); }

امیدوارم کارتون با بیفته.

اگر خواستید از recaptch گوگل هم استفاده کنید می تونم کمکتون کنم.

EBRAHIMIEKOKDARAGHI
چهارشنبه 30 بهمن 1398, 23:38 عصر
ممنون از پاسخ شما