Membuat Custom Login Owin di ASP.NET MVC

Custom Login di ASP.NET
Pagi semuanya, kesempatan kali ini admin ingin berbagi tutorial mengenai cara membuat custom login di ASP.NET dengan menggunakan Microsoft.Owin. Custom Login sendiri merupakan cara lain kita login pada website yang menggunakan server IIS dengan bahasa pemrograman ASP.NET khususnya yang didesain menggunakan pattern MVC.

Pada dasarnya ASP.NET MVC telah menyediakan service tersendiri untuk autentifikasi user account. Caranya pada saat membuat project baru kamu bisa ubah Authentification-nya menjadi "Individual User Account". Maka secara otomatis table User akan terbuat pada database, juga fungsi-fungsi lain seperti halaman registrasi user, halaman my profile, halaman login , ubah password, dan lain sebagainya yang berhubungan dengan aktivitas autentifikasi user. 

Tapi adakalanya kita memerlukan style tersendiri dalam membuat user account. Seperti penamaan table pada database, alur login, dan lain sebagainya. Karena secara default jika kita mengikuti langkah-langkah diatas, maka nama table tidak dapat diubah sesuai dengan kebutuhan programmer karena harus mengikuti standar baku dari layanan yang ada.

ASP.NET menyediakan dukungan atau support terhadap Open Web Interface for .NET atau disingkat OWIN. Owin memiliki banyak fitur diantaranya login menggunakan eksternal akun seperti akun Microsoft, akun Google, akun Facebook dan sebagainya. Dalam tutorial ini admin hanya membahas cara membuat custom login saja dengan menggunakan service dari Microsoft.Owin.

Tutorial dibawah akan menjelaskan langkah-langkah membuat custom login pada ASP.NET MVC menggunakan interface OWIN. Langkah-langkahnya pada dasarnya sama persis seperti kalian menggunakan opsi default authentification pada saat pertama kali membuat website pada Visual Studio, admin hanya meniru saja tapi dengan sedikit "custom" agar sesuai dengan style yang kita inginkan.

Pada tutorial ini admin menggunakan Microsoft Visual Studio 2017 dan IIS Server 10, jadi mungkin akan berbeda bagi yang menggunakan versi Visual Studion dibawah 2017. Dalam tutorial ini juga admin menggunakan service/library yang sama yang digunakan oleh ASP.NET untuk autentifikasi user yaitu Microsoft.Owin dan Microsoft.AspNet.Identity.

Berikut library yang dibutuhkan, Kalian bisa download langsung melalui menu Manage Nuget Packages pada Visual Studio :
  • Microsoft.Owin
  • Microsoft.Owin.Security
  • Microsoft.Owin.Security.Cookies
  • Microsoft.Owin.Security.OAuth
  • Microsoft.Owin.Host.SystemWeb
  • Microsoft.AspNet.Identity.Core
  • Microsoft.AspNet.Identity.Owin

[ads id="ads1"]

Langkah-Langkah Pengerjaan

Buatlah sebuah project baru dengan nama "Custom Login" atau terserah kalian yang terpenting menggunakan versi .NET Framework yang kompatibel dengan versi Microsoft.Owin yang digunakan. Setelahnya, tambahkan library diatas melalui menu Manage Nuget Packages.

Menu Manage NuGet Package

Tambahkan class baru dengan nama Startup.Auth.cs pada direktori App_Start. Fungsinya adalah untuk konfigurasi awal Owin saat startup aplikasi/saat aplikasi pertama kali dijalankan. Disini kalian bisa menambahkan session time/expire time, login url, dan sebagainya yang berguna untuk membuat batas expired login dan halaman login yang digunakan.

Kode lengkapnya dapat dilihat dibawah :
using Owin;
using Microsoft.Owin;
using Microsoft.Owin.Security.Cookies;
using Microsoft.AspNet.Identity;

namespace Custom_Login
{
    public partial class Startup
    {
        public void ConfigureAuth(IAppBuilder app)
        {
            app.UseCookieAuthentication(new CookieAuthenticationOptions {
                AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
                LoginPath = new PathString("/account/login")
            });
        }
    }
}

Konfigurasi Owin Startup

Lalu selanjutnya tambahkan lagi class baru dengan nama Startup.cs pada root directory aplikasi dengan menambahkan atribut assembly:OwinStartupAttribute() diatas namespace. ASP.NET akan membaca file ini untuk pertama kali ketika aplikasi dijalankan, lalu selanjutnya akan mengeksekusi perintah ConfigureAuth().
using Owin;
using Microsoft.Owin;

