初六了,西安的空气还是一如既往的好,睡在卧室里就可以看大秦岭了。北山门,南山门拆迁,很多人都在搬家找房子,在城市没有自己的一套房不行啊。一年挣不了多少,都给房东养房了。想当年自己也在城中村住了好几年,冬天没热水,夏季没空调,即使有了空调但是电却不能保证,停水停电,那日子真是的叫难过。
在高楼包围下的城中村,还能坚持多久。
今天我们就来看一下JWT授权认证,我们的场景是用户一旦登录就会从服务端获取Token,并把Token存储在本地Local或者Session中。然后后面不管请求什么api都会携带这个token,api服务端拿到这个token进行验证,验证通过后转到action去做处理。好的,我们先看一下Swagger,不讲概念,干就完了。在我们的server端引用SwashBuckle.AspNetCore
然后再Startup.cs中增加Swagger的配置,如下
services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo { Version = "v1", Title = "MemberShip Manager APIs", Description = "Swagger Instruction", Contact = new OpenApiContact { Email = "lilei1986abc@163.com", Name = "Bruce Li", Url = new Uri("http://www.51mordern.com") } }); });
然后在我们的Config方法中注册Swagger中间件,如下
app.UseSwagger(); app.UseSwaggerUI(c => { c.SwaggerEndpoint("/swagger/v1/swagger.json", "Customer Management API"); });
OK,我们启动项目,输入https://localhost:44357/swagger/v1/swagger.json,我们可以的看到json格式的api说明,当然这样看起来不怎么直观,可读性不好。
接着我们看一下Swagger UI,输入地址https://localhost:44357/swagger/index.html
展开Customer,我们可以看到所有和Customer相关的api
对于Swagger我们经常是要暴露给其他人去看api定义的,Swagger中也提供了tryOut功能,所以如果有些坏蛋利用这个功能在里面删除或者修改数据,我们的数据毫无安全可言,如下
点击try it out就可以调用我们的api,但是大家看到的这个界面它是有权限认证的,你必须输入access token才可以访问,之前说过了access token是通过验证用户名和密码而产生的,所以在不知道管理员用户名和密码的情况下是不可能拿到token的。要实现这个功能,我们需要在Startup中增加AddSecurityDefinition和AddSecurityRequirement方法。
AddSecurityDefinition:此方法可以通过定义一个或者多个安全方案来保护api的安全访问,用于设置身份认证方案,通常的身份认证方案有以下三种
使用BasicAuthScheme的身份验证
使用ApiKeyScheme的JWT Bearer令牌
使用OAuth2Scheme的OAuth2身份认证
AddSecurityRequirement方法用来设置全局级别的身份验证方案,当我们设置全局身份认证之后,所有的api只要是标记了Authorize的都会执行该认证方案。所以最终的代码如下
services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo { Version = "v1", Title = "MemberShip Manager APIs", Description = "Swagger Instruction", Contact = new OpenApiContact { Email = "lilei1986abc@163.com", Name = "Bruce Li", Url = new Uri("http://www.51mordern.com") } }); 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[] { } } }); });
我们新增了这两个方法,根据刚才的介绍,我们才用的是JWT 验证方案,需要在请求头中包含有效的Authorization才能访问标识了Authorize的action。
对于第二个方法,大家看到方法的参数是一个OpenApiSecurityRequirement类,它的定义如下
public class OpenApiSecurityRequirement : Dictionary<OpenApiSecurityScheme, IList<string>>, IOpenApiSerializable, IOpenApiElement
没错,它是一个字典类型,所以我们Schema指定用Bearer身份认证方式,第二个参数为什么放空数组,根据官方解释,这个参数称之为作用域数组,为空代表使用JWT 授权的新字符串
In AddSecurityRequirement() the array of scopes MUST be empty I.e new string[] {} for JWT authorization.
ok,我们在api端给创建Customer的api打上Authorization标签。
[Authorize] [HttpPost("create")] public HttpResponseMessage CreateCustomer([FromBody] CustomerCreateRequest customerRequest) { var customer = mapper.Map<Customer>(customerRequest); var customerDB = customerService.GetCustomerByUserNo(customerRequest.UserNo); if (customerDB != null) { return new HttpResponseMessage { StatusCode = HttpStatusCode.Conflict, Content = new StringContent("用户名已存在!") }; } customerService.CreateCustomer(customer); return new HttpResponseMessage(HttpStatusCode.OK); }
ok,我们在Swagger UI中调用一下试试,点击Authorization的话会弹出我们在AddSecurityDefinition方法中定义的描述信息,如下
弹出如下界面
此时我们不输入Token,直接请求api,我们发现api返回了401
接下来我们在弹出的界面中输入token,如下,这个时候我们在Swagger请求api的时候就会在header中带上输入的这个token。
我们再次请求创建customer的api,如下,返回了400 bad request,进入了我们的api fluent validation,验证没通过,返回了400。
ok,这就是我们在Swagger加认证的全部流程,下一节的话会捎带FluentValidation连同服务端token的生成一并讲解。
上一篇 Blazor之登录页面设计