Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
oleh Microsoft
Ini adalah langkah 9 dari tutorial aplikasi "NerdDinner" gratis yang memandu cara membangun aplikasi web kecil, tetapi lengkap menggunakan ASP.NET MVC 1.
Langkah 9 menunjukkan cara menambahkan autentikasi dan otorisasi untuk mengamankan aplikasi NerdDinner kami, sehingga pengguna perlu mendaftar dan masuk ke situs untuk membuat makan malam baru, dan hanya pengguna yang menghosting makan malam yang dapat mengeditnya nanti.
Jika Anda menggunakan ASP.NET MVC 3, kami sarankan Anda mengikuti tutorial Memulai MVC 3 atau MVC Music Store .
NerdDinner Langkah 9: Autentikasi dan Otorisasi
Saat ini aplikasi NerdDinner kami memberi siapa pun yang mengunjungi situs kemampuan untuk membuat dan mengedit detail makan malam apa pun. Mari kita ubah ini sehingga pengguna perlu mendaftar dan masuk ke situs untuk membuat makan malam baru, dan menambahkan pembatasan sehingga hanya pengguna yang menghosting makan malam yang dapat mengeditnya nanti.
Untuk mengaktifkan ini, kami akan menggunakan autentikasi dan otorisasi untuk mengamankan aplikasi kami.
Memahami Autentikasi dan Otorisasi
Autentikasi adalah proses mengidentifikasi dan memvalidasi identitas klien yang mengakses aplikasi. Sederhananya, ini tentang mengidentifikasi "siapa" pengguna akhir ketika mereka mengunjungi situs web. ASP.NET mendukung beberapa cara untuk mengautentikasi pengguna browser. Untuk aplikasi web Internet, pendekatan autentikasi paling umum yang digunakan disebut "Autentikasi Formulir". Autentikasi Formulir memungkinkan pengembang untuk menulis formulir masuk HTML dalam aplikasi mereka, lalu memvalidasi nama pengguna/kata sandi yang dikirimkan pengguna akhir terhadap database atau penyimpanan kredensial kata sandi lainnya. Jika kombinasi nama pengguna/kata sandi benar, pengembang kemudian dapat meminta ASP.NET untuk mengeluarkan cookie HTTP terenkripsi untuk mengidentifikasi pengguna di seluruh permintaan di masa mendatang. Kita akan menggunakan autentikasi formulir dengan aplikasi NerdDinner kita.
Otorisasi adalah proses menentukan apakah pengguna yang diautentikasi memiliki izin untuk mengakses URL/sumber daya tertentu atau untuk melakukan beberapa tindakan. Misalnya, dalam aplikasi NerdDinner kami, kami ingin mengotorisasi bahwa hanya pengguna yang masuk yang dapat mengakses URL /Dinners/Create dan membuat Makan Malam baru. Kami juga ingin menambahkan logika otorisasi sehingga hanya pengguna yang menghosting makan malam yang dapat mengeditnya - dan menolak akses edit ke semua pengguna lain.
Autentikasi Formulir dan AccountController
Templat proyek Visual Studio default untuk ASP.NET MVC secara otomatis mengaktifkan autentikasi formulir saat aplikasi MVC ASP.NET baru dibuat. Ini juga secara otomatis menambahkan implementasi halaman masuk akun bawaan ke proyek - yang membuatnya sangat mudah untuk mengintegrasikan keamanan dalam situs.
Halaman master Site.master default menampilkan tautan "Masuk" di kanan atas situs ketika pengguna yang mengaksesnya tidak diautentikasi:
Mengklik tautan "Masuk" membawa pengguna ke URL /Account/LogOn :
Pengunjung yang belum terdaftar dapat melakukannya dengan mengklik tautan "Daftar" - yang akan membawa mereka ke URL /Account/Register dan memungkinkan mereka untuk memasukkan detail akun:
Mengklik tombol "Daftar" akan membuat pengguna baru dalam sistem Keanggotaan ASP.NET, dan mengautentikasi pengguna ke situs menggunakan autentikasi formulir.
Saat pengguna masuk, Site.master mengubah kanan atas halaman untuk menghasilkan pesan "Selamat Datang [nama pengguna]!" dan merender tautan "Log Keluar" alih-alih "Masuk". Mengklik tautan "Log Off" akan mengeluarkan pengguna:
Fungsionalitas masuk, keluar, dan pendaftaran di atas diimplementasikan dalam kelas AccountController yang ditambahkan ke proyek kami oleh Visual Studio saat membuat proyek. UI untuk AccountController diimplementasikan menggunakan templat tampilan dalam direktori \Views\Account:
Kelas AccountController menggunakan sistem Autentikasi Formulir ASP.NET untuk mengeluarkan cookie autentikasi terenkripsi, dan API Keanggotaan ASP.NET untuk menyimpan dan memvalidasi nama pengguna/kata sandi. API Keanggotaan ASP.NET dapat diperluas dan memungkinkan penyimpanan kredensial kata sandi apa pun digunakan. ASP.NET dikirim dengan implementasi penyedia keanggotaan bawaan yang menyimpan nama pengguna/kata sandi dalam database SQL, atau dalam Direktori Aktif.
Kita dapat mengonfigurasi penyedia keanggotaan mana yang harus digunakan aplikasi NerdDinner dengan membuka file "web.config" di akar proyek dan mencari <bagian keanggotaan> di dalamnya. web.config default ditambahkan ketika proyek dibuat mendaftarkan penyedia keanggotaan SQL, dan mengonfigurasinya untuk menggunakan string koneksi bernama "ApplicationServices" untuk menentukan lokasi database.
String koneksi "ApplicationServices" default (yang ditentukan dalam bagian <connectionStrings> dari file web.config) dikonfigurasi untuk menggunakan SQL Express. Ini menunjuk ke database SQL Express bernama "ASPNETDB. MDF" di bawah direktori "App_Data" aplikasi. Jika database ini tidak ada saat pertama kali API Keanggotaan digunakan dalam aplikasi, ASP.NET akan secara otomatis membuat database dan menyediakan skema database keanggotaan yang sesuai di dalamnya:
Jika alih-alih menggunakan SQL Express, kami ingin menggunakan instans SQL Server penuh (atau terhubung ke database jarak jauh), yang perlu kita lakukan adalah memperbarui string koneksi "ApplicationServices" dalam file web.config dan memastikan bahwa skema keanggotaan yang sesuai telah ditambahkan ke database yang ditujukannya. Anda dapat menjalankan utilitas "aspnet_regsql.exe" dalam direktori \Windows\Microsoft.NET\Framework\v2.0.50727\ untuk menambahkan skema yang sesuai untuk keanggotaan dan layanan aplikasi ASP.NET lainnya ke database.
Mengotorisasi URL /Dinners/Create menggunakan filter [Authorize]
Kami tidak perlu menulis kode apa pun untuk mengaktifkan autentikasi yang aman dan implementasi manajemen akun untuk aplikasi NerdDinner. Pengguna dapat mendaftarkan akun baru dengan aplikasi kami, dan login/keluar dari situs.
Sekarang kita dapat menambahkan logika otorisasi ke aplikasi, dan menggunakan status autentikasi dan nama pengguna pengunjung untuk mengontrol apa yang dapat dan tidak dapat mereka lakukan dalam situs. Mari kita mulai dengan menambahkan logika otorisasi ke metode tindakan "Buat" dari kelas DinnersController kami. Secara khusus, kami akan mengharuskan pengguna yang mengakses URL /Dinners/Create harus masuk. Jika mereka tidak masuk, kami akan mengalihkannya ke halaman login sehingga mereka dapat masuk.
Menerapkan logika ini cukup mudah. Yang perlu kita lakukan adalah menambahkan atribut filter [Otorisasi] ke metode tindakan Buat seperti ini:
//
// GET: /Dinners/Create
[Authorize]
public ActionResult Create() {
...
}
//
// POST: /Dinners/Create
[AcceptVerbs(HttpVerbs.Post), Authorize]
public ActionResult Create(Dinner dinnerToCreate) {
...
}
ASP.NET MVC mendukung kemampuan untuk membuat "filter tindakan" yang dapat digunakan untuk menerapkan logika yang dapat digunakan kembali yang dapat diterapkan secara deklaratif ke metode tindakan. Filter [Otorisasi] adalah salah satu filter tindakan bawaan yang disediakan oleh ASP.NET MVC, dan memungkinkan pengembang menerapkan aturan otorisasi secara deklaratif ke metode tindakan dan kelas pengontrol.
Ketika diterapkan tanpa parameter apa pun (seperti di atas) filter [Otorisasi] memberlakukan bahwa pengguna yang membuat permintaan metode tindakan harus masuk - dan akan secara otomatis mengalihkan browser ke URL masuk jika tidak. Saat melakukan pengalihan ini, URL yang awalnya diminta diteruskan sebagai argumen querystring (misalnya: /Account/LogOn? ReturnUrl=%2fDinners%2fCreate). AccountController kemudian akan mengalihkan pengguna kembali ke URL yang awalnya diminta setelah mereka masuk.
Filter [Otorisasi] secara opsional mendukung kemampuan untuk menentukan properti "Pengguna" atau "Peran" yang dapat digunakan untuk mengharuskan pengguna masuk dan dalam daftar pengguna yang diizinkan atau anggota peran keamanan yang diizinkan. Misalnya, kode di bawah ini hanya memungkinkan dua pengguna tertentu, "scottgu" dan "billg", untuk mengakses URL /Dinners/Create:
[Authorize(Users="scottgu,billg")]
public ActionResult Create() {
...
}
Menyematkan nama pengguna tertentu dalam kode cenderung cukup tidak dapat dipertahankan. Pendekatan yang lebih baik adalah menentukan "peran" tingkat yang lebih tinggi yang diperiksa kodenya, lalu memetakan pengguna ke dalam peran menggunakan database atau sistem direktori aktif (memungkinkan daftar pemetaan pengguna aktual disimpan secara eksternal dari kode). ASP.NET menyertakan API manajemen peran bawaan serta serangkaian penyedia peran bawaan (termasuk yang untuk SQL dan Direktori Aktif) yang dapat membantu melakukan pemetaan pengguna/peran ini. Kami kemudian dapat memperbarui kode untuk hanya mengizinkan pengguna dalam peran "admin" tertentu untuk mengakses /Dinners/Create URL:
[Authorize(Roles="admin")]
public ActionResult Create() {
...
}
Menggunakan properti User.Identity.Name saat Membuat Makan Malam
Kita dapat mengambil nama pengguna dari pengguna yang saat ini masuk dari permintaan menggunakan properti User.Identity.Name yang diekspos pada kelas dasar Pengontrol.
Sebelumnya ketika kami menerapkan versi HTTP-POST dari metode tindakan Create() kami telah melakukan hardcoding properti "HostedBy" dari Makan Malam ke string statis. Kita sekarang dapat memperbarui kode ini untuk menggunakan properti User.Identity.Name, serta secara otomatis menambahkan RSVP untuk host yang membuat Makan Malam:
//
// POST: /Dinners/Create
[AcceptVerbs(HttpVerbs.Post), Authorize]
public ActionResult Create(Dinner dinner) {
if (ModelState.IsValid) {
try {
dinner.HostedBy = User.Identity.Name;
RSVP rsvp = new RSVP();
rsvp.AttendeeName = User.Identity.Name;
dinner.RSVPs.Add(rsvp);
dinnerRepository.Add(dinner);
dinnerRepository.Save();
return RedirectToAction("Details", new { id=dinner.DinnerID });
}
catch {
ModelState.AddModelErrors(dinner.GetRuleViolations());
}
}
return View(new DinnerFormViewModel(dinner));
}
Karena kami telah menambahkan atribut [Otorisasi] ke metode Create(), ASP.NET MVC memastikan bahwa metode tindakan hanya dijalankan jika pengguna yang mengunjungi URL /Dinners/Create masuk di situs. Dengan demikian, nilai properti User.Identity.Name akan selalu berisi nama pengguna yang valid.
Menggunakan properti User.Identity.Name saat Mengedit Makan Malam
Sekarang mari kita tambahkan beberapa logika otorisasi yang membatasi pengguna sehingga mereka hanya dapat mengedit properti makan malam yang mereka hosting.
Untuk membantu dengan ini, pertama-tama kita akan menambahkan metode pembantu "IsHostedBy(nama pengguna)" ke objek Makan Malam kami (dalam kelas parsial Dinner.cs yang kami bangun sebelumnya). Metode pembantu ini mengembalikan true atau false tergantung pada apakah nama pengguna yang disediakan cocok dengan properti Dinner HostedBy, dan merangkum logika yang diperlukan untuk melakukan perbandingan string yang tidak peka huruf besar/kecil:
public partial class Dinner {
public bool IsHostedBy(string userName) {
return HostedBy.Equals(userName, StringComparison.InvariantCultureIgnoreCase);
}
}
Kami kemudian akan menambahkan atribut [Otorisasi] ke metode tindakan Edit() dalam kelas DinnersController kami. Ini akan memastikan bahwa pengguna harus masuk untuk meminta URL /Dinners/Edit/[id ].
Kami kemudian dapat menambahkan kode ke metode Edit kami yang menggunakan metode pembantu Dinner.IsHostedBy(nama pengguna) untuk memverifikasi bahwa pengguna yang masuk cocok dengan host Makan Malam. Jika pengguna bukan host, kami akan menampilkan tampilan "InvalidOwner" dan mengakhiri permintaan. Kode untuk melakukan ini terlihat seperti di bawah ini:
//
// GET: /Dinners/Edit/5
[Authorize]
public ActionResult Edit(int id) {
Dinner dinner = dinnerRepository.GetDinner(id);
if (!dinner.IsHostedBy(User.Identity.Name))
return View("InvalidOwner");
return View(new DinnerFormViewModel(dinner));
}
//
// POST: /Dinners/Edit/5
[AcceptVerbs(HttpVerbs.Post), Authorize]
public ActionResult Edit(int id, FormCollection collection) {
Dinner dinner = dinnerRepository.GetDinner(id);
if (!dinner.IsHostedBy(User.Identity.Name))
return View("InvalidOwner");
try {
UpdateModel(dinner);
dinnerRepository.Save();
return RedirectToAction("Details", new {id = dinner.DinnerID});
}
catch {
ModelState.AddModelErrors(dinnerToEdit.GetRuleViolations());
return View(new DinnerFormViewModel(dinner));
}
}
Kita kemudian dapat mengklik kanan pada direktori \Views\Dinners dan memilih perintah menu Add-View> untuk membuat tampilan "InvalidOwner" baru. Kami akan mengisinya dengan pesan kesalahan di bawah ini:
<asp:Content ID="Title" ContentPlaceHolderID="TitleContent" runat="server">
You Don't Own This Dinner
</asp:Content>
<asp:Content ID="Main" ContentPlaceHolderID="MainContent" runat="server">
<h2>Error Accessing Dinner</h2>
<p>Sorry - but only the host of a Dinner can edit or delete it.</p>
</asp:Content>
Dan sekarang ketika pengguna mencoba mengedit makan malam yang tidak mereka miliki, mereka akan mendapatkan pesan kesalahan:
Kami dapat mengulangi langkah-langkah yang sama untuk metode tindakan Delete() dalam pengontrol kami untuk mengunci izin untuk menghapus Makan Malam juga, dan memastikan bahwa hanya tuan rumah Makan Malam yang dapat menghapusnya.
Memperlihatkan/Menyembunyikan Edit dan Hapus Tautan
Kami menautkan ke metode tindakan Edit dan Hapus kelas DinnersController kami dari URL Detail kami:
Saat ini kami menampilkan tautan tindakan Edit dan Hapus terlepas dari apakah pengunjung ke URL detail adalah tuan rumah makan malam. Mari kita ubah ini sehingga tautan hanya ditampilkan jika pengguna yang mengunjungi adalah pemilik makan malam.
Metode tindakan Details() dalam DinnersController kami mengambil objek Makan Malam dan kemudian meneruskannya sebagai objek model ke templat tampilan kami:
//
// GET: /Dinners/Details/5
public ActionResult Details(int id) {
Dinner dinner = dinnerRepository.GetDinner(id);
if (dinner == null)
return View("NotFound");
return View(dinner);
}
Kami dapat memperbarui templat tampilan kami untuk menampilkan/menyembunyikan tautan Edit dan Hapus secara kondisional dengan menggunakan metode pembantu Dinner.IsHostedBy() seperti di bawah ini:
<% if (Model.IsHostedBy(Context.User.Identity.Name)) { %>
<%= Html.ActionLink("Edit Dinner", "Edit", new { id=Model.DinnerID }) %> |
<%= Html.ActionLink("Delete Dinner", "Delete", new {id=Model.DinnerID}) %>
<% } %>
Langkah berikutnya
Sekarang mari kita lihat bagaimana kita dapat mengaktifkan pengguna terautentikasi ke RSVP untuk makan malam menggunakan AJAX.