Я так и не нашел ответ, так сказать, но я выбрал метод:
Итак, я выбрал шаблон, в котором я пишу свой виджет JavaScript и HTML, используя предложенную jQuery UI Widget Factory . Это позволяет моему потребителю реализовать виджет, используя простой синтаксис, такой как:
<script src="widget.js"></script>
$('#someElement').myWidget({ encryptionUrl: handlerPath });
Теперь вы заметили, что как часть моего виджета я прошу потребителя передать "handlerPath". «Обработчик» - это просто контроллер Microsoft MVC, который отвечает за получение авторизованного пользователя и шифрование вызова.
Итак, обработчик в моем приложении выглядит примерно так ...
[Authorize]
public JsonpResult GetToken(string body, string title, string sender)
{
Packet token = new Packet();
try
{
// Get the widget host's public cert
string publicKey = "some.ssl.key.name.here";
// Get the consumer host's private cert
string privateKey = "this.consumers.ssl.key.name.here";
// Build a simple message object containing secure details
// Specifically, the Body will have action items (in JSON) from my widget
// The User will be generated from the consumer's backend, thus secure
Message message = new Message(){
Body = body,
Title = title,
User = System.Web.HttpContext.Current.User.Identity.Name,
EncryptionServerIP = Request.UserHostAddress,
Sender = new Uri(sender),
EncryptionTime = DateTime.Now
};
PacketEncryption encryption = new PacketEncryption();
// This class just wraps basic encryption and signing methods
token = encryption.EncryptAndSign(message, publicKey, privateKey);
token.Trust = "thisConsumerTrustName";
}
catch (Exception exception)
{
throw;
}
return this.Jsonp(token);
}
Теперь у меня есть зашифрованный «токен», который был зашифрован с использованием открытого ключа хоста виджета и подписан с использованием личного ключа потребителя виджета. Этот «токен» передается обратно в виджет через JSONP с сервера-потребителя.
Мой виджет затем отправляет этот «токен» (все еще как JSONP) на свой хост-сервер. Сервер размещения виджетов имеет расшифровывающую логику, которая выглядит примерно так:
public Message DecryptAndVerify(Packet packet, string requestIP)
{
if (packet == null) throw new ArgumentNullException("packet");
if (requestIP == null) throw new ArgumentNullException("requestIP");
Message message = new Message();
try
{
// Decrypt using the widget host's private key
RSAEncryption decrypto = new RSAEncryption("MyPrivateKey");
// Verify the signature using the "trust's" public key
// This is important because like you'll notice, I get the trust name
// from the encrypted packet. I then maintain a "trust store" mapping
// in my web.config, or SQL server
RSAEncryption verifyo = new RSAEncryption(GetPublicKeyFromTrust(packet.Trust));
string decryptedJson = decrypto.DecryptString(packet.EncryptedData);
// Verify the signature
if (!verifyo.Verify(decryptedJson, packet.Signature))
{
Exception ex = new Exception("Secure packet was not verified. Tamper evident");
throw ex;
}
// If the message is encrypted correctly, turn it into a message object
message = decryptedJson.FromJson<Message>();
// Verify the ip
if (message.EncryptionServerIP != requestIP)
{
Exception ex = new Exception("Request IP does not match encryption IP. Tamper evident");
throw ex;
}
// Verify the time
if ((DateTime.Now - message.EncryptionTime).Seconds > 30)
{
Exception ex = new Exception("Secure packet is too old");
throw ex;
}
}
catch (Exception ex)
{
throw ex;
}
return message;
}
Идея состоит в том, что виджет JavaScript определяет безопасные действия, которые хочет выполнить конечный пользователь. Затем он перезванивает своему хосту (используя путь обработчика, предоставленный потребителем) и запрашивает зашифрованный токен. Этот токен содержит IP-адрес абонента, временную метку, текущее имя пользователя AD и набор действий, которые необходимо выполнить. Как только виджет получает токен, он передает его на свой хост-сервер, после чего сервер проверяет, является ли он
- Подписано и зашифровано надлежащим образом в соответствии с предопределенными довериями
- Не старше 30 секунд
- С того же IP-адреса, что и первоначальный запрос к серверу потребителя
После того, как я определю, что эти проверки являются действительными, я могу воздействовать на действия пользователя, создавая идентификатор WindowsPrincipal из строкового имени пользователя следующим образом:
WindowsPrincipal pFoo = new WindowsPrincipal(new WindowsIdentity("username"));
bool test = pFoo.IsInRole("some role");
Все сказано и сделано, я установил доверенный запрос от потребителя виджета, и мне больше не нужно запрашивать аутентификацию.
Надеюсь, это поможет вам. Он работает в моей внутренней среде в течение месяца для обеспечения качества и пока работает отлично.