[assembly:OwinStartupAttribute(typeof(Custom_Login.Startup))]
namespace Custom_Login
{
    public partial class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            ConfigureAuth(app);
        }
    }
}

Sampai langkah ini. Kalian sudah bisa menggunakan atribut [Authorize] yang digunakan untuk otorisasi/autentifikasi aplikasi. Untuk mencobanya, tambahkan atribut [Authorize] pada controller HomeController yang telah ditambahkan otomatis ketika project pertama kali dibuat.

Ketika dijalankan, maka halaman utama website otomatis akan dialihkan (redirect) ke halaman login aplikasi. Berhubung halaman loginnya belum dibuat, maka akan terjadi error 404/Not Found.
namespace Custom_Login.Controllers
{
    [Authorize]
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }

        public ActionResult About()
        {
            ViewBag.Message = "Your application description page.";

            return View();
        }

        public ActionResult Contact()
        {
            ViewBag.Message = "Your contact page.";

            return View();
        }
    }
}


Membuat Model User

Model User digunakan untuk identitas/data user yang dibutuhkan oleh class UserManager (Microsoft.AspNet.Identity.UserManager) sebagai media autentifikasi ke dalam sistem. Model User ini wajib mengikuti ketentuan yang digunakan oleh UserManager yaitu memiliki name field/property Id dan UserName. Kedua property ini tidak dapat diubah penamaannya. 

Selanjutnya Model User ini harus diinheritkan kepada interface IUser (Microsoft.AspNet.Identity.IUser) sebagai syarat yang diberikan oleh UserManager untuk dapat melakukan login.

Buatlah sebuah class baru pada direktori "Models" dan beri nama dengan UserModel.cs. Kode selengkapnya dapat dilihat dibawah :
using Microsoft.AspNet.Identity;
namespace Custom_Login.Models
{
    public class UserModel : IUser
    {
        public string Id { get; set; }
        public string UserName { get; set; }
        public string Password { get; set; }
    }
}


Membuat CustomUserStore

Selanjutnya membuat class CustomUserStore, CustomUserStore digunakan UserManager untuk menangani User seperti membuat User, menghapus User, dan sebagainya yang berkaitan langsung dengan aktivitas UserManager.

Buatlah sebuah class baru pada direktori "Models" dan beri nama dengan CustomUserStore.cs. Kode selengkapnya dapat dilihat dibawah :
using Microsoft.AspNet.Identity;
using System;
using System.Threading.Tasks;

namespace Custom_Login.Models
{
    public class CustomUserStore<T> : IUserStore<T> where T : UserModel
    {
        public Task CreateAsync(T user)
        {
            throw new NotImplementedException();
        }

        public Task DeleteAsync(T user)
        {
            throw new NotImplementedException();
        }

        public void Dispose()
        {
            throw new NotImplementedException();
        }

        public Task<T> FindByIdAsync(string userId)
        {
            throw new NotImplementedException();
        }

        public Task<T> FindByNameAsync(string userName)
        {
            throw new NotImplementedException();
        }

        public Task UpdateAsync(T user)
        {
            throw new NotImplementedException();
        }
    }
}


Membuat CustomUserManager

Selanjutnya membuat CustomUserManager, CustomManager ini bertugas untuk mengatur User yang telah terdaftar (registered) maupun yang belum terdaftar(anonymous) pada CustomUserStore. Tugas CustomUserManager memegang peranan untuk melakukan autentifikasi pada server, logout, claim, dan masih banyak lagi.

Selanjutnya buatlah sebuah class baru pada direktori "Models" dan beri nama dengan CustomUserManager.cs. Kode selengkapnya dapat dilihat dibawah :
using Microsoft.AspNet.Identity;

namespace Custom_Login.Models
{
    public class CustomUserManager : UserManager<UserModel>
    {
        public CustomUserManager() : base (new CustomUserStore<UserModel>()) { }
    }
}


Membuat Account Controller

Setelah selesai dengan konfigurasi dan pembuatan beberapa class diatas, selanjutnya kita akan membuat controller Account yang digunakan sebagai URL/path login sesuai konfigurasi Owin diatas. Jadi ketika user belum melakukan login/otorisasi, maka seluruh aktivitas controller yang memiliki attribute [Authorize] akan diarahkan kehalam login terlebih dahulu.

