授权与认证

使用JWT进行授权验证的步骤

服务注册与参数配置

新建一个.Net6类库,在类库下新建Helper文件夹,并创建Appsetting类,该类用于帮助读取Appsetting.json中的系统配置参数

通过Nuget安装Microsoft.Extensions.Configuration;Microsoft.Extensions.Caching.Abstractions;Microsoft.Extensions.Configuration.Json;Microsoft.Extensions.Configuration.Binder并完成Appsettings类

 

    public class AppSettings
    {
        static IConfiguration Configuration { get; set; }
        static string ContentPath { get; set; }

        public AppSettings()
        {
            string path = "appsettings.json";
            Configuration = new ConfigurationBuilder().SetBasePath(ContentPath).Add(new JsonConfigurationSource { Path = path, Optional = false, ReloadOnChange = true }).Build();
        }
        public AppSettings(IConfiguration configuration)
        {
            Configuration = configuration;
        }
        public static string app(params string[] sections)
        {
            try
            {
                if (sections.Any())
                {
                    return Configuration[string.Join(":", sections)];
                }
            }
            catch (Exception ex)
            {

            }
            return "";
        }

        public static List<T>app<T>(params string[] sections)
        {
            List<T> list=new List<T>();
            Configuration.Bind(string.Join(":", sections), list);
            return list;
        }


    }

在Helper文件夹下继续新建JwtHelper类

    public class JWTHelper
    {
        public static string IssueJwt(TokenModelJwt tokenModel)
        {
            string iss = AppSettings.app(new string[] { "Audience", "Issuer" });
            string aud = AppSettings.app(new string[] { "Audience", "Audience" });
            string secret = AppSettings.app(new string[] { "Audience", "Secret" });
            var claims = new List<Claim> {
                new Claim(JwtRegisteredClaimNames.Jti,  tokenModel.Uid.ToString()),
                new Claim(JwtRegisteredClaimNames.Iat,$"{new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds()}"),
                new Claim(JwtRegisteredClaimNames.Nbf,$"{new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds()}"),
                new Claim(JwtRegisteredClaimNames.Exp,$"{new DateTimeOffset(DateTime.Now.AddSeconds(1000)).ToUnixTimeSeconds()}"),
                new Claim(ClaimTypes.Expiration,DateTime.Now.AddSeconds(1000).ToString()),
                new Claim(JwtRegisteredClaimNames.Iss,iss),
                new Claim(JwtRegisteredClaimNames.Aud,aud)
            };
            claims.AddRange(tokenModel.Role.Split(',').Select(s => new Claim(ClaimTypes.Role, s)));
            var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secret));
            var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

            var jwt = new JwtSecurityToken(issuer: iss, claims: claims, signingCredentials: creds);
            var jwtHandler = new JwtSecurityTokenHandler();
            var encodedJwt = jwtHandler.WriteToken(jwt);
            return encodedJwt;
        }

        public static TokenModelJwt SerializeJwt(string jwtStr)
        {
            var jwtHandler = new JwtSecurityTokenHandler();
            TokenModelJwt tokenModelJwt = new TokenModelJwt();
            if (!string.IsNullOrEmpty(jwtStr) && jwtHandler.CanReadToken(jwtStr))
            {
                JwtSecurityToken jwtToken = jwtHandler.ReadJwtToken(jwtStr);
                object role;
                jwtToken.Payload.TryGetValue(ClaimTypes.Role, out role);
                tokenModelJwt = new TokenModelJwt
                {
                    Uid = Convert.ToInt32(jwtToken.Id),
                    Role = role == null ? "" : role.ToString()
                };
            }
            return tokenModelJwt;
        }

    }

 设计登录接口 

    [ApiController]
    [Route("api/[controller]")]
    public class LoginController : Controller
    {
        [HttpGet]
        public async Task<object> GetJwtStr(string name, string pass)
        {
            TokenModelJwt tokenModelJwt = new TokenModelJwt { Uid = 1, Role = "Admin" };
            var jwtStr = JWTHelper.IssueJwt(tokenModelJwt);
            return Ok(new { success = true, token = jwtStr });
        }
    }
}

使用Swagger作为文档,已经实现了录入Token令牌的功能

在Nuget中搜索Swashbuckle.AspNetCore.Filters,在 ConfigureServices中的AddSwaggerGen服务中增加以下代码 

builder.Services.AddSwaggerGen(c =>
{
    c.OperationFilter<AddResponseHeadersFilter>();
    c.OperationFilter<AppendAuthorizeToSummaryOperationFilter>();
    c.OperationFilter<SecurityRequirementsOperationFilter>();
    c.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme
    {
        Description = "JWT授权",
        Name = "Authorization",
        In = ParameterLocation.Header,
        Type = SecuritySchemeType.ApiKey
    });
});

基于策略的授权机制

builder.Services.AddAuthorization(option =>
{
    option.AddPolicy("Client", policy => policy.RequireRole("Client").Build());
    option.AddPolicy("Admin", policy => policy.RequireRole("Admin").Build());
    option.AddPolicy("SystemOrAdmin", policy => policy.RequireRole("Admin", "System"));
    option.AddPolicy("SystemAndAdmin", policy => policy.RequireRole("Admin").RequireRole("System"));
});

  

直接在API上设置该接口所对应的角色权限信息

   [ApiController]
    [Route("[controller]")]
    [Authorize(Policy = "Admin")]
    public class WeatherForecastController : ControllerBase
    {
        private static readonly string[] Summaries = new[]
        {"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"};

        private readonly ILogger<WeatherForecastController> _logger;

        public WeatherForecastController(ILogger<WeatherForecastController> logger)
        {
            _logger = logger;
        }

        [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();
        }
    }

配置认证服务

只需要在configureService中添加“统一认证”即可

builder.Services.AddAuthentication(x =>
{
    x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(o =>
{
    var audienceConfig = builder.Configuration["Audience:Audience"];
    var symmetricKeyBase64 = builder.Configuration["Audience:Secret"];
    var iss = builder.Configuration["Audience:Issuer"];
    var keyByteArray = Encoding.ASCII.GetBytes(symmetricKeyBase64);
    var signingKey = new SymmetricSecurityKey(keyByteArray);
    o.TokenValidationParameters = new TokenValidationParameters
    {
        ValidateIssuerSigningKey = true,
        IssuerSigningKey = signingKey,
        ValidateIssuer = true,
        ValidIssuer = iss,
        ValidateAudience = true,
        ValidAudience = audienceConfig,
        ValidateLifetime = true,
        ClockSkew = TimeSpan.Zero,
        RequireExpirationTime = true
    };
});

配置官方认证中间件

app.UseAuthentication()

posted on 2022-02-27 14:52  血气方刚  阅读(69)  评论(0编辑  收藏  举报

导航