.NET经销商实战(四)——automapper的配置,jwt授权鉴权,商品信息获取及swagger鉴权集成


1.在DealerPlatform.Service项目中添加引用两个包,automapper的包

AutoMapper,AutoMapper.Extensions.Microsoft.DependencyInjection

2.添加一个新的类:DealerPlatformProfile,代码如下:

点击查看代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using AutoMapper;
using DealerPlatform.Domain.Models;
using DealerPlatform.Service.ProductApp.Dto;

namespace DealerPlatform.Service
{
	/// 
	/// 模型转换映射
	/// 
	public class DealerPlatformProfile : Profile
	{
		public DealerPlatformProfile()
		{
			//.ForMember(dest => dest.Id, opt => opt.Ignore())
			CreateMap().ReverseMap();
			CreateMap().ReverseMap();
			CreateMap().ReverseMap();
			CreateMap().ReverseMap();
		}
	}
}

添加完映射之后,下面就要注入automapper服务了

3.在program中添加builder.Services.AddAutoMapper(typeof(DealerPlatformProfile));

这样就可以了,program的注入顺序会在下面放出完整代码,耐心点,继续往下学

4.下面这个是Service类库的结构,如下,大家自行创建商品productservice类

5.为了让IProductService能够被我们之前写过的注入服务检测到,所以我们需要在IProductService中继承IocTag

代码如下:

点击查看代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using DealerPlatform.Domain;
using DealerPlatform.Service.ProductApp.Dto;

namespace DealerPlatform.Service.ProductApp
{
	public interface IProductService : IocTag
	{
		Task> GetProductDto(string sort = null, int pageIndex = 1, int pageSize = 30);

	}
}

构造函数注入及继承接口等都在ProductService里,在下面

6.ProductService.Photo代码如下(主要为了获取商品图片)

点击查看代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using DealerPlatform.Domain.Models;

namespace DealerPlatform.Service.ProductApp
{
	public partial class ProductService
	{
		/// 
		/// 获取商品的图片
		/// 
		/// 
		/// 
		public async Task> GetProductPhotosByProductNo(params string[] productNos)
		{
			var data = await ProductPhotoRepo.GetListAsync(s => productNos.Contains(s.ProductNo));
			return data;
		}
	}
}

7.ProductService.Sales代码如下,获取商品的销售信息

点击查看代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using DealerPlatform.Domain.Models;

namespace DealerPlatform.Service.ProductApp
{
	public partial class ProductService
	{
		/// 
		/// 获取商品的销售量
		/// 
		/// 
		/// 
		public async Task> GetProductSalesByProductNo(params string[] productNos)
		{
			var data = await ProductSaleRepo.GetListAsync(s => productNos.Contains(s.ProductNo));
			return data;
		}
	}
}

8.在ProductService中写入如下代码,注入服务及继承接口等都在这里

点击查看代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using AutoMapper;
using DealerPlatform.Core.Repository;
using DealerPlatform.Domain.Models;
using DealerPlatform.Service.ProductApp.Dto;

namespace DealerPlatform.Service.ProductApp
{
	public partial class ProductService : IProductService
	{
		public ProductService(
			IRepository productRepo,
			IRepository productSaleRepo,
			IRepository productSaleAreaDiffRepo,
			IRepository productPhotoRepo,
			IMapper mapper)
		{
			ProductRepo = productRepo;
			ProductSaleRepo = productSaleRepo;
			ProductSaleAreaDiffRepo = productSaleAreaDiffRepo;
			ProductPhotoRepo = productPhotoRepo;
			Mapper = mapper;
		}

		public IRepository ProductRepo { get; }
		public IRepository ProductSaleRepo { get; }
		public IRepository ProductSaleAreaDiffRepo { get; }
		public IRepository ProductPhotoRepo { get; }
		public IMapper Mapper { get; }

		/// 
		/// 获取商品数据
		/// 
		/// 
		public async Task> GetProductDto(string sort = null, int pageIndex = 1, int pageSize = 30)
		{
			sort ??= "ProductName";
			int skipNum = (pageIndex - 1) * pageSize;
			//获取商品主档信息
			var products = (await ProductRepo.GetListAsync()).OrderBy(s => s.GetType().Name == sort).Skip(skipNum).Take(pageSize);

			var dtos = Mapper.Map>(products);
			var productPhotos = await GetProductPhotosByProductNo(dtos.Select(s => s.ProductNo).ToArray());
			var productSales = await GetProductSalesByProductNo(dtos.Select(s => s.ProductNo).ToArray());
			dtos.ForEach(s =>
			{
				s.ProductPhoto = productPhotos.FirstOrDefault(c => c.ProductNo == s.ProductNo);
				s.ProductSale = productSales.FirstOrDefault(c => c.ProductNo == s.ProductNo);
			});
			//根据productId取到属性
			return dtos;
		}
	}
}

到这里我们就可以成功获取商品的信息了,下面我们开始jwt授权鉴权,这里我只提供简易版(配置鉴权方案),想学习鉴权策略可以看我另一篇文章,如需更多完整的可以移步看我另一篇文章

9.jwt鉴权方案

