zoukankan      html  css  js  c++  java
  • [基于NetCore的简单博客系统]-登录

    0-项目背景

      一个基于.NET CORE RAZOR PAGES的简单博客系统 技术栈全部采用微软官方实现方式,目的是熟悉新技术

    PS:因为是练手,所以UI界面就比较丑咯

    1-框架结构(参考ABP框架:因为是练手,所以没有使用ABP基础类,只是参考了他的架子)

    1.1)后台用经典的MVC方式实现

    1.2)前台打算使用.NetCore RazorPage页面实现

    2-表结构

    2.1)User - 后台用户

    2.2)Member -前台用户

    2.3)MemberBlogTagRelationship - 前台用户博文标签表

    2.4)Blog -博文

    2.5)BlogCategroy -博文分类

    2.6)BlogPost- 博文评论

    2.7) BlogTag-博文标签(前台用户添加)

    2.8)BlogTagRelationship - 博文-博文标签关联表

    2.9)添加Entity 基类 参考 ABP 的实体基类,所有实体都是派生自 entity 

    3-生成数据库(基于EF code-first 模式)

     3.1)添加实体与数据库表映射关系

     3.2)数据上下文中添加配置

     3.3)生成数据库方式参考https://docs.microsoft.com/en-us/ef/core/ 和以前的EF差不多

    3.4)SetOneToManyCascadeDeleteConvertion 和 AddEntityTypeConfigruations 都是自定义的扩展方法

     1  public static class ModelBuilderExtensions
     2     {
     3         /// <summary>
     4         /// 关掉所有主外键关系的级联删除
     5         /// </summary>
     6         /// <param name="modelBuilder"></param>
     7         /// <param name="deleteBehavior"></param>
     8         public static void SetOneToManyCascadeDeleteConvention(this ModelBuilder modelBuilder, DeleteBehavior deleteBehavior = DeleteBehavior.Restrict)
     9         {
    10             foreach (var relationship in modelBuilder.Model.GetEntityTypes().SelectMany(e => e.GetForeignKeys()))
    11             {
    12                 relationship.DeleteBehavior = deleteBehavior;
    13             }
    14         }
    15 
    16         /// <summary>
    17         /// 自动映射实体与表
    18         /// </summary>
    19         /// <param name="modelBuilder"></param>
    20         /// <param name="executingAssembly"></param>
    21         public static void AddEntityTypeConfigurations(this ModelBuilder modelBuilder, Assembly executingAssembly)
    22         {
    23             var types = executingAssembly.GetTypes();
    24             var filterTypes = types.Where(x => !string.IsNullOrEmpty(x.Namespace));
    25             var result = filterTypes.Where(x => !x.IsAbstract && x.GetInterfaces()
    26             .Any(y => y.GetTypeInfo()
    27             .IsGenericType && y.GetGenericTypeDefinition() == typeof(IEntityTypeConfiguration<>)));
    28 
    29             foreach (var configurationInstance in result.Select(Activator.CreateInstance))
    30             {
    31                 modelBuilder.ApplyConfiguration((dynamic)configurationInstance);
    32             }
    33         }
    34     }
    SetOneToManyCascadeDeleteConvertion 和 AddEntityTypeConfigruations 都是自定义的扩展方法

    4-注册依赖 (IOC:data,application)

     4.1)ApplicationServiceCollectionExtensions:application类库中IOC相关注册扩展类

     1 public static class ApplicationServiceCollectionExtensions
     2     {
     3         public static void ApplicationRegister(this IServiceCollection services)
     4         {
     5             services.AddScoped<IUserService, UserService>();
     6             services.AddScoped<IMemberService, MemberService>();
     7             services.AddScoped<IBlogService, BlogService>();
     8             services.AddScoped<IBlogCategoryService, BlogCategoryService>();
     9         }
    10     }
    ApplicationServiceCollectionExtensions

    4.2)EfCoreServiceCollectionExtensions :data类库中IOC相关注册扩展类

     1  public static class EfCoreServiceCollectionExtensions
     2     {
     3         /// <summary>
     4         /// 注册数据库上下文
     5         /// </summary>
     6         /// <typeparam name="TDbContext"></typeparam>
     7         /// <param name="services"></param>
     8         /// <param name="connectionString"></param>
     9         public static void AddDbContext<TDbContext>(this IServiceCollection services, string connectionString)
    10             where TDbContext : DbContext
    11         {
    12             //UseRowNumberForPaging() 用于分页 ms sql server版本低于2012 需要使用
    13             services.AddDbContext<TDbContext>(options => options.UseSqlServer(connectionString, b => b.UseRowNumberForPaging()));//
    14         }
    15 
    16         /// <summary>
    17         /// 接口注册
    18         /// </summary>
    19         /// <param name="services"></param>
    20         public static void RegisterRepository(this IServiceCollection services)
    21         {
    22             services.AddScoped(typeof(IRepository<,>), typeof(RepositoryBase<,>));
    23         }
    24     }
    EfCoreServiceCollectionExtensions

    5-登录

     5.1)添加IUserService 接口,UserService类,添加UserDto GetData(string userName, string password); 函数

    5.2)添加 UserDto Model 类,实现GetData方法

    5.3)添加 UserExtensions 扩展类

     1 public static class UserExtensions
     2     {
     3         public static UserDto ToDto(this User user)
     4         {
     5             if (user == null)
     6                 return null;
     7             return new UserDto
     8             {
     9                 Id = user.Id,
    10                 IsActived = user.IsActived,
    11                 UserName = user.UserName
    12             };
    13         }
    14 
    15         public static User ToEntity(this UserDto user)
    16         {
    17             if (user == null)
    18                 return null;
    19             return new User
    20             {
    21                 Id = user.Id,
    22                 IsActived = user.IsActived,
    23                 UserName = user.UserName,
    24                 CreatedOn = DateTime.Now
    25             };
    26         }
    27     }
    UserExtensions

     5.4) 添加 Account Controller

     1 using System;
     2 using System.Collections.Generic;
     3 using System.Security.Claims;
     4 using System.Threading.Tasks;
     5 using GR.Blogs.AspNetCore.Security;
     6 using GR.Blogs.AspNetCore.Users;
     7 using GR.Blogs.AspNetCore.Dto;
     8 using Microsoft.AspNetCore.Authentication;
     9 using Microsoft.AspNetCore.Authentication.Cookies;
    10 using Microsoft.AspNetCore.Authorization;
    11 using Microsoft.AspNetCore.Mvc;
    12 using GR.Blogs.AspNetCore.Users.Dto;
    13 
    14 namespace GR.Blogs.AspNetCore.Web.Mvc.Controllers
    15 {
    16     [Authorize]
    17     public class AccountController : Controller
    18     {
    19         private readonly IUserService _userService;
    20 
    21         public AccountController(IUserService userService)
    22         {
    23             _userService = userService;
    24         }
    25 
    26         [AllowAnonymous]
    27         public IActionResult Login(string ReturnUrl = null)
    28         {
    29             var model = new LoginViewModel();
    30             return View(model);
    31         }
    32 
    33         [AllowAnonymous]
    34         [HttpPost]
    35         [ValidateAntiForgeryToken]
    36         public async Task<IActionResult> Login(string ReturnUrl, /*[Bind("UserName,Password")]*/ LoginViewModel model)
    37         {
    38             if (!ModelState.IsValid)
    39             {
    40                 return View(model);
    41             }
    42             var user = _userService.GetData(model.UserName, MD5EncryptHelper.MD5Encrypt(model.Password));
    43             if (user == null)
    44             {
    45                 ModelState.AddModelError("", "用户名或密码错误");
    46                 return View(model);
    47             }
    48 
    49             await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, GetUserClaimsPrincipal(user));
    50             if (ReturnUrl == null)
    51                 return RedirectToAction("index", "home");
    52             else
    53                 return Redirect(ReturnUrl);
    54         }
    55 
    56 
    57         private ClaimsPrincipal GetUserClaimsPrincipal(UserDto user)
    58         {
    59             var claims = new List<Claim>();
    60             claims.Add(new Claim(ClaimTypes.Name, user.UserName, ClaimValueTypes.String));
    61             claims.Add(new Claim(ClaimTypes.UserData, user.Id.ToString(), ClaimValueTypes.String));
    62             //这里写死了,正式的话,角色需要通过获取数据库角色,写入的
    63             //claims.Add(new Claim(ClaimTypes.Role, "Administrator", ClaimValueTypes.String));
    64             //
    65             var userIdentity = new ClaimsIdentity(CookieAuthenticationDefaults.AuthenticationScheme);
    66             userIdentity.AddClaims(claims);
    67             var userPrincipal = new ClaimsPrincipal(userIdentity);
    68             return userPrincipal;
    69         }
    70 
    71         public async Task<IActionResult> Logout()
    72         {
    73             await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
    74             return RedirectToAction("index", "home");
    75         }
    76     }
    77 }
    AccountController

    5.5) Startup 中配置 Cookie 验证 ,注册IOC

    5.6)添加Login页面布局,样式是基于flatUI

     1 @model GR.Blogs.AspNetCore.Dto.LoginViewModel
     2 @{
     3     Layout = null;
     4 }
     5 
     6 <!DOCTYPE html>
     7 
     8 <html lang="zh-CN">
     9 <head>
    10     <meta charset="utf-8" />
    11     <meta http-equiv="X-UA-Compatible" content="IE=edge">
    12     <meta name="viewport" content="width=1000, initial-scale=1.0, maximum-scale=1.0">
    13     <title>登录 - GR博客系统</title>
    14     <link href="~/lib/bootstrap/dist/css/bootstrap.css" rel="stylesheet" />
    15     <link href="~/lib/flatUI/dist/css/flat-ui.css" rel="stylesheet" />
    16     <link href="~/lib/flatUI/docs/assets/css/demo.css" rel="stylesheet" />
    17     <!-- HTML5 shim, for IE6-8 support of HTML5 elements. All other JS at the end of file. -->
    18     <!--[if lt IE 9]>
    19       <script src="~/lib/flatUI/dist/js/vendor/html5shiv.js"></script>
    20       <script src="~/lib/flatUI/dist/js/vendor/respond.min.js"></script>
    21     <![endif]-->
    22 </head>
    23 <body>
    24     <div class="container">
    25         <div class="login" style="margin-top:100px;">
    26             <div class="login-screen">
    27                 <div class="login-icon">
    28                     <img src="~/lib/flatUI/dist/img/icons/png/Mail.png" alt="Welcome to Mail App" />
    29                     <h4>Welcome to <small>Mail App</small></h4>
    30                 </div>
    31 
    32                 <form class="login-form" method="post">
    33                     @Html.AntiForgeryToken()
    34                     <div class="form-group">
    35                         <div asp-validation-summary="ModelOnly" class="text-danger"></div>
    36                     </div>
    37                     <div class="form-group">
    38                         <input type="text" asp-for="UserName" class="form-control login-field" value="" placeholder="用户名">
    39                         <label class="login-field-icon fui-user"></label>
    40                         <span asp-validation-for="UserName" class="text-danger"></span>
    41                     </div>
    42 
    43                     <div class="form-group">
    44                         <input type="password" asp-for="Password" class="form-control login-field" value="" placeholder="密码">
    45                         <label class="login-field-icon fui-lock"></label>
    46                         <span asp-validation-for="Password" class="text-danger"></span>
    47                     </div>
    48 
    49                     <input type="submit" class="btn btn-primary btn-lg btn-block" value="登录">
    50                     <a class="login-link" href="#">忘记密码?</a>
    51                 </form>
    52             </div>
    53         </div>
    54     </div>
    55     @*<environment include="Development">
    56             <script src="~/lib/jquery/dist/jquery.js"></script>
    57             <script src="~/lib/bootstrap/dist/js/bootstrap.js"></script>
    58             <script src="~/js/site.js" asp-append-version="true"></script>
    59         </environment>
    60         <environment exclude="Development">
    61             <script src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-2.2.0.min.js"
    62                     asp-fallback-src="~/lib/jquery/dist/jquery.min.js"
    63                     asp-fallback-test="window.jQuery"
    64                     crossorigin="anonymous"
    65                     integrity="sha384-K+ctZQ+LL8q6tP7I94W+qzQsfRV2a+AfHIi9k8z8l9ggpc8X+Ytst4yBo/hH+8Fk">
    66             </script>
    67             <script src="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.7/bootstrap.min.js"
    68                     asp-fallback-src="~/lib/bootstrap/dist/js/bootstrap.min.js"
    69                     asp-fallback-test="window.jQuery && window.jQuery.fn && window.jQuery.fn.modal"
    70                     crossorigin="anonymous"
    71                     integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa">
    72             </script>
    73             <script src="~/js/site.min.js" asp-append-version="true"></script>
    74         </environment>
    75         @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}*@
    76 
    77 </body>
    78 </html>
    Login

    5-结束了

     文笔不行,不知道该怎么组织语言,所以就以流水账形式记录了

  • 相关阅读:
    Task 和 Function
    FPGA中双向端口的设计原理及仿真
    EDK实用实例之LED
    分频电路设计(笔记)
    你了解Promise么
    配置vue多页
    Chrome控制台console的那些属性
    关于读书
    django常用命令
    django 简易博客开发 2 模板和数据查询
  • 原文地址:https://www.cnblogs.com/ganqiyin/p/8404299.html
Copyright © 2011-2022 走看看