.net 核心认证 [英] .net Core Authentication

查看:7
本文介绍了.net 核心认证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在我的 asp.net MVC Core 应用程序中使用成员身份实现表单身份验证.我们在之前的应用程序中进行了表单身份验证设置,如下所示,并希望在 .net core 中使用相同的设置.

I wanted to implement forms authentication with membership in my asp.net MVC Core application. We had forms authentication setup in our previous application as below and wanted to use the same in .net core.

  [HttpPost]
public ActionResult Login(LoginModel model, string returnUrl)
{
  if (!this.ModelState.IsValid)
  {
      return this.View(model);
   }

   //Authenticate
   if (!Membership.ValidateUser(model.UserName, model.Password))
   {
       this.ModelState.AddModelError(string.Empty, "The user name or 
   password provided is incorrect.");
   return this.View(model);
   }
   else
   {
       FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
        return this.RedirectToAction("Index", "Home");
   }
 return this.View(model);
   }

在我的配置中:

  <membership defaultProvider="ADMembership">
       <providers>
         <add name="ADMembership" 
           type="System.Web.Security.ActiveDirectoryMembershipProvider" 
           connectionStringName="ADConnectionString" 
           attributeMapUsername="sAMAccountName" />
       </providers>
   </membership>

所以我们在成员资格中使用活动目录.

So we are using active directory here in membership.

这是否仍然适用于 .net 核心.

Is this still applicable in .net core.

如果不是 .net 核心中还有什么可用于表单身份验证和 AD.

If not what else is available in .net core for forms authentication and AD.

不胜感激.

推荐答案

是的,你可以在 Core MVC 应用程序中做到这一点.您启用表单身份验证并使用 LDAP 作为后端的用户存储.

Yes you can do that in Core MVC application. You enable form authentication and use LDAP as user store at the back-end.

这是我的设置,让您开始:

Here is how I set things up, to give you start:

public class Startup
{
    ...
    public void ConfigureServices(IServiceCollection services)
    {
        ...
        // Read LDAP settings from appsettings
        services.Configure<LdapConfig>(this.Configuration.GetSection("ldap"));

        // Define an interface for authentication service,
        // We used Novell.Directory.Ldap as implementation.
        services.AddScoped<IAuthenticationService, LdapAuthenticationService>();

        // Global filter is enabled to protect the whole site
        services.AddMvc(config =>
        {
            var policy = new AuthorizationPolicyBuilder()
                .RequireAuthenticatedUser()
                .Build();
            config.Filters.Add(new AuthorizeFilter(policy));
            ...
        });

        // Form authentication and cookies settings
        var cookiesConfig = this.Configuration.GetSection("cookies").Get<CookiesConfig>();
        services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
        .AddCookie(options =>
        {
            options.Cookie.Name = cookiesConfig.CookieName;
            options.LoginPath = cookiesConfig.LoginPath;
            options.LogoutPath = cookiesConfig.LogoutPath;
            options.AccessDeniedPath = cookiesConfig.AccessDeniedPath;
            options.ReturnUrlParameter = cookiesConfig.ReturnUrlParameter;
        });
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        // Redirects all HTTP requests to HTTPS
        if (env.IsProduction())
        {
            app.UseRewriter(new RewriteOptions()
                .AddRedirectToHttpsPermanent());
        }

        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/error");
        }

        app.UseStaticFiles();

        app.UseStatusCodePagesWithReExecute("/error", "?code={0}");

        app.UseAuthentication();

        app.UseMvc(routes =>
        {
            ...
        });
    }
}

appsettings.json

{
  "connectionStrings": {
    "appDbConnection": xxx
  },
  "ldap": {
    "url": "xxx.loc",
    "bindDn": "CN=Users,DC=xxx,DC=loc",
    "username": "xxx",
    "password": "xxx",
    "searchBase": "DC=xxx,DC=loc",
    "searchFilter": "(&(objectClass=user)(objectClass=person)(sAMAccountName={0}))"
  },
  "cookies": {
    "cookieName": "xxx",
    "loginPath": "/account/login",
    "logoutPath": "/account/logout",
    "accessDeniedPath": "/account/accessDenied",
    "returnUrlParameter": "returnUrl"
  }
}

IAuthenticationService.cs

namespace DL.SO.Services.Core
{
    public interface IAuthenticationService
    {
        IAppUser Login(string username, string password);
    }
}

LdapAuthenticationService.cs

身份验证服务的 Ldap 实现,使用 Novell.Directory.Ldap 库与活动目录对话.你可以 Nuget 那个库.

