From 3f0b118063d9e8fee765bde47cb38ed75f22b0af Mon Sep 17 00:00:00 2001 From: hcj <2622428319@qq.com> Date: Sat, 26 Jun 2021 23:04:40 +0800 Subject: [PATCH 1/4] =?UTF-8?q?=E4=BD=BF=E7=94=A8.net=20Core=20Cli=20?= =?UTF-8?q?=E8=BF=9E=E6=8E=A5SqlServer=E6=95=B0=E6=8D=AE=E5=BA=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...45\346\225\260\346\215\256\345\272\223.md" | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 "\351\273\204\345\255\230\346\235\260/WebAPi/2021.6.26-webapi_cli_\350\277\236\346\216\245\346\225\260\346\215\256\345\272\223.md" diff --git "a/\351\273\204\345\255\230\346\235\260/WebAPi/2021.6.26-webapi_cli_\350\277\236\346\216\245\346\225\260\346\215\256\345\272\223.md" "b/\351\273\204\345\255\230\346\235\260/WebAPi/2021.6.26-webapi_cli_\350\277\236\346\216\245\346\225\260\346\215\256\345\272\223.md" new file mode 100644 index 0000000..192358f --- /dev/null +++ "b/\351\273\204\345\255\230\346\235\260/WebAPi/2021.6.26-webapi_cli_\350\277\236\346\216\245\346\225\260\346\215\256\345\272\223.md" @@ -0,0 +1,61 @@ +# 2021.6.26 + + +## 步骤 + +1. 使用 .net core cli安装 Ef Core(连接数库使用的包) +``` +// 根据自己使用的数据库选择安装不同的包,可搜索 efCore 查看其他包 +dotnet add package Microsft.EntityFrameworkCore.SqlServer +``` +2. 创建上下文文件 +``` +using Microsoft.EntityFrameworkCore; // 引入ef的包,存在上下文文件类 + +namespace MyApiDemo.api.Data +{ + public class MyApiDemoDb : DbContext + { + // 添加实体 + public DbSet Users { get; set; } + + // 设置配置 options."UseSqlServer" 可以选择各种数据库 + protected override void OnConfiguring(DbContextOptionsBuilder options)=> options.UseSqlServer(@"server=.;database=Demo;uid=sa;pwd=123456"); + } + + + public class Users + { + public Users(){ + CreateTime = DateTime.Now; + UpdateTime = DateTime.Now; + Remarks = ""; + } + public int Id { get; set; } + public string Username { get; set; } + public string Password { get; set; } + public DateTime CreateTime { get; set; } + public DateTime UpdateTime { get; set; } + public string Remarks { get; set; } + } +} +``` +3. 创建数据库 +``` +需要先把一些工具与依赖安装 + +dotnet tool intall --global dotnet-ef // 全局安装EF工具 + +dotnet add package Microsoft.EntityFremaworkCore.Design // 数据迁移时需要用到的依赖包 + +dotnet ef Migrations add 名字 // 添加迁移文件 + +dotnet ef database update // 在数据库中创建表 + +-------------------------------------------------- + +dotnet ef Migrations remove // 删除所有迁移文件 + +dotnet ef database remove // 在数据库中删除表 +``` + -- Gitee From ba9c193626c19b1ebfececf4dd4a334095584d23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E5=AD=98=E6=9D=B0?= <7434945+huang_cun_jie@user.noreply.gitee.com> Date: Tue, 29 Jun 2021 00:48:15 +0000 Subject: [PATCH 2/4] =?UTF-8?q?update=20=E9=BB=84=E5=AD=98=E6=9D=B0/WebAPi?= =?UTF-8?q?/2021.6.26-webapi=5Fcli=5F=E8=BF=9E=E6=8E=A5=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E5=BA=93.md.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...\277\236\346\216\245\346\225\260\346\215\256\345\272\223.md" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/\351\273\204\345\255\230\346\235\260/WebAPi/2021.6.26-webapi_cli_\350\277\236\346\216\245\346\225\260\346\215\256\345\272\223.md" "b/\351\273\204\345\255\230\346\235\260/WebAPi/2021.6.26-webapi_cli_\350\277\236\346\216\245\346\225\260\346\215\256\345\272\223.md" index 192358f..d5685de 100644 --- "a/\351\273\204\345\255\230\346\235\260/WebAPi/2021.6.26-webapi_cli_\350\277\236\346\216\245\346\225\260\346\215\256\345\272\223.md" +++ "b/\351\273\204\345\255\230\346\235\260/WebAPi/2021.6.26-webapi_cli_\350\277\236\346\216\245\346\225\260\346\215\256\345\272\223.md" @@ -56,6 +56,6 @@ dotnet ef database update // 在数据库中创建表 dotnet ef Migrations remove // 删除所有迁移文件 -dotnet ef database remove // 在数据库中删除表 +dotnet ef database drop // 在数据库中删除表 ``` -- Gitee From eccb4334c10c4c1fd6c47ae5c13436610768c98f Mon Sep 17 00:00:00 2001 From: unknown <2622428319@qq.com> Date: Tue, 29 Jun 2021 08:52:09 +0800 Subject: [PATCH 3/4] =?UTF-8?q?=E7=AC=94=E8=AE=B0=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WebAPi/2021.6.23.md" | 138 ++++++++++++++++++ 1 file changed, 138 insertions(+) create mode 100644 "\351\273\204\345\255\230\346\235\260/WebAPi/2021.6.23.md" diff --git "a/\351\273\204\345\255\230\346\235\260/WebAPi/2021.6.23.md" "b/\351\273\204\345\255\230\346\235\260/WebAPi/2021.6.23.md" new file mode 100644 index 0000000..a2b7aea --- /dev/null +++ "b/\351\273\204\345\255\230\346\235\260/WebAPi/2021.6.23.md" @@ -0,0 +1,138 @@ +# 2021-6-23 + ++ dotnet build 检查 + ++ Prettier - Code formatter 格式化插件名 ++ RESTClient 一款自动化测试REST API的工具,它可以自动化测试RESTful API并生成精美的测试报告,同时基于测试过的历史API,可以生成精美的RESTful API文档。 + ++ dynamic的出现让C#具有了弱语言类型的特性。编译器在编译的时候不再对类型进行检查,编译期默认dynamic对象支持你想要的任何特性。比如,即使你对GetDynamicObject方法返回的对象一无所知,编译器也不会报错 + +1. 在项目内创建Entity文件夹 +``` +User.cs +using System; + +namespace myApi.Api.Entity +{ + public class User + { + public User(){ + createTime=DateTime.Now; + UpdateTime=DateTime.Now; + } + public int Id { get; set; } + + public string Username { get; set; } + + public string Password { get; set; } + + public DateTime createTime { get; set; } + + public DateTime UpdateTime { get; set; } + + public string Remark { get; set; } + } +} +``` +2. 在项目下Controllers 下创建 UserConteroller.cs +``` +using System.Collections.Generic; +using System.Linq; +using Microsoft.AspNetCore.Mvc; +using myApi.Api.Entity; + +namespace myApi.Api.Controllers +{ + [ApiController] + [Route("[controller]")] + public class UserController : ControllerBase + { + [HttpGet] + public IEnumerable Get() + { + var user = GetUsers(); + return user; + } + + [HttpGet("{id}")] + public dynamic Get(int id) + { + var users = GetUsers(); + var user = users.Where(x => x.Id == id).FirstOrDefault(); + return user; + } + + [HttpPost] + public dynamic Post(dynamic model) + { + return new{ + Code=1000, + Data=model, + Msg="创建成功" + }; + } + + [HttpPut("{id}")] + public dynamic Put(int id,dynamic model) + { + return new{ + Code=1000, + Data=model, + Msg=string.Format("你修改的id为:{0},修改成功",id) + }; + } + + [HttpDelete("{id}")] + public dynamic Delete(int id) + { + return new{ + Code=1000, + Msg=string.Format("你删除的id为:{0},删除成功",id) + }; + } + + + + private IEnumerable GetUsers() + { + var user = + new List { + new User { Id = 1, Username = "root", Password = "123" }, + new User { Id = 2, Username = "admin", Password = "123" } + }; + return user; + } + } +} +``` +3. RESTClient +``` +api.http +### 获取用户 + +GET http://localhost:5000/User HTTP/1.1 + +###获取指定id用户 +GET http://localhost:5000/User/1 HTTP/1.1 + +###创建用户 +POST http://localhost:5000/User HTTP/1.1 +Content-Type:application/json + +{ + "username":"123", + "password":"1113" +} + +###修改指定用户 +PUT http://localhost:5000/User/1 HTTP/1.1 +Content-Type: application/json + +{ + "username":"123", + "password":"1113" +} + +###删除指定用户 +DELETE http://localhost:5000/User/1 HTTP/1.1 +``` -- Gitee From 030ffcefd9c3114a7669aa2c76fd153060cde544 Mon Sep 17 00:00:00 2001 From: hcj <2622428319@qq.com> Date: Fri, 9 Jul 2021 08:29:32 +0800 Subject: [PATCH 4/4] =?UTF-8?q?=E8=A1=A5=E5=85=85=E4=B8=80=E7=82=B9?= =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...63\345\256\236\350\267\265\344\270\200.md" | 301 ++++++++++++++++++ ...41\350\256\241\346\227\245\345\277\227.md" | 68 ++++ 2 files changed, 369 insertions(+) create mode 100644 "\351\273\204\345\255\230\346\235\260/WebAPi/2021.7.9-\346\234\200\344\275\263\345\256\236\350\267\265\344\270\200.md" create mode 100644 "\351\273\204\345\255\230\346\235\260/WebAPi/2021.7.9-\346\234\200\344\275\263\345\256\236\350\267\265\344\272\214\344\270\216\345\256\241\350\256\241\346\227\245\345\277\227.md" diff --git "a/\351\273\204\345\255\230\346\235\260/WebAPi/2021.7.9-\346\234\200\344\275\263\345\256\236\350\267\265\344\270\200.md" "b/\351\273\204\345\255\230\346\235\260/WebAPi/2021.7.9-\346\234\200\344\275\263\345\256\236\350\267\265\344\270\200.md" new file mode 100644 index 0000000..1ffa2cd --- /dev/null +++ "b/\351\273\204\345\255\230\346\235\260/WebAPi/2021.7.9-\346\234\200\344\275\263\345\256\236\350\267\265\344\270\200.md" @@ -0,0 +1,301 @@ +# JWT最佳实践 + +1. 安装JWT认证支持库(必须引入) +``` +dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer + +dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer -h +查看帮助 +``` +2. ParamModel创建TokenParameter.cs +``` +namespace MyApi.Api.ParamModel +{ + public class TokenParameter + { + //token的密钥,不能泄露,泄露意味着所有人都可以生成你的token并且访问你的服务或者接口 + public string Secret { get; set; } + + //发行人(可以是个人或组织) + public string Issuer { get; set; } + + //token的作用时间,单位为分钟,过期后需要重新获取 + public int AccessExpiration { get; set; } + + //类似一个token的东西的作用时间,单位为分钟,用于重新获取token + public int RefreshExpiration { get; set; } + } +} +``` +3. appsettings.json 生成JWT Token需要预设一些参数 +``` +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" + } + }, + "AllowedHosts": "*", + "TokenParameter": { + "secret": "123456123456123456", + //secret: JWT加密的密钥16个字符以上 + + "issuer": "Root", + //issuer: 签发人的名称 + + "accessExpiration": 120, + //accessExpiration: Token的有效分钟数,过时间后Token会过期 + + "refreshExpiration": 1440 + //refreshExpiration: refreshToken的有效分钟数。过了这个时间,用户需要重新登录。 + } +} + +``` +``` +Token过期后,可以让用户重新登录认证拿Token。但这个方式会比较Low。高大上的方式是签发Token的时候,同时也签发一个refreshToken给用户。用户Token过期后,可以拿refreshToken去申请新的Token,同时刷新refreshToken。如果用户长时间未使用系统,refreshToken也过期了,才让用户重新登录认证。 + +refreshToken可以用JWT生成,也可以自己生成,不影响认证。 +``` + + +4. 生成Token 创建Utils文件夹下创建TokenHelper.cs +``` +using MyApi.Api.ParamModel; +using MyApi.Api.Entity; +using System.Security.Claims; +using Microsoft.IdentityModel.Tokens; +using System.Text; +using System.IdentityModel.Tokens.Jwt; +using System; + +namespace MyApi.Api.Utils +{ + public class TokenHelper + { + //这儿是真正的生成Token代码 + public static string GenerateToekn(TokenParameter tokenParameter,Users user) + { + var claims = new[] + { + new Claim(ClaimTypes.Name,user.Username), + new Claim(ClaimTypes.Role, "root"), + }; + + var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(tokenParameter.Secret)); + var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); + var jwtToken = new JwtSecurityToken(tokenParameter.Issuer, null, claims, expires: DateTime.UtcNow.AddMinutes(tokenParameter.AccessExpiration), signingCredentials: credentials); + + var token = new JwtSecurityTokenHandler().WriteToken(jwtToken); + + return token; + } + } +} +``` +5. Controllers/UsersController.cs +``` +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Logging; +using MyApi.Api.Entity; +using MyApi.Api.ParamModel; +using MyApi.Api.Repository; +using MyApi.Api.Utils; + + +namespace MyApi.Api.Controllers +{ + [ApiController] + [Route("[controller]")] + public class UsersController : ControllerBase + { + // private MyApi.Api.Db.MyApiDb db = new Api.Db.MyApiDb(); + private IRepository _usersRespository; + private TokenParameter _tokenParameter; + private readonly IConfiguration _configuration; + + public UsersController(IConfiguration configuration,IRepository UsersRespository){ + _usersRespository=UsersRespository; + _configuration=configuration; + _tokenParameter=_configuration.GetSection("TokenParameter").Get(); + } + [HttpGet] + public IEnumerable Get() + { + var user = _usersRespository.Table.ToList(); + return user; + } + + [HttpGet("{id}")] + public dynamic Get(int id) + { + var user = _usersRespository.GetById(id); + if(user==null){ + return new{ + Code=1001, + Data ="", + Msg ="用户不存在", + }; + } + return new{ + Code=1000, + Data =user, + Msg ="用户以获取", + }; + } + + [HttpPost] + public dynamic post(NewUser model) + { + var user=new Users{ + Username=model.Username, + Password=model.Password, + }; + _usersRespository.Insert(user); + + + return new + { + Code=1000, + Data =user, + ParallelMergeOptions="创建成功" + }; + } + + [HttpPut("{id}")] + public dynamic Put(int id,NewUser model) + { + var user = _usersRespository.GetById(id); + + if (user != null) + { + user.Username = model.Username; + user.Password = model.Password; + user.UpdatedTime=DateTime.Now; + _usersRespository.Update(user); + return new + { + Code = 1000, + Data = user, + Msg = string.Format("你修改的用户的id为:{0},已经修改成功,请注意查收", id) + }; + } + else + { + return new + { + Code = 104, + Data = "", + Msg = "指定Id的用户不存在,请确认后重试" + }; + } + + + } + + [HttpDelete("{id}")] + public dynamic Delete(int id) + { + // var user = db.Users.Where(x => x.Id == id).FirstOrDefault(); + var user=_usersRespository.GetById(id); + if (user != null) + { + // db.Users.Remove(user); + // db.SaveChanges(); + _usersRespository.Delete(id); + return new + { + Code = 1000, + Msg = string.Format("删除指定id为{0}的用户成功", id) + }; + } + else + { + return new + { + Code = 104, + Data = "", + Msg = "指定Id的用户不存在,请确认后重试" + }; + } + } + + [HttpPost, Route("token")] + public dynamic GetToken(NewUser model) + { + var username = model.Username.Trim(); + var password = model.Password.Trim(); + + var user = _usersRespository.Table.Where(x => x.Username == username && x.Password == password).FirstOrDefault(); + + if (user == null) + { + return new + { + Code = 1001, + Data = user, + Msg = "用户名或密码不正确,请核对后重试" + }; + } + + var token = TokenHelper.GenerateToekn(_tokenParameter, user); + var refreshToken = "123456"; + + var res = new + { + Code = 1000, + Data = new { Token = token, RefreshToken = refreshToken }, + Msg = "用户登录成功,获取token成功" + }; + return res; + } + + } +} +``` +6. api.http +``` +### 获取用户 + +GET http://localhost:5000/Users HTTP/1.1 + +###获取指定id用户 +GET http://localhost:5000/Users/10 HTTP/1.1 + +###创建用户 +POST http://localhost:5000/Users HTTP/1.1 +Content-Type:application/json + +{ + "username":"123", + "password":"1113" +} + +###修改指定用户 +PUT http://localhost:5000/Users/1 HTTP/1.1 +Content-Type: application/json + +{ + "username":"666", + "password":"1113" +} + +###删除指定用户 +DELETE http://localhost:5000/Users/1 HTTP/1.1 + +### 登录并获取token +POST http://localhost:5000/Users/token HTTP/1.1 +Content-Type: application/json + +{ + "username":"123", + "password":"1113" +} +``` \ No newline at end of file diff --git "a/\351\273\204\345\255\230\346\235\260/WebAPi/2021.7.9-\346\234\200\344\275\263\345\256\236\350\267\265\344\272\214\344\270\216\345\256\241\350\256\241\346\227\245\345\277\227.md" "b/\351\273\204\345\255\230\346\235\260/WebAPi/2021.7.9-\346\234\200\344\275\263\345\256\236\350\267\265\344\272\214\344\270\216\345\256\241\350\256\241\346\227\245\345\277\227.md" new file mode 100644 index 0000000..41d8039 --- /dev/null +++ "b/\351\273\204\345\255\230\346\235\260/WebAPi/2021.7.9-\346\234\200\344\275\263\345\256\236\350\267\265\344\272\214\344\270\216\345\256\241\350\256\241\346\227\245\345\277\227.md" @@ -0,0 +1,68 @@ +# JWT最佳实践 和 日志审计 + +## JWT最佳实践(二) ++ Token认证 + +1. 在Startup.cs中,ConfigureServices方法里,添加以下内容 +``` + // 注册数据库上下文到容器 + services.AddDbContext(o =>o.UseSqlServer()); + // 注册对数据库的基本操作服务到容器 + services.AddScoped(typeof(IRepository<>),typeof(EfRepository<>)); + + // 注册验证器(使用何种配置来验证token) + services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) + .AddJwtBearer(option => + { + // 是否要求使用https + option.RequireHttpsMetadata=false; + // 是否保存token + option.SaveToken=true; + // 使用配置中间件,获得token的配置 + var tokenParameter=Configuration.GetSection("TokenParameter").Get(); + // 验证器的核心属性 + option.TokenValidationParameters=new TokenValidationParameters + { + ValidateIssuerSigningKey=true,//要不要验证生成token的密钥 + IssuerSigningKey=new SymmetricSecurityKey(Encoding.UTF8.GetBytes(tokenParameter.Secret)), + ValidateIssuer=true, // 要不要验证发行token的人(个人或者组织) + ValidIssuer=tokenParameter.Issuer, + ValidateAudience=false // 是否验证受众 + }; + }); + services.AddControllers(); +``` +2. 在Startup.cs里,Configure方法中,打开认证 +``` +// 将token的验证注册到中间件 +app.UseAuthentication(); +app.UseAuthorization(); +``` +3. 设置API认证。 在UsersController.cs下的Get方法来测试 ++ 在方法前边,我们加上Authorize +``` + [Authorize] + [ApiController] + [Route("[controller]")] + public class UsersController : ControllerBase{} +``` +4. 认证后的访问 +``` +api.http +### 获取用户 + +GET http://localhost:5000/Users HTTP/1.1 +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1lIjoicm9vdCIsImh0dHA6Ly9zY2hlbWFzLm1pY3Jvc29mdC5jb20vd3MvMjAwOC8wNi9pZGVudGl0eS9jbGFpbXMvcm9sZSI6InJvb3QiLCJleHAiOjE2MjU3NDQwNTIsImlzcyI6IlJvb3QifQ.C_aUR4JDPl-2r6Cccv-BrNnmJgYG7OhJhq6VbOfB5l4 + +### 登录并获取token +POST http://localhost:5000/Users/token HTTP/1.1 +Content-Type: application/json + +{ + "username":"root", + "password":"1113" +} +``` +# 日志审计 +1. 创建Filters文件夹下创建AuditLogActionFilter.cs + -- Gitee