[基于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-结束了

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

 

posted @ 2018-02-02 12:04  细品人生  阅读(609)  评论(0编辑  收藏  举报