我正在试图弄清楚如何在SS中支持ws-security作为身份验证机制。
我的目标是让所有DTO都在json,xml,saop11,saop12中处理(该部分已在SS documentation之后实现)并支持多个auth提供程序,包括一个基于ws-security的提供程序。 DTO不应受到认证机制的影响。
如果使用saop12发送DTO,soap消息将是元数据端点(soap envelope + soap body)生成的调用样本以及包含WS-Security用户名的ws-security元素的soap头验证。一个dedidcated“soap auth提供者”应检查该消息,使用soap标题 - >安全元素并执行身份验证。
与soap auth提供程序一起,我可能有其他内置的auth机制,可用于json消息和/或其他格式。
基于我不知道的ws-security存在SS身份验证提供程序?
有任何指导方针,建议,实施方法吗?
目前比我的解决方案
// APPHOST
Plugins.Add(new AuthFeature(() => new CustomAuthUserSession(),
new IAuthProvider[] {
new CustomCredentialsAuthProvider(),
new SoapMessageAuthProvider(),
}
));
// required by the SoapMessageAuthProvider to inspect the message body serching for ws-security element
PreRequestFilters.Add((httpReq, httpRes) =>
{
httpReq.UseBufferedStream = false;
});
我将SoapMessageAuthProvider基于内置的BasicAuthProvider。 由于SoapMessageAuthProvider需要在ws-security元素的每个调用serching上检查传入消息,因此我实现了IAuthWithRequest
public void PreAuthenticate(IRequest req, IResponse res)
{
//Need to run SessionFeature filter since its not executed before this attribute (Priority -100)
SessionFeature.AddSessionIdToRequestFilter(req, res, null);
var userPass = ExtractSoapMessageUserNameCredentials(req);//req.GetBasicAuthUserAndPassword();
if (userPass != null)
{
var authService = req.TryResolve<AuthenticateService>();
//var response = authService.Post(new Authenticate
//{
// provider = Name,
// UserName = userPass.Value.Key,
// Password = userPass.Value.Value
//});
authService.Request = req;
var session = authService.GetSession(false);
var userName = userPass.Value.Key;
//Add here your custom auth logic (database calls etc)
var userAuth = new UserAuth();
userAuth.Id = 10;
userAuth.UserName = userName;
var holdSessionId = session.Id;
session.PopulateWith(userAuth); //overwrites session.Id
session.Id = holdSessionId;
session.IsAuthenticated = true;
session.UserAuthId = userAuth.Id.ToString(CultureInfo.InvariantCulture);
session.UserAuthName = userName;
}
}
//called by CustomAuthUserSession.IsAuthorized
// to be reviewed to keep isolated from other providers
public override bool IsAuthorized(IAuthSession session, IAuthTokens tokens, Authenticate request = null)
{
if (request != null)
{
if (!LoginMatchesSession(session, request.UserName))
{
return false;
}
}
return !session.UserAuthId.IsNullOrEmpty();//filled by PreAuthenticate
}
自定义会话调用每个提供程序,包括SoapMessageAuthProvider,同时通过PreAuthenticate方法,使用经过身份验证的用户数据填充会话。
public class CustomAuthUserSession : AuthUserSession
{
public override bool IsAuthorized(string provider)
{
var tokens = ProviderOAuthAccess.FirstOrDefault(x => x.Provider == provider);
return AuthenticateService.GetAuthProvider(provider).IsAuthorizedSafe(this, tokens);
}
...
}
我需要确保始终为soap消息w / ws-security调用soap提供程序,并且该调用不应由其他提供程序进行身份验证: - 用户通过CustomCredentialsAuthProvider获取身份验证(基于cookie) - 用户在携带auth cookie的Web请求中调用service supply json消息 - 另一个呼叫发送携带相同身份验证cookie的soap消息:由于消息是soap格式并且包含soap头ws-security,因此应仅使用soap提供程序使用soap头ws-security对消息进行身份验证
我理解这是一个奇怪的场景,但我正在努力了解如何实现它。
我的猜测是通过ServiceStack.AuthenticateAttribute第72行
发生的matchingOAuthConfigs.OfType<IAuthWithRequest>()
.Each(x => x.PreAuthenticate(req, res));