قم بإنشاء آلية تسجيل دخول باستخدام مصادقة ملفات تعريف الارتباط ، وقم بإنشاء آلية لإعادة توجيهك إذا لم تتم مصادقتك

تحديث الصفحة :
تاريخ إنشاء الصفحة :

بيئة التشغيل

فيجوال ستوديو
  • مجتمع فيجوال ستوديو 2022
ASP.NET الأساسية (MVC ، صفحات الحلاقة)
6.0

في البداية

هذه المرة ، ستستخدم ASP.NET Core مصادقة ملفات تعريف الارتباط كآلية مصادقة لتسجيل الدخول. يمكنك التفكير في مصادقة ملفات تعريف الارتباط على أنها مشابهة لمصادقة النماذج التقليدية.

آلية مصادقة أخرى ل ASP.NET Core هي ASP.NET Core Identity. بالإضافة إلى المصادقة باستخدام النماذج ، يتيح لك ذلك المصادقة باستخدام واجهات برمجة التطبيقات ، واستخدام خدمات تسجيل الدخول الخارجية ، وإدارة كلمات المرور وإعادة تعيينها ، وما إلى ذلك. يمكنك استخدام الكثير من الميزات. ومع ذلك ، من وجهة نظر مجرد إنشاء شاشة تسجيل دخول بسيطة هذه المرة ، ستكون آلية مصادقة مبالغ فيها إلى حد ما. لن نستخدمها هذه المرة.

في نصائح مصادقة ملفات تعريف الارتباط المقدمة هذه المرة ، لا يمكنك عرض أي شيء آخر غير شاشة تسجيل الدخول إلا إذا قمت بتسجيل الدخول. إذا حاولت الانتقال إلى شاشة أخرى ، فستتم إعادة توجيهك إلى شاشة تسجيل الدخول. إذا قمت بتسجيل الدخول ، يمكنك عرض الشاشات الأخرى.

في الوقت الحالي ، يمكنك تسجيل الدخول عن طريق إدخال اسم المستخدم وكلمة المرور على شاشة تسجيل الدخول. يتم تنفيذ مصادقة المستخدم نفسها كمكان مؤقت. في هذه الحالة ، ينصب التركيز الرئيسي على تنفيذ مصادقة ملفات تعريف الارتباط ، وبالتالي فإن جوهر عملية التحديد مثل ما إذا كانت كلمة المرور صحيحة ليس هو الجوهر.

تصف هذه النصيحة جزءا فقط من البرنامج. للحصول على الكود الكامل ، قم بتنزيل البرنامج الكامل. كما يغطي كلا من أطر MVC و Razor Pages.

إنشاء مشروع

بدء تشغيل Visual Studio وإنشاء مشروع جديد.

بالنسبة لصفحات Razor، حدد ASP.NET تطبيق الويب الأساسي، أو بالنسبة إلى MVC، حدد ASP.NET تطبيق الويب الأساسي (وحدة التحكم في عرض النموذج).

حدد اسم مشروع من اختيارك وموقعا للمشروع.

بالنسبة لنوع المصادقة ، حدد "بلا". إذا اخترت مصادقة أخرى، فستستخدم ASP.NET الهوية الأساسية. عند الانتهاء من الإعدادات ، انقر فوق الزر "إنشاء".

بعد إنشاء المشروع ، سيتم عرض الشاشة الموضحة أدناه عند تنفيذ التصحيح. سنقوم بإنشاء برنامج يعتمد على هذه الشاشة.

تحرير البرنامج.cs (صفحات الحلاقة ، MVC المشتركة)

أضف التعريفات المطلوبة لمصادقة ملفات تعريف الارتباط إلى Program.cs. مساحات الأسماء المراد إضافتها هي كما يلي:

using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authorization;

إليك builder.Services الكود الذي يجب إضافته إلى .

// === 省略 ===

// 「Razor Pages」のコード
// builder.Services.AddRazorPages();
// 「MVC」のコード
// builder.Services.AddControllersWithViews();

// ※ここから追加

