对与asp.net core web api验证,多种方式,本例子的方式采用的是李争的《微软开源跨平台移动开发实践》中的token验证方式。

Asp.net core web api项目代码:

首先定义三个Token相关的类,一个Token实体类,一个TokenProvider类,一个TokenProviderOptions类

代码如下:

/// /// Token实体/// public class TokenEntity{    ///     /// token字符串    ///     public string access_token { get; set; }    ///     /// 过期时差    ///     public int expires_in { get; set; }}/// /// token提供属性/// public class TokenProviderOptions{    ///     /// 发行人    ///     public string Issuer { get; set; }    ///     /// 订阅者    ///     public string Audience { get; set; }    ///     /// 过期时间间隔    ///     public TimeSpan Expiration { get; set; } = TimeSpan.FromSeconds(30);    ///     /// 签名证书    ///     public SigningCredentials SigningCredentials { get; set; }} ///  /// Token提供类 ///  public class TokenProvider {     readonly TokenProviderOptions _options;     public TokenProvider(TokenProviderOptions options)     {         _options = options;     }     ///      /// 生成令牌     ///      /// 
http上下文     /// 
用户名     /// 
密码     /// 
角色     /// 
     public async Task
 GenerateToken(HttpContext context, string username, string password, string role)     {         var identity = await GetIdentity(username);         if (identity == null)         {             return null;         }         var now = DateTime.UtcNow;         //声明         var claims = new Claim[]         {             new Claim(JwtRegisteredClaimNames.Sub,username),             new Claim(JwtRegisteredClaimNames.Jti,Guid.NewGuid().ToString()),             new Claim(JwtRegisteredClaimNames.Iat,ToUnixEpochDate(now).ToString(),ClaimValueTypes.Integer64),             new Claim(ClaimTypes.Role,role),             new Claim(ClaimTypes.Name,username)         };         //Jwt安全令牌         var jwt = new JwtSecurityToken(             issuer: _options.Issuer,             audience: _options.Audience,             claims: claims,             notBefore: now,             expires: now.Add(_options.Expiration),             signingCredentials: _options.SigningCredentials);         //生成令牌字符串         var encodedJwt = new JwtSecurityTokenHandler().WriteToken(jwt);         var response = new TokenEntity         {             access_token = encodedJwt,             expires_in = (int)_options.Expiration.TotalSeconds         };         return response;     }      private static long ToUnixEpochDate(DateTime date)     {         return (long)Math.Round((date.ToUniversalTime() - new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero)).TotalSeconds);     }     /// 
     /// 查看令牌是否存在     ///      /// 
用户名     /// 
     private Task
 GetIdentity(string username)     {         return Task.FromResult(             new ClaimsIdentity(new System.Security.Principal.GenericIdentity(username, "token"),             new Claim[] {                 new Claim(ClaimTypes.Name, username)             }));     } }

Startup.cs

