.NET经销商实战(三)——md5加密,反射注入仓储与服务,及生成token


1.添加DealerPlatform.Common类库项目,这个项目被DealerPlatform.Service所引用
首先在该项目中添加nuget包 Microsoft.AspNetCore.Authentication.JwtBearer
2.添加TokenModule文件夹,这是为了写token的生成帮助类,这个类库结构如下

3.JwtTokenModel代码如下:

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

namespace DealerPlatform.Common.JwtTokenModule.Models
{
	/// 
	/// jwt模型
	/// 
	public class JwtTokenModel
	{
		/// 
		/// 发行人
		/// 
		/// 
		public string Issuer { get; set; }
		/// 
		/// 观众
		/// 
		/// 
		public string Audience { get; set; }
		/// 
		/// 过期时间
		/// 
		/// 
		public int Expires { get; set; }
		/// 
		/// 安全
		/// 
		/// 
		public string Security { get; set; }
		public int Id { get; set; }
		public string CustomerNo { get; set; }
		public string CustomerName { get; set; }

	}
}

这个类只是起到映射的作用,为了和appsetting中的jwt键值对匹配,添加一些我们需要的用户信息,比如ID,CustomerNo,CustomerName等信息
4.为了方便我们调用,所以写成了静态类
TokenHelper代码如下:

点击查看代码
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
using DealerPlatform.Common.JwtTokenModule.Models;
using Microsoft.IdentityModel.Tokens;

namespace DealerPlatform.Common
{
	public static class TokenHelper
	{
		public static string CreateToken(JwtTokenModel model)
		{
			var claims = new[]{
						new Claim("Id",model.Id.ToString()),
						new Claim("CustomerNo",model.CustomerNo),
						new Claim("CustomerName",model.CustomerName)
			};
			//生成密钥
			var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(model.Security));
			//通过HmacSha256算法生成秘钥
			var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
			var token = new JwtSecurityToken(
				issuer: model.Issuer,
				audience: model.Audience,
				expires: DateTime.Now.AddMinutes(model.Expires),
				signingCredentials: creds,//秘钥
				claims: claims);
			//通过我们传入的参数生成token
			var accessToken = new JwtSecurityTokenHandler().WriteToken(token);
			return accessToken;
		}
	}
}

具体过程不解释了,都在注释里了,这时,我们已经封装好了token帮助类,留着后面用,
生成token的话,我们先将用户输入的密码加密一下,我们接下来写md5加密扩展类

5.为了方便我们调用,所以写成了扩展类,代码如下,很简单的代码,不解释了

点击查看代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace DealerPlatform.Common.Md5Helper
{
	public static class Md5Helper
	{
		/// 
		/// MD5加密
		/// 
		/// 
		public static string ToMd5(this string str)
		{
			MD5 md5 = new MD5CryptoServiceProvider();
			byte[] bytes = md5.ComputeHash(Encoding.Default.GetBytes(str + "@rookie.Wang"));
			var md5Str = BitConverter.ToString(bytes).Replace("-", "");
			return md5Str;
		}
	}
}

6.一般情况下,我们不在controller写生成token的方法,一般另外写一个服务用来生成token,我为了偷懒就写在了LoginController中
代码如下:

点击查看代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using DealerPlatform.Common;
using DealerPlatform.Common.JwtTokenModule.Models;
using DealerPlatform.Service.CustomerApp;
using DealerPlatform.Service.CustomerApp.Dto;
using Microsoft.AspNetCore.Mvc;

namespace DealerPlatform.Web.Controllers
{
	[ApiController]
	[Route("[controller]/[action]")]
	public class LoginController : Controller
	{
		public IConfiguration Configuration { get; set; }
		public LoginController(ICustomerService customerService, IConfiguration configuration)
		{
			this.Configuration = configuration;
			CustomerService = customerService;
		}

		public ICustomerService CustomerService { get; }
		[HttpPost]
		public async Task CheckLogin(CustomerLoginDto dto)
		{
			var isSuccess = await CustomerService.CheckPassword(dto);

			if (isSuccess)
			{
				var customer = await CustomerService.GetCustomerAsync(dto.CustomerNo);
				var token = GetToken(customer.Id, customer.CustomerNo, customer.CustomerName);
				return token;
			}
			return "用户或密码错误!";
		}
		/// 
		/// 获取token
		/// 
		/// 
		/// 
		/// 
		/// 
		private string GetToken(int userId, string customerNo, string customerName)
		{
			//将appsetting中的配置读取到model中
			var tokenModel = Configuration.GetSection("Jwt").Get();
			tokenModel.Id = userId;
			tokenModel.CustomerNo = customerNo;
			tokenModel.CustomerName = customerName;
			var token = TokenHelper.CreateToken(tokenModel);
			return token;
		}
	}
}

