如何在.net核心休息服务中实现基本身份验证和授权?

时间:2019-07-31 06:01:40

标签: c# authentication .net-core authorization

我是.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;
}

0 个答案:

没有答案