生成Jwt Token
AuthController
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.IdentityModel.Tokens;
using WebAPI.Models;
namespace WebAPI.Controllers
{
[Produces("application/json")]
[Route("api/v1/[controller]")]
public class AuthController : Controller
{
private readonly IConfiguration _configuration;
public AuthController(IConfiguration configuration)
{
_configuration = configuration;
}
/// <summary>
/// login
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
[AllowAnonymous]
[HttpPost]
public IActionResult RequestToken([FromBody] TokenRequest request)
{
string username = request.Username;
string password = request.Password;
if (AuthenticationMiddleware.ValidateDomainUser(username, password))
{
// push the user’s name into a claim, so we can identify the user later on.
var claims = new[]
{
new Claim(ClaimTypes.Name, request.Username)
};
//sign the token using a secret key.This secret will be shared between your API and anything that needs to check that the token is legit.
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["SecurityKey"]));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
//.NET Core’s JwtSecurityToken class takes on the heavy lifting and actually creates the token.
/**
* Claims (Payload)
Claims 部分包含了一些跟这个 token 有关的重要信息。 JWT 标准规定了一些字段,下面节选一些字段:
iss: The issuer of the token,token 是给谁的
sub: The subject of the token,token 主题
exp: Expiration Time。 token 过期时间,Unix 时间戳格式
iat: Issued At。 token 创建时间, Unix 时间戳格式
jti: JWT ID。针对当前 token 的唯一标识
除了规定的字段外,可以包含其他任何 JSON 兼容的字段。
* */
var token = new JwtSecurityToken(
issuer: "yourdomain.com",
audience: "yourdomain.com",
claims: claims,
expires: DateTime.Now.AddMinutes(30),
signingCredentials: creds);
var accessToken = new JwtSecurityTokenHandler().WriteToken(token);
var response = new {
username = username,
access_token = accessToken,
expires_in = 1800
};
return Ok(response);
//return Ok(new
//{
// token = new JwtSecurityTokenHandler().WriteToken(token)
//});
}
else
{
return BadRequest("Could not verify username and password");
}
}
}
public class TokenRequest
{
public string Username { get; set; }
public string Password { get; set; }
}
}
在appsettings.json中添加
"SecurityKey": "234d#;pvsfa88*sdfaf377f6d&f£$$£$sfxvgdf%"
使用jwt验证
在Startup.cs中
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Tokens;
using System.Text;
namespace WebAPI
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
//添加jwt验证:
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options=> {
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,//是否验证Issuer
ValidateAudience = true,//是否验证Audience
ValidateLifetime = true,//是否验证失效时间
ValidateIssuerSigningKey = true,//是否验证SecurityKey
ValidAudience = "yourdomain.com",//Audience
ValidIssuer = "yourdomain.com",//Issuer,这两项和前面签发jwt的设置一致
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["SecurityKey"]))//拿到SecurityKey
};
});
services.AddMvc();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseAuthentication();//注意添加这一句,启用验证
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseMvc();
}
}
}
如果你的前后端涉及到跨域,还需在Startup.cs中加上
public void ConfigureServices(IServiceCollection services){
//其他
services.AddCors(options =>
{
options.AddPolicy("cors", builder =>
{
//builder.WithOrigins("http://a.example.com", "http://c.example.com")
builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials();
});
});
//"http://a.example.com", "http://c.example.com" 代表着允许访问的域,就好像给这个域开放了一个权限,允许访问的权限,可以写多个逗号分隔
//AllowAnyMethod允许跨域策略允许所有的方法:GET/POST/PUT/DELETE 等方法 如果进行限制需要 AllowAnyMethod("GET","POST") 这样来进行访问方法的限制
//AllowAnyHeader允许任何的Header头部标题 有关头部标题如果不设置就不会进行限制
//AllowAnyOrigin 允许任何来源
//AllowCredentials 设置凭据来源
services.AddMvc();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env){
app.UseAuthentication();
app.UseCors("cors"); // 加上这一句
app.UseMvc();
}
设置超时时间
在appsettins.json中添加
"Expire_in": 10
AuthController中添加
int expires_in = int.Parse(_configuration["Expire_in"]);
完整AuthController代码
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Text;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.IdentityModel.Tokens;
using WebAPI.Data;
using WebAPI.Models;
namespace WebAPI.Controllers
{
[Produces("application/json")]
[Route("api/v1/[controller]")]
public class AuthController : Controller
{
private readonly IConfiguration _configuration;
private readonly UserTokenContext _context;
public AuthController(IConfiguration configuration, UserTokenContext context)
{
_configuration = configuration;
_context = context;
}
//public UserController(UserToken context)
//{
// _context = context;
//}
/// <summary>
/// login
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
[AllowAnonymous]
[HttpPost]
public IActionResult RequestToken([FromBody] TokenRequest request)
{
string username = request.Username;
string password = request.Password;
//这里主要是用来验证用户名密码合不合法的,不重要,主要看下面if里面的就行
if (AuthenticationMiddleware.ValidateDomainUser(username, password))
{
// push the user’s name into a claim, so we can identify the user later on.
var claims = new[]
{
new Claim(ClaimTypes.Name, request.Username)
};
//sign the token using a secret key.This secret will be shared between your API and anything that needs to check that the token is legit.
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["SecurityKey"]));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
//.NET Core’s JwtSecurityToken class takes on the heavy lifting and actually creates the token.
/**
* Claims (Payload)
Claims 部分包含了一些跟这个 token 有关的重要信息。 JWT 标准规定了一些字段,下面节选一些字段:
iss: The issuer of the token,token 是给谁的
sub: The subject of the token,token 主题
exp: Expiration Time。 token 过期时间,Unix 时间戳格式
iat: Issued At。 token 创建时间, Unix 时间戳格式
jti: JWT ID。针对当前 token 的唯一标识
除了规定的字段外,可以包含其他任何 JSON 兼容的字段。
* */
int expires_in = int.Parse(_configuration["Expire_in"]);
var token = new JwtSecurityToken(
issuer: "yourdomain.com",
audience: "yourdomain.com",
claims: claims,
expires: DateTime.Now.AddMinutes(expires_in),
signingCredentials: creds);
var accessToken = new JwtSecurityTokenHandler().WriteToken(token);
UserToken userToken = new UserToken();
//var user = _context.User
//.FirstOrDefault(m => m.UserName == username);
//userToken.Id = Guid.NewGuid();
//userToken.UserId = user.UserId;
//userToken.Token = accessToken;
//userToken.LoginTime = DateTime.Now;
//_context.UserToken.Add(userToken);
//_context.SaveChanges();
var response = new {
username,
access_token = accessToken,
expires_in = expires_in
};
return Ok(response);
}
else
{
return BadRequest("Could not verify username or password");
}
}
[HttpGet("checklogin")]
[Authorize]
public IActionResult CheckLogin() {
return Ok();
}
[HttpGet("logout")]
[Authorize]
public IActionResult Logout()
{
return Ok();
}
}
public class TokenRequest
{
public string Username { get; set; }
public string Password { get; set; }
}
}
测试
Postman
http://localhost:3019/api/v1/auth Post请求
请求体,放在Postman的Body中
{
"username":"shajia_shan",
"password":"123456"
}
看一下接口拦截
先写一个UserController
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
namespace WebAPI.Controllers
{
[Route("api/v1/[controller]")]
[ApiController]
public class UserController : ControllerBase
{
// GET api/values
[HttpGet]
[Authorize]//添加Authorize标签,可以加在方法上,也可以加在类上
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
// GET api/values/5
[HttpGet("{id}")]
public string Get(int id)
{
return "value";
}
}
}
打开Postman
http://localhost:3019/api/v1/user Get请求
Authorization选择Bearer Token,填入刚刚登录接口返回的access_token
返回200表示认证成功, 如果token超时或者没有填,接口返回401。