2017-10-10 43 views

回答

0

我會回答我的問題,因爲這是非常痛苦的,找到正確的信息和工作發生了什麼事情上有一定的路徑(如/ API)。

我想使用WebApi v2並能夠使用現有的基於webforms會話的應用程序,並且還可以使用其他任何更標準的身份驗證策略來使用它。

下面的代碼是如何將WebApi嵌入WebForms並支持基於會話和基本身份驗證的大部分完整示例。

所以在Global.asax中,我只是叫MyWebApi.Global.Start();

爲什麼我得到重定向的最關鍵的事情是由於代碼恢復會話狀態的的WebAPI。如果您返回SessionControllerHandler並且沒有會話,則它將執行重定向以獲取cookie,並且在無Cookie模式下將其添加到URL中。這對我正在使用的代理來說是一場災難。但是,通過檢查它是否嘗試使用標準授權機制並返回正常的WebApi路由處理程序,它不會經歷302重定向。然後它會過濾到Authroization函數,該函數確定它是使用標準授權還是基於Session,然後驗證(根據您在應用程序中的操作方式,此部分需要自定義)

public static class Global 
{ 
    public static void Start() 
    { 
     GlobalConfiguration.Configure(Register); 
    } 

    private static void Register(HttpConfiguration config) 
    { 
     var httpControllerRouteHandler = typeof(HttpControllerRouteHandler).GetField("_instance", 
      System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic); 

     if (httpControllerRouteHandler != null) 
     { 
      httpControllerRouteHandler.SetValue(null, 
       new Lazy<HttpControllerRouteHandler>(() => new SessionHttpControllerRouteHandler(), true)); 
     } 
     config.Filters.Add(new AuthenticationFilter()); 
     config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html")); 
     // Web API routes 
     config.MapHttpAttributeRoutes(); 

     config.Routes.MapHttpRoute(
      name: "DefaultApi", 
      routeTemplate: "api/{controller}/{id}", 
      defaults: new {id = RouteParameter.Optional} 
     ); 
    } 
} 

public class SessionControllerHandler : HttpControllerHandler, IRequiresSessionState 
{ 
    public SessionControllerHandler(RouteData routeData) 
     : base(routeData) 
    { 
    } 
} 

public class SessionHttpControllerRouteHandler : HttpControllerRouteHandler 
{ 
    protected override IHttpHandler GetHttpHandler(RequestContext requestContext) 
    { 
     if (requestContext.HttpContext.Request.Headers.Get("Authorization") != null) 
     { 
      return new HttpControllerHandler(requestContext.RouteData); 
     } 
     return new SessionControllerHandler(requestContext.RouteData); 
    } 
} 

public class AuthenticationFilter : AuthorizationFilterAttribute 
{ 
    public override void OnAuthorization(HttpActionContext actionContext) 
    { 
     if (!Authorize(actionContext)) 
     { 
      actionContext.Response = new HttpResponseMessage(HttpStatusCode.Unauthorized); 
      return; 
     } 
     base.OnAuthorization(actionContext); 
    } 

    private static bool Authorize(HttpActionContext actionContext) 
    { 
     try 
     { 
      var request = actionContext.Request; 
      var authorization = request.Headers.Authorization; 
      var roles = new string[0]; 
      if (authorization != null) 
      { 
       if (authorization.Scheme == "Basic") 
       { 
        var decodedToken = Encoding.UTF8.GetString(Convert.FromBase64String(authorization.Parameter)); 
        var username = decodedToken.Substring(0, decodedToken.IndexOf(":", StringComparison.Ordinal)); 
        var password = decodedToken.Substring(decodedToken.IndexOf(":", StringComparison.Ordinal) + 1); 

        if(ValidUser(username, password)) 
        { 
         Thread.CurrentPrincipal = 
          new GenericPrincipal(new GenericIdentity(username, "Basic"), roles); 
         if (HttpContext.Current != null) 
         { 
          HttpContext.Current.User = Thread.CurrentPrincipal; 
         } 
         return true; 
        } 
       } 
      } 
      var context = request.Properties["MS_HttpContext"] as HttpContextWrapper; 
      // Use your session...which is up to your implementation 
      var user = context?.Session["User"]?.ToString(); 
      if (user != null) 
      { 
       Thread.CurrentPrincipal = new GenericPrincipal(new GenericIdentity(user, "Session"), roles); 
       return true; 
      } 
     } 
     catch (Exception) 
     { 
     } 
     return false; 
    } 
}