不用不知道,一用香到爆。

老哥是个屌丝前端,但也想写点web应用耍一耍。之前弄过了NodeJs,也弄过JAVA,最近由于写游戏的原因用C#,索性上手一波asp.net core。

这篇博客记录的是,如何在分分钟内搭建一个博客程序。包括:

  1. 发博客
  2. 看博客
  3. 用户注册登录
  4. 用户权限设置。

其中用的就是微软提供的EntityFrame和Identity类库。简直他妈爽出翔。

1.快速生成一个项目

反正增删改查就那么回事儿,快速生成一个项目模板才是主要的。

我不想创建一个带Razor页面的项目。因为我只需要API。老夫可是个前端!

这个时候按F5运行网站,然后就可以用Postman向 http://localhost:55536/api/values发送请求了。如果有过开发经验的人一眼就能看明白这是怎么回事儿。

2.给程序添加用户系统。

添加用户系统的意思是,允许用户注册和登录。

如果我用NodeJs或者Java,我就要开始写数据库了,甚至设计数据表。可是微软已经把好用的东西给准备好了,那就是:Identity类库。这个类库老JB好了。我只需要轻轻点几下,一套完备的用户系统就能生成到我的代码上。

我现在来解释一波我进行了什么操作。

1.刚才我加的一大堆东西,其实就是最开始创建项目的时候,“身份验证”那一部分帮我们做的事。当时我没选,现在我手动加上。

2.上面这个图,“替代所有文件”这部分如果选中,框架会帮我们生成相应的业务逻辑和Html模板(当然是Razor模板)。

3.因为注册登录需要和数据库交互,所以“新建数据库上下文类”帮我们新生成了一个和数据库交互的上下文类。这个类是EntityFramework提供的。巨牛逼巨方便。

4.“新建用户类”,这没什么好说的吧?这个用户类用于和数据库的用户表进行对应。

这下我们牛逼了。然后你会发现项目目录里多了一些文件,这些都是asp.net core帮我们生成的。

可以随便探索一下。那个Readme.txt文件可以读一下。是一个指导手册,告诉你接下来要怎么做。

3.那么接下来要怎么做?

如readme文件所说,一步一步来。我还是贴出来readme文件:

  1. Support for ASP.NET Core Identity was added to your project
  2. - The code for adding Identity to your project was generated under Areas/Identity.
  3.  
  4. Configuration of the Identity related services can be found in the Areas/Identity/IdentityHostingStartup.cs file.
  5.  
  6. If your app was previously configured to use Identity, then you should remove the call to the AddIdentity method from your ConfigureServices method.
  7. //生成的UI需要静态文件支持,用下面这段代码使你的app支持静态文件
  8. The generated UI requires support for static files. To add static files to your app:
  9. . Call app.UseStaticFiles() from your Configure method
  10. //用下面这段代码开启身份认证功能
  11. To use ASP.NET Core Identity you also need to enable authentication. To authentication to your app:
  12. . Call app.UseAuthentication() from your Configure method (after static files)
  13. //生成的UI需要MVC支持,用这面这段代码开启MVC功能
  14. The generated UI requires MVC. To add MVC to your app:
  15. . Call services.AddMvc() from your ConfigureServices method
  16. . Call app.UseMvc() from your Configure method (after authentication)
  17. //生成的数据库结构需要你执行Migration来同步数据库
  18. The generated database code requires Entity Framework Core Migrations. Run the following commands:
    //在cmd中执行下面两个命令
  19. . dotnet ef migrations add CreateIdentitySchema
  20. . dotnet ef database update
    //或者 在包管理命令行执行下面两个命令
  21. Or from the Visual Studio Package Manager Console:
  22. . Add-Migration CreateIdentitySchema
  23. . Update-Database
  24.  
  25. Apps that use ASP.NET Core Identity should also use HTTPS. To enable HTTPS see https://go.microsoft.com/fwlink/?linkid=848054.

按照上面的操作来撸好app以后。框架就搭成了。牛逼到爆。一行代码都没写,一个非常完备的基础架子已经OK了。

需要注意的是,你要额外安装EntityFramework类库。这个百度教程太多了。我就不说了。

当你执行完那两个命令后,你会发现你的数据库里多了一些表。酷!成功了。

注:在这里执行命令的时候可能会说EntityFramework没安装什么的这时候不要虚,仔细看输出,会说你装了EF6和EFCore,你要指定一下用哪个EF来运行命令,asp.net core的话就用 EntityFrameworkCore\Update-Database

4.写一波注册用户的API吧!

