Пользовательская аутентификация в ASP.Net-Core
Я работаю над веб-приложением, которое необходимо интегрировать с существующей пользовательской базой данных. Я все равно хотел бы использовать атрибуты [Authorize]
, но я не хочу использовать структуру Identity. Если бы я хотел использовать структуру Identity, я бы добавил что-то вроде этого в файле startup.cs:
services.AddIdentity<ApplicationUser, IdentityRole>(options =>
{
options.Password.RequireNonLetterOrDigit = false;
}).AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
Я предполагаю, что мне нужно добавить что-то еще, а затем создать какой-то класс, который реализует определенный интерфейс? Может кто-нибудь указать мне в правильном направлении? Я использую RC1 из asp.net 5 прямо сейчас.
Ответы
Ответ 1
Создание пользовательской аутентификации в ASP.NET Core может быть выполнено различными способами. Если вы хотите скомпоновать существующие компоненты (но не хотите использовать личность), проверьте категорию документов "Безопасность" на docs.asp.net. https://docs.asp.net/en/latest/security/index.html
Некоторые статьи, которые могут вам пригодиться:
Использование промежуточного ПО Cookie без идентификатора ASP.NET
Пользовательская авторизация на основе политик
И, конечно, если это не удается или документы недостаточно ясны, исходный код находится в
https://github.com/aspnet/Security, который содержит некоторые примеры.
Ответ 2
Из того, что я узнал после нескольких дней исследований,
Вот Руководство по пользовательской аутентификации пользователя 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();
}
имейте в виду, что в приведенном выше коде мы сказали, что если любой неаутентифицированный пользователь запрашивает действие, которое аннотировано [Authorize]
, он вполне принудительно перенаправляет на URL /Account/Login
.
Добавьте следующие строки в метод 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);
}
}
}
Теперь вы можете использовать аннотацию [Authorize]
на любом Action
или Controller
.
Не стесняйтесь комментировать любые вопросы или ошибки.