// Cookie による認証スキームを追加する
builder.Services
  .AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
  .AddCookie();

builder.Services.AddAuthorization(options =>
{
  // AllowAnonymous 属性が指定されていないすべての画面、アクションなどに対してユーザー認証が必要となる
  options.FallbackPolicy = new AuthorizationPolicyBuilder()
    .RequireAuthenticatedUser()
    .Build();
});

// ※ここまで追加

var app = builder.Build();

// === 省略 ===

AddAuthenticationAddCookie يمكنك تمكين مصادقة ملفات تعريف الارتباط عن طريق تنفيذ طريقة و. إذا لم تكن بحاجة إلى تغيير اسم النظام، CookieAuthenticationDefaults.AuthenticationScheme فحدد .

AddAuthorization إذا حددت options.FallbackPolicy RequireAuthenticatedUser للطريقة يمكنك تطبيق نهج مطلوب للمصادقة على جميع الصفحات وجميع وحدات التحكم والإجراءات. إذا كنت تريد طلب المصادقة لأي شيء آخر غير شاشة تسجيل الدخول ، فهذه طريقة مفيدة من حيث تقليل الرمز ومنع الأخطاء في الوصف. سيتعين عليك كتابة رمز لا يتطلب مصادقة لشاشة تسجيل الدخول بشكل منفصل.

فيما يلي app رمز ل .

// === 省略 ===

app.UseRouting();

app.UseAuthentication(); // [追加] 認証
app.UseAuthorization(); // 認可

// 「Razor Pages」のコード
// app.MapRazorPages();
// 「MVC」のコード
// app.MapControllerRoute(
//     name: "default",
//     pattern: "{controller=Home}/{action=Index}/{id?}");

// === 省略 ===

نظرا لأننا نريد إضافة وظيفة المصادقة إلى التطبيق ، app.UseAuthentication() فسنضيف . يتم تحديد موقع الوصف وفقا لوثائق MSDN، التطبيق. UseAuthorization(). بخلاف ذلك ، لا يزال قالبا.

برامج لمشاريع صفحات الحلاقة

إنشاء صفحة تسجيل دخول (الصفحات/الحساب/Login.cshtml.cs)

إنشاء ملف

إنشاء صفحة تسجيل دخول. يجب إنشاء مسار الملف ك "/ pages / Account / Login.cshtml". هذا لأن مسار تسجيل الدخول الافتراضي يشبه ذلك. إذا كنت تريد تغيير هذا المسار ، فيمكنك Program.cs القيام بذلك عن طريق تعيين وسيطة AddCookie طريقة .

يمكنك إنشائه عن طريق نسخ ملفات أخرى بدلا من إنشائه من القائمة ، ولكن في هذه الحالة ، يرجى إصلاح البرنامج بشكل صحيح.

السماح للمستخدمين بالوصول إلى صفحة تسجيل الدخول دون تسجيل الدخول

Program.cs نظرا لأنه لا يمكن الوصول إلى جميع الصفحات إلا عند تسجيل الدخول ، فأنت بحاجة إلى تعيين صفحة تسجيل الدخول فقط حتى تتمكن من الوصول إليها حتى إذا لم تقم بتسجيل الدخول.

AllowAnonymous عن طريق إضافة سمات ، يمكن الوصول إلى الصفحة المستهدفة حتى إذا لم تتم مصادقتها. AllowAnonymous يمكن استخدام السمات في أماكن أخرى غير شاشة تسجيل الدخول، مثل عمليات واجهة برمجة التطبيقات التي لا علاقة لها بمصادقة ملفات تعريف الارتباط.

using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Security.Claims;

namespace AspNetCoreCookieAuthenticationRazorPages.Pages.Account
{
  [AllowAnonymous]
  public class LoginModel : PageModel
  {
  }
}

إنشاء متغير لتلقي المدخلات

عند تسجيل الدخول ، فإنك تعلن عن اسم المستخدم الخاص بك لتتمكن من تلقي هذه القيم لأنك تدخل كلمة المرور الخاصة بك.

// 省略

