[基于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 都是自定义的扩展方法
public static class ModelBuilderExtensions
{
/// <summary>
/// 关掉所有主外键关系的级联删除
/// </summary>
/// <param name="modelBuilder"></param>
/// <param name="deleteBehavior"></param>
public static void SetOneToManyCascadeDeleteConvention(this ModelBuilder modelBuilder, DeleteBehavior deleteBehavior = DeleteBehavior.Restrict)
{
foreach (var relationship in modelBuilder.Model.GetEntityTypes().SelectMany(e => e.GetForeignKeys()))
{
relationship.DeleteBehavior = deleteBehavior;
}
} /// <summary>
/// 自动映射实体与表
/// </summary>
/// <param name="modelBuilder"></param>
/// <param name="executingAssembly"></param>
public static void AddEntityTypeConfigurations(this ModelBuilder modelBuilder, Assembly executingAssembly)
{
var types = executingAssembly.GetTypes();
var filterTypes = types.Where(x => !string.IsNullOrEmpty(x.Namespace));
var result = filterTypes.Where(x => !x.IsAbstract && x.GetInterfaces()
.Any(y => y.GetTypeInfo()
.IsGenericType && y.GetGenericTypeDefinition() == typeof(IEntityTypeConfiguration<>))); foreach (var configurationInstance in result.Select(Activator.CreateInstance))
{
modelBuilder.ApplyConfiguration((dynamic)configurationInstance);
}
}
}
SetOneToManyCascadeDeleteConvertion 和 AddEntityTypeConfigruations 都是自定义的扩展方法
4-注册依赖 (IOC:data,application)
4.1)ApplicationServiceCollectionExtensions:application类库中IOC相关注册扩展类
public static class ApplicationServiceCollectionExtensions
{
public static void ApplicationRegister(this IServiceCollection services)
{
services.AddScoped<IUserService, UserService>();
services.AddScoped<IMemberService, MemberService>();
services.AddScoped<IBlogService, BlogService>();
services.AddScoped<IBlogCategoryService, BlogCategoryService>();
}
}
ApplicationServiceCollectionExtensions
4.2)EfCoreServiceCollectionExtensions :data类库中IOC相关注册扩展类
public static class EfCoreServiceCollectionExtensions
{
/// <summary>
/// 注册数据库上下文
/// </summary>
/// <typeparam name="TDbContext"></typeparam>
/// <param name="services"></param>
/// <param name="connectionString"></param>
public static void AddDbContext<TDbContext>(this IServiceCollection services, string connectionString)
where TDbContext : DbContext
{
//UseRowNumberForPaging() 用于分页 ms sql server版本低于2012 需要使用
services.AddDbContext<TDbContext>(options => options.UseSqlServer(connectionString, b => b.UseRowNumberForPaging()));//
} /// <summary>
/// 接口注册
/// </summary>
/// <param name="services"></param>
public static void RegisterRepository(this IServiceCollection services)
{
services.AddScoped(typeof(IRepository<,>), typeof(RepositoryBase<,>));
}
}
EfCoreServiceCollectionExtensions
5-登录
5.1)添加IUserService 接口,UserService类,添加UserDto GetData(string userName, string password); 函数
5.2)添加 UserDto Model 类,实现GetData方法

5.3)添加 UserExtensions 扩展类
public static class UserExtensions
{
public static UserDto ToDto(this User user)
{
if (user == null)
return null;
return new UserDto
{
Id = user.Id,
IsActived = user.IsActived,
UserName = user.UserName
};
} public static User ToEntity(this UserDto user)
{
if (user == null)
return null;
return new User
{
Id = user.Id,
IsActived = user.IsActived,
UserName = user.UserName,
CreatedOn = DateTime.Now
};
}
}
UserExtensions
5.4) 添加 Account Controller
using System;
using System.Collections.Generic;
using System.Security.Claims;
using System.Threading.Tasks;
using GR.Blogs.AspNetCore.Security;
using GR.Blogs.AspNetCore.Users;
using GR.Blogs.AspNetCore.Dto;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using GR.Blogs.AspNetCore.Users.Dto; namespace GR.Blogs.AspNetCore.Web.Mvc.Controllers
{
[Authorize]
public class AccountController : Controller
{
private readonly IUserService _userService; public AccountController(IUserService userService)
{
_userService = userService;
} [AllowAnonymous]
public IActionResult Login(string ReturnUrl = null)
{
var model = new LoginViewModel();
return View(model);
} [AllowAnonymous]
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Login(string ReturnUrl, /*[Bind("UserName,Password")]*/ LoginViewModel model)
{
if (!ModelState.IsValid)
{
return View(model);
}
var user = _userService.GetData(model.UserName, MD5EncryptHelper.MD5Encrypt(model.Password));
if (user == null)
{
ModelState.AddModelError("", "用户名或密码错误");
return View(model);
} await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, GetUserClaimsPrincipal(user));
if (ReturnUrl == null)
return RedirectToAction("index", "home");
else
return Redirect(ReturnUrl);
} private ClaimsPrincipal GetUserClaimsPrincipal(UserDto user)
{
var claims = new List<Claim>();
claims.Add(new Claim(ClaimTypes.Name, user.UserName, ClaimValueTypes.String));
claims.Add(new Claim(ClaimTypes.UserData, user.Id.ToString(), ClaimValueTypes.String));
//这里写死了,正式的话,角色需要通过获取数据库角色,写入的
//claims.Add(new Claim(ClaimTypes.Role, "Administrator", ClaimValueTypes.String));
//
var userIdentity = new ClaimsIdentity(CookieAuthenticationDefaults.AuthenticationScheme);
userIdentity.AddClaims(claims);
var userPrincipal = new ClaimsPrincipal(userIdentity);
return userPrincipal;
} public async Task<IActionResult> Logout()
{
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
return RedirectToAction("index", "home");
}
}
}
AccountController
5.5) Startup 中配置 Cookie 验证 ,注册IOC

