NETCore使用帶有權限驗證的Swagger

Swagger

什麼是Swagger

Swagger 是一個規範和完整的框架,用於生成、描述、調用和可視化 RESTful 風格的 Web 服務。方便前後端接口對接。

NuGet安裝

打開NuGet程序包,搜索“Swashbuckle.AspNetCore”安裝。
注意:NETCore3.0版本需要使用Swashbuckle.AspNetCore5.0以上的版本。我這個用的是NETCore2.2。
在這裏插入圖片描述

Startup註冊Swagger

在Startup的ConfigureServices方法中註冊Swagger服務。

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

    #region Swagger
    services.AddSwaggerGen(c =>
    {
        c.SwaggerDoc("v1", new Info
        {
            Version = "v0.1.0",//版本號
            Title = "ZZTApi文檔",//文檔標題
            Description = "框架說明文檔",//文檔描述
            TermsOfService = "None",//服務條款
            Contact = new Contact { Name = "zzt", Email = "[email protected]", Url = "www.baidu.com" }//聯繫人
        });       
    });
    #endregion
}

在Startup的Configure方法裏面調用Swagger服務

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }

    app.UseMvc();
   
    #region Swagger
    app.UseSwagger();
    app.UseSwaggerUI(c =>
    {
        c.SwaggerEndpoint("/swagger/v1/swagger.json", "ApiHelp V1");
    });
    #endregion
}

保存後按F5調試,瀏覽器地址訪問http://localhost:51146/swagger/index.html(每個人端口號可能不一樣)。
在這裏插入圖片描述

設置默認首頁打開Swagger

如果不想每次訪問都要輸入/swagger/index.html來使用Swagger,希望根目錄就是Swagger界面。可以這樣設置:

app.UseSwaggerUI(c =>
{
    c.SwaggerEndpoint("/swagger/v1/swagger.json", "ApiHelp V1");
    c.RoutePrefix = "";//路徑配置,設置爲空,表示直接訪問該文件。
});

有可能每次運行都會默認訪問http://localhost:51146/api/values這個路徑下的地址。需要在launchSettings.json文件下修改。
在這裏插入圖片描述

爲接口添加註釋

如圖,文檔裏面我們需要在紅框裏面爲接口添加註釋,以方便理解每個接口的功能。
在這裏插入圖片描述
右鍵項目名稱=>屬性=>生成,勾選“輸出”下面的“xml文檔文件”,系統會默認生成一個,你也可以自定義。
這裏我用的是相對路徑。添加取消警告代碼1590。否則會有一些警告。
在這裏插入圖片描述
在接口方法上邊添加註釋,說明每個接口的功能。
在這裏插入圖片描述
最後在services.AddSwaggerGen裏面添加XML文檔的路徑。

#region Swagger
services.AddSwaggerGen(c =>
{
    c.SwaggerDoc("v1", new Info
    {
        Version = "v0.1.0",
        Title = "ZZTApi文檔",
        Description = "框架說明文檔",
        TermsOfService = "None",
        Contact = new Contact { Name = "zzt", Email = "[email protected]", Url = "www.baidu.com" }
    });

    #region 爲 Swagger JSON and UI設置xml文檔註釋路徑
    var basePath = Path.GetDirectoryName(typeof(Program).Assembly.Location);//獲取應用程序所在目錄(絕對,不受工作目錄影響,建議採用此方法獲取路徑)
    var xmlAPIPath = Path.Combine(basePath, "ZZTCoreAPI.xml");//這個就是剛剛配置的xml文件名
    var xmlModelPath = Path.Combine(basePath, "ZZTCoreModel.xml");//這個是引用model層的XML文檔。設置輸出XML文檔的方法跟上面的一樣。
    c.IncludeXmlComments(xmlAPIPath, true);//第二個參數true表示用控制器的XML註釋。默認是false
    c.IncludeXmlComments(xmlModelPath, true);
    #endregion
});

以上代碼還添加了一個model層的XML文檔。設置方法是一樣的。它的效果可以看以下幾張圖。
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
以上就是Swagger一些簡單應用

JWT

什麼是JWT

