使用WebApi加Token驗證(JWT)


今天來做一個webapi的安全管控驗證的案例

我們知道webapi密匙驗證也有不少,比如OAuth2.0.。。。我們今天用JWT這種方式來做一個賬號密碼換取Token的案例

基本流程是 輸入賬號密碼--->后台比對==true -->return Token else 未登錄

                                             所有控制器必須繼承自基礎類,基礎類我們用權限特性控制

 

老規矩,需要用到的工具

VS2019 NetCore3.1,Postman 調試用

 

我們看下主要結構如下

記得引用包

 

 

 

我們一個個類來看

 1  /// <summary>
 2     /// 基礎控制器類
 3     /// </summary>
 4     [Route("api/[controller]/[action]")]
 5     [ApiController]
 6     [ActionFilterAttribute]
 7     public class BaseController : ControllerBase
 8     {
 9         /// <summary>
10         /// 獲取Token的方法
11         /// </summary>
12         /// <param name="userId"></param>
13         /// <param name="token1"></param>
14         /// <returns></returns>
15         [NonAction]
16         protected string GetJwtToken(string userId,string token1)
17         {
18             var jwtHandle = new JwtSecurityTokenHandler { };
19 
20             var token = jwtHandle.CreateJwtSecurityToken(
21                 "test",
22                 "test",
23                 new ClaimsIdentity(new Claim[]{
24                     new Claim("name2","tt2"),
25                     new Claim("role2","user"),
26                     new Claim("token",token1),
27                     new Claim("c_uid",userId),
28                 }),
29                 System.DateTime.Now,
30                 //設置過期
31                 System.DateTime.Now.AddMilliseconds(3000.00),
32                 System.DateTime.Now,
33                 new SigningCredentials(
34                     new SymmetricSecurityKey(System.
35                     Text.
36                     Encoding.
37                     ASCII.GetBytes("6mSzczZX3KgZ3HOX")),
38                     SecurityAlgorithms.HmacSha256)
39             );
40 
41             return jwtHandle.WriteToken(token);
42         }
43     }

 

 這個基礎控制類我們這里就寫一個方法吧,就是生成Token,當然是在匹配用戶名密碼正確之后調用

接下來是這個權限特性 這里都做了注釋,不再一一解釋

    /// 權限過濾特性 /// </summary>
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)] public class ActionFilterAttribute : Attribute, IAsyncActionFilter, IAsyncAlwaysRunResultFilter { /// <summary>
        /// 忽略token的方法 /// </summary>
        public static readonly string[] IgnoreToken = {"Login"}; /// <summary>
        /// 校驗過濾器 /// </summary>
        /// <param name="context"></param>
        /// <param name="next"></param>
        /// <returns></returns>
        public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) { //獲取用戶聲明中的Token
            var UserToken = context.HttpContext.User.FindFirstValue("token"); //執行的動作
            var action = context.RouteData.Values["Action"].ToString(); if (IgnoreToken.Count(s => s == action) == 0) { if (UserToken is null) { context.Result = new JsonResult("用戶未登錄!"); return; } //現實中獲取數據庫對比用戶唯一識別token,非加密的那個
                if (!UserToken.Equals("123456")) { context.Result = new JsonResult("Token失效!"); return; } } //拋轉下一個中間件
            var resultContext = await next(); } /// <summary>
        /// 
        /// </summary>
        /// <param name="context"></param>
        /// <param name="next"></param>
        /// <returns></returns>
        public async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next) { var resultContext = await next(); }
}

然后我們需要看下StartUp類中我們需要使用這個中間件才可以正常使用

public void ConfigureServices(IServiceCollection services)
        {
            //注冊JWT
            services.AddAuthentication()
                    .AddIdentityServerJwt();
            services.Configure<JwtBearerOptions>(
                IdentityServerJwtConstants.IdentityServerJwtBearerScheme,
                options =>
                {
                    var onTokenValidated = options.Events.OnTokenValidated;
                    var onMessageReceived = options.Events.OnMessageReceived;

                    options.Events.OnTokenValidated = async context =>
                    {
                        await onTokenValidated(context);
                    };
                    options.Events.OnMessageReceived = async context =>
                    {
                        /*
                        https://www.cnblogs.com/liuww/p/12177272.html
                        https://www.cnblogs.com/RainingNight/p/jwtbearer-authentication-in-asp-net-core.html
                        https://www.cnblogs.com/jesse2013/p/integrate-with-lagacy-auth.html
                        https://www.cnblogs.com/nsky/p/10312101.html
                        */
                        // await onMessageReceived(context);
                        var token = context.Request.Headers["token"];
                        if (string.IsNullOrEmpty(token))
                        {
                            token = context.Request.Query["token"];
                        }
                        context.Token = token.FirstOrDefault();
                        // return await System.Threading.Tasks.Task.CompletedTask;
                    };
                    //Token認證注冊
                    options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
                    {
                        ValidIssuer = "test",
                        ValidAudience = "test",
                        IssuerSigningKey = new Microsoft.IdentityModel.Tokens.SymmetricSecurityKey(System.Text.Encoding.ASCII.GetBytes("6mSzczZX3KgZ3HOX"))
                    };
                });

            services.AddControllers();
        }
 
         
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseRouting();

            app.UseAuthentication();
            //app.UseAuthorization();
           

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }

 

上面都寫好之后

我們看下用戶類這里只做兩個東西,一個登錄,一個獲取數據,注意登錄是公開的,獲取用戶信息是私密的

 

我們運行一下調試看看
打開Postman發現直接調用獲取用戶信息是被拒絕的

 

 
         

 好了,我們再嘗試通過用戶名密碼換取Token

 

 

我們發現我們成功換取到了token,然后我們再用Token去請求剛才提示拒絕的接口

 

 

我們看到已經非常友好的接受了我們的請求。當然這是一個最基本的用戶名密碼換取Token的驗證,如果是前后端分離,我們還要有秘鑰等等驗證,但是小程序里面的話,那么我們可以通過這種驗證實現移動端網頁端的調用。

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM