给出一个现有的webforms应用程序,其web.config具有...
<sessionState cookieless="true" ...
我已经在项目中添加了一个webapi,但这意味着任何进入的请求都会获得302响应并在网址中给出“cookie”。
如何使sessionstate cookieless忽略某个路径(如/ api)
答案 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;
}
}