保护Web Api以使其被控制台应用程序使用

时间:2018-08-30 21:28:25

标签: oauth-2.0 access-token windows-authentication basic-authentication asp.net-core-webapi

我已经创建了一个Asp核心Web API,将由组织外部的C#控制台应用程序使用。该控制台应用程序计划定期运行。因此,在运行控制台应用程序时,Web api的点击率会很高。 请协助我如何保护我的Web Api免受恶意软件攻击或未经授权的访问。我无法使用AD身份验证,因为我无法在AAD(Azure活动目录)中注册客户端应用程序。

1 个答案:

答案 0 :(得分:1)

通常来说,有很多方法可以做到这一点。例如,使用基本方案身份验证,其中客户端使用base64-encoding发送username:password。但是。那不是那么安全。

我建议您使用JWT令牌。 Jwt方案的身份验证非常简单:

  1. 客户端发送请求,要求使用JWTclient_id的{​​{1}}令牌。 (您可以在服务器上的配置文件或数据库中配置它们)
  2. 如果client_keyclient_id匹配,则服务器会发送一个带有client_key访问令牌的响应,如果您愿意,可以添加一个刷新令牌;否则,发送带有JWT的响应。
  3. 客户端使用带有401标头的webapi。服务器将对Authorization: Bearer ${access_token}进行解密,并在有效时执行正确的操作。

以下是详细操作方法:

  1. 用于保存信息的虚拟类

为了表示控制台发送的access_tokenclient_id,我们创建一个虚拟Dto类:

client_key

在创建和验证Jwt令牌时,我们需要有关发行者,受众和秘密密钥的信息。为了保存这些信息,让我们创建另一个虚拟类:

public class AskForTokenRequest
{
    public string ClientId { get; set; }
    public string ClientKey { get; set; }
}
  1. 在继续之前,我们先创建一个public class SecurityInfo { public static readonly string Issuer = "xxx"; public static readonly string[] Audiences = new[] { "yyy" }; public static readonly string SecretKey = "!@#$%^&*()&!!!@#$%^&*()&!!!@#$%^&*()&!!!@#$%^&*()&!!!@#$%^&*()&!"; } 来生成令牌:

JwtTokenHelper有助于验证JwtTokenHelperclient_id并生成client_key令牌。

Jwt
  1. 配置服务器以启用JwtBearer身份验证:

public class JwtTokenHelper { //private AppDbContext _dbContext { get; set; } //public JwtTokenHelper(AppDbContext dbContext) { // this._dbContext = dbContext; //} public virtual bool ValidateClient(string clientId, string clientKey) { // check the client_id & clientKey with database , config file , or sth else if (clientId == "your_console_client_id" && clientKey == "your_console_client_key") return true; return false; } /// construct a token public virtual JwtSecurityToken GenerateToken(string clientId, DateTime expiry, string audience) { ClaimsIdentity identity = new ClaimsIdentity(new GenericIdentity(clientId, "jwt")); var token=new JwtSecurityToken ( claims: identity.Claims, issuer: SecurityInfo.Issuer, audience: audience, expires: expiry, notBefore: DateTime.UtcNow, signingCredentials: new SigningCredentials( new SymmetricSecurityKey(Encoding.UTF8.GetBytes(SecurityInfo.SecretKey)), SecurityAlgorithms.HmacSha256 ) ); return token; } public virtual string GenerateTokenString(string clientId, DateTime expiry,string audience) { // construct a jwt token var token = GenerateToken(clientId,expiry,audience); // convert the token to string JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler(); return tokenHandler.WriteToken(token); } } 添加到DI容器并添加JwtBearer身份验证方案

JwtTokenHelper

不要忘记在您的public void ConfigureServices(IServiceCollection services) { services.AddScoped<JwtTokenHelper>(); services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { options.RequireHttpsMetadata = false; options.SaveToken = true; options.TokenValidationParameters = new TokenValidationParameters { ValidIssuer = SecurityInfo.Issuer, ValidAudiences = SecurityInfo.Audiences, ValidateAudience = true, ValidateIssuer = true, ValidateIssuerSigningKey = true, IssuerSigningKeys = new List<SecurityKey> { new SymmetricSecurityKey(Encoding.UTF8.GetBytes(SecurityInfo.SecretKey) ) }, ValidateLifetime = true, ClockSkew = TimeSpan.FromMinutes(60) }; }); services.AddMvc(); } 方法中添加app.UseAuthentication();

  1. 使用方法:

现在,创建一个控制器以生成Jwt令牌

Configure()

并使用[Route("/api/token")] public class TokenController : Controller { private readonly JwtTokenHelper _tokenHelper; public TokenController(JwtTokenHelper tokenHelper) { this._tokenHelper = tokenHelper; } [HttpPost] public IActionResult Create([FromBody] AskForTokenRequest client) { if(! this._tokenHelper.ValidateClient(client.ClientId , client.ClientKey)) return new StatusCodeResult(401); DateTime expiry = DateTime.UtcNow.AddMinutes(60); // expires in 1 hour var audience = "yyy"; var access_token = this._tokenHelper.GenerateTokenString(client.ClientKey, expiry,audience); return new JsonResult(new { access_token = access_token, }); } } 属性保护您的webapi:

[Authorize]