關於ASP.Net Core Web及API身份認證的解決方案


     6月15日,在端午節前的最后一個工作日,想起有段日子沒有寫過文章了,倒有些荒疏了。今借夏日蒸蒸之氣,偷得浮生半日悠閑。閑話就說到這里吧,提前祝大家端午愉快(屈原聽了該不高興了:))!
.NetCore自發布以來,頗受關注,現在.Net Core2.0已經正式發布,邊迫不及待的將.Net跨平台移植的工作進行到底。想來,也費不了多少事兒。我經常和同事們說,要敢於嘗試新鮮事物,不陰損守舊,方能使自己不斷進步,站在隊伍的前列。下面就關於Asp.Net Core在Web 及API項目上身份認證的問題做下簡單的闡述。

一、Asp.Net Core Web項目的登錄認證

    在MVC Web項目中,做用戶登錄授權,是必不可少的工作,不知道大家平時是怎么做的,我想,大多朋友還是使用微軟提供的一套認證機制,可以省去很多功夫。從WebForm時代的Form身份認證,無非是通過客戶端Cookie中存儲認證票據,在請求受保護的資源時,通過Cookie中攜帶的身份票據,再有Asp.net的認證模塊,完整對請求者的身份認證。這一過程,是很清晰簡單的了。在MVC中,大多是通過中間件(MiddleWare)來完整認證授權過程。在ASP.NETMVC中,我們了解到基於聲明的授權認證(Claim),這種認證方式,好處在於,我們想在用戶授權時,存儲多個屬性信息,只需要添加多個聲明即可,我們在微軟的認證中間件中,看到的都是定義好的常量,當然,我們可以定義自己的ClaimTypes。然我們看看微軟在.NetCore中定義的一些聲明吧:

 //
        // Summary:
        //     http://schemas.xmlsoap.org/ws/2009/09/identity/claims/actor.
        public const string Actor = "http://schemas.xmlsoap.org/ws/2009/09/identity/claims/actor";
        //
        // Summary:
        //     The URI for a claim that specifies the postal code of an entity, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/postalcode.
        public const string PostalCode = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/postalcode";
        //
        // Summary:
        //     The URI for a claim that specifies the primary group SID of an entity, http://schemas.microsoft.com/ws/2008/06/identity/claims/primarygroupsid.
        public const string PrimaryGroupSid = "http://schemas.microsoft.com/ws/2008/06/identity/claims/primarygroupsid";
        //
        // Summary:
        //     The URI for a claim that specifies the primary SID of an entity, http://schemas.microsoft.com/ws/2008/06/identity/claims/primarysid.
        public const string PrimarySid = "http://schemas.microsoft.com/ws/2008/06/identity/claims/primarysid";
        //
        // Summary:
        //     The URI for a claim that specifies the role of an entity, http://schemas.microsoft.com/ws/2008/06/identity/claims/role.
        public const string Role = "http://schemas.microsoft.com/ws/2008/06/identity/claims/role";
        //
        // Summary:
        //     The URI for a claim that specifies an RSA key, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/rsa.
        public const string Rsa = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/rsa";
        //
        // Summary:
        //     The URI for a claim that specifies a serial number, http://schemas.microsoft.com/ws/2008/06/identity/claims/serialnumber.
        public const string SerialNumber = "http://schemas.microsoft.com/ws/2008/06/identity/claims/serialnumber";
        //
        // Summary:
        //     The URI for a claim that specifies a security identifier (SID), http://schemas.xmlsoap.org/ws/2005/05/identity/claims/sid.
        public const string Sid = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/sid";
        //
        // Summary:
        //     The URI for a claim that specifies a service principal name (SPN) claim, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/spn.
        public const string Spn = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/spn";
        //
        // Summary:
        //     The URI for a claim that specifies the state or province in which an entity resides,
        //     http://schemas.xmlsoap.org/ws/2005/05/identity/claims/stateorprovince.
        public const string StateOrProvince = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/stateorprovince";
        //
        // Summary:
        //     The URI for a claim that specifies the street address of an entity, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/streetaddress.
        public const string StreetAddress = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/streetaddress";
        //
        // Summary:
        //     The URI for a claim that specifies the surname of an entity, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname.
        public const string Surname = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname";
        //
        // Summary:
        //     The URI for a claim that identifies the system entity, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/system.
        public const string System = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/system";
        //
        // Summary:
        //     The URI for a claim that specifies a thumbprint, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/thumbprint.
        //     A thumbprint is a globally unique SHA-1 hash of an X.509 certificate.
        public const string Thumbprint = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/thumbprint";
        //
        // Summary:
        //     The URI for a claim that specifies a user principal name (UPN), http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn.
        public const string Upn = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn";
        //
        // Summary:
        //     The URI for a claim that specifies a URI, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/uri.
        public const string Uri = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/uri";
        //
        // Summary:
        //     http://schemas.microsoft.com/ws/2008/06/identity/claims/userdata.
        public const string UserData = "http://schemas.microsoft.com/ws/2008/06/identity/claims/userdata";
        //
        // Summary:
        //     http://schemas.microsoft.com/ws/2008/06/identity/claims/version.
        public const string Version = "http://schemas.microsoft.com/ws/2008/06/identity/claims/version";
        //
        // Summary:
        //     The URI for a claim that specifies the webpage of an entity, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/webpage.
        public const string Webpage = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/webpage";
        //
        // Summary:
        //     The URI for a claim that specifies the Windows domain account name of an entity,
        //     http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname.
        public const string WindowsAccountName = "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname";
        //
        // Summary:
        //     http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsdeviceclaim.
        public const string WindowsDeviceClaim = "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsdeviceclaim";
        //
        // Summary:
        //     http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsdevicegroup.
        public const string WindowsDeviceGroup = "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsdevicegroup";
        //
        // Summary:
        //     http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsfqbnversion.
        public const string WindowsFqbnVersion = "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsfqbnversion";
        //
        // Summary:
        //     http://schemas.microsoft.com/ws/2008/06/identity/claims/windowssubauthority.
        public const string WindowsSubAuthority = "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowssubauthority";
        //
        // Summary:
        //     The URI for a claim that specifies the alternative phone number of an entity,
        //     http://schemas.xmlsoap.org/ws/2005/05/identity/claims/otherphone.
        public const string OtherPhone = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/otherphone";
        //
        // Summary:
        //     The URI for a claim that specifies the name of an entity, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier.
        public const string NameIdentifier = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier";
        //
        // Summary:
        //     The URI for a claim that specifies the name of an entity, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name.
        public const string Name = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name";
        //
        // Summary:
        //     The URI for a claim that specifies the mobile phone number of an entity, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/mobilephone.
        public const string MobilePhone = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/mobilephone";
        //
        // Summary:
        //     The URI for a claim that specifies the anonymous user; http://schemas.xmlsoap.org/ws/2005/05/identity/claims/anonymous.
        public const string Anonymous = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/anonymous";
        //
        // Summary:
        //     The URI for a claim that specifies details about whether an identity is authenticated,
        //     http://schemas.xmlsoap.org/ws/2005/05/identity/claims/authenticated.
        public const string Authentication = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/authentication";
        //
        // Summary:
        //     The URI for a claim that specifies the instant at which an entity was authenticated;
        //     http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationinstant.
        public const string AuthenticationInstant = "http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationinstant";
        //
        // Summary:
        //     The URI for a claim that specifies the method with which an entity was authenticated;
        //     http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationmethod.
        public const string AuthenticationMethod = "http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationmethod";
        //
        // Summary:
        //     The URI for a claim that specifies an authorization decision on an entity; http://schemas.xmlsoap.org/ws/2005/05/identity/claims/authorizationdecision.
        public const string AuthorizationDecision = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/authorizationdecision";
        //
        // Summary:
        //     The URI for a claim that specifies the cookie path; http://schemas.microsoft.com/ws/2008/06/identity/claims/cookiepath.
        public const string CookiePath = "http://schemas.microsoft.com/ws/2008/06/identity/claims/cookiepath";
        //
        // Summary:
        //     The URI for a claim that specifies the country/region in which an entity resides,
        //     http://schemas.xmlsoap.org/ws/2005/05/identity/claims/country.
        public const string Country = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/country";
        //
        // Summary:
        //     The URI for a claim that specifies the date of birth of an entity, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/dateofbirth.
        public const string DateOfBirth = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/dateofbirth";
        //
        // Summary:
        //     The URI for a claim that specifies the deny-only primary group SID on an entity;
        //     http://schemas.microsoft.com/ws/2008/06/identity/claims/denyonlyprimarygroupsid.
        //     A deny-only SID denies the specified entity to a securable object.
        public const string DenyOnlyPrimaryGroupSid = "http://schemas.microsoft.com/ws/2008/06/identity/claims/denyonlyprimarygroupsid";
        //
        // Summary:
        //     The URI for a claim that specifies the deny-only primary SID on an entity; http://schemas.microsoft.com/ws/2008/06/identity/claims/denyonlyprimarysid.
        //     A deny-only SID denies the specified entity to a securable object.
        public const string DenyOnlyPrimarySid = "http://schemas.microsoft.com/ws/2008/06/identity/claims/denyonlyprimarysid";
        //
        // Summary:
        //     The URI for a claim that specifies a deny-only security identifier (SID) for
        //     an entity, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/denyonlysid.
        //     A deny-only SID denies the specified entity to a securable object.
        public const string DenyOnlySid = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/denyonlysid";
        //
        // Summary:
        //     http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsuserclaim.
        public const string WindowsUserClaim = "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsuserclaim";
        //
        // Summary:
        //     http://schemas.microsoft.com/ws/2008/06/identity/claims/denyonlywindowsdevicegroup.
        public const string DenyOnlyWindowsDeviceGroup = "http://schemas.microsoft.com/ws/2008/06/identity/claims/denyonlywindowsdevicegroup";
        //
        // Summary:
        //     http://schemas.microsoft.com/ws/2008/06/identity/claims/dsa.
        public const string Dsa = "http://schemas.microsoft.com/ws/2008/06/identity/claims/dsa";
        //
        // Summary:
        //     The URI for a claim that specifies the email address of an entity, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/email.
        public const string Email = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress";

    那么我們在Asp.Net Core項目中的認證,也是比較簡單的。也是通過HttpContext的擴展方法SignInAsync,來傳入聲明的身份信息。要使用的微軟的認證組件,我們在.Net Core Web項目中,做如下改動:

