我是.NET Core REST API的新手。这是我实现基本认证和授权之后的第一枪。到目前为止,一切正常。
我想知道这是否正确完成。任何对改进的评论或建议都值得赞赏。
关键组件是身份验证中间件和用户名处理程序。
在身份验证中间件中,由授权标头传递的用户名和密码将根据有效的登录进行检查。
如果登录名有效,则将新标识添加到用户对象,并将标签设置为传入的用户名(在其前面加上软糖)。
在用户名处理程序中,此新身份用于授权用户。
以下是相关的代码片段:
appsettings.json
{
"Logins": {
"test": "B0Lo8tsQpKs=",
"tryme": "B0Lo8tsQpKs="
},
"Policies": {
"UserPolicySnrCounter": "test,tryme"
}
}
启动
public void ConfigureServices(IServiceCollection services)
{
var policies = Configuration.GetSection("Policies");
...
services.AddAuthentication().AddCustomAuth(options => {});
services.AddSingleton<IAuthorizationHandler, UserNamesHandler>();
services.AddAuthorization(options =>
{
options.AddPolicy("PolicySnrCounter", policy => policy.Requirements.Add(new UserNamesRequirement(policies.GetValue<string>("UserPolicySnrCounter"))));
});
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseAuthentication();
app.UseMiddleware<AuthenticationMiddleware>(Configuration.GetSection("Logins"));
...
}
AuthenticationMiddleware
public async Task Invoke(HttpContext context)
{
string authHeader = context.Request.Headers["Authorization"];
if (authHeader != null && authHeader.StartsWith("Basic"))
{
string encodedUsernamePassword = authHeader.Substring("Basic ".Length).Trim();
string usernamePassword = _encoding.GetString(Convert.FromBase64String(encodedUsernamePassword));
int seperatorIndex = usernamePassword.IndexOf(':');
var username = usernamePassword.Substring(0, seperatorIndex);
var password = usernamePassword.Substring(seperatorIndex + 1);
var loginPassword = _logins.GetValue<string>(username);
if (string.IsNullOrEmpty(loginPassword))
{
context.Response.StatusCode = 401; //Unauthorized
return;
}
else
{
loginPassword = Crypto.Decrypt(loginPassword);
}
if (password == loginPassword)
{
context.User.AddIdentity(new System.Security.Claims.ClaimsIdentity() { Label = "CustomAuth" + username });
await _next.Invoke(context);
}
else
{
context.Response.StatusCode = 401; //Unauthorized
return;
}
}
else
{
// no authorization header
context.Response.StatusCode = 401; //Unauthorized
return;
}
}
UserNamesHandler
public class UserNamesHandler : AuthorizationHandler<UserNamesRequirement>
{
protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, UserNamesRequirement requirement)
{
var userNames = (UserNamesRequirement)context.Requirements.FirstOrDefault();
var currentUserClaimsIdentity = context.User.Identities.FirstOrDefault(p => p.Label != null && p.Label.StartsWith("CustomAuth"));
if (userNames != null && currentUserClaimsIdentity != null)
{
var names = userNames.UserNames[0].Split(',').ToList();
var currentUser = currentUserClaimsIdentity.Label.Replace("CustomAuth", "");
if (names.Any(s => s.Equals(currentUser)))
{
context.Succeed(requirement);
}
}
await Task.CompletedTask;
}