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


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

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

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

    /// 
    /// 配置类(假定从配置或库取得的,这些信息多次使用)
    /// 
    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);
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    二、在 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;
    			}
    		};
    
    	});
    //...略
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57

    三、在某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
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76

    四、启动调试

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

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

  • 相关阅读:
    python+ipc+改造过的插线板写一个控制ipc疯狂上下电的脚本
    JavaEE-线程进阶
    Packet Tracer - 综合技能练习(通过调整 OSPF 计时器来修改 OSPFv2 配置)
    计算机视觉40例案例介绍
    笔记软件 Keep It mac v2.3.3中文版新增功能
    Javaweb之Axios的详细解析
    4G/5G频谱资源协同关键技术
    <Linux开发>驱动开发 -之-基于pinctrl/gpio子系统的beep驱动
    阿里P8架构师谈微服务架构:Dubbo+Docker+SpringBoot+Cloud
    微服务12:系统服务熔断、限流
  • 原文地址:https://blog.csdn.net/FlashElf/article/details/126485514