/// <summary>
/// Token实体
/// </summary>
public class TokenEntity
{
/// <summary>
/// token字符串
/// </summary>
public string access_token { get; set; }
/// <summary>
/// 过期时差
/// </summary>
public int expires_in { get; set; }
}
/// <summary>
/// token提供属性
/// </summary>
public class TokenProviderOptions
{
/// <summary>
/// 发行人
/// </summary>
public string Issuer { get; set; }
/// <summary>
/// 订阅者
/// </summary>
public string Audience { get; set; }
/// <summary>
/// 过期时间间隔
/// </summary>
public TimeSpan Expiration { get; set; } = TimeSpan.FromSeconds(30);
/// <summary>
/// 签名证书
/// </summary>
public SigningCredentials SigningCredentials { get; set; }
}
/// <summary>
/// Token提供类
/// </summary>
public class TokenProvider
{
readonly TokenProviderOptions _options;
public TokenProvider(TokenProviderOptions options)
{
_options = options;
}
/// <summary>
/// 生成令牌
/// </summary>
/// <param name="context">http上下文</param>
/// <param name="username">用户名</param>
/// <param name="password">密码</param>
/// <param name="role">角色</param>
/// <returns></returns>
public async Task<TokenEntity> 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);
}
/// <summary>
/// 查看令牌是否存在
/// </summary>
/// <param name="username">用户名</param>
/// <returns></returns>
private Task<ClaimsIdentity> 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();
}
/// <summary>
/// 登录action
/// </summary>
/// <param name="username">用户名</param>
/// <param name="password">密码</param>
/// <param name="role">角色</param>
/// <returns></returns>
[HttpPost]
[AllowAnonymous]
public async Task<IActionResult> 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}");
}
}
}
}