首先,在Start.cs類中,添加服務,具體代碼如下:

         /// <summary>
        /// 
        /// </summary>
        /// <param name="services"></param>
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
            .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, o =>
            {
                o.Cookie.Name = "_AdminTicketCookie";
                o.LoginPath = new PathString("/Account/Login");
                o.LogoutPath = new PathString("/Account/Login");
                o.AccessDeniedPath = new PathString("/Error/Forbidden");
            });
            services.AddTransient<TiKu.Application.Interfaces.IAdminService, TiKu.Application.AdminService>();
            services.AddMvc();
        }

    其次,添加認證中間件

        /// <summary>
        /// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        /// </summary>
        /// <param name="app"></param>
        /// <param name="env"></param>
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
        {

            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
            }
            app.UseStaticFiles();
            app.UseAuthentication();//添加認證中間件
            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });
            
        }

  最后,在用戶登錄的地方,登錄成功后,調用HttpContext的SignIn方法,將授權信息寫入Cookie,示例代碼如下:

        /// <summary>
        /// <![CDATA[登陸]]>
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<ActionResult> Login(Models.LoginViewModel model)
        {
            try
            {
                //模型驗證通過后
                if (ModelState.IsValid)
                {
                    model.password = TiKu.Common.Security.MD5.Md5(model.password);//MD5加密
                    TiKu.Domain.Entity.tb_Admin admin = await _AdminService.CheckAccountAndPassword(account: model.account, password: model.password);
                    //驗證用戶名密碼
                    if (admin != null)
                    {
                        var identity = new ClaimsIdentity(CookieAuthenticationDefaults.AuthenticationScheme);//一定要聲明AuthenticationScheme
                        identity.AddClaim(new Claim(ClaimTypes.Name, admin.Account));
                        identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, admin.Id.ToString()));

                        await HttpContext.SignInAsync(identity.AuthenticationType,
                                                      new ClaimsPrincipal(identity),
                                                      new AuthenticationProperties
                                                      {
                                                          IsPersistent = model.isPersistent,
                                                          RedirectUri = "/Home/Index",
                                                          ExpiresUtc = new System.DateTimeOffset(dateTime: DateTime.Now.AddHours(6)),
                                                      });
                        //更新登陸時間
                        await _AdminService.UpdateLastLoginTime(id: admin.Id);
                    }
                    else
                    {
                        await HttpContext.ChallengeAsync(CookieAuthenticationDefaults.AuthenticationScheme);
                        ModelState.AddModelError("", "用戶名或密碼錯誤!");
                    }
                }
            }
            catch (Exception ex)
            {
                ModelState.AddModelError("", "用戶名或密碼錯誤!");
                _Logger.Error("用戶登錄時發生錯誤!", ex);
            }
            return View(model);
        }

  這樣就完成了Asp.net core web項目的登錄認證工作。

