SSO与AD FS和OWIN如何创建一个帐户,并办理权限 [英] SSO with AD FS and OWIN how to create an account and handle permissions

查看:636
本文介绍了SSO与AD FS和OWIN如何创建一个帐户,并办理权限的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我配置Web应用程序使用AD FS,为了这个,我用OWIN。

I configure a Web App that use AD FS, for this I use OWIN.

有关登录,一切正常。如果我是一个域的用户,并去的网站,他都会自动连接。

For the login, all is ok. If i'm an user of a domain and go to the website, he is automatically connected.

但我想有是由我自己登录后处理用户和角色。

But what I want to have is to handle users and roles by myself after login.

所以,我要检查,一个用户在我这个AD帐户数据库是否存在(这个过程会在另一个应用程序登录之前进行)

So I want to check that an user exists in my database with this AD account (this process will be make before the login in another application)

我想要使用的微软来处理索赔(角色和权限)。但我不知道如何把我的code,以处理从AD FS的全成连接(使用WS-联邦)和添加验证并填写正确的角色。

I want to use Identity from Microsoft to handle claims (roles and permissions). But I don't understand how to put my code to handle the successfull connection from AD FS (with Ws-Federation) and add verification and fill in the right roles.

我的code在ConfigureAuth:

My code in ConfigureAuth:

public partial class Startup
{
    private static string realm = ConfigurationManager.AppSettings["ida:Wtrealm"];
    private static string adfsMetadata = ConfigurationManager.AppSettings["ida:ADFSMetadata"];
    private NLogLoggingService _loggingService;

    public void ConfigureAuth(IAppBuilder app)
    {
        _loggingService = new NLogLoggingService("Startup");
        _loggingService.Debug("ConfigureAuth");

        app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);

        app.UseCookieAuthentication(new CookieAuthenticationOptions());

        app.UseWsFederationAuthentication(
            new WsFederationAuthenticationOptions
            {
                Wtrealm = realm,
                MetadataAddress = adfsMetadata,

                //CallbackPath = PathString.FromUriComponent("/Account/TestCallback"),

                // https://msdn.microsoft.com/en-us/library/microsoft.owin.security.authenticationmode(v=vs.113).aspx
                AuthenticationMode = AuthenticationMode.Passive,

                //Notifications = new WsFederationAuthenticationNotifications
                //{

                //}
            });

    }

在Web.config中,境界是链接到我的Web应用程序( HTTPS://ssoadfs.test )和adfsMetadata是链接到元数据从AD FS .XML。

In Web.config, realm is the link to my Web App (https://ssoadfs.test) and adfsMetadata is the link to metadata.xml from AD FS.

什么是要去把我的角色和AD FS连接后登录逻辑?顺便

What is the way to go to set my role and login logic after AD FS connection ?

模式是我在想什么:

编辑:
一些尝试后,我不能处理任何成功回调。我不希望有处理HomeController的...

After some tries, I cannot handle any success callback. I don't want to have to handle roles in HomeController ...

我最后的验证配置:

            _loggingService = new NLogLoggingService("Startup");
        _loggingService.Debug("ConfigureAuth");

        // Configure the db context, user manager and signin manager to use a single instance per request
        app.CreatePerOwinContext(ApplicationUser.ApplicationDbContext.Create);
        app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
        app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);

        app.SetDefaultSignInAsAuthenticationType(DefaultAuthenticationTypes.ApplicationCookie);

        app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            Provider = new CookieAuthenticationProvider
            {
                OnResponseSignIn = ctx =>
                {
                    _loggingService.Debug("OnResponseSignIn");
                    ctx.Identity = TransformClaims(ctx, app);
                },
                // Enables the application to validate the security stamp when the user logs in.
                // This is a security feature which is used when you change a password or add an external login to your account.  
                OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
                    validateInterval: TimeSpan.FromMinutes(30),
                    regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
            }
        });

        app.UseWsFederationAuthentication(
            new WsFederationAuthenticationOptions
            {
                Wtrealm = realm,
                MetadataAddress = adfsMetadata,
                Caption = "Active Directory",

                CallbackPath = PathString.FromUriComponent("/Account/TestCallback"),

                Notifications = new WsFederationAuthenticationNotifications
                {
                    SecurityTokenValidated = n =>
                    {
                        new NLogLoggingService("Startup").Debug("SecurityTokenValidated");

                        var incomingClaimsFromAdfs = n.AuthenticationTicket.Identity.Claims.ToList();
                        var incomingClaimsHasNameIdentifier =
                            incomingClaimsFromAdfs.Any(
                                c => c.Type == System.Security.Claims.ClaimTypes.NameIdentifier);

                        _loggingService.Debug("SecurityTokenValidated - incomingClaimsHasNameIdentifier: " +
                                              incomingClaimsHasNameIdentifier);
                        if (!incomingClaimsHasNameIdentifier)
                        {
                            var emailClaim =
                                incomingClaimsFromAdfs.First(c => c.Type == System.Security.Claims.ClaimTypes.Name);
                            _loggingService.Debug(emailClaim.Value);
                        }

                        //if (!incomingClaimsHasNameIdentifier)
                        //{
                        //    var emailClaim = incomingClaimsFromAdfs.First(c => c.Type == System.Security.Claims.ClaimTypes.Name);
                        //    incomingClaimsFromAdfs.Add();

                        //    IUser user = await this.UserStore.FindByNameOrEmailAsync(userNameOrEmailAddress);
                        //    if ((Entity<long>)user == (Entity<long>)null)
                        //        LoginResult = new ApplicationUserManager.LoginResult(LoginResultType.InvalidUserNameOrEmailAddress, default(IUser));
                        //    //else if (!loggedInFromExternalSource && new PasswordHasher().VerifyHashedPassword(user.Password, plainPassword) != PasswordVerificationResult.Success)
                        //    //    LoginResult = new UserManager<TTenant, TRole, TUser>.LoginResult(LoginResultType.InvalidPassword, user);
                        //    else
                        //        LoginResult = await this.CreateLoginResultAsync(user, tenant);
                        //}
                        //else
                        //{
                        //    throw new ApplicationException("Get ADFS to provide the NameIdentifier claim!");
                        //}

                        //var normalizedClaims = incomingClaimsFromAdfs.Distinct(new ClaimComparer());
                        //var claimsIdentity = new ClaimsIdentity(normalizedClaims, n.AuthenticationTicket.Identity.AuthenticationType);
                        //n.AuthenticationTicket = new AuthenticationTicket(claimsIdentity, n.AuthenticationTicket.Properties);
                        return Task.FromResult(0);
                    }
                }
            });