JWT,即JSON Web Tokens,是一種基於JSON的、用於在網絡上聲明某種主張的令牌(token)。JWT通常由三部分組成: 頭信息(header), 消息體(payload)和簽名(signature)。它是一種用於雙方之間傳遞安全信息的表述性聲明規範。JWT作爲一個開放的標準(RFC 7519),定義了一種簡潔的、自包含的方法,從而使通信雙方實現以JSON對象的形式安全的傳遞信息。

註冊授權認證服務

在Startup的ConfigureServices方法裏面添加以下代碼

#region JWT
var signingKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(Configuration["Audience:Secret"])); 
services.AddAuthentication("Bearer").AddJwtBearer(o=> {
    o.TokenValidationParameters = new TokenValidationParameters
    {
        //是否開啓密鑰認證和key值
        ValidateIssuerSigningKey = true,
        IssuerSigningKey = signingKey,

        //是否開啓發行人認證和發行人
        ValidateIssuer = true,
        ValidIssuer = Configuration["Audience:Issuer"],

        //是否開啓訂閱人認證和訂閱人
        ValidateAudience = true,
        ValidAudience = Configuration["Audience:Audience"],

        //認證時間的偏移量
        ClockSkew = TimeSpan.Zero,
        //是否開啓時間認證
        ValidateLifetime = true,
        //是否該令牌必須帶有過期時間
        RequireExpirationTime = true
    };
});
#endregion

其中Configuration[“Audience:xxx”]是讀取appsettings.json配置文件裏面的一些參數,參數如下:

{
  "Logging": {
    "LogLevel": {
      "Default": "Warning"
    }
  },
  "AllowedHosts": "*",
  "Audience": {
    "Secret": "sdfsdfsrty45634kkhllghtdgdfss345t678fs",
    "Issuer": "ZZT",
    "Audience": "Nobody"
  }
}

註冊後需要在Configure方法裏面加入代碼app.UseAuthentication();來開啓服務

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }

    //HTTP管道是有先後順序的,一定要寫在 app.Mvc() 之前,否則不起作用。
    app.UseAuthentication();
    app.UseMvc();
   
    #region Swagger
    app.UseSwagger();
    app.UseSwaggerUI(c =>
    {
        c.SwaggerEndpoint("/swagger/v1/swagger.json", "ApiHelp V1");
        c.RoutePrefix = "";//路徑配置,設置爲空,表示直接訪問該文件,
    });
    #endregion
}

API接口添加授權策略

在接口方法上邊加入Authorize特性,表示該接口需要進行授權認證。
帶上Roles參數表示是基於角色的策略
在這裏插入圖片描述
如果有多個角色授權的話,在Startup的ConfigureServices方法中加入以下代碼

// 【授權】,好處就是不用在controller中,寫多個 roles 。
// 然後接口授權這麼寫 [Authorize(Policy = "Admin")]
services.AddAuthorization(options =>
{
    options.AddPolicy("Client", policy => policy.RequireRole("Client").Build());
    options.AddPolicy("Admin", policy => policy.RequireRole("Admin").Build());
    options.AddPolicy("SystemOrAdmin", policy => policy.RequireRole("Admin", "System"));
});

獲取JWT的Token

以下代碼是獲取JWTToken的方法,作用是傳入一個model,生成Token,這個model可以根據需求自己定義,涉及主要的兩個對象JwtSecurityTokenJwtSecurityTokenHandler

using Microsoft.IdentityModel.Tokens;
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;

namespace ZZTCoreAPI.Common
{
    public class JwtHelper
    {
        public static string IssueJWT(TokenModelJWT tokenModel)
        {
            var dateTime = DateTime.UtcNow;
            string iss = Appsettings.GetConfigure("Audience:Issuer");
            string aud = Appsettings.GetConfigure("Audience:Audience");
            string secret = Appsettings.GetConfigure("Audience:Secret");

            //var claims = new Claim[] //old
            var claims = new List<Claim>
                {
                    //下邊爲Claim的默認配置
                new Claim(JwtRegisteredClaimNames.Jti, tokenModel.Uid.ToString()),
                new Claim(JwtRegisteredClaimNames.Iat, $"{new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds()}"),
                new Claim(JwtRegisteredClaimNames.Nbf,$"{new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds()}") ,
                //這個就是過期時間,目前是過期100秒,可自定義,注意JWT有自己的緩衝過期時間
                new Claim (JwtRegisteredClaimNames.Exp,$"{new DateTimeOffset(DateTime.Now.AddSeconds(100)).ToUnixTimeSeconds()}"),
                new Claim(JwtRegisteredClaimNames.Iss,iss),
                new Claim(JwtRegisteredClaimNames.Aud,aud),
                
                //new Claim(ClaimTypes.Role,tokenModel.Role),//爲了解決一個用戶多個角色(比如:Admin,System),用下邊的方法
               };

            // 可以將一個用戶的多個角色全部賦予;
            // 作者:DX 提供技術支持;
            claims.AddRange(tokenModel.Role.Split(',').Select(s => new Claim(ClaimTypes.Role, s)));


            //祕鑰 (SymmetricSecurityKey 對安全性的要求,密鑰的長度太短會報出異常)
            var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secret));
            var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
            var jwt = new JwtSecurityToken(
                issuer: iss,
                claims: claims,
                signingCredentials: creds);

