避免某些路径的Cookieless 302重定向

时间:2017-10-10 03:31:33

标签: asp.net-web-api webforms

给出一个现有的webforms应用程序,其web.config具有...

<sessionState cookieless="true" ...

我已经在项目中添加了一个webapi,但这意味着任何进入的请求都会获得302响应并在网址中给出“cookie”。

如何使sessionstate cookieless忽略某个路径(如/ api)

1 个答案:

答案 0 :(得分:0)

我会回答我自己的问题,因为找到正确的信息并找出正在发生的事情是非常痛苦的。

我想使用WebApi v2并且能够从现有的基于webforms会话的应用程序中使用,并且还可以使用任何其他更标准的身份验证策略来使用它。

以下代码是如何将WebApi嵌入WebForms并支持基于会话和基本身份验证的完整示例。

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

我获得重定向的关键原因是由于代码恢复了webapi的会话状态。如果您返回 SessionControllerHandler 并且没有会话,那么它将执行重定向以获取Cookie,并且在无cookie模式下,它会将其添加到URL。这对我正在使用的代理来说是一场灾难。但是,通过检查它是否正在尝试使用标准的Authorization mechanisim并返回正常的WebApi路由处理程序,它不会通过302重定向。然后它会过滤到Authroization函数,该函数确定它是使用标准授权还是基于会话然后验证(此部分需要根据您在应用程序中的操作进行自定义)

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;
    }
}
相关问题