授权与认证
使用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()
浙公网安备 33010602011771号