Asp.Net Core混合使用cookie和JwtBearer认证方案

参照: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)]

上切换。

原文地址:https://www.cnblogs.com/ceci/p/11995489.html