[AllowAnonymous]
public class LoginModel : PageModel
{
  /// <summary>ユーザー名。</summary>
  [BindProperty]
  [Required]
  [DisplayName("ユーザー名")]
  public string UserName { get; set; } = "";

  /// <summary>パスワード。</summary>
  [BindProperty]
  [Required]
  [DataType(DataType.Password)]
  [DisplayName("パスワード")]
  public string Password { get; set; } = "";
}

تحديد اسم مستخدم وكلمة مرور لمصادقة تسجيل الدخول

في الأصل ، سيتم تخزينه في قاعدة بيانات ، وما إلى ذلك ، ولكن نظرا لأن حكم المستخدم ليس هو التركيز الرئيسي هذه المرة ، فسوف أجعله مكانا مؤقتا.

// 省略

[AllowAnonymous]
public class LoginModel : PageModel
{
  // 省略

  /// <summary>仮のユーザーデータベースとする。</summary>
  private Dictionary<string, string> UserAccounts { get; set; } = new Dictionary<string, string>
    {
      { "user1", "password1" },
      { "user2", "password2" },
    };
}

عملية تسجيل الدخول

/// <summary>ログイン処理。</summary>
public async Task<ActionResult> OnPost()
{
  // 入力内容にエラーがある場合は処理を中断してエラー表示
  if (ModelState.IsValid == false) return Page();

  // ユーザーの存在チェックとパスワードチェック (仮実装)
  // 本 Tips は Cookie 認証ができるかどうかの確認であるため入力内容やパスワードの厳密なチェックは行っていません
  if (UserAccounts.TryGetValue(UserName, out string? getPass) == false || Password != getPass)
  {
    ModelState.AddModelError("", "ユーザー名またはパスワードが一致しません。");
    return Page();
  }

  // サインインに必要なプリンシパルを作る
  var claims = new[] { new Claim(ClaimTypes.Name, UserName) };
  var identity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
  var principal = new ClaimsPrincipal(identity);

  // 認証クッキーをレスポンスに追加
  await HttpContext.SignInAsync(principal);

  // ログインが必要な画面にリダイレクトします
  return RedirectToPage("/Index");
}

هذه هي عملية المصادقة بعد الضغط على زر تسجيل الدخول. إذا تطابق اسم المستخدم وكلمة المرور، تكون المصادقة ممكنة.

الرمز الموضح هو الحد الأدنى من التعليمات البرمجية المطلوبة للمصادقة،ClaimClaimsIdentityClaimsPrincipal و HttpContext.SignInAsync من خلال استدعاء الطريقة ، يتم إنشاء ملف تعريف ارتباط والمصادقة عليه.

إذا كانت هناك حاجة إلى مطالبات إضافية أو كان انتهاء صلاحية ملف تعريف الارتباط مطلوبا ، تتم إضافة معلمات إضافية.

بعد تسجيل الدخول ، تتم إعادة توجيهك إلى ، حيث /Index تكون المصادقة مطلوبة.

عملية تسجيل الخروج

/// <summary>ログアウト処理。</summary>
public async Task OnGetLogout()
{
  // 認証クッキーをレスポンスから削除
  await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
}

Logout عند الوصول إليه باستخدام معالج ، تتم معالجته لتسجيل الخروج. HttpContext.SignOutAsync من خلال استدعاء الطريقة ، يمكنك حذف ملف تعريف الارتباط وإعادته إلى حالة لم تقم بتسجيل الدخول إليها.

إنشاء طريقة عرض

نحن لا نأخذ في الاعتبار المظهر. أضف حقولا لإدخال اسم المستخدم وكلمة المرور كما هو موضح أدناه ، وضع زرا لتسجيل الدخول. يجب أن يكون لديك أيضا رابط للوصول إليه دون تسجيل الدخول للاختبار /Index .

نظرا لأنه من المزعج إدخال اسم المستخدم وكلمة المرور ، يتم تعيين القيمة الأولية.

@page
@model AspNetCoreCookieAuthenticationRazorPages.Pages.Account.LoginModel
@{}