Langkah-langkahnya :
  1. Tambahkan controller baru dengan cara klik kanan pada direktori Controller >> Add >> Controller. Pada jendela yang terbuka, pilih MVC 5 Controller - Empty, lalu klik tombol Add dan beri nama dengan AccountController.cs.
  2. Setelah AccountController terbuat, buatlah 2 buah View dengan type GET dan POST dan beri nama Login. View Login dengan type GET akan digunakan sebagai halaman login aplikasi. View Login dengan type POST digunakan untuk memproses login pada aplikasiPastikan view dapat diakses oleh semua user dengan cara menambahkan atribut [AllowAnonymous]. Dan jangan lupa untuk menambahkan view CSHTML nya juga.
    using Custom_Login.Models;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    
    namespace Custom_Login.Controllers
    {
        public class AccountController : Controller
        {
            public ActionResult Index()
            {
                return RedirectPermanent("~/account/login");
            }
    
            [HttpGet]
            [AllowAnonymous]
            public ActionResult Login()
            {
                return View();
            }
    
            [HttpPost]
            [AllowAnonymous]
            public ActionResult Login(UserModel user)
            {
                return View();
            }
        }
    }
  3. Buatlah beberapa variabel baru dengan class CustomUserManager yang digunakan untuk inisiasi objek UserManager pada AccountController.cs dan class IAuthenticationManager untuk pengecekan autentifikasi. Kode lengkapnya seperti berikut ini :
    private CustomUserManager _customUserManager { get; set; }
    public AccountController(CustomUserManager customUser) => this._customUserManager = customUser;
    public AccountController() : this(new CustomUserManager()) { }
    private IAuthenticationManager AuthenticationManager
    {
       get
         {
           return HttpContext.GetOwinContext().Authentication;
         }
    }
  4. Buat juga fungsi/method untuk melakukan Login dan Logout dari aplikasi.
    private async Task SignInAsync(UserModel user, bool isPersistent)
    {
        AuthenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie);
        var identity = await _customUserManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);
        AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, identity);
    }
    
    public ActionResult Logout()
    {           
        AuthenticationManager.SignOut();
        return RedirectToAction("login", "account");
    }
  5. Hasil akhirnya menjadi seperti berikut :

    AccountController.cs
    using Custom_Login.Models;
    using Microsoft.AspNet.Identity;
    using Microsoft.Owin.Security;
    using System.Threading.Tasks;
    using System.Web;
    using System.Web.Mvc;
    
    namespace Custom_Login.Controllers
    {
        public class AccountController : Controller
        {
            private CustomUserManager _customUserManager { get; set; }
            public AccountController(CustomUserManager customUser) => this._customUserManager = customUser;
            public AccountController() : this(new CustomUserManager()) { }
            private IAuthenticationManager AuthenticationManager
            {
                get
                {
                    return HttpContext.GetOwinContext().Authentication;
                }
            }
    
            public ActionResult Index()
            {
                return RedirectToAction("login", "account");
            }
    
            [HttpGet]
            [AllowAnonymous]
            public ActionResult Login()
            {
                return View();
            }
    
            [HttpPost]
            [AllowAnonymous]
            public async Task<ActionResult> Login(UserModel user)
            {
                if(user.UserName == "admin" && user.Password == "admin")
                {
                    user.Id = "1";
                    bool rememberMe = false;
                    await SignInAsync(user, rememberMe);
                    return RedirectToAction("index", "home");
                }
                return View();
            }
    
            private async Task SignInAsync(UserModel user, bool isPersistent)
            {
                AuthenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie);
                var identity = await _customUserManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);
                AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, identity);
            }
    
            public ActionResult Logout()
            {           
                AuthenticationManager.SignOut();
                return RedirectToAction("login", "account");
            }
        }
    }

    Pada baris yang ditandai diatas seperti username dan password hanyalah sebagai contoh login saja (username dan password diambil dari database).

    Login.cshtml
    @{
        Layout = null;
    }
    
    <!DOCTYPE html>
    
    <html>
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Login</title>
        <link rel="stylesheet" type="text/css" href="https://colorlib.com/etc/lf/Login_v10/vendor/bootstrap/css/bootstrap.min.css">
        <link rel="stylesheet" type="text/css" href="https://colorlib.com/etc/lf/Login_v10/fonts/font-awesome-4.7.0/css/font-awesome.min.css">
        <link rel="stylesheet" type="text/css" href="https://colorlib.com/etc/lf/Login_v10/fonts/Linearicons-Free-v1.0.0/icon-font.min.css">
        <link rel="stylesheet" type="text/css" href="https://colorlib.com/etc/lf/Login_v10/vendor/animate/animate.css">
        <link rel="stylesheet" type="text/css" href="https://colorlib.com/etc/lf/Login_v10/vendor/css-hamburgers/hamburgers.min.css">
        <link rel="stylesheet" type="text/css" href="https://colorlib.com/etc/lf/Login_v10/vendor/animsition/css/animsition.min.css">
        <link rel="stylesheet" type="text/css" href="https://colorlib.com/etc/lf/Login_v10/vendor/select2/select2.min.css">
        <link rel="stylesheet" type="text/css" href="https://colorlib.com/etc/lf/Login_v10/vendor/daterangepicker/daterangepicker.css">
        <link rel="stylesheet" type="text/css" href="https://colorlib.com/etc/lf/Login_v10/css/util.css">
        <link rel="stylesheet" type="text/css" href="https://colorlib.com/etc/lf/Login_v10/css/main.css">
    </head>
    <body>
        <div class="limiter">
            <div class="container-login100">
                <div class="wrap-login100 p-t-50 p-b-90">
                    <form class="login100-form validate-form flex-sb flex-w" action="~/account/login" method="post">
                        <span class="login100-form-title p-b-51">
                            Login
                        </span>
                        <div class="wrap-input100 validate-input m-b-16" data-validate="Username is required">
                            <input class="input100" type="text" name="username" placeholder="Username">
                            <span class="focus-input100"></span>
                        </div>
                        <div class="wrap-input100 validate-input m-b-16" data-validate="Password is required">
                            <input class="input100" type="password" name="password" placeholder="Password">
                            <span class="focus-input100"></span>
                        </div>
                        <div class="flex-sb-m w-full p-t-3 p-b-24">
                            <div class="contact100-form-checkbox">
                                <input class="input-checkbox100" id="ckb1" type="checkbox" name="remember-me">
                                <label class="label-checkbox100" for="ckb1">
                                    Remember me
                                </label>
                            </div>
                            <div>
                                <a href="#" class="txt1">
                                    Forgot?
                                </a>
                            </div>
                        </div>
                        <div class="container-login100-form-btn m-t-17">
                            <button class="login100-form-btn">
                                Login
                            </button>
                        </div>
                    </form>
                </div>
            </div>
        </div>
        <div id="dropDownSelect1"></div>
        <script src="https://colorlib.com/etc/lf/Login_v10/vendor/jquery/jquery-3.2.1.min.js" type="text/javascript"></script>
        <script src="https://colorlib.com/etc/lf/Login_v10/vendor/animsition/js/animsition.min.js" type="text/javascript"></script>
        <script src="https://colorlib.com/etc/lf/Login_v10/vendor/bootstrap/js/popper.js" type="text/javascript"></script>
        <script src="https://colorlib.com/etc/lf/Login_v10/vendor/bootstrap/js/bootstrap.min.js" type="text/javascript"></script>
        <script src="https://colorlib.com/etc/lf/Login_v10/vendor/select2/select2.min.js" type="text/javascript"></script>
        <script src="https://colorlib.com/etc/lf/Login_v10/vendor/daterangepicker/moment.min.js" type="text/javascript"></script>
        <script src="https://colorlib.com/etc/lf/Login_v10/vendor/daterangepicker/daterangepicker.js" type="text/javascript"></script>
        <script src="https://colorlib.com/etc/lf/Login_v10/vendor/countdowntime/countdowntime.js" type="text/javascript"></script>
        <script src="https://colorlib.com/etc/lf/Login_v10/js/main.js" type="text/javascript"></script>
        <script src="https://ajax.cloudflare.com/cdn-cgi/scripts/7089c43e/cloudflare-static/rocket-loader.min.js"></script>
    </body>
    </html>
    

[ads id="ads2"] Untuk memastikan Custom Login telah bekerja, kita dapat melakukan pengecekan identitas username dengan cara memanggil langsung melalui view dengan menggunakan kode @HttpContext.Current.User.Identity.Name atau @User.Identity.Name.

Kita juga dapat memanggil informasi user lainnya (current user) seperti ID user, jenis kelamin, alamat, no telepon dan lain sebagainya yang berkaitan dengan user. Informasi terkait user selain username, dapat disimpan menggunakan Claim (semacam session). Tutorial tentang Claim dapat dibaca di artikel mengenal Claim Identity pada ASP.NET.

Terima kasih sudah membaca dan untuk yang membutuhkan source code sebagai panduan atau sekedar pembelajaran lebih lanjut, dapat kalian download di https://drive.google.com/open?id=1Byyi6m2JW1EgQwcwP1A1-DnxoJCh-xAB

Semoga bermanfaat.


0/Post a Comment/Comments

Lebih baru Lebih lama