二、Asp.Net Core WebApi基於JWT的認證授權

      關於JWT的工作原理,大家可以自行了解(https://jwt.io/)。JWT實現了服務端無狀態,在分布式服務,會話一致性,單點登錄等方面,凸顯優勢,不占用服務端資源。使用JWT需要注意的是,令牌過期后刷新,以及更改密碼后令牌未過期的處理問題。

這里,我以JWT作為.net core webapi項目的認證方式。

首先,我再Api項目中新建了一個名為OAuthController的控制器,定義一個Action名為Token的方法,用來讓客戶端獲取令牌之用,具體代碼如下:

        /// <summary>
        /// <![CDATA[獲取訪問令牌]]>
        /// </summary>
        /// <param name="user"></param>
        /// <param name="password"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<TiKu.Domain.ValueObject.RestfulData<TiKu.Domain.ValueObject.AccessTokenObj>> Token(string user, string password)
        {
            var result = new TiKu.Domain.ValueObject.RestfulData<TiKu.Domain.ValueObject.AccessTokenObj>();
            try
            {
                if (string.IsNullOrEmpty(user)) throw new ArgumentNullException("user", "用戶名不能為空!");
                if (string.IsNullOrEmpty(password)) throw new ArgumentNullException("password", "密碼不能為空!");

                //驗證用戶名和密碼
                var userInfo = await _UserService.CheckUserAndPassword(mobile: user, password: password);
                var claims = new Claim[]
                {
                    new Claim(ClaimTypes.Name,user),
                    new Claim(ClaimTypes.NameIdentifier,userInfo.Id.ToString()),
                };

                var key = new SymmetricSecurityKey(System.Text.Encoding.UTF8.GetBytes(Configuration["JwtSecurityKey"]));
                var expires = DateTime.Now.AddDays(28);//
                var token = new JwtSecurityToken(
                            issuer: Configuration["issuer"],
                            audience: Configuration["audience"],
                            claims: claims,
                            notBefore: DateTime.Now,
                            expires: expires,
                            signingCredentials: new SigningCredentials(key, SecurityAlgorithms.HmacSha256));

                //生成Token
                string jwtToken = new JwtSecurityTokenHandler().WriteToken(token);
                result.code = 1;
                result.data = new Domain.ValueObject.AccessTokenObj() { AccessToken = jwtToken, Expires = TiKu.Common.Utility.Util.ToUnixTime(expires) };
                result.message = "授權成功!";
                return result;
            }
            catch (Exception ex)
            {
                result.message = ex.Message;
                result.code = 0;
                logger.Error("獲取訪問令牌時發生錯誤!", ex);
                return result;
            }
        }

  這里,我定義了一個統一返回數據格式的模型-RestfulData,其中有不返回數據data的RestfulData和帶data數據的RestfulData<T>,以及返回集合類型的RestfulArray<T>,具體代碼如下:

  /// <summary>
    /// 
    /// </summary>
    public class RestfulData
    {
        /// <summary>
        /// <![CDATA[錯誤碼]]>
        /// </summary>
        public int code { get; set; }

        /// <summary>
        ///<![CDATA[消息]]>
        /// </summary>
        public string message { get; set; }

        /// <summary>
        /// <![CDATA[相關的鏈接幫助地址]]>
        /// </summary>
        public string url { get; set; }

    }

    /// <summary>
    /// 
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class RestfulData<T> : RestfulData
    {
        /// <summary>
        /// <![CDATA[數據]]>
        /// </summary>
        public virtual T data { get; set; }
    }

    /// <summary>
    /// <![CDATA[返回數組]]>
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class RestfulArray<T> : ResultData<IEnumerable<T>>
    {

    }

  

配置JWT認證服務,在Start.cs啟動類中,配置如下:

/// <summary>
        /// 
        /// </summary>
        /// <param name="services"></param>
        public IServiceProvider ConfigureServices(IServiceCollection services)
        {
            services.AddSingleton<IConfiguration>(Configuration);
            services.AddMemoryCache();//添加基於內存的緩存支持
            services.AddAutofac();

            //配置授權
            services.AddAuthentication(options =>
            {
                options.DefaultAuthenticateScheme = "JwtBearer";
                options.DefaultChallengeScheme = "JwtBearer";

            }).AddJwtBearer("JwtBearer",
            (jwtBearerOptions) =>
            {
                jwtBearerOptions.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateIssuerSigningKey = true,
                    IssuerSigningKey = new SymmetricSecurityKey(System.Text.Encoding.UTF8.GetBytes(Configuration["JwtSecurityKey"])),//秘鑰
                    ValidateIssuer = true,
                    ValidIssuer = Configuration["issuer"],
                    ValidateAudience = true,
                    ValidAudience = Configuration["audience"],
                    ValidateLifetime = true,
                    ClockSkew = TimeSpan.FromMinutes(5)
                };
            });

            services.AddMvc();

            //IOC Autofac
            var builder = new ContainerBuilder();
            builder.Populate(services);

            //注冊應用服務
            var assemblyApplicationService = System.Reflection.Assembly.Load("TiKu.Application");
            builder.RegisterAssemblyTypes(assemblyApplicationService).AsImplementedInterfaces();

            var container = builder.Build();
            Container = container;

            return new AutofacServiceProvider(container);
        }

  上面使用了IOC容器Autofac。