LdapAuthenticationService.cs

Ldap implementation of authentication service, using Novell.Directory.Ldap library to talk to active directory. You can Nuget that library.

using Microsoft.Extensions.Options;
using Novell.Directory.Ldap;
...
using DL.SO.Services.Core;

namespace DL.SO.Services.Security.Ldap
{
    public class LdapAuthenticationService : IAuthenticationService
    {
        private const string MemberOfAttribute = "memberOf";
        private const string DisplayNameAttribute = "displayName";
        private const string SAMAccountNameAttribute = "sAMAccountName";
        private const string MailAttribute = "mail";

        private readonly LdapConfig _config;
        private readonly LdapConnection _connection;

        public LdapAuthenticationService(IOptions<LdapConfig> configAccessor)
        {
            // Config from appsettings, injected through the pipeline
            _config = configAccessor.Value;
            _connection = new LdapConnection();
        }

        public IAppUser Login(string username, string password)
        {
            _connection.Connect(_config.Url, LdapConnection.DEFAULT_PORT);
            _connection.Bind(_config.Username, _config.Password);

            var searchFilter = String.Format(_config.SearchFilter, username);
            var result = _connection.Search(_config.SearchBase, LdapConnection.SCOPE_SUB, searchFilter,
            new[] { MemberOfAttribute, DisplayNameAttribute, SAMAccountNameAttribute, MailAttribute }, false);

            try
            {
                var user = result.next();
                if (user != null)
                {
                    _connection.Bind(user.DN, password);
                    if (_connection.Bound)
                    {
                        var accountNameAttr = user.getAttribute(SAMAccountNameAttribute);
                        if (accountNameAttr == null)
                        {
                            throw new Exception("Your account is missing the account name.");
                        }

                        var displayNameAttr = user.getAttribute(DisplayNameAttribute);
                        if (displayNameAttr == null)
                        {
                            throw new Exception("Your account is missing the display name.");
                        }

                        var emailAttr = user.getAttribute(MailAttribute);
                        if (emailAttr == null)
                        {
                            throw new Exception("Your account is missing an email.");
                        }

                        var memberAttr = user.getAttribute(MemberOfAttribute);
                        if (memberAttr == null)
                        {
                            throw new Exception("Your account is missing roles.");
                        }

                        return new AppUser
                        {
                            DisplayName = displayNameAttr.StringValue,
                            Username = accountNameAttr.StringValue,
                            Email = emailAttr.StringValue,
                            Roles = memberAttr.StringValueArray
                                .Select(x => GetGroup(x))
                                .Where(x => x != null)
                                .Distinct()
                                .ToArray()
                        };
                    }
                }
            }
            finally
            {
                _connection.Disconnect();
            }

            return null;
        }
    }
}

AccountController.cs

最后在用户通过验证后,你需要从用户声明中构造主体用于登录过程,这将在幕后生成cookie.

AccountController.cs

Then finally after the user is verified, you need to construct the principal from the user claims for sign in process, which would generate the cookie behind the scene.

public class AccountController : Controller
{
    private readonly IAuthenticationService _authService;

    public AccountController(IAuthenticationService authService)
    {
        _authService = authService;
    }

    ...
    [HttpPost]
    [AllowAnonymous]
    public async Task<IActionResult> Login(LoginViewModel model)
    {
        if (ModelState.Valid)
        {
            try
            {
                var user = _authService.Login(model.Username, model.Password);
                if (user != null)
                {
                    var claims = new List<Claim>
                    {
                        new Claim(ClaimTypes.Name, user.Username),
                        new Claim(CustomClaimTypes.DisplayName, user.DisplayName),
                        new Claim(ClaimTypes.Email, user.Email)
                    }

                    // Roles
                    foreach (var role in user.Roles)
                    {
                        claims.Add(new Claim(ClaimTypes.Role, role));
                    }

                    // Construct Principal
                    var principal = new ClaimsPrincipal(new ClaimsIdentity(claims, _authService.GetType().Name));

                    await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, 
                        principal,
                        new AuthenticationProperties
                        {
                            IsPersistent = model.RememberMe
                        }
                    );

                    return Redirect(Url.IsLocalUrl(model.ReturnUrl)
                        ? model.ReturnUrl
                        : "/");              
                }

                ModelState.AddModelError("", @"Your username or password is incorrect.");
            }
            catch(Exception ex)
            {
                ModelState.AddModelError("", ex.Message);
            }
        }
        return View(model);
    }
}

这篇关于.net 核心认证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