固然,你也能夠直接以前前往coding倉庫查看源碼,要是發現bug記得提醒我啊~ LoginDemo地址css
完整Login.cshtml視圖代碼戳這裏-共計55行
效果預覽圖html
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>登陸界面</title> <meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=no"> <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css"> <style type="text/css"> body { color: #fff; font-family: "微軟雅黑"; font-size: 14px; background: url('https://dn-coding-net-production-pp.qbox.me/96ec8cc7-0e5f-4217-b853-4a88c15579f3.png') no-repeat; } .wrap1 { position: absolute; top: 0; right: 0; bottom: 0; left: 0; margin: auto; height: 450px; } /*把整個屏幕真正撐開--並且能本身實現居中*/ .main_content { background: url(https://dn-coding-net-production-pp.qbox.me/2ed70a05-04ad-4ccf-81d4-bc1fad2b6e41.png) repeat; margin-left: auto; margin-right: auto; text-align: left; float: none; border-radius: 8px; } .form-group { position: relative; } .login_btn { display: block; background: #3872f6; color: #fff; font-size: 15px; width: 100%; line-height: 50px; border-radius: 3px; border: none; } .login_input { width: 100%; border: 1px solid #3872f6; border-radius: 3px; line-height: 40px; padding: 2px 5px 2px 30px; background: none; } .icon_font { position: absolute; top: 12px; left: 10px; font-size: 18px; color: #3872f6; } .font16 { font-size: 16px; } .mg-t20 { margin-top: 20px; } @media (min-width:200px) {.pd-xs-20 { padding: 20px; }} @media (min-width:768px) {.pd-sm-50 { padding: 50px; }} #grad { background: -webkit-linear-gradient(#4990c1, #52a3d2, #6186a3); /* Safari 5.1 - 6.0 */ background: -o-linear-gradient(#4990c1, #52a3d2, #6186a3); /* Opera 11.1 - 12.0 */ background: -moz-linear-gradient(#4990c1, #52a3d2, #6186a3); /* Firefox 3.6 - 15 */ background: linear-gradient(#4990c1, #52a3d2, #6186a3); /* 標準的語法 */ } /*==jquery.validate css==*/ .field-validation-error { color: #e14430 !important; padding-top: 5px; } .input-validation-error { border-color: #d38e99; } </style> </head> <body> <div class="container wrap1"> <h2 class="mg-b20 text-center">後臺管理系統</h2> <div class="col-sm-8 col-md-5 center-auto pd-sm-50 pd-xs-20 main_content"> <p class="text-center font16">用戶登陸</p> <form asp-action="Login" method="post" > <div class="form-group mg-t20"> <i class="icon_font glyphicon glyphicon-user"></i> <input type="text" class="login_input" asp-for="UserName" placeholder="請輸入用戶名" autofocus /> <span asp-validation-for="UserName"></span> </div> <div class="form-group mg-t20"> <i class="icon_font glyphicon glyphicon-lock"></i> <input type="password" class="login_input" asp-for="UserPwd" placeholder="請輸入密碼" /> <span asp-validation-for="UserPwd"></span> </div> <div class="checkbox mg-b25 hide"> <label> <input type="checkbox">記住個人登陸信息 </label> </div> <button type="submit" class="login_btn">登 錄</button> </form> </div> </div> </body> </html>
AccountController
控制器裏面至少擁有一個呈現登陸頁的action,一個接收登陸請求的action,一個退出的action
·登陸· 判斷是否存在用戶,將用戶名或者用戶ID加密後記錄到cookie中,跳轉到管理頁
·退出· 將cookie移出掉,跳轉到登陸頁
加密的方法可自行切換爲其餘的加密方法jquery
public class AccountController : Controller { private readonly IUserService _userService; public AccountController(IUserService userService) { _userService = userService; } public IActionResult Login() { return View(); } [HttpPost] [ValidateAntiForgeryToken] public IActionResult Login(AccountModel model) { //驗證模型是否正確 if (!ModelState.IsValid) { return View(model); } //調用服務驗證用戶名密碼 if (!_userService.Login(model.UserName, model.UserPwd)) { ModelState.AddModelError(nameof(model.UserPwd), "用戶名或密碼錯誤"); return View(); } //加密用戶名寫入cookie中,AdminAuthorizeAttribute特性標記取出cookie並解碼除用戶名 var encryptValue = _userService.LoginEncrypt(model.UserName, ApplicationKeys.User_Cookie_Encryption_Key); HttpContext.Response.Cookies.Append(ApplicationKeys.User_Cookie_Key, encryptValue); return Redirect("/"); } public IActionResult Logout() { HttpContext.Response.Cookies.Delete(ApplicationKeys.User_Cookie_Key); return Redirect(WebContext.LoginUrl); } }
本文只是簡單的驗證是否登陸,關於更復雜的權限驗證可參考文章:http://www.cnblogs.com/morang/p/7606843.html,以及示例項目
將此特性標記加到須要的地方便可在訪問時驗證用戶是否登陸,未登陸則跳轉到登陸頁。git
public class AdminAuthorizeAttribute : Attribute, IAuthorizationFilter { public void OnAuthorization(AuthorizationFilterContext filterContext) { if (string.IsNullOrEmpty(WebContext.AdminName)) { if (filterContext.HttpContext.Request.Headers["X-Requested-With"] == "XMLHttpRequest") { filterContext.Result = new JsonResult("未登陸"); } else { filterContext.Result = new RedirectResult("Account/Login"); } return; } } }
上面特性標記代碼中的WebContext.AdminName
是如何取到的呢?還須要結合以下代碼web
//服務定位器 public static class ServiceLocator { public static IServiceProvider Instance { get; set; } public static T GetService<T>() where T : class { return Instance.GetService<T>(); } } //一些通用的信息 public static class WebContext { public static string AdminName { get { //獲取cookie var hasCookie = ServiceLocator.GetService<IHttpContextAccessor>() .HttpContext .Request.Cookies .TryGetValue(ApplicationKeys.User_Cookie_Key, out string encryptValue); if (!hasCookie || string.IsNullOrEmpty(encryptValue)) return null; var adminName = ServiceLocator.GetService<IUserService>().LoginDecrypt(encryptValue, ApplicationKeys.User_Cookie_Encryption_Key); return adminName; } } public const string LoginUrl = "/account/login"; } //全局的一些Key值 public class ApplicationKeys { public const string User_Cookie_Encryption_Key = "User_Cookie_Encryption_Key"; public const string User_Cookie_Key = "User_Cookie_Key"; } //Startup public void ConfigureServices(IServiceCollection services) { services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();//用於獲取請求上下文 services.AddTransient<IUserService, UserService>(); services.AddMvc(); } public void Configure(IApplicationBuilder app, IHostingEnvironment env) { //app.UseMvc().. //最末的時候賦值 ServiceLocator.Instance = app.ApplicationServices; }
ServiceLocator
IApplicationBuilder.ApplicationServices
賦值給ServiceLocator.Instance
,這樣就可以在任何地方使用ServiceLocator.Instance
獲取到注入的服務T GetService<T>()
方法)ServiceLocator.GetService<IHttpContextAccessor>().HttpContext.Request.Cookies
ServiceLocator.GetService<IUserService>().LoginDecrypt(encryptValue, ApplicationKeys.User_Cookie_Encryption_Key);
WebContext.AdminName
獲取到當前登陸用戶名,或者根據用戶名獲取登陸信息IFilterMetadata
,換言之:特性標記實現了IFilterMetadata
就等因而個過濾器(我的理解)asp-for
Startup.ConfigureServices
方法中注入 services.AddTransient<IUserService, UserService>()
asp.net core獲取HttpContext
對象 參考:ASP.NET Core開發之HttpContextbootstrap
ASP.NET Core中提供了一個
IHttpContextAccessor
接口,HttpContextAccessor
默認實現了它簡化了訪問HttpContext
。
它必須在程序啓動時在IServicesCollection
中註冊,這樣在程序中就能獲取到HttpContextAccessor
,並用來訪問HttpContext
。
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
cookie
form
標籤,asp-action
,asp-controller
等指定路由參數便可,而且可以自動生成防僞字段標識,配合ValidateAntiForgeryToken
特性標記預防CSRF
代碼生成比較圖autofocus
屬性 可以使文本框自動獲取焦點app
git clone https://git.coding.net/yimocoding/WeDemo.git -b LoginDemo LoginDemo
探索學習中,如有錯誤或者不足指出還望園友指出。asp.net