其次,配置認證中間件:

        /// <summary>
        /// 
        /// </summary>
        /// <param name="app"></param>
        /// <param name="env"></param>
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            app.UseAuthentication();//配置授權
            //處理異常
            app.UseStatusCodePages(new StatusCodePagesOptions()
            {
                HandleAsync = (context) =>
                {
                    if (context.HttpContext.Response.StatusCode == 401)
                    {
                        using (System.IO.StreamWriter sw = new System.IO.StreamWriter(context.HttpContext.Response.Body))
                        {
                            sw.Write(Newtonsoft.Json.JsonConvert.SerializeObject(new
                            {
                                status = 401,
                                message = "access denied!",
                            }));
                        }
                    }
                    return System.Threading.Tasks.Task.Delay(0);
                }
            });
            app.UseMvc(routes =>
            {
                routes.MapRoute(name: "default", template: "api/{controller=Home}/{action=Index}/{id?}");
                routes.MapRoute(name: "mvc", template: "{controller=Home}/{action=Index}/{id?}");
            });
        }  

為了測試,我們給ValuesController控制器添加Authorize特性。

    /// <summary>
    /// 
    /// </summary>
    [Authorize]
    [Route("api/[controller]")]
    public class ValuesController : Controller
    {

        // GET api/values
        [HttpGet]
        public IEnumerable<string> Get()
        {
            return new string[] { "value1", "value2" };
        }
   } 

最后,讓我們測試下API的授權,這里,我以Ajax模擬API的調用:

script type="text/javascript">
    //獲取令牌
    $.post("/oauth/token", $.param({ user: "lichaoqiang", password: "fdsfds" })).done(function (data) {

        if (data.code === 1) {
            localStorage.setItem("token", data.data.accessToken);
        }
    });

    //設置HTTP頭
    $.ajaxSetup({
        beforeSend: function (xhr) {
            if (localStorage.getItem("token") !== null) {
                xhr.setRequestHeader('Authorization', 'Bearer ' + localStorage.getItem("token"));
            }
        }
    });

    $.getJSON("/api/values", function (data) { console.log(data); });//獲取受保護的資源
</script>

  看下效果,直接訪問/api/values,會出現如下圖:

    當客戶請求受保護的資源時,通過HTTP header攜帶上token。這里需要注意的是,請求頭必須是Authorization,值是Bearer空格加上token。這樣訪問資源時,通過HTTP header攜帶令牌信息,服務端,通過認證中間件,完成授權認證過程。在上面的示例中,通過向全局Ajax注冊事件,將token寫入請求Header。、

至此,就完成了JWT認證授權的過程,.Net Core WebAPI配置起來也很簡單。

 


免責聲明!

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



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