将jwt添加到具有基本身份验证的webapi.net中



我创建了一个带有内置身份验证的web api项目(创建它时,我选中了"带有身份验证"框(,现在我想让它更安全。有没有一种方法可以将jwt身份验证与项目创建的现有身份验证集成在一起?我在Startup.cs:的ConfigureServices方法中添加了这一点

services.AddAuthentication()
.AddIdentityServerJwt();

我是asp.net和jwt的新手,我发现很难理解这些过程。

定义如下的多重身份验证方法:

builder.Services.AddAuthentication(opt =>
{
//default config
opt.DefaultScheme = "UNKNOWN";
opt.DefaultChallengeScheme = "UNKNOWN";
})
.AddJwtBearer("keycloak", options =>
{
// first auth method (validate keycloak token with publicKey)
options.RequireHttpsMetadata = false;
var publicKey = new ReadOnlySpan<byte>(Convert.FromBase64String(builder.Configuration["KeycloakJwtAuth:key"]));
var rsa = RSA.Create();
int readByte = 0;
rsa.ImportSubjectPublicKeyInfo(publicKey, out readByte);
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = builder.Configuration["KeycloakJwtAuth:Issuer"],
ValidAudience = builder.Configuration["KeycloakJwtAuth:Audience"],
ValidAlgorithms = new List<string>() { "RS256" },
AuthenticationType = "JWT",
IssuerSigningKey = new RsaSecurityKey(rsa)
};
options.Events = new JwtBearerEvents()
{
OnMessageReceived = context =>
{
var Token = context.Request.Headers["Authorization"].ToString();
context.Token = Token;
return Task.CompletedTask;
},
OnAuthenticationFailed = context =>
{
return Task.CompletedTask;
},
OnChallenge = context =>
{
return Task.CompletedTask;
},
OnTokenValidated = context =>
{
return Task.CompletedTask;
}
};
options.Validate();
})
.AddJwtBearer("pas", options =>
{
//secound auth method (validate jwt token with securityKey ) 
options.RequireHttpsMetadata = false;
var securityKey = new SymmetricSecurityKey(System.Text.Encoding.Default.GetBytes(builder.Configuration["PasJwtAuth:key"]));
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
// ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = builder.Configuration["PasJwtAuth:Issuer"],
ValidAudience = builder.Configuration["PasJwtAuth:Audience"],
AuthenticationType = "JWT",
IssuerSigningKey = securityKey,
};
options.Events = new JwtBearerEvents()
{
OnMessageReceived = context =>
{
var Token = context.Request.Headers["Authorization"].ToString();
context.Token = Token;
return Task.CompletedTask;
},
OnAuthenticationFailed = context =>
{
return Task.CompletedTask;
},
OnChallenge = context =>
{
return Task.CompletedTask;
},
OnTokenValidated = context =>
{
return Task.CompletedTask;
}
};
options.Validate();
})
.AddScheme<AuthenticationSchemeOptions, BasicAuthenticationHandler>("basic",null)//therd auth method (validate basic auth)

然后定义authSelector,如下所示:

.AddPolicyScheme("UNKNOWN", "UNKNOWN", options =>
{
options.ForwardDefaultSelector = context =>
{
string authorization = context.Request.Headers[HeaderNames.Authorization];
{

var jwtHandler = new JwtSecurityTokenHandler();
if (jwtHandler.CanReadToken(authorization))
{
var issuer = jwtHandler.ReadJwtToken(authorization).Issuer;
if (issuer == builder.Configuration["PasJwtAuth:Issuer"]) 
{
return "pas";
}
else if (issuer == builder.Configuration["KeycloakJwtAuth:Issuer"]) 
{
return "keycloak";
}
}
}
return "basic";
};
});

如果你需要授权,你可能会使用这样的东西:

builder.Services.AddAuthorization(opt =>
{
var policy = opt.DefaultPolicy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.AddAuthenticationSchemes("keycloak", "pas", "basic")
.Build();
opt.AddPolicy("user", policy);
opt.AddPolicy("backoffice", policy => policy.RequireRole("backoffice"));
});

如果您需要了解BasicAuthenticationHandler的实现,请阅读本文

要配置Swagger UI,请按照以下方式操作:

builder.Services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo() { Version = "V1", Title = "Sepehr Customer Club" });
c.AddSecurityDefinition("basic", new OpenApiSecurityScheme
{
Description = "Basic auth added to authorization header",
Name = "Authorization",
In = ParameterLocation.Header,
Scheme = "basic",
Type = SecuritySchemeType.Http
});
c.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "basic" }
},
new string[] { }
}
});
c.AddSecurityDefinition("pas", new OpenApiSecurityScheme
{
Description = "Please insert JWT with pas Bearer into field",
Name = "Authorization",
In = ParameterLocation.Header,
Scheme = "pas",
Type = SecuritySchemeType.ApiKey,
BearerFormat = "JWT"
});
c.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference{Type = ReferenceType.SecurityScheme, Id = "pas"}
},
new string[] { }
}
});
c.AddSecurityDefinition("keycloak", new OpenApiSecurityScheme
{
Description = "Please insert JWT with keycloak Bearer into field",
Name = "Authorization",
In = ParameterLocation.Header,
Scheme = "keycloak",
Type = SecuritySchemeType.ApiKey,
BearerFormat = "JWT"
});
c.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference{Type = ReferenceType.SecurityScheme, Id = "keycloak"}
},
new string[] { }
}
});
});

最新更新