From 4482fe4272dfc2c22b06a002488e42a93b22e704 Mon Sep 17 00:00:00 2001 From: wenyongda Date: Tue, 6 Dec 2022 17:41:24 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/_posts/ASP.Net 6.md | 288 ++++++++++++++++++++++++++++++++++++ source/_posts/SQL Server.md | 4 + 2 files changed, 292 insertions(+) diff --git a/source/_posts/ASP.Net 6.md b/source/_posts/ASP.Net 6.md index f7baadb..60e93f4 100644 --- a/source/_posts/ASP.Net 6.md +++ b/source/_posts/ASP.Net 6.md @@ -120,3 +120,291 @@ options.UseOracle(builder.Configuration.GetConnectionString("OracleDbContext"))) builder.Services.AddDbContext(options => options.UseSqlServer(builder.Configuration.GetConnectionString("SqlServerDbContext"))); ``` +### 2.5 使用JWT进行授权与认证 + +安装NuGet包 + +`Microsoft.AspNetCore.Authentication.JwtBearer` + +![image-20221206130808039](https://markdownhexo.oss-cn-hangzhou.aliyuncs.com/img/image-20221206130808039.png) + +`appsettings.json`配置文件中配置 + +```json +"Authentication": { + "SecretKey": "nadjhfgkadshgoihfkajhkjdhsfaidkuahfhdksjaghidshyaukfhdjks", + "Issuer": "www.xiaoda", + "Audience": "www.xiaoda" + } +``` + +`Program.cs`顶级语句配置 + +```c# +// 使用Autofac自动注入Service +builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory()); +builder.Host.ConfigureContainer(builder => +{ + Assembly assembly = Assembly.Load(ServiceAutofac.GetAssemblyName());//注入Service程序集 可以是其他程序集 + builder.RegisterAssemblyTypes(assembly) + .AsImplementedInterfaces() + .InstancePerDependency(); + // 在IOC容器中注入 + // 用于Jwt的各种操作 + builder.RegisterType().InstancePerLifetimeScope(); + // 支持泛型存入Jwt + builder.RegisterType().InstancePerLifetimeScope(); +}); + +//JWT认证 +builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options => +{ + //取出私钥 + var secretByte = Encoding.UTF8.GetBytes(builder.Configuration["Authentication:SecretKey"]); + options.TokenValidationParameters = new TokenValidationParameters() + { + //验证发布者 + ValidateIssuer = true, + ValidIssuer = builder.Configuration["Authentication:Issuer"], + //验证接受者 + ValidateAudience = true, + ValidAudience = builder.Configuration["Authentication:Audience"], + //验证是否过期 + ValidateLifetime = true, + //验证私钥 + IssuerSigningKey = new SymmetricSecurityKey(secretByte) + }; + +}); +// 顺序不能颠倒 +// 你是谁 授权 +app.UseAuthentication(); +// 你可以干什么 验证 +app.UseAuthorization(); +``` + +新建`TokenHelper.cs`工具类 + +```c# +using Microsoft.IdentityModel.Tokens; +using System.IdentityModel.Tokens.Jwt; +using System.Reflection; +using System.Security.Claims; +using System.Text; +using XiaodaERP.Models; + +namespace XiaodaERP.Utils +{ + public class TokenHelper + { + private readonly IConfiguration _configuration; + private readonly JwtSecurityTokenHandler _jwtSecurityTokenHandler; + public TokenHelper(IConfiguration configuration, JwtSecurityTokenHandler jwtSecurityTokenHandler) + { + this._configuration = configuration; + this._jwtSecurityTokenHandler = jwtSecurityTokenHandler; + } + public static string? Token { get; set; } + // 生成Token + public string CreateJwtToken(T user) + { + // 生成JWT + // Header,选择签名算法 + var signingAlogorithm = SecurityAlgorithms.HmacSha256; + // Payload,存放用户信息,放用户ID,用户名 + var claimList = this.CreateClaimList(user); + //Signature + //取出私钥并以utf8编码字节输出 + var secretByte = Encoding.UTF8.GetBytes(_configuration["Authentication:SecretKey"]); + //使用非对称算法对私钥进行加密 + var signingKey = new SymmetricSecurityKey(secretByte); + //使用HmacSha256来验证加密后的私钥生成数字签名 + var signingCredentials = new SigningCredentials(signingKey, signingAlogorithm); + //生成Token + var Token = new JwtSecurityToken( + issuer: _configuration["Authentication:Issuer"], //发布者 + audience: _configuration["Authentication:Audience"], //接收者 + claims: claimList, //存放的用户信息 + notBefore: DateTime.UtcNow, //发布时间 + expires: DateTime.UtcNow.AddMinutes(30), //有效期设置为1天 + signingCredentials //数字签名 + ); + //生成字符串token + var TokenStr = new JwtSecurityTokenHandler().WriteToken(Token); + return TokenStr; + } + // 获取Token Payload信息 + public T GetToken(string token) + { + Type t = typeof(T); + object obj = Activator.CreateInstance(t); + var b = _jwtSecurityTokenHandler.ReadJwtToken(token); + foreach (var item in b.Claims) + { + PropertyInfo propertyInfo = t.GetProperty(item.Type); + if (propertyInfo != null && propertyInfo.CanRead) + { + propertyInfo.SetValue(obj, item.Value, null); + } + } + return (T)obj; + } + // 根据类生成Token 断言列表 + private List CreateClaimList(T authUser) + { + var Class = typeof(T); + List claimList = new(); + foreach (var item in Class.GetProperties()) + { + // 不将PassWord放入Token中 + if (item.Name == "PassWord") + { + continue; + } + // 将UserName属性名重命名为username存入Token中 + if (item.Name == "UserName") + { + claimList.Add(new Claim("username", Convert.ToString(item.GetValue(authUser)))); + continue; + } + claimList.Add(new Claim(item.Name, Convert.ToString(item.GetValue(authUser)))); + } + return claimList; + } + } +} + +``` + +在登录方法中加入 + +```c# +public ViewUser Login(string UserName, string PassWord) +{ + var res = _sqlServerDbContext.Users.Include(user => user.Role).FirstOrDefault(x => x.UserName == UserName); + if (res != null) + { + if (res.PassWord == Md5Encoding(PassWord)) + { + // 生成JWT + var TokenStr = _tokenHelper.CreateJwtToken(res); + var config = new MapperConfiguration(cfg => cfg.CreateMap() + .ForMember(d => d.username, opt => opt.MapFrom(src => src.UserName)) + .AfterMap((src, des) => des.Roles = new Role[1] { src.Role }) + .AfterMap((src, des) => des.Token = "bearer " + TokenStr) // 需要加上bearer + .AfterMap((src, des) => des.HomePath = "/dashboard/analysis") + .AfterMap((src, des) => des.password = null)); + var mapper = config.CreateMapper(); + return mapper.Map(res); + } + } + return null; +} +``` + +WebAPI 需要认证的加上`[Authorize]`注解,注意登录不能加 + +```c# +[AuthFilter] +[HttpPost(Name = "login")] +public ResultUtil Login(ViewUser viewUser) => + ResultUtil.ok(_userService.Login(viewUser.username, viewUser.password)); +// 需要认证的API +[Authorize] +[AuthFilter] +[HttpGet(Name = "getUserInfo")] +public ResultUtil GetUserInfo() +{ + Token = HttpContext.Request.Headers["Authorization"]; + Token = Token.Split(" ")[1]; + TokenHelper.Token = Token; + ViewUser us = _tokenHelper.GetToken(Token); + return ResultUtil.ok(us); +} +``` + +访问登录接口 + +![image-20221206131847333](https://markdownhexo.oss-cn-hangzhou.aliyuncs.com/img/image-20221206131847333.png) + +访问需要认证的接口,需要把Token放在请求头中,如果不携带Token,访问则报401 + +![image-20221206132042533](https://markdownhexo.oss-cn-hangzhou.aliyuncs.com/img/image-20221206132042533.png) + +请求头Key 为 Authorization + +访问成功 + +![image-20221206132124913](https://markdownhexo.oss-cn-hangzhou.aliyuncs.com/img/image-20221206132124913.png) + +## 3. 面向切面编程(AOP) + +三大拦截器 + +`AuthorizeAttribute` + +认证拦截器 + +`ActionFilterAttribute` + +方法拦截器 + +```c# +using Microsoft.AspNetCore.Mvc.Filters; + +namespace XiaodaERP.Attributes +{ + public class AuthFilter : ActionFilterAttribute + { + // 方法请求后 + public override void OnActionExecuted(ActionExecutedContext context) + { + // 获取请求Host + Console.WriteLine(context.HttpContext.Request.Host); + // 获取请求方法 + Console.WriteLine(context.HttpContext.Request.Method); + // 获取请求Url + Console.WriteLine(context.HttpContext.Request.Path); + } + // 方法请求时 + public override void OnActionExecuting(ActionExecutingContext context) + { + //Console.WriteLine(context.ActionArguments.ToList()); + foreach (var kv in context.ActionArguments) + { + Console.WriteLine("{0}, : ,{1}", kv.Key, kv.Value); + } + + + } + + } +} +``` + +接口上使用 + +```c# +[AuthFilter] +[HttpPost(Name = "login")] +public ResultUtil Login(ViewUser viewUser) => + ResultUtil.ok(_userService.Login(viewUser.username, viewUser.password)); + +[Authorize] +[AuthFilter] // 注解为拦截器类名 +[HttpGet(Name = "getUserInfo")] +public ResultUtil GetUserInfo() +{ + Token = HttpContext.Request.Headers["Authorization"]; + Token = Token.Split(" ")[1]; + TokenHelper.Token = Token; + ViewUser us = _tokenHelper.GetToken(Token); + return ResultUtil.ok(us); +} +``` + + + +`ExceptionFilterAttribute` + +异常拦截器 diff --git a/source/_posts/SQL Server.md b/source/_posts/SQL Server.md index 428fb5a..061235f 100644 --- a/source/_posts/SQL Server.md +++ b/source/_posts/SQL Server.md @@ -10,3 +10,7 @@ ALTER DATABASE ACT_DEV COLLATE Chinese_PRC_CI_AS; ALTER DATABASE ACT_DEV SET MULTI_USER; ``` +## 精度标度 + +精度指数字的位数,标度指小数点后的位数。例如,123.45,精度是5,标度是2,decimal(5, 2) +