2017-09-20 26 views
0

我正在将我们的asp.net MVC应用程序与SAML2身份验证进行整合。并使用Kentor.AuthServices作为模块作为kentor.AuthServices ConfigurationKentor Auth Services根据页面url选择programmaticaly entityId

描述Everithing工作正常。但下一步是仅为指定范围的页面添加第二个服务提供者(它被配置为在服务器端使用另一个认证机制)的使用。

首先,如何通过web.config配置它以添加不同的entityId的第二个SP(不是第一个SP的范围中的第二个IdP)。

;第二,如何以编程方式切换到第二SP?我认为它应该在的Global.asax文件在happend方法的Application_BeginRequest,但如何?

回答

0

在同一应用程序中使用两个不同的SP实例是非常罕见的情况。但是如果你确实需要它,那就可以实现。

你将不得不使用Kentor.AuthServices.Owin包并做配置代码 - web.config中不会做。注册中间件的两个实例。每个人都有自己的配置,包括他们自己的SP EntityID。另外请务必更改其中至少一个的ModulePath,以便它们获得不同的端点地址。

从任一个挑战的认证,设置正确的认证方案中的挑战(通常在ChallengeResult来自控制器返回)

+0

是否有可能不使用Owin? – aleha

+0

不,MVC和HttpModule包不支持同一进程中的多个SP实例。即将推出的ASP.NET Core 2版本也将支持多个SP实例。 –

0

自应答。

这里是用于MVC或HTTP模块封装中的多个SP一种变通方法,切换是基于URL的指定范围内。在我的情况下,不同的SP实现不同数量的安全因素。

首先,实现自定义IOptions和的CookieHandler,有能力切换到正确的实例。在web.config文件中,必须定义两个kentor.authServices部分。在我的情况下,只有“entityId”属性不同。

public class CustomOptions : IOptions 
    { 
     private IOptions options1Factor; 
     private IOptions options2Factor; 
     private Func<bool> _checkIsSecure; 

     public CustomOptions(Func<bool> checkIsSecure) 
     { 
      _checkIsSecure = checkIsSecure; 

      AddOption(out options2Factor, "kentor.authServices1"); 
      AddOption(out options1Factor, "kentor.authServices"); 
     } 

     private void AddOption(out IOptions options, string sectionName) 
     { 
      var sp = new SPOptions((KentorAuthServicesSection)ConfigurationManager.GetSection(sectionName)); 
      options = new Options(sp); 
      KentorAuthServicesSection.Current.IdentityProviders.RegisterIdentityProviders(options); 
      KentorAuthServicesSection.Current.Federations.RegisterFederations(options); 
     } 

     public SPOptions SPOptions 
     { 
      get 
      { 
       if (_checkIsSecure()) 
        return options2Factor.SPOptions; 

       return options1Factor.SPOptions; 
      } 
     } 

     public IdentityProviderDictionary IdentityProviders 
     { 
      get 
      { 
       if (_checkIsSecure()) 
        return options2Factor.IdentityProviders; 

       return options1Factor.IdentityProviders; 
      } 

     } 

     public KentorAuthServicesNotifications Notifications 
     { 
      get 
      { 
       if (_checkIsSecure()) 
        return options2Factor.Notifications; 

       return options1Factor.Notifications; 
      } 
     } 
    } 

    public class CustomCookieHandler : CookieHandler 
    { 
     private Func<bool> _checkIsSecure; 
     private CookieHandler _originalCookieHandler1Factor; 
     private CookieHandler _originalCookieHandler2Factor; 

     public CustomCookieHandler(Func<bool> checkIsSecure) 
     { 
      _checkIsSecure = checkIsSecure; 
      _originalCookieHandler1Factor = new ChunkedCookieHandler() 
      { 
       Name = "commonAuth", 
       RequireSsl = false 
      }; 

      _originalCookieHandler2Factor = new ChunkedCookieHandler() 
      { 
       Name = "securedAuth", 
       RequireSsl = false 
      }; 
     } 

     public override string MatchCookiePath(Uri baseUri, Uri targetUri) 
     { 
      if (_checkIsSecure()) 
       return _originalCookieHandler2Factor.MatchCookiePath(baseUri, targetUri); 

      return _originalCookieHandler1Factor.MatchCookiePath(baseUri, targetUri); 
     } 

     protected override void DeleteCore(string name, string path, string domain, HttpContext context) 
     { 
      if (_checkIsSecure()) 
       _originalCookieHandler2Factor.Delete(); 
      else 
       _originalCookieHandler1Factor.Delete(); 
     } 

     protected override byte[] ReadCore(string name, HttpContext context) 
     { 
      if (_checkIsSecure()) 
       return _originalCookieHandler2Factor.Read(); 

      return _originalCookieHandler1Factor.Read(); 
     } 

     protected override void WriteCore(byte[] value, string name, string path, string domain, DateTime expirationTime, bool secure, bool httpOnly, HttpContext context) 
     { 
      if (_checkIsSecure()) 
       _originalCookieHandler2Factor.Write(value, true, expirationTime); 
      else 
       _originalCookieHandler1Factor.Write(value, true, expirationTime); 
     } 
    } 

在Global.asax文件中将静态属性设置为自定义实现。不需要更多的修改。

protected void Application_Start() 
    { 
     FederatedAuthentication.FederationConfiguration.CookieHandler = new CustomCookieHandler(CheckIsSecure); 
     Kentor.AuthServices.Mvc.AuthServicesController.Options = new CustomOptions(CheckIsSecure); 
    } 

    private bool CheckIsSecure() 
    { 
     if (HttpContext.Current == null) 
      return false; 

     var mainHost = "http://host.local"; // host url 
     var sp = new [] { "/Home/Secure" }; // array of URLs which must be secured with other SP 
     var request = HttpContext.Current.Request; 
     var isSecured = sp.Any(x => x.Equals(request.Path, StringComparison.InvariantCultureIgnoreCase)); 

     if (!isSecured && request.Path.Equals("/AuthServices/SignIn", StringComparison.InvariantCultureIgnoreCase)) 
     { 
      var returnUrl = request.QueryString["ReturnUrl"]; 
      isSecured = !string.IsNullOrEmpty(returnUrl) && 
         sp.Any(x => x.Equals(returnUrl, StringComparison.InvariantCultureIgnoreCase)); 
     } 

     if (!isSecured && request.Path.Equals("/AuthServices/Acs", StringComparison.InvariantCultureIgnoreCase)) 
     { 
      var _r = new HttpRequestWrapper(request).ToHttpRequestData(); 
      isSecured = _r != null && _r.StoredRequestState != null && _r.StoredRequestState.ReturnUrl != null 
         && sp.Any(x => x.Equals(_r.StoredRequestState.ReturnUrl.ToString(), 
          StringComparison.InvariantCultureIgnoreCase)); 
     } 

     if (!isSecured && !string.IsNullOrEmpty(request.Headers["Referer"])) 
     { 
      var referer = request.Headers["Referer"]; 
      isSecured = sp 
       .Select(x => string.Format("{0}/{1}", mainHost.TrimEnd('/'), x.TrimStart('/'))) 
       .Any(x => x.Equals(referer, StringComparison.InvariantCultureIgnoreCase)); 
     } 

     return isSecured; 
    } 
相关问题