其实注册的业务逻辑已经生成好了,直接拿来用就可以。去Areas/Identity/Pages/Account/Register.cshtml里面,可以看到这段代码。稍微改动一下就可以拿来用了。

首先是,我打算用Postman模拟用户前端的输入,后端在注册的时候接收3个值,邮箱,用户名,密码。于是俺创建一个类代表这个数据格式。强类型语言就是爽。

  1. public class UserRegisterInput
  2. {
  3. public string UserName { get; set; }
  4. public string Email { get; set; }
  5. public string Password { get; set; }
  6. public bool RememberMe { get; set; }
  7. }

现在开始写controller。新建一个APIController,这个简直不用再描述了。最后Controller代码如下:

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Threading.Tasks;
  5. using Microsoft.AspNetCore.Http;
  6. using Microsoft.AspNetCore.Identity;
  7. using Microsoft.AspNetCore.Mvc;
  8. using TinyBlog2.Areas.Identity.Data;
  9. using TinyBlog2.DTO;
  10.  
  11. namespace TinyBlog2.Controllers
  12. {
  13. [Route("api/[controller]")]
  14. [ApiController]
  15. public class UserController : ControllerBase
  16. {
  17. private readonly UserManager<TinyBlog2User> _userManager;
  18. public UserController(UserManager<TinyBlog2User> userManager)
  19. {
  20. _userManager = userManager;
  21. }
  22. [HttpPost]
  23. [Route("Reg")] //这里是你的路由地址 post发往 https://localhost:55683/api/user/reg
  24. public async Task<IActionResult> Post([FromBody] UserRegisterInput Input)
  25. {
  26. var user = new TinyBlog2User { UserName = Input.UserName, Email = Input.Email };
  27. var result = await _userManager.CreateAsync(user, Input.Password);
  28. if (result.Succeeded)
  29. {
  30. return Ok("注册成功");
  31. }
  32. else
  33. {
  34. return BadRequest();
  35. }
  36. }
  37.  
  38. [HttpGet]
  39. public ActionResult<IEnumerable<string>> Get()
  40. {
  41. return new string[] { "value1", "value2" };
  42. }
  43. }
  44. }

然后我用Postman发一波请求试试。

注册的最后,查看数据库,你的用户显然已经存在数据库里了。这些数据表都是asp.net core + EntityFramework给我们建立好的。

5.用户权限校验

接下来我要做的是,给某个Action增加权限校验,说句白话就是,有的接口我希望登录用户才能访问,有的接口我希望管理员才能访问,或者有的接口我希望只有付费Vip才能访问。怎么做呢?

这里用已经存在的ViewController来举例子。目前为止,ValueController的数据是谁都可以访问的。但是我来加一行代码,就一行!

  1. [HttpGet]
  2. [Authorize(Policy = "VipOnly")]//很明显,从此这个Action只能是Vip才能访问。
  3. public ActionResult<IEnumerable<string>> Get()
  4. {
  5. return new string[] { "value1", "value2" };
  6. }

显然我定制了一个策略,这个策略名字叫做VipOnly。那么接下来我要定义这个策略。

  1. public void ConfigureServices(IServiceCollection services)
  2. {
  3. services.AddAuthorization(options =>
  4. {
  5. options.AddPolicy("VipOnly", policy => policy.RequireClaim("Role", "VipUser"));
  6. });
  7. services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
  8. }

我在startup.cs里面加入这一行代码,应该显而易见。意思是:增加一个名为VipOnly的策略,这个策略的要求是,如果用户有一个属性Role,这个Role的值是VipUser,那么就符合这个策略。

Claim就是用户的一个属性。这个属性可以在任何时候创建。这个Claim也是Asp.net core提供给我们的工具!很方便。来看一波代码吧。

5.1 如何给用户添加一个Claim

我更改了一下注册流程,每一个注册用户都被默认设置为VipUser

  1. [HttpPost]
  2. [Route("Reg")]
  3. public async Task<IActionResult> Post([FromBody] UserRegisterInput Input)
  4. {
  5. var user = new TinyBlog2User { UserName = Input.UserName, Email = Input.Email };
  6. var result = await _userManager.CreateAsync(user, Input.Password);
  7. //给用户增加一个Claim
  8. var addClaimResult = await _userManager.AddClaimAsync(user, new System.Security.Claims.Claim("Role", "VipUser"));
  9. if (result.Succeeded)
  10. {
  11. return Ok("注册成功");
  12. }
  13. else
  14. {
  15. return BadRequest();
  16. }
  17. }

简单到爆炸不是吗?我现在注册一个用户,就会看到这个用户被添加了一个Claim,Role=VipUser

6.用户登录