<form asp-action="Login">
  <div class="row m-1 g-3">
    <div class="col-sm-6 offset-sm-3">
      <div asp-validation-summary="ModelOnly" class="text-danger"></div>
    </div>
  </div>

  <div class="row m-1 g-3">
    <div class="col-sm-6 offset-sm-3">
      <label asp-for="UserName" class="form-label"></label>
      <input asp-for="UserName" class="form-control" value="user1" />
      <span asp-validation-for="UserName" class="text-danger"></span>
    </div>
  </div>
  <div class="row m-1 g-3">
    <div class="col-sm-6 offset-sm-3">
      <label asp-for="Password" class="form-label"></label>
      <input asp-for="Password" class="form-control" value="password1" />
      <span asp-validation-for="Password" class="text-danger"></span>
    </div>
  </div>
  <div class="row m-1 g-3">
    <div class="col-sm-6 offset-sm-3">
      <button type="submit" class="btn btn-primary">ログイン</button>
    </div>
  </div>
  <div class="row m-1 g-3">
    <div class="col-sm-6 offset-sm-3">
      <a asp-page="/Index">認証が必要な画面へ直接リンク</a>
    </div>
  </div>
</form>

@section Scripts {
  @{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); }
}

إنشاء رابط تسجيل خروج (/Pages/Shared/_Layout.cshtml)

لن نجري أي تغييرات على الشاشة الرئيسية ، لكننا سنضع رابط تسجيل الخروج في شريط التنقل. أيضا ، للاختبار ، انشر رابطا ينقلك إلى شاشة تسجيل الدخول دون تسجيل الخروج.

<!-- 中略 -->
<div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
  <ul class="navbar-nav flex-grow-1">
    <li class="nav-item">
      <a class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a>
    </li>
    <li class="nav-item">
      <a class="nav-link text-dark" asp-area="" asp-page="/Privacy">Privacy</a>
    </li>
    <!-- ここから追加 -->
    <li class="nav-item">
      <a class="nav-link text-dark" asp-page="/Account/Login" asp-page-handler="Logout">ログアウト</a>
    </li>
    <li class="nav-item">
      <a class="nav-link text-dark" asp-page="/Account/Login">ログアウトせずログインへ</a>
    </li>
    <!-- ここまで追加 -->
  </ul>
</div>
<!-- 中略 -->

هذا كل شيء لرمز صفحات الحلاقة.

برامج لمشاريع MVC

إنشاء نموذج تسجيل دخول

لقد قمت بإنشاء نموذج لتلقي القيم التي تم إدخالها على شاشة تسجيل الدخول.

namespace AspNetCoreCookieAuthenticationMvc.Models
{
  public class LoginModel
  {
    /// <summary>ユーザー名。</summary>
    [Required]
    [DisplayName("ユーザー名")]
    public string UserName { get; set; } = "";

    /// <summary>パスワード。</summary>
    [Required]
    [DataType(DataType.Password)]
    [DisplayName("パスワード")]
    public string Password { get; set; } = "";
  }
}

إنشاء مراقب حساب

قم بإنشاء وحدات التحكم والإجراءات المطلوبة لإنشاء شاشة تسجيل الدخول. قم بإنشاء اسم AccountController وحدة التحكم ك . هذا لأنه بشكل افتراضي ، يتم تعيين اسم وحدة التحكم واسم الإجراء على شاشة تسجيل الدخول على "~ / Account / Login". إذا كنت تريد تغيير هذا المسار ، يمكنك القيام بذلك في خيارات AddCookie الطريقة في Program.cs. في الوقت الحالي ، سننتقل إلى الإعدادات الافتراضية.

أولا ، دعنا ننشئ جانب وحدة التحكم.

using AspNetCoreCookieAuthenticationMvc.Models;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.Security.Claims;

namespace AspNetCoreCookieAuthenticationMvc.Controllers
{
  /// <remarks>
  /// <see cref="AllowAnonymous"/> 属性は Cookie 認証していなくてもアクセスできる Action (Controller) であることを示す。
  /// </remarks>
  [AllowAnonymous]
  public class AccountController : Controller
  {
  }
}