在program中加入如下代码(想知道完整的代码请继续往下看,说完swagger集成,我就放出完整代码):

点击查看代码
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
		.AddJwtBearer(opt =>
		{
			//是否是https 默认true
			opt.RequireHttpsMetadata = false;
			opt.SaveToken = true;
			opt.TokenValidationParameters = new()
			{
				IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(token.Security)),
				ValidIssuer = token.Issuer,
				ValidAudience = token.Audience
			};
			opt.Events = new JwtBearerEvents
			{
				OnChallenge = context =>
				{
					//此处终止代码
					context.HandleResponse();
					var res = "{\"code\":401,\"err\":\"无权限\"}";
					context.Response.ContentType = "application/json";
					context.Response.StatusCode = StatusCodes.Status401Unauthorized;
					context.Response.WriteAsync(res);
					return Task.FromResult(0);
				}
			};
		});

10.swagger集成

点击查看代码
builder.Services.AddSwaggerGen(c =>
{
	//添加安全定义
	c.AddSecurityDefinition(JwtBearerDefaults.AuthenticationScheme, new OpenApiSecurityScheme
	{
		Description = "格式:Bearer {token}",
		Name = "Authorization",//默认的参数名
		In = ParameterLocation.Header,//放于请求头中
		Type = SecuritySchemeType.ApiKey,
		BearerFormat = "JWT",
		Scheme = JwtBearerDefaults.AuthenticationScheme
	});
	//添加安全要求
	c.AddSecurityRequirement(new OpenApiSecurityRequirement
				 {
					{
						new OpenApiSecurityScheme
						{
							Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = JwtBearerDefaults.AuthenticationScheme }
						},
						new List()
					}
				});
});

11.在program中使用鉴权方案

app.UseAuthentication();

既然已经添加了授权鉴权方案及swagger集成,我们现在可以启动一下我们的项目,可以看到swagger上已经有了小锁子,就是需要你的token就行鉴权
这时,我们没有为控制器上或者方法上添加鉴权方案,需要添加一下,这里有坑,注意!

12.在控制器上添加鉴权方案


按下f12进入Authorize特性中,发现如下:

program完整代码:

点击查看代码
using System.Net;
using System.Text;
using DealerPlatform.Common.JwtTokenModule.Models;
using DealerPlatform.Core.Repository;
using DealerPlatform.Domain.Models;
using DealerPlatform.Extensions;
using DealerPlatform.Service;
using DealerPlatform.Service.CustomerApp;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.EntityFrameworkCore;
using Microsoft.IdentityModel.Tokens;
using Microsoft.OpenApi.Models;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
var configuration = builder.Configuration;
//获取jwt配置文件



builder.Services.AddControllers();

// builder.Services.AddTransient(typeof(IRepository<>), typeof(Repository<>));
// builder.Services.AddTransient();

// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
// builder.Services.AddEndpointsApiExplorer();
builder.Services.AddCors(c => c.AddPolicy("any", p => p.AllowAnyHeader().AllowAnyMethod().AllowAnyOrigin()));
var token = configuration.GetSection("Jwt").Get();
//
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
		.AddJwtBearer(opt =>
		{
			//是否是https 默认true
			opt.RequireHttpsMetadata = false;
			opt.SaveToken = true;
			opt.TokenValidationParameters = new()
			{
				IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(token.Security)),
				ValidIssuer = token.Issuer,
				ValidAudience = token.Audience
			};
			opt.Events = new JwtBearerEvents
			{
				OnChallenge = context =>
				{
					//此处终止代码
					context.HandleResponse();
					var res = "{\"code\":401,\"err\":\"无权限\"}";
					context.Response.ContentType = "application/json";
					context.Response.StatusCode = StatusCodes.Status401Unauthorized;
					context.Response.WriteAsync(res);
					return Task.FromResult(0);
				}
			};
		});
builder.Services.AddDbContext(opt =>
opt.UseSqlServer(configuration.GetConnectionString("Default")));
builder.Services.AddAutoMapper(typeof(DealerPlatformProfile));
//反射注册Repository
builder.Services.RepositoryRegister();
builder.Services.ServiceRegister();


builder.Services.AddSwaggerGen(c =>
{
	//添加安全定义
	c.AddSecurityDefinition(JwtBearerDefaults.AuthenticationScheme, new OpenApiSecurityScheme
	{
		Description = "格式:Bearer {token}",
		Name = "Authorization",//默认的参数名
		In = ParameterLocation.Header,//放于请求头中
		Type = SecuritySchemeType.ApiKey,
		BearerFormat = "JWT",
		Scheme = JwtBearerDefaults.AuthenticationScheme
	});
	//添加安全要求
	c.AddSecurityRequirement(new OpenApiSecurityRequirement
				 {
					{
						new OpenApiSecurityScheme
						{
							Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = JwtBearerDefaults.AuthenticationScheme }
						},
						new List()
					}
				});
});

var app = builder.Build();
app.UseAuthentication();
app.UseAuthorization();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
	app.UseSwagger();
	app.UseSwaggerUI();
}

// app.UseHttpsRedirection();

app.UseCors("any");
app.MapControllers();

app.Run();

相关