参照:https://www.cnblogs.com/sunnytrudeau/p/9693512.html
MVC部分的登录不赘述,主要是JwtBearer混合部分的问题。
- 创建JwtSettings类:
/// <summary>
/// JWT授权的配置项
/// </summary>
public class JwtSettings
{
public JwtSettings()
{
//CreateKey();
}
/// <summary>
/// 谁颁发的
/// </summary>
public string Issuer { get; set; }
/// <summary>
/// 颁发给谁
/// </summary>
public string Audience { get; set; }
/// <summary>
/// 令牌密码
/// </summary>
public string SecurityKey { get; set; }
public int ExpiresMinute { get; set; } = 1440; //默认一天
///对称秘钥
public SymmetricSecurityKey Key { get
{
return new SymmetricSecurityKey(Encoding.UTF8.GetBytes(SecurityKey));
}
}
///数字签名
public SigningCredentials Credentials { get
{
return new SigningCredentials(Key, SecurityAlgorithms.HmacSha256);
}
}
///修改密码,重新创建数字签名
public void SetSecurityKey(string value)
{
SecurityKey = value;
//CreateKey();
}
//private void CreateKey()
//{
// Key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(SecurityKey));
// Credentials = new SigningCredentials(Key, SecurityAlgorithms.HmacSha256);
//}
}
}
- appsettings.json中加入配置信息
"JwtSettings": {
"Issuer": "server",
"Audience": "client",
"ExpiresMinute": 10080, //超时分钟数,7天
"SecurityKey": "69f48e18-3409-40ce-b7a7-8c0362245cf8" //不少于16位长度
},
- 修改Startup.cs中认证内容
#region Authentication
var jwtSettings = Configuration.GetSection("JwtSettings").Get<JwtSettings>();
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, opts =>
{
opts.AccessDeniedPath = "/Account/Login";
opts.Cookie.HttpOnly = true;
opts.LoginPath = "/Account/Login";
opts.Cookie.Name = MyConsts.AuthCookieName;
})
.AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, opts =>
{
opts.RequireHttpsMetadata = false; //无需https
//x.SaveToken = true;
opts.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = jwtSettings.Key,
ValidateIssuer = true,
ValidIssuer = jwtSettings.Issuer,
ValidateAudience = true,
ValidAudience = jwtSettings.Audience,
ValidateLifetime = true,
ClockSkew = TimeSpan.FromMinutes(5)
};
});
#endregion
- APIController中增加一个Login方法的Controller,用于登录并返回token
[Route("api/[controller]")]
[ApiController]
public class AccountController : ControllerBase
{
....
/// <summary>
/// 登录方法,默认7天超时
/// </summary>
/// <param name="UserName">用户名</param>
/// <param name="Password">密码</param>
/// <returns></returns>
[HttpGet,HttpPost]
[Route("Login")]
public async Task<IActionResult> LoginAsync(string UserName, string Password)
{
.....
var claims = new Claim[]
{
new Claim(ClaimTypes.Sid, UserName),
new Claim(ClaimTypes.Name, UserName),
new Claim(ClaimTypes.Role, "user"),
new Claim("guid",user.Id.ToString()),
new Claim("avatar",""),
//new Claim("displayName",user.NameDisplay),
//new Claim("loginName",user.Account),
//new Claim("emailAddress",""),
//new Claim("userType",IsAdmin ? "1": "0")
};
var token = JwtBearerAuthenticationExtension.GetJwtAccessToken(claims);
rp.SetData(token);
return Ok(rp);
}
}
- 加入api的路由
#region 路由
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}")
.RequireAuthorization();
endpoints.MapControllerRoute(
name: "apiDefault",
pattern: "api/{controller=Home}/{action=Index}/{id?}");
});
#endregion
- 为ValuesController加入登录验证,并使用HttpContext获取当前登录用户
[Route("api/[controller]")]
[ApiController]
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
public class ValuesController : ControllerBase
{
/// <summary>
/// 获取所有values,GET api/values
/// </summary>
/// <returns></returns>
[HttpGet]
public ActionResult<IEnumerable<string>> Get()
{
var current = MyHttpContext.Current;
return new string[] { current.User.Identity.Name, current.User.Claims.Count().ToString() };
}
}
验证,以下是Swagger的截图,Postman等也一样:
- 未登录时:

- 登录获取Token

- 将该Token前面加Bearer作为传入Header中的Authorization中,

- 再次执行Values

调用成功。
总结:MVC的Controller使用
.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie块的逻辑,ApiController使用AddJwtBearer部分逻辑,具体可以在Controller的Attribute
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
上切换。