用户登录的原理是JWT。是一个独立知识点。这里我只提供代码。教程网上一堆。需要我写的话请留言,我再补充。

  1. using System;
  2. using System.Collections.Generic;
  3. using System.IdentityModel.Tokens.Jwt;
  4. using System.Linq;
  5. using System.Security.Claims;
  6. using System.Text;
  7. using System.Threading.Tasks;
  8. using Microsoft.AspNetCore.Http;
  9. using Microsoft.AspNetCore.Identity;
  10. using Microsoft.AspNetCore.Mvc;
  11. using Microsoft.Extensions.Configuration;
  12. using Microsoft.IdentityModel.Tokens;
  13. using TinyBlog2.Areas.Identity.Data;
  14. using TinyBlog2.DTO;
  15.  
  16. namespace TinyBlog2.Controllers
  17. {
  18. [Route("api/[controller]")]
  19. [ApiController]
  20. public class UserController : ControllerBase
  21. {
  22. private readonly UserManager<TinyBlog2User> _userManager;
  23. private readonly IConfiguration _config;
  24. private readonly SignInManager<TinyBlog2User> _signInManager;
  25. public UserController(UserManager<TinyBlog2User> userManager, IConfiguration configuration, SignInManager<TinyBlog2User> signInManager)
  26. {
  27. _config = configuration;
  28. _signInManager = signInManager;
  29. _userManager = userManager;
  30. }
  31. [HttpPost]
  32. [Route("Reg")]
  33. public async Task<IActionResult> Post([FromBody] UserRegisterInput Input)
  34. {
  35. var user = new TinyBlog2User { UserName = Input.UserName, Email = Input.Email };
  36. var result = await _userManager.CreateAsync(user, Input.Password);
  37. //给用户增加一个Claim
  38. var addClaimResult = await _userManager.AddClaimAsync(user, new System.Security.Claims.Claim("Role", "VipUser"));
  39. if (result.Succeeded && addClaimResult.Succeeded)
  40. {
  41. var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Jwt:Key"]));
  42. //将加密后的密码用JWT指定算法进行加密
  43. var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
  44. //拿到当前登录用户
  45. TinyBlog2User currentUser = await _userManager.FindByEmailAsync(Input.Email);
  46. //获取当前用户的Claims
  47. IList<Claim> claimsList = await _userManager.GetClaimsAsync(currentUser);
  48. var unSecruityToken = new JwtSecurityToken(_config["Jwt:Issuer"], _config["Jwt:Issuer"], claimsList, expires: DateTime.Now.AddMinutes(), signingCredentials: creds);
  49. var token = new JwtSecurityTokenHandler().WriteToken(unSecruityToken);
  50. return Ok(new { user = user, token = token });
  51. }
  52. else
  53. {
  54. return BadRequest();
  55. }
  56. }
  57.  
  58. /// <summary>
  59. /// 前后端分离,前端的登录请求发送到这里。
  60. /// 返回200或者401,代表登录成功和失败,如果登录成功,返回一个token。
  61. /// </summary>
  62. /// <param name="inputUser"></param>
  63. /// <returns>
  64. /// {"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6IjFAMS5jb20iLCJqdGkiOiI0ZDNiZGFjMC1hNjYzLTQwNTMtYjU1Yy02Njg2YjAyNjk0MmIiLCJFbWFpbCI6IjFAMS5jb20iLCJleHAiOjE1NDQxODgwMDcsImlzcyI6Imh0dHA6Ly9sb2NhbGhvc3Q6NjM5MzkvIiwiYXVkIjoiaHR0cDovL2xvY2FsaG9zdDo2MzkzOS8ifQ.GTFmUKiAfLTaOuv7rZ-g4Cns033RWehB8u3iFB59rFM"}
  65. /// </returns>
  66. [HttpPost]
  67. [Route("Login")]
  68. public async Task<IActionResult> Login([FromBody]UserLoginInput inputUser)
  69. {
  70. //拿到用户名和密码,用asp.net Core 自带的Identity来进行登录
  71. var result = await _signInManager.PasswordSignInAsync(inputUser.UserName, inputUser.Password, inputUser.RememberMe, lockoutOnFailure: true);
  72. if (result.Succeeded)
  73. {
  74. //把你自己的密码进行对称加密
  75. var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Jwt:Key"]));
  76. //将加密后的密码用JWT指定算法进行加密,这个加密算法有很多,可以去JWT官网上看
  77. var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
  78. //拿到当前登录用户
  79. TinyBlog2User user = await _userManager.FindByEmailAsync(inputUser.Email);
  80. //获取当前用户的Claims
  81. IList<Claim> claimsList = await _userManager.GetClaimsAsync(user);
  82. //用各种信息组成一个JWT
  83. var unSecruityToken = new JwtSecurityToken(_config["Jwt:Issuer"], _config["Jwt:Issuer"], claimsList, expires: DateTime.Now.AddMinutes(), signingCredentials: creds);
  84. //把JWT加密一下返回给客户端
  85. var token = new JwtSecurityTokenHandler().WriteToken(unSecruityToken);
  86. return Ok(new { token = token });
  87. }
  88. else
  89. {
  90. return Unauthorized();
  91. }
  92. }
  93.  
  94. [HttpGet]
  95. public ActionResult<IEnumerable<string>> Get()
  96. {
  97. return new string[] { "value1", "value2" };
  98. }
  99. }
  100. }