using System;using System.Collections.Generic;using System.Linq;using System.Threading.Tasks;using Microsoft.AspNetCore.Builder;using Microsoft.AspNetCore.Hosting;using Microsoft.Extensions.Configuration;using Microsoft.Extensions.DependencyInjection;using Microsoft.Extensions.Logging;using Microsoft.IdentityModel.Tokens;using System.Text;  namespace WebApiAuthentication{    public class Startup    {        public Startup(IHostingEnvironment env)        {            var builder = new ConfigurationBuilder()                .SetBasePath(env.ContentRootPath)                .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)                .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)                .AddEnvironmentVariables();            Configuration = builder.Build();        }         public IConfigurationRoot Configuration { get; }          public void ConfigureServices(IServiceCollection services)        {            services.AddMvc();        }         public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)        {            loggerFactory.AddConsole(Configuration.GetSection("Logging"));            loggerFactory.AddDebug();            //自定义密钥            var secretKey = "ThisIsASecretKeyForAspNetCoreAPIToken";            //生成SymmetricSecurityKey密钥            var signingKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(secretKey));            //令牌验证参数            var tokenValidationParameters = new TokenValidationParameters            {                ValidateIssuerSigningKey = true,                IssuerSigningKey = signingKey,                ValidateIssuer = true,                ValidIssuer = "issuer",                ValidateAudience = true,                ValidAudience = "audience",                ValidateLifetime = true,                ClockSkew = TimeSpan.Zero             };            //使用Jwt持票人身份验证            app.UseJwtBearerAuthentication(new JwtBearerOptions            {                AutomaticAuthenticate = true,                AutomaticChallenge = true,                TokenValidationParameters = tokenValidationParameters            });             app.UseMvc();        }    }}

AccountController.cs

using System.Threading.Tasks;using Microsoft.AspNetCore.Mvc;using Microsoft.AspNetCore.Authorization;using Microsoft.IdentityModel.Tokens;using System.Text;using Microsoft.Extensions.Options; namespace WebApiAuthentication.Controllers{       [Route("api/v1/[controller]/[action]")]    public class AccountController : Controller    {              [HttpPost]        [Authorize(Roles ="admin")]        public JsonResult ABC()        {            return new JsonResult(new            {                Name = "张三",                Age = 12,                Sex = true,                User=User.Identity.Name,                            }, new Newtonsoft.Json.JsonSerializerSettings());        }        [AllowAnonymous]        public IActionResult Login()        {            return View();        }        ///         /// 登录action        ///         /// 
用户名        /// 
密码        /// 
角色        /// 
        [HttpPost]        [AllowAnonymous]        public async Task
 Login(string username, string password,string role)        {            var signingKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("ThisIsASecretKeyForAspNetCoreAPIToken"));            var options = new TokenProviderOptions            {                Audience = "audience",                Issuer = "issuer",                SigningCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256)            };            var tpm = new TokenProvider(options);            var token = await tpm.GenerateToken(HttpContext, username, password,role);            if (null != token)            {                return new JsonResult(token);            }            else            {                return NotFound();            }        }    }}

客户端代代码是用RestSharp来实现,代码如下:

using RestSharp;using System;using System.Collections.Generic;using System.Diagnostics;using System.Linq;using System.Text;using System.Threading.Tasks; namespace WebApiAuthenticationClientTest{    class Program    {        static void Main(string[] args)        {                     dynamic token = null;            while (true)            {                Console.WriteLine("1、登录 2、查询数据 ");                var mark = Console.ReadLine();                var  stopwatch = new Stopwatch();                stopwatch.Start();                switch (mark)                {                    case "1":                        var loginClient = new RestClient("http://localhost:5000");                        var loginRequest = new RestRequest("/api/v1/account/login", Method.POST);                        loginRequest.AddParameter("username", "dsfsdf");                        loginRequest.AddParameter("password", "111111");                        //或用用户名密码查询对应角色                        loginRequest.AddParameter("role", "admin");                        IRestResponse loginResponse = loginClient.Execute(loginRequest);                        var loginContent = loginResponse.Content;                        Console.WriteLine(loginContent);                        token = Newtonsoft.Json.JsonConvert.DeserializeObject(loginContent);                        break;                    case "2":                        var client = new RestClient("http://localhost:5000");                        //这里要在获取的令牌字符串前加Bearer                        string tk = "Bearer " + Convert.ToString(token?.access_token);                        client.AddDefaultHeader("Authorization", tk);                        var request = new RestRequest("/api/v1/account/abc", Method.POST);                        IRestResponse response = client.Execute(request);                        var content = response.Content;                                      Console.WriteLine($"状态:{response.StatusCode}  返回结果:{content}");                        break;                            }                    stopwatch.Stop();                TimeSpan timespan = stopwatch.Elapsed;                Console.WriteLine($"间隔时间:{timespan.TotalSeconds}");            }        }    }}

运行服务端,再运行客户端,测试如下,没有登录前的查询返回状态是Unauthorized,登录后再查询的状态是OK