AllowAnonymous من خلال منح السمة ، يمكن تنفيذ جميع الإجراءات الموجودة فيها دون مصادقتها. يتيح لك ذلك الوصول إلى شاشة تسجيل الدخول فقط دون مصادقة.

AllowAnonymous يمكن أيضا استخدام السمات في وحدات تحكم واجهة برمجة التطبيقات فقط التي لا تتعلق بمصادقة ملفات تعريف الارتباط في أماكن أخرى غير شاشة تسجيل الدخول.

بعد ذلك ، حدد المستخدمين وكلمات المرور التي يمكنها تسجيل الدخول. في الأصل ، سيتم تخزينه في قاعدة بيانات ، وما إلى ذلك ، ولكن نظرا لأن حكم المستخدم ليس هو التركيز الرئيسي هذه المرة ، فسوف أجعله مكانا مؤقتا.

[AllowAnonymous]
public class AccountController : Controller
{
  /// <summary>仮のユーザーデータベースとする。</summary>
  private Dictionary<string, string> UserAccounts { get; set; } = new Dictionary<string, string>
    {
      { "user1", "password1" },
      { "user2", "password2" },
    };
}

فيما يلي إجراء يعرض شاشة تسجيل الدخول. نظرا لأنه يتم عرضه فقط ، فإنه يعيد العرض كما هو.

/// <summary>ログイン画面を表示します。</summary>
public IActionResult Login() => View();

يوجد أدناه الرمز المراد معالجته عند تسجيل الدخول.

/// <summary>ログイン処理を実行します。</summary>
[HttpPost]
public async Task<IActionResult> Login(LoginModel model)
{
  // 入力内容にエラーがある場合は処理を中断してエラー表示
  if (ModelState.IsValid == false) return View(model);

  // ユーザーの存在チェックとパスワードチェック (仮実装)
  // 本 Tips は Cookie 認証ができるかどうかの確認であるため入力内容やパスワードの厳密なチェックは行っていません
  if (UserAccounts.TryGetValue(model.UserName, out string? getPass) == false || model.Password != getPass)
  {
    ModelState.AddModelError("", "ユーザー名またはパスワードが一致しません。");
    return View(model);
  }

  // サインインに必要なプリンシパルを作る
  var claims = new[] { new Claim(ClaimTypes.Name, model.UserName) };
  var identity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
  var principal = new ClaimsPrincipal(identity);

  // 認証クッキーをレスポンスに追加
  await HttpContext.SignInAsync(principal);

  // ログインが必要な画面にリダイレクトします
  return RedirectToAction(nameof(HomeController.Index), "Home");
}

هذه هي عملية المصادقة بعد الضغط على زر تسجيل الدخول. إذا تطابق اسم المستخدم وكلمة المرور، تكون المصادقة ممكنة.

الرمز الموضح هو الحد الأدنى من التعليمات البرمجية المطلوبة للمصادقة،ClaimClaimsIdentityClaimsPrincipal و HttpContext.SignInAsync من خلال استدعاء الطريقة ، يتم إنشاء ملف تعريف ارتباط والمصادقة عليه.

إذا كانت هناك حاجة إلى مطالبات إضافية أو كان انتهاء صلاحية ملف تعريف الارتباط مطلوبا ، تتم إضافة معلمات إضافية.

بعد تسجيل الدخول ، تتم إعادة توجيهك إلى ، حيث ~/Home/Index تكون المصادقة مطلوبة.

أخيرا ، تتم إضافة عملية تسجيل الخروج.

/// <summary>ログアウト処理を実行します。</summary>
public async Task<IActionResult> Logout()
{
  // 認証クッキーをレスポンスから削除
  await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);

  // ログイン画面にリダイレクト
  return RedirectToAction(nameof(Login));
}

HttpContext.SignOutAsync من خلال استدعاء الطريقة ، يمكنك حذف ملف تعريف الارتباط وإعادته إلى حالة لم تقم بتسجيل الدخول إليها.

