web-dev-qa-db-ja.com

ASP.Net-Coreのカスタム認証

私は、既存のユーザーデータベースと統合する必要があるWebアプリに取り組んでいます。 [Authorize]属性を引き続き使用したいのですが、Identityフレームワークは使用したくありません。 Identityフレームワークを使用したい場合は、startup.csファイルに次のようなものを追加します。

services.AddIdentity<ApplicationUser, IdentityRole>(options =>
{
    options.Password.RequireNonLetterOrDigit = false;
}).AddEntityFrameworkStores<ApplicationDbContext>()
  .AddDefaultTokenProviders();

私はそこに何か他のものを追加し、特定のインターフェイスを実装する何らかのクラスを作成する必要があると仮定していますか?誰かが私を正しい方向に向けることができますか?現在、asp.net 5のRC1を使用しています。

52
rgvassar

ASP.NET Coreでカスタム認証を作成するには、さまざまな方法があります。既存のコンポーネントからビルドしたい(ただしIDを使用したくない)場合は、docs.asp.netのドキュメントの「セキュリティ」カテゴリを確認してください。 https://docs.asp.net/en/latest/security/index.html

役立つと思われる記事:

ASP.NET IDなしでCookieミドルウェアを使用

カスタムポリシーベース認証

そしてもちろん、それが失敗するか、ドキュメントが十分に明確でない場合、ソースコードは https://github.com/aspnet/Security にあります。これにはいくつかのサンプルが含まれています。

48
natemcmaster

数日間の調査の後に学んだことから、ここにASP .Net Core MVC 2.xカスタムユーザー認証のガイド

Startup.csで:

以下の行をConfigureServicesメソッドに追加します。

public void ConfigureServices(IServiceCollection services)
{

services.AddAuthentication(
    CookieAuthenticationDefaults.AuthenticationScheme
).AddCookie(CookieAuthenticationDefaults.AuthenticationScheme,
    options =>
    {
        options.LoginPath = "/Account/Login";
        options.LogoutPath = "/Account/Logout";
    });

    services.AddMvc();

    // authentication 
    services.AddAuthentication(options =>
    {
       options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    });

    services.AddTransient(
        m => new UserManager(
            Configuration
                .GetValue<string>(
                    DEFAULT_CONNECTIONSTRING //this is a string constant
                )
            )
        );
     services.AddDistributedMemoryCache();
}

上記のコードでは、nauthenticatedユーザーが[Authorize]アノテーションが付けられたアクションをリクエストした場合、/Account/Login urlへのリダイレクトを強制することに注意してください。

以下の行をConfigureメソッドに追加します。

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
        app.UseBrowserLink();
        app.UseDatabaseErrorPage();
    }
    else
    {
        app.UseExceptionHandler(ERROR_URL);
    }
     app.UseStaticFiles();
     app.UseAuthentication();
     app.UseMvc(routes =>
    {
        routes.MapRoute(
            name: "default",
            template: DEFAULT_ROUTING);
    });
}

ログインとログアウトも管理するUserManagerクラスを作成します。以下のスニペットのように見えるはずです(私はdapperを使用していることに注意してください):

public class UserManager
{
    string _connectionString;

    public UserManager(string connectionString)
    {
        _connectionString = connectionString;
    }

    public async void SignIn(HttpContext httpContext, UserDbModel user, bool isPersistent = false)
    {
        using (var con = new SqlConnection(_connectionString))
        {
            var queryString = "sp_user_login";
            var dbUserData = con.Query<UserDbModel>(
                queryString,
                new
                {
                    UserEmail = user.UserEmail,
                    UserPassword = user.UserPassword,
                    UserCellphone = user.UserCellphone
                },
                commandType: CommandType.StoredProcedure
            ).FirstOrDefault();

            ClaimsIdentity identity = new ClaimsIdentity(this.GetUserClaims(dbUserData), CookieAuthenticationDefaults.AuthenticationScheme);
            ClaimsPrincipal principal = new ClaimsPrincipal(identity);

            await httpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, principal);
        }
    }

    public async void SignOut(HttpContext httpContext)
    {
        await httpContext.SignOutAsync();
    }

    private IEnumerable<Claim> GetUserClaims(UserDbModel user)
    {
        List<Claim> claims = new List<Claim>();

        claims.Add(new Claim(ClaimTypes.NameIdentifier, user.Id().ToString()));
        claims.Add(new Claim(ClaimTypes.Name, user.UserFirstName));
        claims.Add(new Claim(ClaimTypes.Email, user.UserEmail));
        claims.AddRange(this.GetUserRoleClaims(user));
        return claims;
    }

    private IEnumerable<Claim> GetUserRoleClaims(UserDbModel user)
    {
        List<Claim> claims = new List<Claim>();

        claims.Add(new Claim(ClaimTypes.NameIdentifier, user.Id().ToString()));
        claims.Add(new Claim(ClaimTypes.Role, user.UserPermissionType.ToString()));
        return claims;
    }
}

次に、以下のように見えるはずのAccountControllerアクションを持つLoginがあります:

public class AccountController : Controller
{
    UserManager _userManager;

    public AccountController(UserManager userManager)
    {
        _userManager = userManager;
    }

    [HttpPost]
    public IActionResult LogIn(LogInViewModel form)
    {
        if (!ModelState.IsValid)
            return View(form);
         try
        {
            //authenticate
            var user = new UserDbModel()
            {
                UserEmail = form.Email,
                UserCellphone = form.Cellphone,
                UserPassword = form.Password
            };
            _userManager.SignIn(this.HttpContext, user);
             return RedirectToAction("Search", "Home", null);
         }
         catch (Exception ex)
         {
            ModelState.AddModelError("summary", ex.Message);
            return View(form);
         }
    }
}

これで、任意のActionまたはController[Authorize]注釈を使用できます。

質問やバグはコメントしてください。

55
AmiNadimi