.net Core .net6 Cookie加Jwt认证 同时生效

本文环境 Visual Studio 2022, .Net6
关于Cookie认证见,上篇 http://t.csdn.cn/ebmkT本文是接着添加Jwt认证的。流程简单代码不多。

一、确定Jwt令牌秘钥等基础信息

本案放到一个公用的类里面

/// <summary>
/// 配置类(假定从配置或库取得的,这些信息多次使用)
/// </summary>
public class JwtConfig
{
    //谁颁发的(本案没用)
    public static string Issuer { get; set; } = "serverIssuer";

    //颁发给谁(本案没用)
    public static string Audience { get; set; } = "clientAudience";

    //令牌密码 AddJwtBearer 时用
    private static string sKey = "ACB83f96a142409e";
    //对称秘钥
    public static SymmetricSecurityKey SigningKey { get; private set; } = new SymmetricSecurityKey(
        Encoding.UTF8.GetBytes(sKey)
        );
	//生成 Token 串用
	public static SigningCredentials Credentials { get; set; } =  new SigningCredentials(SigningKey, SecurityAlgorithms.HmacSha256);

}

二、在 Program.cs 添加Cookie、Jwt认证

这里只有Jwt补充的部分,其余见
上篇Cookie认证 http://t.csdn.cn/ebmkT

//...略
builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
	.AddCookie(option => option.LoginPath = "/Home/Login")
	//1)添加Jwt
	.AddJwtBearer(options =>
	{
		options.TokenValidationParameters = new TokenValidationParameters
		{
			
			ValidateIssuerSigningKey = true, //是否验证秘钥
			IssuerSigningKey = JwtConfig.SigningKey, //秘钥
			ValidateIssuer = false,	 //是否验证必须有颁发人,默认是True	
			ValidateAudience = false,   //是否验证必须有颁发给谁	,默认是True	
			ValidateLifetime = false, //是否验证必须有生效时间,默认是True
			RequireExpirationTime=false, //是否验证必须有过期时间,默认是True
			ClockSkew = TimeSpan.Zero //时间偏差

		};
		
		
		options.Events = new JwtBearerEvents()
		{
			//如下3个事件,如果要拦截或改写一些事儿比较有用
			//首次收到协议消息时调用
			OnMessageReceived = context => {

				var url = context.Request.Path.Value;
				appRef?.Logger.LogInformation($"OnMessageReceived Request.Path {url}");

				var token = context.Request.Headers["Authorization"];
				appRef?.Logger.LogInformation($"OnMessageReceived Token {token}");								

				return Task.CompletedTask;
				
			},
			//安全令牌已通过验证并生成 ClaimsIdentity 后调用
			OnTokenValidated = context =>
			{
				var url = context.Request.Path.Value;
				appRef?.Logger.LogInformation($"OnTokenValidated Request.Path {url}");
				var cm = context.Principal?.Identities; //下断点,这会看见 Jwt的身份
				return Task.CompletedTask;

			},
			//身份验证失败
			OnAuthenticationFailed = context =>
			{
				var url = context.Request.Path.Value;
				appRef?.Logger.LogInformation($"OnAuthenticationFailed Request.Path {url}");
				var ex = context.Exception;
				appRef?.Logger.LogInformation($"OnAuthenticationFailed Exception {ex}");				
				return Task.CompletedTask;
			}
		};

	});
//...略

三、在某Controller添加Jwt登录、测试登录等

为方便就找个微软 Api Controller 例子添加代码。

代码按 1)、2)…n)这样的顺序看。

[ApiController]
[Route("api/[controller]")]
[Authorize(AuthenticationSchemes = AuthSchemes)] //启用认证
public class WeatherForecastController : ControllerBase, IActionFilter //IActionFilter 为了调试输出
{
	//1)是这个串是 "Bearer,Cookies" 支持这两种
	private const string AuthSchemes 
		= JwtBearerDefaults.AuthenticationScheme
			+ "," + CookieAuthenticationDefaults.AuthenticationScheme;
	
	private readonly ILogger<WeatherForecastController> _logger; //调试输出用
	public WeatherForecastController(ILogger<WeatherForecastController> logger)
	{
		_logger = logger;
	}
	
	[AllowAnonymous]
	[HttpGet("JwtLogin")]
	public IActionResult JwtLogin(string name, string psw)
	{
		string rtn = string.Empty;
		if (!string.IsNullOrEmpty(name) && !string.IsNullOrEmpty(psw)) //假定认证了
		{
			//2)登录并返回token串,本例是最小化的token,只有一个登陆名(起码能知道是谁)。
			//因为 AddJwtBearer 时关闭了大多数内容,如需要什么根据需求可自行增加
			//附加的信息越多token也越长
			var claims = new Claim[]
			{
				new Claim(ClaimTypes.Name, name),
			};
			var token = new JwtSecurityToken(
				claims: claims
				, signingCredentials: JwtConfig.Credentials //加密用参数
			);
			rtn = new JwtSecurityTokenHandler().WriteToken(token);
		}
		return Ok(rtn);
	}

	void IActionFilter.OnActionExecuting(ActionExecutingContext context)
	{
		var cad = (ControllerActionDescriptor)context.ActionDescriptor;
		//3)输出调试信息
		_logger.LogInformation($"{cad.ActionName}"
	+ $" 用户登录状态 {User.Identity?.IsAuthenticated}"
	+ $" 登录名 {User.Identity?.Name}"
	+ $" 认证类型 {User.Identity?.AuthenticationType}"
	+ $" 身份数量 {User.Identities.Count()}"
	+ $" 所有身份 {string.Join(" -- ", User.Identities.Select(a => a.Name).ToArray())}" //调试看多个身份的 Name
	);

	}

	void IActionFilter.OnActionExecuted(ActionExecutedContext context)
	{
		//...本案没用
	}

	//4)微软的天气预报例子测试用
	private static readonly string[] Summaries = new[]{
		"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
	};
	[HttpGet(Name = "GetWeatherForecast")]
	public IEnumerable<WeatherForecast> Get()
	{
			
		return Enumerable.Range(1, 5).Select(index => new WeatherForecast
		{
			Date = DateTime.Now.AddDays(index),
			TemperatureC = Random.Shared.Next(-20, 55),
			Summary = Summaries[Random.Shared.Next(Summaries.Length)]
		})
		.ToArray();
	}		

}

四、启动调试

1)登录
在这里插入图片描述
2)用 Swagger 调用 JwtLogin 返回 Token 并复制串
在这里插入图片描述
3)把刚才复制的 Token 前面加 Bearer 粘贴到Swagger的认证窗口里面(锁头按钮)
在这里插入图片描述
4)调用函数测试

可以看见,传递了 Token返回值正常
在这里插入图片描述
5)调试信息,Cookie、Jwt都生效了
在这里插入图片描述

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值