UserController.cs

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using Microsoft.AspNetCore.Authentication.JwtBearer;
  7. using Microsoft.AspNetCore.Builder;
  8. using Microsoft.AspNetCore.Hosting;
  9. using Microsoft.AspNetCore.HttpsPolicy;
  10. using Microsoft.AspNetCore.Mvc;
  11. using Microsoft.Extensions.Configuration;
  12. using Microsoft.Extensions.DependencyInjection;
  13. using Microsoft.Extensions.Logging;
  14. using Microsoft.Extensions.Options;
  15. using Microsoft.IdentityModel.Tokens;
  16.  
  17. namespace TinyBlog2
  18. {
  19. public class Startup
  20. {
  21. public Startup(IConfiguration configuration)
  22. {
  23. Configuration = configuration;
  24. }
  25.  
  26. public IConfiguration Configuration { get; }
  27.  
  28. // This method gets called by the runtime. Use this method to add services to the container.
  29. public void ConfigureServices(IServiceCollection services)
  30. {
  31. services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
  32. .AddJwtBearer(options =>
  33. {
  34. options.TokenValidationParameters = new TokenValidationParameters
  35. {
  36. ValidateIssuer = true,
  37. ValidateAudience = true,
  38. ValidateLifetime = true,
  39. ValidateIssuerSigningKey = true,
  40. ValidIssuer = Configuration["Jwt:Issuer"],
  41. ValidAudience = Configuration["Jwt:Issuer"],
  42. IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Jwt:Key"]))
  43. };
  44. });
  45.  
  46. services.AddAuthorization(options =>
  47. {
  48. options.AddPolicy("VipOnly", policy => policy.RequireClaim("Role", "VipUser"));
  49. });
  50. services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
  51. }
  52.  
  53. // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
  54. public void Configure(IApplicationBuilder app, IHostingEnvironment env)
  55. {
  56. if (env.IsDevelopment())
  57. {
  58. app.UseDeveloperExceptionPage();
  59. }
  60. else
  61. {
  62. app.UseHsts();
  63. }
  64. app.UseStaticFiles();
  65. app.UseAuthentication();
  66. app.UseHttpsRedirection();
  67. app.UseMvc();
  68. }
  69. }
  70. }

Startup.cs

现在用户登录以后就会得到一串JWT。以后每次发请求的时候在头部附带JWT,浏览器就会认出用户的身份,并且方便的做权限验证了。这里附上PostMan设置。美滋滋。

7.试验一波

8.搞定和额外说明

  • 用户注册默认是依靠UserName来注册的。

其实用户系统才是最大的门槛。至于帖子的增删改查。可以用很简单的一篇博客就能搞定了。祝你开心。

