zoukankan      html  css  js  c++  java
  • 关于ASP.Net Core Web及API身份认证的解决方案

    https://www.cnblogs.com/ibeisha/p/jwt-webapi.html

    .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 { getset; }
     
          /// <summary>
          ///<![CDATA[消息]]>
          /// </summary>
          public string message { getset; }
     
          /// <summary>
          /// <![CDATA[相关的链接帮助地址]]>
          /// </summary>
          public string url { getset; }
     
      }
     
      /// <summary>
      ///
      /// </summary>
      /// <typeparam name="T"></typeparam>
      public class RestfulData<T> : RestfulData
      {
          /// <summary>
          /// <![CDATA[数据]]>
          /// </summary>
          public virtual T data { getset; }
      }
     
      /// <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" };
         }
    }<em id="__mceDel" style=" font-family: 'PingFang SC', 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14px;"> </em>

    最后,让我们测试下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配置起来也很简单。

  • 相关阅读:
    记录一个jsonb_array_elements因数据问题被坑的点
    postgresql 中的 with 用法
    Java中4个元注解
    Java8 stream filter map
    sql 函数
    sql 判断选择语句
    面试里的套路(1)
    python 路径
    postsql sqlalchemy的事务提交问题
    网站响应过慢问题
  • 原文地址:https://www.cnblogs.com/frank0812/p/11156535.html
Copyright © 2011-2022 走看看