安装相关的NuGet包:
二、编码首先编写数据库模型:
用户表 User.cs:
public class User { [Key] public GuID ID { get; set; } [required] [Column(Typename = "VARCHAR(16)")] public string Username { get; set; } [required] [Column(Typename = "VARCHAR(16)")] public string Password { get; set; } }
数据库上下文 DemoContext.cs,在数据库创建时增加一条种子数据admin:
public class DemoContext : DbContext { public DemoContext(DbContextoptions<DemoContext> options) : base(options) { } public DbSet<User> Users { get; set; } protected overrIDe voID OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); modelBuilder.Entity<User>().HasData(new User { ID = GuID.Parse("94430DDF-E6E1-4836-A7D2-49A9FCEF722E"),Username = "admin",Password = "123456" }); } }
编写数据访问服务:IUserService接口,这里简单定义几个添加查询的方法:
public interface IUserService { Task<IEnumerable<User>> GetUserAsync(); Task<User> GetUserAsync(GuID ID); Task<User> GetUserAsync(string username,string password); Task<User> AddUserAsync(string username,string password); }
UserService实现类:
public class UserService : IUserService { private Readonly DemoContext context; public UserService(DemoContext context) { this.context = context ?? throw new ArgumentNullException(nameof(context)); } public async Task<User> AddUserAsync(string username,string password) { User user = new User(); user.ID = GuID.NewGuID(); user.Username = username; user.Password = password; await context.Users.AddAsync(user); context.SaveChanges(); return user; } public async Task<User> GetUserAsync(string username,string password) { return await context.Users.FirstOrDefaultAsync(p => p.Username == username && p.Password == password); } public async Task<IEnumerable<User>> GetUserAsync() { return await context.Users.ToListAsync(); } public async Task<User> GetUserAsync(GuID ID) { return await context.Users.FirstOrDefaultAsync(p => p.ID == ID); } }
appsettings.Json中增加jwt,efcore相关的配置 JwtSetting、ConnectionStrings:{ "Logging": { "LogLevel": { "Default": "information","Microsoft": "Warning","Microsoft.Hosting.lifetime": "information" } },"AllowedHosts": "*","JwtSetting": { "SecurityKey": "88d082e6-5672-4c6c-bc42-6fcce20fbf51",// 密钥 "Issuer": "jwtIssuertest",// 颁发者 "AudIEnce": "jwtAudIEncetest",// 接收者 "ExpireSeconds": 3600 // 过期时间(3600) },"ConnectionStrings": { "DemoContext": "data source=.;Initial Catalog=WebAPIDemoDB;User ID=sa;Password=123456;MultipleActiveResultSets=True;App=EntityFramework" }}
增加jwt配置对象: /// <summary> /// jwt配置对象 /// </summary> public class JwtSetting { public string SecurityKey { get; set; } public string Issuer { get; set; } public string AudIEnce { get; set; } public int ExpireSeconds { get; set; } }
public static class AppSettings { public static JwtSetting JwtSetting { get; set; } /// <summary> /// 初始化jwt配置 /// </summary> /// <param name="configuration"></param> public static voID Init(IConfiguration configuration) { JwtSetting = new JwtSetting(); configuration.Bind("JwtSetting",JwtSetting); } }
在Startup.cs中配置相关服务和中间件:public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } // This method gets called by the runtime. Use this method to add services to the container. public voID ConfigureServices(IServiceCollection services) { AppSettings.Init(Configuration); services.AddSwaggerGen(c => { c.SwaggerDoc("v1",new OpenAPIInfo { Title = "My API",Version = "v1" }); // Set the comments path for the Swagger JsON and UI. var xmlfile = $"{Assembly.GetExecutingAssembly().Getname().name}.xml"; var xmlPath = Path.Combine(AppContext.BaseDirectory,xmlfile); c.IncludeXmlComments(xmlPath); c.AddSecurityDeFinition("Bearer",new OpenAPISecurityScheme() { Description = "在下框中输入请求头中需要添加Jwt授权Token:Bearer Token",name = "Authorization",In = ParameterLocation.header,Type = SecuritySchemeType.APIKey,BearerFormat = "JWT",Scheme = "Bearer" }); c.AddSecurityRequirement(new OpenAPISecurityRequirement { { new OpenAPISecurityScheme{ Reference = new OpenAPIReference { Type = ReferenceType.SecurityScheme,ID = "Bearer"} },new string[] { } } }); }); services .AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { options.TokenValIDationParameters = new TokenValIDationParameters { Validissuer = AppSettings.JwtSetting.Issuer,ValIDAudIEnce = AppSettings.JwtSetting.AudIEnce,IssuerSigningKey = new SymmetricSecurityKey(EnCoding.UTF8.GetBytes(AppSettings.JwtSetting.SecurityKey)),// 默认允许 300s 的时间偏移量,设置为0 ClockSkew = TimeSpan.Zero,}; }); services.AddCors(options => { options.AddPolicy("any",builder => { builder.AllowAnyMethod() .AllowAnyOrigin() .AllowAnyheader(); }); }); services.AddControllers(); services.AddScoped<IUserService,UserService>(); services.AddDbContext<DemoContext>(opt => opt.UsesqlServer(Configuration.GetConnectionString("DemoContext"))); } // This method gets called by the runtime. Use this method to configure the http request pipeline. public voID Configure(IApplicationBuilder app,IWebHostEnvironment env) { app.UseAuthentication(); if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseSwagger(); app.UseSwaggerUI(c => { c.SwaggerEndpoint("/swagger/v1/swagger.Json","My API V1"); }); app.UseRouting(); app.UseAuthorization(); //CORS 中间件必须配置为在对 UseRouting 和 UseEndpoints的调用之间执行。 配置不正确将导致中间件停止正常运行。 app.UseCors("any"); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); } }
打开项目文件,增加项目xml文档生成配置,swagger需要用到:<Generatedocumentationfile>true</Generatedocumentationfile><Nowarn>$(Nowarn);1591</Nowarn>
数据库迁移:打开程序包管理控制台:执行命令
Add-Migration Initial
然后执行
Update-Database
此时数据库已经成功生成:
下面是controller:
先建一个数据传输实体,方便统一controller的返回值:
public class BaseDto<T> { public BaseDto(StatusCode code,string message) { Code = code; Message = message; } public BaseDto(StatusCode code,string message,T data) { Code = code; Message = message; Data = data; } public StatusCode Code { get; set; } public string Message { get; set; } public T Data { get; set; } } public enum StatusCode { Success = 0,Error = 1,}
UserController:
/// <summary> /// 用户 /// </summary> [Authorize] [Route("API/[controller]")] [APIController] public class UserController : ControllerBase { private Readonly IUserService userService; public UserController(IUserService userService) { this.userService = userService; } /// <summary> /// 所有用户 /// </summary> /// <returns></returns> [Route("")] [httpGet] public async Task<ActionResult<BaseDto<IEnumerable<User>>>> Get() { var users = await userService.GetUserAsync(); BaseDto<IEnumerable<User>> dto = new BaseDto<IEnumerable<User>>(Dto.StatusCode.Success,"",users); return Ok(dto); } /// <summary> /// 当前用户 /// </summary> /// <returns></returns> [Route("me")] [httpGet] public async Task<ActionResult<BaseDto<User>>> UserInfo() { string ID = User.FindFirst("ID")?.Value; var user = await userService.GetUserAsync(GuID.Parse(ID)); BaseDto<User> dto = new BaseDto<User>(Dto.StatusCode.Success,user); return Ok(dto); } /// <summary> /// 根据ID获取用户 /// </summary> /// <param name="ID"></param> /// <returns></returns> [Route("{ID}")] [httpGet] public async Task<ActionResult<BaseDto<User>>> Get(GuID ID) { var user = await userService.GetUserAsync(ID); BaseDto<User> dto = new BaseDto<User>(Dto.StatusCode.Success,user); return Ok(dto); } /// <summary> /// 添加用户 /// </summary> /// <param name="loginParameter"></param> /// <returns></returns> [httpPost] public async Task<ActionResult<BaseDto<User>>> Add(LoginParameter loginParameter) { var user = await userService.AddUserAsync(loginParameter.Username,loginParameter.Password); BaseDto<User> dto = new BaseDto<User>(Dto.StatusCode.Success,user); return Ok(dto); } } public class LoginParameter { public string Username { get; set; } public string Password { get; set; } }
TokenController:
/// <summary> /// 鉴权 /// </summary> [Route("API/[controller]")] [APIController] public class TokenController : ControllerBase { private Readonly IUserService userService; public TokenController(IUserService userService) { this.userService = userService; } /// <summary> /// 获取token /// </summary> /// <param name="loginParameter"></param> /// <returns></returns> [AllowAnonymous] [httpPost(name = nameof(Login))] public async Task<ActionResult<BaseDto<object>>> Login([FromBody]LoginParameter loginParameter) { var user = await userService.GetUserAsync(loginParameter.Username,loginParameter.Password); if (user != null) { var token = AppHelper.Instance.GetToken(user); BaseDto<object> dto = new BaseDto<object>(Dto.StatusCode.Success,new { token }); return Ok(dto); } return Ok(new BaseDto<object>(Dto.StatusCode.Error,null)); } }
AppHelper中生成token的方法:
public class AppHelper { public Readonly static AppHelper Instance = new AppHelper(); private AppHelper() { } /// <summary> /// 生成token /// </summary> /// <param name="user"></param> /// <returns></returns> public string GetToken(User user) { //创建用户身份标识,可按需要添加更多信息 var claims = new Claim[] { new Claim(JwtRegisteredClaimnames.Jti,GuID.NewGuID().ToString()),new Claim("ID",user.ID.ToString(),ClaimValueTypes.Integer32),// 用户ID new Claim("name",user.Username),// 用户名 }; var key = new SymmetricSecurityKey(EnCoding.UTF8.GetBytes(AppSettings.JwtSetting.SecurityKey)); var creds = new SigningCredentials(key,SecurityAlgorithms.HmacSha256); //创建令牌 var token = new JwtSecurityToken( issuer: AppSettings.JwtSetting.Issuer,audIEnce: AppSettings.JwtSetting.AudIEnce,signingCredentials: creds,claims: claims,notBefore: DateTime.Now,expires: DateTime.Now.AddSeconds(AppSettings.JwtSetting.ExpireSeconds) ); string jwtToken = new JwtSecurityTokenHandler().Writetoken(token); return jwtToken; } }
三、效果运行项目,浏览器访问:
测试一下用户接口:
这时返回401错误,因为我们还没有鉴权
使用admin/123456获取token:
拿到token 点击authorize:
然后再测试用户接口:
此时已经可以正常请求。
代码:https://github.com/xiajingren/NetCore3.1-WebApi-Demo 总结
以上是内存溢出为你收集整理的ASP.NET Core 3.1 WebApi+JWT+Swagger+EntityFrameworkCore构建REST API全部内容,希望文章能够帮你解决ASP.NET Core 3.1 WebApi+JWT+Swagger+EntityFrameworkCore构建REST API所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)