2021年02月17日 13:09
原创作品,转载时请务必以超链接形式标明文章原始出处,否则将追究法律责任。

初六了,西安的空气还是一如既往的好,睡在卧室里就可以看大秦岭了。北山门,南山门拆迁,很多人都在搬家找房子,在城市没有自己的一套房不行啊。一年挣不了多少,都给房东养房了。想当年自己也在城中村住了好几年,冬天没热水,夏季没空调,即使有了空调但是电却不能保证,停水停电,那日子真是的叫难过。

捕获.PNG

在高楼包围下的城中村,还能坚持多久。

今天我们就来看一下JWT授权认证,我们的场景是用户一旦登录就会从服务端获取Token,并把Token存储在本地Local或者Session中。然后后面不管请求什么api都会携带这个token,api服务端拿到这个token进行验证,验证通过后转到action去做处理。好的,我们先看一下Swagger,不讲概念,干就完了。在我们的server端引用SwashBuckle.AspNetCore

image.png

然后再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说明,当然这样看起来不怎么直观,可读性不好。

image.png

接着我们看一下Swagger UI,输入地址https://localhost:44357/swagger/index.html

image.png

展开Customer,我们可以看到所有和Customer相关的api

image.png

对于Swagger我们经常是要暴露给其他人去看api定义的,Swagger中也提供了tryOut功能,所以如果有些坏蛋利用这个功能在里面删除或者修改数据,我们的数据毫无安全可言,如下

image.png

点击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方法中定义的描述信息,如下

image.png

弹出如下界面

image.png

此时我们不输入Token,直接请求api,我们发现api返回了401

image.png

接下来我们在弹出的界面中输入token,如下,这个时候我们在Swagger请求api的时候就会在header中带上输入的这个token。

image.png

我们再次请求创建customer的api,如下,返回了400 bad request,进入了我们的api fluent validation,验证没通过,返回了400。

image.png

ok,这就是我们在Swagger加认证的全部流程,下一节的话会捎带FluentValidation连同服务端token的生成一并讲解。


发表评论
匿名  
用户评论
暂无评论