            var jwtHandler = new JwtSecurityTokenHandler();
            var encodedJwt = jwtHandler.WriteToken(jwt);

            return encodedJwt;
        }

    }
    /// <summary>
    /// 令牌
    /// </summary>
    public class TokenModelJWT
    {
        /// <summary>
        /// Id
        /// </summary>
        public long Uid { get; set; }
        /// <summary>
        /// 角色
        /// </summary>
        public string Role { get; set; }
        /// <summary>
        /// 職能
        /// </summary>
        public string Work { get; set; }

    }
}

以下代碼是獲取Token的接口,作用是根據傳入的賬號密碼生成一個model傳入以下代碼中的IssueJWT方法以獲取Token返回給前端。前端在 Http 的 Header 裏,增加屬性Authorization,並把這個Token帶上Bearer 即Bearer {Token}這個值賦給Authorization屬性作爲訪問其他接口的授權校驗。爲什麼一定要加Bearer?這是規定。

[HttpGet]
public ActionResult<string> GetToken(string name, string pwd)
{
    string jwtStr = string.Empty;
    bool suc = false;
    //這裏就是用戶登陸以後,通過數據庫去調取數據,分配權限的操作
    //這裏直接寫死了

    if (string.IsNullOrEmpty(name) || string.IsNullOrEmpty(pwd))
    {
        return new JsonResult(new
        {
            Status = false,
            message = "用戶名或密碼不能爲空"
        });
    }

    TokenModelJWT tokenModel = new TokenModelJWT();
    tokenModel.Uid = 1;
    tokenModel.Role = name;

    jwtStr = JwtHelper.IssueJWT(tokenModel);
    suc = true;
    return Ok(new
    {
        success = suc,
        token = jwtStr
    });
}

以上就是JWT的應用。

Swagger中開啓JWT服務

我們要測試 JWT 授權認證,就必定要輸入 Token令牌。Swagger 已經幫我們實現了這個錄入 Token令牌的功能,需要在服務中開啓:
在ConfigureServices -> AddSwaggerGen 服務中,增加以下代碼,注意是swagger服務內部:

#region Token綁定到ConfigureServices
//添加header驗證信息
//c.OperationFilter<SwaggerHeader>();
var security = new Dictionary<string, IEnumerable<string>> { { "ZZTAPI", new string[] { } }, };
c.AddSecurityRequirement(security);
//方案名稱“Blog.Core”可自定義,上下一致即可
c.AddSecurityDefinition("ZZTAPI", new ApiKeyScheme
{
    Description = "JWT授權(數據將在請求頭中進行傳輸) 直接在下框中輸入Bearer {token}(注意兩者之間是一個空格)\"",
    Name = "Authorization",//jwt默認的參數名稱
    In = "header",//jwt默認存放Authorization信息的位置(請求頭中)
    Type = "apiKey"
});
#endregion

測試流程

F5進入調試,進入Swagger界面,調用剛剛寫的GetToken接口獲取Token
在這裏插入圖片描述
將Token複製填到Authorize屬性
在這裏插入圖片描述
最後訪問我們之前加了[Authorize(Roles ="zzt")]特性的接口
在這裏插入圖片描述
可以看到是訪問得到的,如果我們不帶Token去訪問的話會返回401的狀態碼,請求要求身份驗證。
完!

參考文章:https://www.cnblogs.com/laozhang-is-phi/p/9511869.html#autoid-2-0-0

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章