إنشاء طريقة عرض (نموذج تسجيل الدخول) (/ طرق العرض / الحساب / Login.cshtml)

Login انقر بزر الماوس الأيمن فوق الإجراء لإضافة طريقة عرض. يمكنك أيضا إنشائه عن طريق نسخه من ملف آخر.

نحن لا نأخذ في الاعتبار المظهر. أضف حقولا لإدخال اسم المستخدم وكلمة المرور كما هو موضح أدناه ، وضع زرا لتسجيل الدخول. يجب أن يكون لديك أيضا رابط للوصول إليه دون تسجيل الدخول للاختبار Home/Index .

نظرا لأنه من المزعج إدخال اسم المستخدم وكلمة المرور ، يتم تعيين القيمة الأولية.

@model LoginModel
@{}

<form asp-action="Login">
  <div class="row m-1 g-3">
    <div class="col-sm-6 offset-sm-3">
      <div asp-validation-summary="ModelOnly" class="text-danger"></div>
    </div>
  </div>

  <div class="row m-1 g-3">
    <div class="col-sm-6 offset-sm-3">
      <label asp-for="UserName" class="form-label"></label>
      <input asp-for="UserName" class="form-control" value="user1" />
      <span asp-validation-for="UserName" class="text-danger"></span>
    </div>
  </div>
  <div class="row m-1 g-3">
    <div class="col-sm-6 offset-sm-3">
      <label asp-for="Password" class="form-label"></label>
      <input asp-for="Password" class="form-control" value="password1" />
      <span asp-validation-for="Password" class="text-danger"></span>
    </div>
  </div>
  <div class="row m-1 g-3">
    <div class="col-sm-6 offset-sm-3">
      <button type="submit" class="btn btn-primary">ログイン</button>
    </div>
  </div>
  <div class="row m-1 g-3">
    <div class="col-sm-6 offset-sm-3">
      <a asp-controller="Home" asp-action="Index">認証が必要な画面へ直接リンク</a>
    </div>
  </div>
</form>

@section Scripts {
  @{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); }
}

إنشاء رابط تسجيل خروج (/ طرق العرض / المشتركة / _Layout.cshtml)

لن نجري أي تغييرات على الشاشة الرئيسية ، لكننا سنضع رابط تسجيل الخروج في شريط التنقل. أيضا ، للاختبار ، انشر رابطا ينقلك إلى شاشة تسجيل الدخول دون تسجيل الخروج.

<!-- 中略 -->
<div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">
  <ul class="navbar-nav flex-grow-1">
    <li class="nav-item">
      <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Index">Home</a>
    </li>
    <li class="nav-item">
      <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
    </li>
    <!-- ここから追加 -->
    <li class="nav-item">
      <a class="nav-link text-dark" asp-controller="Account" asp-action="Logout">ログアウト</a>
    </li>
    <li class="nav-item">
      <a class="nav-link text-dark" asp-controller="Account" asp-action="Login">ログアウトせずログインへ</a>
    </li>
    <!-- ここまで追加 -->
  </ul>
</div>
<!-- 中略 -->

هذا كل شيء لرمز MVC.

تأكيد العملية

هذا يكمل الحد الأدنى المطلوب لتنفيذ مصادقة ملفات تعريف الارتباط. حاول تشغيله وشاهد كيف يعمل. يجب أن يتغير السلوك اعتمادا على ما إذا كنت قد قمت بتسجيل الدخول أم لا. كمثال بسيط ، يمكنك رؤية السلوك التالي.

العملية نتيجة العملية
العودة إلى المنزل دون تسجيل الدخول إعادة التوجيه إلى شاشة تسجيل الدخول
تسجيل الدخول انتقل إلى الشاشة الرئيسية
تسجيل الخروج من المنزل والعودة إلى المنزل دون تسجيل الدخول إعادة التوجيه إلى شاشة تسجيل الدخول
العودة إلى المنزل دون تسجيل الخروج من المنزل وتسجيل الدخول انتقل إلى الشاشة الرئيسية