在此code,我试图CallbackPath(没有出现在我的日志),WsFederationAuthenticationNotifications.SecurityTokenValidated(没有出现在我的日志),CookieAuthenticationProvider.OnResponseSignIn(同样没有发生)

In this code, I tried CallbackPath (nothing appeared in my log), WsFederationAuthenticationNotifications.SecurityTokenValidated (nothing appeared in my log), CookieAuthenticationProvider.OnResponseSignIn (same nothing happened)

在HomeController的我能有Identity.Name:

In HomeController i'm able to have Identity.Name:

public ActionResult Index()
    {
        if (HttpContext.GetOwinContext().Authentication.User.Identity.IsAuthenticated)
        {
            new NLogLoggingService("Home").Debug("User is authenticated");
        }

        return View();
    }

我错过了什么得到通知在CookieAuthenticationOptions工作或提供???

Did I miss something to get Notifications working or Provider in CookieAuthenticationOptions ???

推荐答案

如果您使用 ASP.NET 2.0身份或更高版本,您可以使用类似于它的方法如下所示。请注意,这种方法分配 GroupRoles 用户,而不是由一个分配每个角色之一的。您可以根据自己的需要更改必要的部分。

If you use ASP.NET Identity 2.0 or later version, you can use an approach similar to it shown below. Please note that this approach assign GroupRoles to the user instead of assigning each of roles one by one. You can change necessary parts according to your needs.

[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
    if (!ModelState.IsValid)
    {
        return View(model);
    }

    ApplicationGroupManager groupManager = new ApplicationGroupManager();

    if (Membership.ValidateUser(model.UserName, model.Password))
    {
        FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);

        //Assign Roles to the current User
        ApplicationUser user = UserManager.FindByName(model.UserName);

        //If the user is registered in the system (ASP.NET Identity) add record to AspNetUsers table 
        if (user != null)
        {
            //Returns Group Id and Role Id by using User Id parameter
            var userGroupRoles = groupManager.GetUserGroupRoles("bfd9730e-2093-4fa0-89a2-226e301d831b"); 
            foreach (var role in userGroupRoles)
            {
                string roleName = RoleManager.FindById(role.ApplicationRoleId).Name;
                UserManager.AddToRole(user.Id, roleName);
            }
        }
        else
        {
            //crate new user
            //first retrieve user info from LDAP:
            // Create an array of properties that we would like and add them to the search object  
            string[] requiredProperties = new string[] { "samaccountname", "givenname", "sn", "mail", "physicalDeliveryOfficeName", "title" };
            var userInfo = CreateDirectoryEntry(model.UserName, requiredProperties);

            var newUser = new ApplicationUser();
            newUser.UserName = userInfo.GetDirectoryEntry().Properties["samaccountname"].Value.ToString();
            newUser.Name = userInfo.GetDirectoryEntry().Properties["givenname"].Value.ToString();
            newUser.Surname = userInfo.GetDirectoryEntry().Properties["sn"].Value.ToString();
            newUser.Email = userInfo.GetDirectoryEntry().Properties["mail"].Value.ToString();
            newUser.EmailConfirmed = true;
            newUser.PasswordHash = null;

            var result = await UserManager.CreateAsync(newUser);
            if (result.Succeeded)
            {
                //If the user is created ...
            }

            //Assign user group (and roles)
            var defaultGroup = "751b30d7-80be-4b3e-bfdb-3ff8c13be05e";
            groupManager.SetUserGroups(newUser.Id, new string[] { defaultGroup });
        }
        return this.RedirectToAction("Index", "Issue");
    }

    this.ModelState.AddModelError(string.Empty, "Wrong username or password!");
    return this.View(model);
}


static SearchResult CreateDirectoryEntry(string sAMAccountName, string[] requiredProperties)
{
    DirectoryEntry ldapConnection = null;

    try
    {
        ldapConnection = new DirectoryEntry("LDAP://OU=******, DC=******, DC=******", "acb@xyz.com", "YourPassword");
        ldapConnection.AuthenticationType = AuthenticationTypes.Secure;

        DirectorySearcher search = new DirectorySearcher(ldapConnection);
        search.Filter = String.Format("(sAMAccountName={0})", sAMAccountName);

        foreach (String property in requiredProperties)
            search.PropertiesToLoad.Add(property);

        SearchResult result = search.FindOne();
        //SearchResultCollection searchResultCollection = search.FindAll(); //You can also retrieve all information

        if (result != null)
        {                
            return result;
        }
        else {
            return null;
            //Console.WriteLine("User not found!");
        }
    }
    catch (Exception e)
    {
        Console.WriteLine("Exception caught:\n\n" + e.ToString());
    }

    return null;
}



希望这有助于...


Hope this helps...

这篇关于SSO与AD FS和OWIN如何创建一个帐户,并办理权限的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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