在单点登录项目中检索身份声明

时间:2016-08-07 06:14:53

标签: asp.net asp.net-mvc single-sign-on claims-based-identity asp.net-identity-2

我们有三个ASP.NET MVC 5项目。对于身份验证,我们使用Single Sign On,遵循非常简单的教程:

Implementation of Single Sign On (SSO) in ASP.NET MVC

主要想法是在3之间创建共享MachineKey,并在3 web.config个文件中添加相同的身份验证设置。

现在我们有3个网站叫做:

  • SSO
  • WebApp1
  • webapp2的

我们的一个项目(SSO)完成了这项工作,另外两个项目依赖于它。它有效,我们很高兴,但......

我们在SSO项目中使用Identity 2基于声明的身份验证,当用户登录时,我们会在其“身份”中添加一些自定义声明。这样,我们就有2个单独的cookie:一个用于单点登录过程,另一个用于保存声明。

这是C#代码:

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

        var result = await SignInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, shouldLockout: false);
        switch (result)
        {
            case SignInStatus.Success:
                // here the cookie which contains claims *is created* by Identity 2

                // here we create the cookie used for Single Sing On
                FormsAuthentication.SetAuthCookie(username, false);

                // redirecting
                if (string.IsNullOrWhiteSpace(fromSite))
                {
                    if (string.IsNullOrWhiteSpace(returnUrl)) return RedirectToAction("Index", "Home");
                    return RedirectToLocal(returnUrl);
                }

                return Redirect(string.Format("{0}{1}", fromSite, returnUrl));

                // other cases inside switch
                .
                .
                .
        }
    }

当用户从SSO网站转到另一个网站时,请说WebApp1,他仍然登录但我们丢失了声明。

有没有办法“合并”这两个cookie并在另一个网站上检索声明?

2 个答案:

答案 0 :(得分:2)

我终于成功了!这是闷闷不乐的:

使用个人身份验证创建3个新的MVC 5项目。在MachineKey标记内的web.config文件中添加相同的system.web。现在你已经完成了,每件事都像魅力一样!简单易用:) OWIN负责处理所有事情。

为了更清晰,请从3个项目中的2个项目中删除与身份验证和授权相关的任何内容。这样,其中一个将成为核心,另外两个将依赖它。我的项目是:

  • SSO
  • WebApp1
  • webapp2的

例如,从AccountController.cs文件夹中删除ManageController.csControllers,然后删除Account下的ManageViews个文件夹及其相关的ViewModel。您还可以删除两个项目中Startup.Auth.cs文件夹下的App_Start文件,例如WebApp1WebApp2

完成所有删除后,用以下内容替换该2个项目根目录中Startup.cs的内容:

using Microsoft.AspNet.Identity;
using Microsoft.Owin;
using Microsoft.Owin.Security.Cookies;
using Owin;

[assembly: OwinStartupAttribute(typeof(WebApp1.Startup))]
// for the other one, rename the WebApp1 to WebApp2
namespace WebApp1
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            app.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
            });
        }
    }
}

以上代码最初是您删除的Startup.Auth.cs文件的一部分!现在OWIN知道cookie的类型并且可以读取它。

还有一件事:当尚未登录的未授权用户前往WebApp1时,他会看到HTTP 401错误页面,不会重定向到SSO的登录页面。你应该以任何你想要的方式处理这种情况。我认为Filter可以胜任。

希望我帮助过:)

答案 1 :(得分:0)

考虑我们有4个项目。

  • WebAppMain(该项目包含登录页面)

  • App2

  • App3

  • App4

如果您使用的是ASP.Net Identity,则需要在Startup类中添加代码(不是在主项目中,对于App2、3和4,这是必需的)。

[assembly: OwinStartupAttribute(typeof(ABC.Startup))]
namespace ABC
{
    public partial class Startup
    {
        public void Configuration(IAppBuilder app)
        {

                app.CreatePerOwinContext(ApplicationDbContext.Create);
                app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
                app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);
                app.UseCookieAuthentication(new CookieAuthenticationOptions
                {
                    AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
                    AuthenticationMode = Microsoft.Owin.Security.AuthenticationMode.Active,
                    CookieDomain = ConfigurationManager.AppSettings["DomainNameForSSO"],
                    CookieName = "SSOCookie",

                });

        }
    }
}

使用appsettings变量存储域

<add key="DomainNameForSSO" value=".test.com"/>

在主项目Startup.Auth.cs文件中使用相同的CookieName和CookieDomain。

将公用机器密钥添加到所有项目的web.config文件。

<machineKey
       validationKey="{Update this value}"
       decryptionKey="{Update this value}"
       validation="SHA1"
       decryption="AES"
    />

您可以使用在线工具生成机器,也可以在Internet上获得自定义代码。

完成后,创建如下的“自定义授权”属性。

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)]
    public class CustomAuthorize : ActionFilterAttribute
    {

        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            bool skipAuthorization = filterContext.ActionDescriptor.IsDefined(typeof(AllowAnonymousAttribute), true) ||
                                     filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(typeof(AllowAnonymousAttribute), true);
            if (skipAuthorization) return;

            var authManager = HttpContext.Current.GetOwinContext().Authentication;
            if (authManager == null || authManager.User == null || authManager.User.Identity == null || !authManager.User.Identity.IsAuthenticated)
            {
                UnAuthorizedProcess(filterContext);// handle unathorized request here, we can redirect the request to main project from here
            }
            else
            {
                AuthorizedProcess(filterContext);// Do the default action or if we have any custom validation, write here.
            }
        }
}

在需要授权的所有操作/控制器中添加属性。

 [CustomAuthorize]
 public ActionResult Dashboard()
 {
    return View();
 }

您必须将完整的URL作为returnURL参数提供给主网站。