.Net Core WebApi 使用 JWT 验证身份

一、注册身份验证服务

  StartUp.ConfigureServices()

    //策略授权
    services.AddAuthorization(options =>
    {
        options.AddPolicy("Admin", po => po.RequireRole("Admin"));
        options.AddPolicy("Client", policy => policy.RequireRole("Client"));
        options.AddPolicy("Systems", policy => policy.RequireRole("Admin", "System", "Client"));
    });

    //JWT 身份验证
    services.AddAuthentication(options =>
    {
        options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
        options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
    }).AddJwtBearer(options =>
    {
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuerSigningKey = true,
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(setting.SecretKey)),
            ValidateAudience = true,
            ValidAudience = setting.Audience,
            ValidateIssuer = true,
            ValidIssuer = setting.Issuer,
            ClockSkew = TimeSpan.Zero,
            ValidateLifetime = true,
            RequireExpirationTime = true
        };
        options.Events = new JwtBearerEvents
        {
            OnChallenge = context =>
            {
                //跳过所有默认的逻辑
                context.HandleResponse();
                var result = new
                {
                    status = 401,
                    msg = "无效的Token",
                    err = "无效的Token"
                };
                context.Response.StatusCode = StatusCodes.Status401Unauthorized;
                context.Response.ContentType = "application/json";
                context.Response.WriteAsync(JsonConvert.SerializeObject(result)); 
                return Task.CompletedTask;
            }
        };
    });

二、添加认证中间件(官方定义)

  StartUp.Configure() 

//这里注意 一定要在 UseMvc前面,顺序不可改变
app.UseAuthentication(); 
app.UseMvc();

三、设置Controller访问权限

  将需要身份验证才可访问的 API 增加验证 [Authorize] ,如果允许匿名访问 ,添加 [AllowAnonymous]

    [Route("api/[controller]")]
    //[ApiExplorerSettings(IgnoreApi = true)]//awagger忽略当前Api
    //[Authorize(Roles = "Admin")] //只允许 用户 Role 是 Admin 可以访问
    //[Authorize] //任何登陆的用户都可以访问
    [Authorize(Policy = "Admin")] //对应 services.AddAuthorization 定义的策略名 
    public class EmployeeController1 : Controller
    {
        /// <summary>
        /// 获取所有员工
        /// </summary>
        /// <returns></returns> 
        [HttpGet]
        public async Task<ResultData<IList<Employee>>> Get()
        {
            var data = await Task.Run(() => GetSourceEmployees());
var result = new ResultData<IList<Employee>> { Code = (int)ResultCodeEnum.SUCCESS, Msg = "成功", Data = data }; return result; } /// <summary> /// 根据Id 获取员工 /// </summary> /// <param name="id"></param> /// <returns></returns> [HttpGet("{id}")] [AllowAnonymous] //允许匿名访问 public async Task<ResultData<Employee>> Get(int id) { var result = new ResultData<Employee> { Code = (int)ResultCodeEnum.SUCCESS, Msg = "成功", }; var employees = await Task.Run(() => GetSourceEmployees()); var data = employees.FirstOrDefault(l => l.Id == id); if (data != null) { result.Code = (int)ResultCodeEnum.DATA_NULL; result.Msg = "找不到所需数据"; } else { result.Code = (int)ResultCodeEnum.SUCCESS; result.Msg = "成功"; result.Data = data; } return result; } [NonAction] private IList<Employee> GetSourceEmployees() { IList<Employee> employees = new List<Employee>(); employees.Add(new Employee { Address = "北京市朝阳公园", Gender = 1, Id = 1, Mobile = "16578976589", Name = "张三" }); employees.Add(new Employee { Address = "批量添加", Gender = 2, Id = 2, Mobile = "16897623407", Name = "测试员工-001" }); return employees; } }

四、创建Token

    [Route("api/[controller]")]
    [ApiController]
    public class TokenController : ControllerBase
    {
        JwtSettings setting;//Token 配置信息
        IMerchantRepository _merchantRepository;

        //IOptions<JwtSettings> 是在 appsetting.json 的配置项
        //需要提前在 StartUp.ConfigureServices注册 
        public TokenController(IOptions<JwtSettings> jwtSettings, IMerchantRepository merchantRepository)
        {
            setting = jwtSettings.Value;
            _merchantRepository = merchantRepository;
        }

        [HttpGet]
        public async Task<IActionResult> Get(string appid, string appsecret)
        {
            try
            {
                var merchants = await _merchantRepository.LoadAll();
                var merchant = merchants.FirstOrDefault(l => l.AppId == appid && l.AppSecret == appsecret);
                if (merchant == null)
                {
                    return new JsonResult(new
                    {
                        status = 400,
                        msg = "无效的用户",
                        token = string.Empty
                    }); ;
                }

                var claims = new List<Claim>();
                claims.Add(new Claim(ClaimTypes.Name, merchant.Name));
                var roles = merchant.Roles.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                for (int i = 0; i < roles.Length; i++)
                {
                    //添加用户的角色
                    claims.Add(new Claim(ClaimTypes.Role, roles[i]));
                }

                //SecretKey 必须>= 16位
                var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(setting.SecretKey));
                var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
                //设置 token 生成元素
                var token = new JwtSecurityToken(
                    issuer: setting.Issuer,
                    audience: setting.Audience,
                    claims: claims,
                    notBefore: DateTime.Now,
                    expires: DateTime.Now.AddSeconds(100),
                    signingCredentials: creds);
                var result = new JwtSecurityTokenHandler().WriteToken(token);
                return new JsonResult(new
                {
                    status = 200,
                    msg = "成功",
                    token = result
                });
            }
            catch (Exception ex)
            {
                return new JsonResult(new
                {
                    status = 500,
                    msg = "服务器开小差了",
                    err = ex.Message
                });
            }
        }
    }

五、测试

  1、直接访问 /api/values,出现以下提示

  2、访问 /api/values/1 可正常访问

  3、请求 /api/token,然后添加到 /api/values 的 Headers 再次访问

 

原文地址:https://www.cnblogs.com/Zing/p/13339039.html