【分分钟内搭建一个带用户系统的博客程序(一)用户系统】asp.net core的Identity真香,EF真香!的更多相关文章

  1. 怎样搭建一个自有域名的 WORDPRESS 博客?

    博客搭建并不复杂,只是过程有点繁琐,适合喜欢折腾的人,主要有下面几个步骤: 新建一个博客文件 购买域名(Domain Name) 注册一个主机空间(Web Host) 域名解析(DNSPod) 安装W ...

  2. 技术人如何利用 github+Jekyll ,搭建一个独立免费的技术博客

    上次有人留言说,技术博客是程序员的标配,但据我所知绝大部分技术同学到现在仍然没有自己的技术博客.原因有很多,有的是懒的写,有的是怕写不好,还有的是一直想憋个大招,幻想做到完美再发出来,结果一直胎死腹中 ...

  3. 用 node.js 的 hexo 框架搭建一个支持 markdown 的静态博客系统

    1,Hexo如何在线可视化写博客:   可以试试这款插件 hexo-admin. 2,马克飞象:   一个非常好的 markdown 编辑器. 3,Hexo博客文章设置密码的方法: 首先,在Hexo中 ...

  4. 在Github上面搭建一个自己域名的Hexo博客

    前言 在一次看到别人的博客主页,觉得设计很漂亮.但是由于自己对于前台这块没什么办法,煞是羡慕.偶然中发现这种样式是在Github上面搭建的,使用的是Next主题.于是便想自己也搭建一个,于是便去就去查 ...

  5. 从零开始,搭建博客系统MVC5+EF6搭建框架(5),博客详情页、留言、轮播图管理、右侧统计博文

    一.博客系统进度回顾 上一遍博客介绍到,系统已经实现到了发布以及前台布局展示,接下来就是实现一些,详情页,留言.轮播图管理.右侧博文统计信息实现. 二.博客系统详情页实现 2.1先来看看详情页展示的效 ...

  6. 一个基于 Beego 的,能快速创建个人博客,cms 的系统

    学习beego时候开发的一个博客系统,在持续完善,有不足之处,望大佬们多多体谅,并且指出.感谢! Go Blog 一个基于Beego的,能快速创建个人博客,cms 的系统 包含功能 查看 Go Blo ...

  7. 一个 "开箱即用" 个人博客全栈系统项目!vue+node+express+mysql+sequlize+uniapp

    " MG'Blog " 一个 "开箱即用" 个人博客全栈系统项目! 探索本项目的源码 » 前台预览 · 管理端预览 v1.0.2 小程序预览 v1.0.2 介绍 ...

  8. 使用Jekyll搭建免费的Github Pages个人博客

    一.Git 1.Git概述 Git is a free and open source distributed version control system designed to handle ev ...

  9. Java语言课程设计——博客作业教学数据分析系统(201521123107 张翔)

    #Java语言课程设计--博客作业教学数据分析系统(个人博客) 1.团队课程设计博客链接 [博客作业教学数据分析系统(From:网络五条狗)](http://www.cnblogs.com/fanta ...

随机推荐

  1. nodejs连接mongodb

    一.安装 a.访问mongodb官网下载https://www.mongodb.com/,有zip或者msi版本,zip解压缩就可以用,msi需要安装后使用 b.安装,指定好安装路径,一路下一步 c. ...

  2. 配置myslq提示 the configuration step starting server is taking longer than expected we apologize for thi

    .卸载重新安装,勾选日志配置选项,自定义日志输出路径

  3. OpenCL 三种内存对象的使用

    ▶ 包括带有 CL_MEM_READ_ONLY,CL_MEM_WRITE_ONLY,CL_MEM_READ_WRITE 标识的显示拷贝(函数 clEnqueueWriteBuffer 和 clEnqu ...

  4. Git---远程仓库之从远程仓库克隆03

    远程仓库之添加远程仓库02我们讲了先有本地库,后有远程库,如何关联远程库. 现在假设我们从零开发,那么最好的方式是先创建远程库,然后,从远程库克隆. 首先,登录GitHub,创建一个新的仓库,名字叫g ...

  5. Git--时光穿梭机之删除文件06

    在Git中,删除也是一个修改操作,我们实际操作一下吧,先添加一个文件test.txt到Git并且提交 $ git add test.txt $ git commit -m "add test ...

  6. 行为型-命令模式(Command)

    装修新房的最后几道工序之一是安装插座和开关,通过开关可以控制一些电器的打开和关闭,例如电灯或者排气扇.在购买开关时,我们并不知道它将来到底用于控制什么电器,也就是说,开关与电灯.排气扇并无直接关系,一 ...

  7. 【321】python进程监控:psutil

    参考:Python进程监控-MyProcMonitor 参考:Python3.6 安装psutil 模块和功能简介 参考:psutil module (Download files) 参考:廖雪峰 - ...

  8. 为Eclipse安装功能扩展插件

    ---------siwuxie095                 关于 Eclipse 的下载.安装与配置,详见本人博客分类:利剑出鞘, 里面的 Eclipse的配置         本人博客( ...

  9. ubuntu账户密码正确但是登录不进去系统

    ubuntu12.04管理员账户登录不了桌面,只能客人会话登录 求助!!ubuntu12.04管理员账户登录不了桌面,只能客人会话登录. ctrl+alt+f1 ,切换到tty1,输入管理员帐号和密码 ...

  10. Java初学者不得不知的概念,JDK,JRE,JVM的区别?(转)

    JVM(Java Virtual Machine Java虚拟机)可以理解为是一个虚拟出来的计算机,具备着计算机的基本运算方式,它主要负责将java程序生成的字节码文件解释成具体系统平台上的机器指令. ...