我已经实施了 BasicAuthenticationHandler 用于基本身份验证,因此您可以将其与标准属性一起使用 Authorize 和 AllowAnonymous 。
BasicAuthenticationHandler
Authorize
AllowAnonymous
public class BasicAuthenticationHandler : AuthenticationHandler<BasicAuthenticationOptions> { protected override Task<AuthenticateResult> HandleAuthenticateAsync() { var authHeader = (string)this.Request.Headers["Authorization"]; if (!string.IsNullOrEmpty(authHeader) && authHeader.StartsWith("basic", StringComparison.OrdinalIgnoreCase)) { //Extract credentials string encodedUsernamePassword = authHeader.Substring("Basic ".Length).Trim(); Encoding encoding = Encoding.GetEncoding("iso-8859-1"); string usernamePassword = encoding.GetString(Convert.FromBase64String(encodedUsernamePassword)); int seperatorIndex = usernamePassword.IndexOf(':'); var username = usernamePassword.Substring(0, seperatorIndex); var password = usernamePassword.Substring(seperatorIndex + 1); //you also can use this.Context.Authentication here if (username == "test" && password == "test") { var user = new GenericPrincipal(new GenericIdentity("User"), null); var ticket = new AuthenticationTicket(user, new AuthenticationProperties(), Options.AuthenticationScheme); return Task.FromResult(AuthenticateResult.Success(ticket)); } else { return Task.FromResult(AuthenticateResult.Fail("No valid user.")); } } this.Response.Headers["WWW-Authenticate"]= "Basic realm=\"yourawesomesite.net\""; return Task.FromResult(AuthenticateResult.Fail("No credentials.")); } } public class BasicAuthenticationMiddleware : AuthenticationMiddleware<BasicAuthenticationOptions> { public BasicAuthenticationMiddleware( RequestDelegate next, IOptions<BasicAuthenticationOptions> options, ILoggerFactory loggerFactory, UrlEncoder encoder) : base(next, options, loggerFactory, encoder) { } protected override AuthenticationHandler<BasicAuthenticationOptions> CreateHandler() { return new BasicAuthenticationHandler(); } } public class BasicAuthenticationOptions : AuthenticationOptions { public BasicAuthenticationOptions() { AuthenticationScheme = "Basic"; AutomaticAuthenticate = true; } }
在Startup.cs注册 - app.UseMiddleware<BasicAuthenticationMiddleware>(); 。使用此代码,您可以使用标准属性Autorize限制任何控制器:
app.UseMiddleware<BasicAuthenticationMiddleware>();
[Authorize(ActiveAuthenticationSchemes = "Basic")] [Route("api/[controller]")] public class ValuesController : Controller
并使用属性 AllowAnonymous 如果您在应用程序级别应用授权筛选器。
我想你可以和JWT(Json Web Tokens)一起去。
首先,您需要安装包System.IdentityModel.Tokens.Jwt:
$ dotnet add package System.IdentityModel.Tokens.Jwt
您需要添加一个用于令牌生成和身份验证的控制器,如下所示:
public class TokenController : Controller { [Route("/token")] [HttpPost] public IActionResult Create(string username, string password) { if (IsValidUserAndPasswordCombination(username, password)) return new ObjectResult(GenerateToken(username)); return BadRequest(); } private bool IsValidUserAndPasswordCombination(string username, string password) { return !string.IsNullOrEmpty(username) && username == password; } private string GenerateToken(string username) { var claims = new Claim[] { new Claim(ClaimTypes.Name, username), new Claim(JwtRegisteredClaimNames.Nbf, new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds().ToString()), new Claim(JwtRegisteredClaimNames.Exp, new DateTimeOffset(DateTime.Now.AddDays(1)).ToUnixTimeSeconds().ToString()), }; var token = new JwtSecurityToken( new JwtHeader(new SigningCredentials( new SymmetricSecurityKey(Encoding.UTF8.GetBytes("Secret Key You Devise")), SecurityAlgorithms.HmacSha256)), new JwtPayload(claims)); return new JwtSecurityTokenHandler().WriteToken(token); } }
之后更新Startup.cs类如下所示:
namespace WebAPISecurity { public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddMvc(); services.AddAuthentication(options => { options.DefaultAuthenticateScheme = "JwtBearer"; options.DefaultChallengeScheme = "JwtBearer"; }) .AddJwtBearer("JwtBearer", jwtBearerOptions => { jwtBearerOptions.TokenValidationParameters = new TokenValidationParameters { ValidateIssuerSigningKey = true, IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("Secret Key You Devise")), ValidateIssuer = false, //ValidIssuer = "The name of the issuer", ValidateAudience = false, //ValidAudience = "The name of the audience", ValidateLifetime = true, //validate the expiration and not before values in the token ClockSkew = TimeSpan.FromMinutes(5) //5 minute tolerance for the expiration date }; }); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseAuthentication(); app.UseMvc(); } }
就是这样,现在剩下的就是放 [Authorize] 您想要的控制器或操作的属性。
[Authorize]
这是一个完整的直接教程的链接。
http://www.blinkingcaret.com/2017/09/06/secure-web-api-in-asp-net-core/
要仅将其用于特定控制器,请使用以下命令:
app.UseWhen(x => (x.Request.Path.StartsWithSegments("/api", StringComparison.OrdinalIgnoreCase)), builder => { builder.UseMiddleware<AuthenticationMiddleware>(); });
现在,在我指出正确的方向后,这是我的完整解决方案:
这是在每个传入请求上执行的中间件类,并检查请求是否具有正确的凭据。如果没有凭据或者它们是错误的,则服务响应a 401未经授权 立即出错。
public class AuthenticationMiddleware { private readonly RequestDelegate _next; public AuthenticationMiddleware(RequestDelegate next) { _next = next; } public async Task Invoke(HttpContext context) { string authHeader = context.Request.Headers["Authorization"]; if (authHeader != null && authHeader.StartsWith("Basic")) { //Extract credentials string encodedUsernamePassword = authHeader.Substring("Basic ".Length).Trim(); Encoding encoding = Encoding.GetEncoding("iso-8859-1"); string usernamePassword = encoding.GetString(Convert.FromBase64String(encodedUsernamePassword)); int seperatorIndex = usernamePassword.IndexOf(':'); var username = usernamePassword.Substring(0, seperatorIndex); var password = usernamePassword.Substring(seperatorIndex + 1); if(username == "test" && password == "test" ) { await _next.Invoke(context); } else { context.Response.StatusCode = 401; //Unauthorized return; } } else { // no authorization header context.Response.StatusCode = 401; //Unauthorized return; } } }
需要在服务Startup类的Configure方法中调用中间件扩展
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) { loggerFactory.AddConsole(Configuration.GetSection("Logging")); loggerFactory.AddDebug(); app.UseMiddleware<AuthenticationMiddleware>(); app.UseMvc(); }
就这样! :)
可以在此处找到.Net Core中的中间件和身份验证的非常好的资源: https://www.exceptionnotfound.net/writing-custom-middleware-in-asp-net-core-1-0/
在这个公共Github回购 https://github.com/boskjoett/BasicAuthWebApi 您可以看到一个简单的ASP.NET Core 2.2 Web API示例,其端点受基本身份验证保护。
的 带有Angular的ASP.NET Core 2.0 强>
https://fullstackmark.com/post/13/jwt-authentication-with-aspnet-core-2-web-api-angular-5-net-core-identity-and-facebook-login
确保使用身份验证过滤器类型
的 [授权(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] 强>
您可以实现处理基本身份验证的中间件。
public async Task Invoke(HttpContext context) { var authHeader = context.Request.Headers.Get("Authorization"); if (authHeader != null && authHeader.StartsWith("basic", StringComparison.OrdinalIgnoreCase)) { var token = authHeader.Substring("Basic ".Length).Trim(); System.Console.WriteLine(token); var credentialstring = Encoding.UTF8.GetString(Convert.FromBase64String(token)); var credentials = credentialstring.Split(':'); if(credentials[0] == "admin" && credentials[1] == "admin") { var claims = new[] { new Claim("name", credentials[0]), new Claim(ClaimTypes.Role, "Admin") }; var identity = new ClaimsIdentity(claims, "Basic"); context.User = new ClaimsPrincipal(identity); } } else { context.Response.StatusCode = 401; context.Response.Headers.Set("WWW-Authenticate", "Basic realm=\"dotnetthoughts.net\""); } await _next(context); }
此代码是在asp.net核心的beta版本中编写的。希望能帮助到你。