我们有三个ASP.NET MVC 5项目。对于身份验证,我们使用Single Sign On,遵循非常简单的教程:
Implementation of Single Sign On (SSO) in ASP.NET MVC
主要想法是在3之间创建共享MachineKey
,并在3 web.config
个文件中添加相同的身份验证设置。
现在我们有3个网站叫做:
我们的一个项目(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并在另一个网站上检索声明?
答案 0 :(得分:2)
我终于成功了!这是闷闷不乐的:
使用个人身份验证创建3个新的MVC 5项目。在MachineKey
标记内的web.config
文件中添加相同的system.web
。现在你已经完成了,每件事都像魅力一样!简单易用:) OWIN负责处理所有事情。
为了更清晰,请从3个项目中的2个项目中删除与身份验证和授权相关的任何内容。这样,其中一个将成为核心,另外两个将依赖它。我的项目是:
例如,从AccountController.cs
文件夹中删除ManageController.cs
和Controllers
,然后删除Account
下的Manage
和Views
个文件夹及其相关的ViewModel。您还可以删除两个项目中Startup.Auth.cs
文件夹下的App_Start
文件,例如WebApp1
和WebApp2
。
完成所有删除后,用以下内容替换该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参数提供给主网站。