OpenIddict身份验证与授权之: 二. 2(密码模式)资源服务器
密码模式(最简化示例)
为了简化步骤便于理解, 在密码模式下,我只生成两个项目,一个是验证服务器,一个是资源服务器,客户端用postman或者自带的swagger, 详情请看系列文章,此文章为密码模式中的资源服务器篇
一. Nuget
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.31" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.6.2" />
</ItemGroup>
二. 配置
1.授权
1.1 未加密Jwt
builder.Services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.Authority = "https://localhost:7097/";
options.Audience = "resource_api_1";
options.RequireHttpsMetadata = false; // 仅限开发环境
});
1.2 加密Jwt
builder.Services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
// 配置解密密钥
TokenDecryptionKey = new X509SecurityKey(new X509Certificate2(
builder.Configuration.GetValue<string>("Certificate:Path"),
builder.Configuration.GetValue<string>("Certificate:PassWord"))
),
// 配置证书的公钥
IssuerSigningKey = new X509SecurityKey(new X509Certificate2(
builder.Configuration.GetValue<string>("Certificate:Path"),
builder.Configuration.GetValue<string>("Certificate:PassWord"))
),
// 验证令牌发行者
ValidateIssuer = true,
ValidIssuer = "https://localhost:7097/",
// 验证令牌受众
ValidateAudience = true,
ValidAudience = "resource_api_1",
// 验证令牌签名
ValidateIssuerSigningKey = true,
// 验证令牌有效期
ValidateLifetime = true,
// 如果需要时钟偏差,可以设置ClockSkew
// ClockSkew = TimeSpan.FromMinutes(5)
};
// 是否要求HTTPS
options.RequireHttpsMetadata = false; // 仅限开发环境
});
2.身份验证(根据自己的控制器中的角色来添加)
builder.Services.AddAuthorization(options =>
{
options.AddPolicy("Admin", policy =>
{
policy.RequireRole("Admin");
});
options.AddPolicy("User", policy =>
{
policy.RequireRole("User");
});
});
3.路由相关
app.UseSwagger();
app.UseSwaggerUI();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
三. 控制器
以下是示例,示例四种情况
[ApiController]
[Route("[controller]")]
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("GetWeatherForecastV1")]
public IEnumerable<WeatherForecast> GetV1()
{
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();
}
//通用授权
[Authorize]
[HttpGet("GetWeatherForecastV2")]
public IEnumerable<WeatherForecast> GetV2()
{
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();
}
//特定角色授权
[Authorize("Admin")]
[HttpGet("GetWeatherForecastV3")]
public IEnumerable<WeatherForecast> GetV3()
{
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();
}
//特定角色授权
[Authorize("User")]
[HttpGet("GetWeatherForecastV4")]
public IEnumerable<WeatherForecast> GetV4()
{
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();
}
}
appsettings
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
},
},
"Certificate": {
"Path": "Certificate/SelfSignedCertificate.pfx",
"PassWord": "12345678"
},
"AllowedHosts": "*"
}