5.6)添加Login页面布局,样式是基于flatUI
@model GR.Blogs.AspNetCore.Dto.LoginViewModel
@{
Layout = null;
} <!DOCTYPE html> <html lang="zh-CN">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1000, initial-scale=1.0, maximum-scale=1.0">
<title>登录 - GR博客系统</title>
<link href="~/lib/bootstrap/dist/css/bootstrap.css" rel="stylesheet" />
<link href="~/lib/flatUI/dist/css/flat-ui.css" rel="stylesheet" />
<link href="~/lib/flatUI/docs/assets/css/demo.css" rel="stylesheet" />
<!-- HTML5 shim, for IE6-8 support of HTML5 elements. All other JS at the end of file. -->
<!--[if lt IE 9]>
<script src="~/lib/flatUI/dist/js/vendor/html5shiv.js"></script>
<script src="~/lib/flatUI/dist/js/vendor/respond.min.js"></script>
<![endif]-->
</head>
<body>
<div class="container">
<div class="login" style="margin-top:100px;">
<div class="login-screen">
<div class="login-icon">
<img src="~/lib/flatUI/dist/img/icons/png/Mail.png" alt="Welcome to Mail App" />
<h4>Welcome to <small>Mail App</small></h4>
</div> <form class="login-form" method="post">
@Html.AntiForgeryToken()
<div class="form-group">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
</div>
<div class="form-group">
<input type="text" asp-for="UserName" class="form-control login-field" value="" placeholder="用户名">
<label class="login-field-icon fui-user"></label>
<span asp-validation-for="UserName" class="text-danger"></span>
</div> <div class="form-group">
<input type="password" asp-for="Password" class="form-control login-field" value="" placeholder="密码">
<label class="login-field-icon fui-lock"></label>
<span asp-validation-for="Password" class="text-danger"></span>
</div> <input type="submit" class="btn btn-primary btn-lg btn-block" value="登录">
<a class="login-link" href="#">忘记密码?</a>
</form>
</div>
</div>
</div>
@*<environment include="Development">
<script src="~/lib/jquery/dist/jquery.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.js"></script>
<script src="~/js/site.js" asp-append-version="true"></script>
</environment>
<environment exclude="Development">
<script src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-2.2.0.min.js"
asp-fallback-src="~/lib/jquery/dist/jquery.min.js"
asp-fallback-test="window.jQuery"
crossorigin="anonymous"
integrity="sha384-K+ctZQ+LL8q6tP7I94W+qzQsfRV2a+AfHIi9k8z8l9ggpc8X+Ytst4yBo/hH+8Fk">
</script>
<script src="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.7/bootstrap.min.js"
asp-fallback-src="~/lib/bootstrap/dist/js/bootstrap.min.js"
asp-fallback-test="window.jQuery && window.jQuery.fn && window.jQuery.fn.modal"
crossorigin="anonymous"
integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa">
</script>
<script src="~/js/site.min.js" asp-append-version="true"></script>
</environment>
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}*@ </body>
</html>
Login