第二个方法是生成token用的
7.在customer.Pwd类中修改代码如下,添加md5加密

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

namespace DealerPlatform.Service.CustomerApp
{

	public partial class CustomerService
	{
		public async Task CheckPassword(CustomerLoginDto dto)
		{
			// if (string.IsNullOrWhiteSpace(dto.CustomerNo) || string.IsNullOrWhiteSpace(dto.Password))
			// {
			// 	throw new Exception("账号或密码不能为空!");
			// }
			//判断当前dto中是否为空
			var res = CustomerPwdRepo.GetAsync(s => s.CustomerNo == dto.CustomerNo && s.CustomerPwd1 == dto.Password.ToMd5());
			if (res != null)
			{
				return true;
			}
			else
			{
				return false;
			}
		}
	}
}

8.这样我们的md5加密与生成token1就做好了,为了方便我们以后的开发,利用反射注入仓储与服务,新增一个项目
DealerPlatform.Extensions,这个项目也是被service项目引用,这个项目引入Microsoft.Extensions.DependencyInjection
10.新增ServiceCollectionExtensions类,为了反射注入仓储与服务,差点忘记了,在Domain项目中加入一个接口IocTag,让所有service的接口继承它,为了方便检索程序集,
在DealerPlatform.Core中的Repository文件夹中的泛型接口IRepository,添加一个接口IRepository,让泛型接口IRepository继承IRepository即可
代码如下:

点击查看代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using DealerPlatform.Core.Repository;
using DealerPlatform.Domain;
using Microsoft.Extensions.DependencyInjection;

namespace DealerPlatform.Extensions
{
	/// 
	/// 服务注入扩展类
	/// 
	public static class ServiceCollectionExtensions
	{
		public static IServiceCollection RepositoryRegister(this IServiceCollection services)
		{
			//读取DealerPlatform.Core程序集
			var asmCore = Assembly.Load("DealerPlatform.Core");
			//获取所有类型
			//获取Repository的泛型类"Repository`1"
			//反射获取泛型接口有问题
			var implementationTypes = asmCore.GetTypes().Where(s => s.IsAssignableTo(typeof(IRepository))
			&& !s.IsInterface
			&& !s.IsAbstract);
			foreach (var implementationType in implementationTypes)
			{
				services.AddTransient(typeof(IRepository<>), implementationType);
			}
			// var interfaceType = implementationType?.GetInterface("IRepository`1");
			// services.AddTransient(interfaceType, implementationType);
			return services;
		}
		public static IServiceCollection ServiceRegister(this IServiceCollection services)
		{
			//读取DealerPlatform.Core程序集
			var asmService = Assembly.Load("DealerPlatform.Service");
			//获取所有类型
			//获取Repository的泛型类"Repository`1"
			//反射获取泛型接口有问题
			var implementationTypes = asmService.GetTypes().Where(s =>
			s.IsAssignableTo(typeof(IocTag))
			&& !s.IsInterface
			&& !s.IsAbstract);
			foreach (var implementationType in implementationTypes)
			{
				var interfaceType = implementationType.GetInterfaces().Where(s => s != typeof(IocTag)).FirstOrDefault();
				services.AddTransient(interfaceType, implementationType);
			}
			return services;
		}
	}
}

9.修改Program文件如下:

点击查看代码
using DealerPlatform.Core.Repository;
using DealerPlatform.Domain.Models;
using DealerPlatform.Extensions;
using DealerPlatform.Service;
using DealerPlatform.Service.CustomerApp;
using Microsoft.EntityFrameworkCore;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
var configuration = builder.Configuration;
builder.Services.AddDbContext(opt =>
opt.UseSqlServer(configuration.GetConnectionString("Default")));
builder.Services.AddAutoMapper(typeof(DealerPlatformProfile));
//反射注册Repository
builder.Services.RepositoryRegister();
builder.Services.ServiceRegister();
// builder.Services.AddTransient(typeof(IRepository<>), typeof(Repository<>));
//builder.Services.AddTransient();
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
	app.UseSwagger();
	app.UseSwaggerUI();
}

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();

这样就可以生成token了,试一下你的登录接口,看看能不能正确生成token,有问题及时向我反馈

下一节开始讲automapper的使用

相关