我正在建立一个新项目,我正在讨论如何开发它。总体情况是开发一个可消费的JavaScript小部件,其他内部开发人员可以将其嵌入到他们的Web应用程序中。诀窍是消费者需要能够告诉我AD用户当前登录到他们的页面...然后我需要相信传递的用户名来自消费者并且没有被外部来源篡改
整体解决方案需要在消费方面进行非常简单的设置,不需要编译代码。它还需要在ASP.net和PHP应用程序中都能正常运行(因此我决定使用JavaScript)。
总的来说,它有点像Oauth解决方案......除了域之间的信任可以是固有的,因为我已经知道公司中的每个用户都信任主机域。
我开始将其删除并陷入困境。我的想法是,我基本上会托管客户端主机可以嵌入其页面的JavaScript文件。在他们的页面加载周期中,他们可以初始化我的JavaScript小部件并传递一个纯文本用户名(我真正需要的)。不知怎的,我会在客户端主机的网页和我的小部件之间建立一个安全的信任,这样第三方就不可能将我的小部件嵌入到虚假的网页中,并在他们自己以外的用户下发送动作命令。 / p>
我希望这对某人有意义。
答案 0 :(得分:1)
我还没有真正找到答案,但我决定采用一种方法:
所以,我决定使用建议的jQuery UI Widget Factory编写JavaScript和HTML小部件的模式。这允许我的消费者使用简单的语法来实现小部件,如:
<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用户名以及要完成的操作包。一旦小部件收到令牌,它就会将其传递给它自己的主机服务器,此时服务器会检查以确保它是
在我确定这些检查有效后,我可以通过从字符串用户名创建WindowsPrincipal标识来执行用户的操作,如下所示:
WindowsPrincipal pFoo = new WindowsPrincipal(new WindowsIdentity("username"));
bool test = pFoo.IsInRole("some role");
所有的说法和完成,我已经从小部件使用者建立了一个受信任的请求,我不再需要提示进行身份验证。
希望这会帮助你。它已经在我的内部环境中运行了大约一个月的QA,到目前为止它的工作效果很好。