5-结束了
文笔不行,不知道该怎么组织语言,所以就以流水账形式记录了
[基于NetCore的简单博客系统]-登录的更多相关文章
- 26种基于PHP的开源博客系统
26种基于PHP的开源博客系统 来源:本站原创 PHP学习笔记 以下列举的PHP开源Blog系统中,除了我们熟知的WordPress之外,大多都没有使用过,其中一些已经被淘汰,或者有人还在使用.除了做 ...
- Docker——基于Docker安装Drupal博客系统
Docker--基于Docker安装Drupal博客系统 向脚本文件追加内容 cat << EOF > build.sh #设置主机名 hostnamectl set-hostnam ...
- Java基于SSM的个人博客系统(源码 包含前后台)
@ 目录 系统简介 系统运行截图 核心代码 写在最后 系统简介 技术点:Java.JSP.SSM框架,实现了个人博客系统 用户角色分为:普通用户.管理员.系统管理员 功能:发博客.博客分类.博客删除. ...
- 基于开源博客系统(mblog)搭建网站
基于开源博客系统(mblog)搭建网站 上一章讲了基于jpress部署的博客系统,这一章了解一下 mblog这个开源的基于springboot的博客系统,相比与jpress 的热度fork数量要少一些 ...
- 欢迎阅读daxnet的新博客:一个基于Microsoft Azure、ASP.NET Core和Docker的博客系统
2008年11月,我在博客园开通了个人帐号,并在博客园发表了自己的第一篇博客.当然,我写博客也不是从2008年才开始的,在更早时候,也在CSDN和系统分析员协会(之后名为"希赛网" ...
- 一个基于Microsoft Azure、ASP.NET Core和Docker的博客系统
2008年11月,我在博客园开通了个人帐号,并在博客园发表了自己的第一篇博客.当然,我写博客也不是从2008年才开始的,在更早时候,也在CSDN和系统分析员协会(之后名为“希赛网”)个人空间发布过一些 ...
- 基于Microsoft Azure、ASP.NET Core和Docker的博客系统
欢迎阅读daxnet的新博客:一个基于Microsoft Azure.ASP.NET Core和Docker的博客系统 2008年11月,我在博客园开通了个人帐号,并在博客园发表了自己的第一篇博客 ...
- Essay3.0发布,基于JavaScript的前后端同构博客系统
前言 转眼间距离我开源这个项目已经两年了,最初是奔着学习的目的开发了这个项目,后来一直记录自己的学习笔记.随着时间的增长,发现之前写的代码简直不忍直视,于是就有了重构的想法.这个过程有些漫长,竟然用了 ...
- 基于开源博客系统(jpress)搭建网站
基于开源博客系统(jpress)搭建网站 JPress 使用 Java8 开发,基于流行的JFinal和Jboot框架. 目前JPress已经内置的文章和页面其实是两个模块,可以移除和新增其他模块,因 ...
随机推荐
- react组件间传值详解
一.父子组件间传值 <1>父传子 父组件:
- linux操作之ntsysv
命令nysysv , 提示Command nod found 先在命令行输入 export PATH=/usr/bin:/usr/sbin:/bin:/sbin:/usr/X11R6/bin: ...
- English_phonetic symbol
Introduction 本人学习了奶爸课程---45天的搞定发音课,结合自己的英语水平,为自己撰写的一个系统的英语发音课,不只是音标,还有音标辨析.连读.音调等. 重点:英语发音时一个持续一生的东西 ...
- 前端页面加载速度优化---Ngnix之GZIP压缩
gzip on; #开启Gzip gzip_static on;#是否开启gzip静态资源 #nginx对于静态文件的处理模块,该模块可以读取预先压缩的gz文件,这样可以减少每次请求进行gzip压缩的 ...
- Ubuntu 安装 搜狗输入法
1.去下载搜狗输入法安装包: https://pinyin.sogou.com/linux/ 2.安装 sudo dpkg sougou****.deb 3.去设置 参考:https://blog.c ...
- linux初学体会
第一篇随笔,其实是为了写作业,可是老师的要求是对的,其实自己在配环境和做作业的时候也会把遇到的问题的解决方法记录下来,以便以后查找方便.这次借此将那些内容放在这里,也跟大家一起分享下. 上周六算是第二 ...
- PS 去皱纹
1.打开一个有皱纹的图片,选择修复画笔工具,按住Alt键吸取一块光滑的皮肤,然后再在有皱纹的位置上点击即可
- python3基础盲点
数值类型 Python支持四种不同的数值类型,包括int(整数)long(长整数)float(浮点数)complex (复数) python3对整数的大小不做限制 算数运算符 优先级: 逻辑运算符 优 ...
- Python3安装pywin32模块
假如你安装的是Python3.6, 那么可以直接用PyCharm或者pip安装pywin32模块: 但是, 由于我安装的是Python3.7, 所以PyCharm或者pip都无法成功安装pywin32 ...
- Java开发工程师(Web方向) - 02.Servlet技术 - 期末考试
Servlet课程考试 Servlet课程考试 Servlet课程考试 总分:55分 限定时间:120分钟 进入考试 答案已成功提交!请耐心等待成绩公布 Servlet课程考试: 1(12分) 简单谈 ...