我一直在阅读OWIN规范和.NET中的Katana实现.我之所以选择Katana路由,是因为与ADFS和令牌/ Cookie生成相关的owin组件.
我有两个项目,一个用于MVC 5网站,另一个用于Web API.它们将来可能会停留在两台独立的服务器上,但现在它们是相同的.
我知道我将使用IIS,所以Owin管道不是我调查的必要条件.
我的要求是将有使用ADFS登录的用户,以及将使用角色/成员资格提供程序使用令牌/ Cookie生成登录的其他用户.根据谁进行身份验证,我的网页的某些部分将被公开.网页工程师用剃须刀完成.
有没有人有任何我可以阅读的材料来帮助解释我可以采取的设计流程?或者任何人都做了类似于我正在经历的项目,可以添加任何建议?有很多不同的文件描述了我需要的特定事物,但不是大局;比如只讨论WebAPI和ADFS,或WebAPI和windows azure等.
我的理论是在MVC5网站项目上实现认证/授权,在Web API上进行授权(两者之间需要以某种方式进行通信).然后,我可能为ADFS创建项目的副本,并为令牌/ cookie身份验证创建另一个副本?或者我可能需要进行4种不同的身份验证:2个用于adfs,我根据MVC5网站和Web API进行身份验证,另外2个用于令牌/ cookie生成.
任何建议都会有所帮助,因为我对这种技术不是很熟悉.
解决方法
更新:经过一段时间的努力,我已经想出如何让这两种身份验证类型在同一个Web应用程序中和平共存.使用OWIN,设置调用UseCookieAuthentication TWICE,一次启用新的WsFederationAuthentication中间件,再次启用本地cookie身份验证.这不是直观的,但在幕后,为每个指定不同的身份验证类型将它们设置为不同的auth“引擎”.以下是我在Startup中的外观:
app.UseCookieAuthentication(new CookieAuthenticationOptions { AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,LoginPath = new PathString("/Account/Login"),Provider = new CookieAuthenticationProvider { OnResponseSignIn = ctx => { ctx.Identity = TransformClaims(ctx,app); } } }); app.UseCookieAuthentication(new CookieAuthenticationOptions { Provider = new CookieAuthenticationProvider { OnResponseSignIn = ctx => { ctx.Identity = TransformClaims(ctx,app); } } }); app.UseWsFederationAuthentication(new WsFederationAuthenticationOptions { Wtrealm = Realm,MetadataAddress = Metadata,Caption = "Active Directory",SignInAsAuthenticationType = CookieAuthenticationDefaults.AuthenticationType });
这成功地允许用户对本地sql表或ADFS 2.0进行身份验证. TransformClaims标注允许我规范化这两个提供者之间的声明,使它们保持一致.
编辑:这是一个非常基本的TransformClaims.你可以在其中做很多事情:从你的数据库中获取用户,设置导航声明,自定义权限,角色集合等等.我刚刚从一个更大的实现中构建了这个精简版本,所以我没有运行它,但希望你能够了解如何利用OnResponseSignIn事件.
private static ClaimsIdentity TransformClaims(CookieResponseSignInContext ctx,IAppBuilder app) { var ident = ctx.Identity; var claimEmail = ident.Claims.SingleOrDefault(c => c.Type == ClaimTypes.Email); var claimName = ident.Claims.SingleOrDefault(c => c.Type == ClaimTypes.Name); //normalize my string identifier var loginString = (claimEmail != null) ? claimEmail.Value : (claimName != null) ? claimName.Value : null; var efctx = ctx.OwinContext.Get<DBEntities>(); var user = UserBL.GetActiveUserByEmailOrName(efctx,loginString); if (user == null) { //user was auth'd by ADFS but hasn't been auth'd by this app ident.AddClaim(new Claim(ClaimTypesCustom.Unauthorized,"true")); return ident; } if (ident.Claims.First().Issuer == "LOCAL AUTHORITY") { //Local //local already has claim type "Name" //local didn't have claim type "Email" - adding it ident.AddClaim(new Claim(ClaimTypes.Email,user.Email)); } else { //ADFS //ADFS already has claim type "Email" //ADFS didn't have claim type "Name" - adding it ident.SetClaim(ClaimTypes.Name,user.UserName); } //now ident has "Name" and "Email",regardless of where it came from return ident; }