C# 使用基本身份验证向Katana托管的WebAPI添加cookie
我已经为Katana实现了一个基本的身份验证中间件(代码如下) (我的客户端托管在跨域上,而实际上是API) 如果出现以下情况,浏览器可以跳过飞行前请求 是真的: 请求方法是GET、HEAD或POST,而应用程序没有 设置除Accept、Accept Language、, 内容语言、内容类型或上次事件ID以及内容类型 标题(如果已设置)是以下内容之一: 应用程序/x-www-form-urlencoded多部分/form data text/plain 在javascript中,我在所有请求上设置身份验证头(使用jquery,beforeSend),以便服务器接受请求。这意味着上面将发送所有请求的选项请求。我不想那样C# 使用基本身份验证向Katana托管的WebAPI添加cookie,c#,asp.net-web-api,owin,katana,C#,Asp.net Web Api,Owin,Katana,我已经为Katana实现了一个基本的身份验证中间件(代码如下) (我的客户端托管在跨域上,而实际上是API) 如果出现以下情况,浏览器可以跳过飞行前请求 是真的: 请求方法是GET、HEAD或POST,而应用程序没有 设置除Accept、Accept Language、, 内容语言、内容类型或上次事件ID以及内容类型 标题(如果已设置)是以下内容之一: 应用程序/x-www-form-urlencoded多部分/form data text/plain 在javascript中,我在所有请求上设
function make_base_auth(user, password) {
var tok = user + ':' + password;
var hash = Base64.encode(tok);
return "Basic " + hash;
}
我该怎么做才能避开这件事?我的想法是,当用户通过身份验证时,将用户信息存储在cookie中
我在katana项目中也看到了一个Microsoft.Owin.Security.Cookies-这可能是我想要的,而不是我自己的基本身份验证吗
因此,我现在可以从webapi控制器将用户名/密码交换到cookie,我还可以直接使用基本方案进行不使用cookie的设置。如果web api和javascript文件来自不同的来源,您必须向请求添加授权标头或cookie标头,您不能阻止浏览器发送飞行前请求。否则将对任何受保护的web api造成CSRF攻击 您可以使用或启用CORS场景,它可以为您处理飞行前请求 OWIN cookie中间件负责设置auth cookie并对其进行验证。这似乎是你想要的 顺便说一句,基本身份验证挑战可能会导致浏览器弹出浏览器身份验证对话框,这在大多数web应用程序中是不可能的。不知道这是不是你想要的。相反,使用form post发送用户名和密码并与cookie交换是常见web应用程序的功能 如果您的计算机上安装了VS 2013 RC或VWD 2013 RC,则可以创建启用了个人身份验证的MVC项目。该模板使用cookie中间件和表单post登录。虽然它是MVC控制器,但您可以简单地将代码转换为Web API [更新] 对于预览请求,它将根据Cookie报头根据规范发送。您可以考虑添加页眉以使其在浏览器上缓存。 是另一个不需要飞行前准备的选项 [Update2]要通过owin中间件设置cookie,请使用以下示例代码
var identity = new ClaimsIdentity(CookieAuthenticationDefaults.ApplicationAuthenticationType);
identity.AddClaim(new Claim(ClaimTypes.Name, "Test"));
AuthenticationManager.AuthenticationResponseGrant = new AuthenticationResponseGrant(identity, new AuthenticationProperties()
{
IsPersistent = true
});
谢谢你的评论。我正在调查cookies auth的事情。我也在看MVC项目,但我一直在把它转换成webapi。MVC使用带有CheckPasswordAndSignInAsync的Owin.Identity东西——我没有这个。我会在几秒钟内用更多的信息更新我的问题。我已经有了cors。我只是不想发送两个请求,因为基本的身份验证,这就是为什么我开始研究cookies的原因。我想要两个选项,cookies和基本身份验证。我还有一个命令行工具,需要访问webapi。不确定两者是否都应该有mode=active,或者只是cookies。我更新了我的答案以回应您的评论。使用cookie无助于避免飞行前请求。您可以考虑飞行前缓存或JSONP作为选择。谢谢。您发布的最后一个代码段。我应该使用它,而不是Context.Authentication.sign,并且我仍然能够执行authenticateSync来再次读取它吗?
using Microsoft.Owin.Logging;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Infrastructure;
using System;
using System.Text;
using System.Threading.Tasks;
namespace Composite.WindowsAzure.Management.Owin
{
public class BasicAuthenticationHandler : AuthenticationHandler<BasicAuthenticationOptions>
{
private readonly ILogger _logger;
public BasicAuthenticationHandler(ILogger logger)
{
_logger = logger;
}
protected override Task ApplyResponseChallengeAsync()
{
_logger.WriteVerbose("ApplyResponseChallenge");
if (Response.StatusCode != 401)
{
return Task.FromResult<object>(null);
}
AuthenticationResponseChallenge challenge = Helper.LookupChallenge(Options.AuthenticationType, Options.AuthenticationMode);
if (challenge != null)
{
Response.Headers.Set("WWW-Authenticate", "Basic");
}
return Task.FromResult<object>(null);
}
protected override async Task<AuthenticationTicket> AuthenticateCoreAsync()
{
_logger.WriteVerbose("AuthenticateCore");
AuthenticationProperties properties = null;
var header = Request.Headers["Authorization"];
if (!String.IsNullOrWhiteSpace(header))
{
var authHeader = System.Net.Http.Headers.AuthenticationHeaderValue.Parse(header);
if ("Basic".Equals(authHeader.Scheme, StringComparison.OrdinalIgnoreCase))
{
string parameter = Encoding.UTF8.GetString(Convert.FromBase64String(authHeader.Parameter));
var parts = parameter.Split(':');
if (parts.Length != 2)
return null;
var identity = await Options.Provider.AuthenticateAsync(userName: parts[0], password: parts[1], cancellationToken: Request.CallCancelled);
return new AuthenticationTicket(identity, properties);
}
}
return null;
}
}
}
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = "Application",
AuthenticationMode = AuthenticationMode.Active,
LoginPath = "/Login",
LogoutPath = "/Logout",
Provider = new CookieAuthenticationProvider
{
OnValidateIdentity = context =>
{
// context.RejectIdentity();
return Task.FromResult<object>(null);
},
OnResponseSignIn = context =>
{
}
}
});
app.SetDefaultSignInAsAuthenticationType("Application");
public async Task<HttpResponseMessage> Get()
{
var context = Request.GetOwinContext();
//Validate Username and password
context.Authentication.SignIn(new AuthenticationProperties()
{
IsPersistent = true
},
new ClaimsIdentity(new[] { new Claim(ClaimsIdentity.DefaultNameClaimType, "MyUserName") }, "Application"));
return Request.CreateResponse(HttpStatusCode.OK);
}
var authContext = await Context.Authentication.AuthenticateAsync("Application");
if (authContext != null)
return new AuthenticationTicket(authContext.Identity, authContext.Properties);
var identity = new ClaimsIdentity(CookieAuthenticationDefaults.ApplicationAuthenticationType);
identity.AddClaim(new Claim(ClaimTypes.Name, "Test"));
AuthenticationManager.AuthenticationResponseGrant = new AuthenticationResponseGrant(identity, new AuthenticationProperties()
{
IsPersistent = true
});