将 ASP.NET 页面添加到 ASP 经典网站
我有一个 ASP 经典网站,我想添加一些新代码。我想开始使用 .net 进行编码。有没有一种简单的方法可以做到这一点。
我正在考虑一个调用我的 .net 页面的 iframe,但是我将如何共享需要登录我的 ASP 经典网站的用户。
如果我使用 iframe,共享用户的最佳技术是什么。我正在考虑在查询中传递加密信息:test.com?users=[mycrypteduser]
。但我该如何加密它呢?
I have an asp classic web site and I want to add some new code. I would want to begin to code with .net. Is there an easy way of doing this.
I was thinking an iframe that call my .net pages, but how will I share my user that need to be logged in my asp classic web site.
If I would use an iframe, what would be the best technique to share my user. I was thinking of passing the crypted info in query: test.com?users=[mycrypteduser]
. But how would I encrypt it?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我非常确定您可以在单个 Web 项目中混合 aspx 和 asp 文件。因此,创建 web-proj,然后将现有的网站文件放入其中(从 VS 内)。然后,慢慢地开始将现有站点重构为 aspx,尽可能逐页,当然,并创建新页面为 aspx。
使用 IFRAME 而不是这种方法可能会需要做更多的工作。但是,无论如何,您遇到了两个不相关的网站需要信任彼此经过身份验证的会话的问题 - 而且,这主要是通过这些网站在后台相互通信此类信息来解决的,而无需浏览器的直接参与。您需要能够更改两个站点上的代码(因此,您必须拥有这两个站点)。因此,如果您想走这条路,通常会这样做:
用户登录到您的 ASP 站点
您的 ASP 站点调用以下 Web 服务:您的 ASP.NET 站点,并通知它用户将在查询中携带特定的一次性身份验证令牌,并且该令牌应该受到信任。这里的重点是:Web服务必须受到身份验证机制的良好保护(否则您将面临巨大的安全问题);提到的 auth-token 在使用一次且仅一次后就会过期(否则,您将打开您的 ASP.NET 站点进行滥用)。通常,您的 ASP 应用程序会使用如下签名调用 ASP.NET 上的服务:
string GetAuthToken(string username)
。 ASP.NET 应用程序应将此信息作为记录存储在数据库中:用户名、一些随机且唯一的字符串值(例如 guid)、创建时间(至少精确到一秒)以及使用的时间。您的 ASP 应用程序从 ASP.NET 应用程序接收一次性身份验证令牌。
您的 ASP 应用程序需要将此令牌包含在 ASP.NET 站点页面框架上使用的 URL 中。
然后,您的 ASP 应用程序将向浏览器提供带有框架的页面。
浏览器开始显示页面,然后开始向外部 asp.net 页面显示框架
浏览器请求包含 auth-token 的 asp.net url
ASP.NET 站点收到请求并假定 auth-token令牌存在并且 有效的;否则,例外。有效令牌是:从未使用过(步骤 2 中提到的数据库中使用的时间),并且有效(其存在于数据库中)。当接收页面验证此令牌时,它会立即检查其是否已使用。最好将此逻辑作为一个原子操作(例如,如果您使用的是 MS SQL Server,则为存储过程)。这样,您可以在一个步骤中同时执行 get-token 和 mark-token-used。该 URL 必须是匿名的;无论如何,您必须在此站点上拥有 forms-auth,并且该特定处理程序应该可由匿名用户访问。如果您不喜欢抛出该异常,那么可以创建一个 HttpModule,它会检查每个请求,并且仅对那些匿名且包含身份验证令牌的请求执行操作(通过验证令牌,然后,根据情况,中断请求或让它执行);这样,您的框架页面不必关心身份验证,但它也必须受到表单身份验证保护。我个人会这样做(http 模块)。另外,如果您确定步骤 1 和步骤 2 之间会经过相对较短的时间(例如,最多几秒),那么请在您的令牌验证逻辑中包含令牌过期时间(验证时间不得晚于 token-create-time + 一定秒数,例如 30) - 只是为了额外的安全性。否则,如果您不实现过期 - 想象一下用户今天登录,这会生成这个永不过期的令牌,并且恶意用户以某种方式获取令牌字符串。然后,如果经过身份验证的用户从未访问过带有 ASP.NET 框架的页面,那么令牌从发布之日起数天、数月、数年都可以使用,即使在真实用户关闭其帐户之后也是如此。你不想要这个风险。如果登录页面没有重定向到带有框架的页面,则从该页面进行服务调用(每个会话一次)。理想情况下,令牌在创建后最多应在 30 秒左右过期。
如果令牌有效,则 ASP.NET 应用程序中验证令牌的部分将负责发出 forms-auth cookie。你会发现很多例子;关键词:FormsAuthentication、创建cookie、验证用户。确保除了将 cookie 插入到响应中(默认情况下由 FormsAuthentication 模块完成)之外,您还立即设置该当前/特定请求的身份,因为在您这样做之前,您的请求仍然是被认为是匿名的。如果你不这样做(人们也这样做,但我认为没有必要),你将不得不重定向该请求(这将迫使浏览器发送它刚刚在 302 中收到的 auth-cookie响应)。
最后,您的框架页面会收到用户签出的许可,并且他们可以查看该页面生成的内容。您的页面将 HTML 流式传输到浏览器,浏览器会在框架中显示该内容。
请注意,您将无法能够在页面和框架之间进行任何类型的客户端脚本(javascript)(安全原因),这将是我宁愿的另一种方式将 asp 与 asp.net 文件混合在一起(并慢慢将 asp 部分升级到 asp.net),前提是这在其他业务相关方面有意义。
请注意与出站请求相关的共享托管问题。有些主机会阻止所有出站流量;因此,如果您的 ASP 应用程序处于此类环境中,您将无法对 ASP.NET 进行 Web 服务调用。如果您的 asp 应用程序通过互联网进行其他/不相关的 http 调用(例如,它与第 3 方 Web 服务通信),那么您就很好(它会工作);否则,一定要以某种方式测试,因为你永远无法确定。此外,即使您的站点在您自己的环境中运行,公司通常也设有出站防火墙,因此您可能必须为此请求例外。
请记住,页面刷新不会成为问题,并且您不需要在每个经过身份验证的会话中多次调用 get-token。这是因为,在第一个框架加载后,浏览器将拥有来自 ASP.net 站点的 auth-cookie,并且令牌(即使存在于后续框架 url 中)将不会被验证(请记住,模块会验证匿名上的令牌)仅会话;参见步骤 8)。
请考虑调整两个站点之间的 cookie 过期设置。想象一下 asp.net auth cookie 在 asp auth cookie 过期之前就过期了:用户重新加载页面,iframe 显示 asp.net 上的登录页面 - 丑陋。因此,您的 asp.net auth cookie 可能应该设置为比 asp auth cookie 的过期时间更长(无论您将其设置为多久,都无法解决问题,因为将 cookie 设置为不过期很长时间是错误的时间,例如 7 天,或者理论上您的 ASP 站点的用户在看到一次页面后可能会一直坐在那里,而不会使用框架触摸该页面,并且您的 ASP.NET Cookie 将过期)。因此,可以做这样的事情:将 asp.net auth cookie 设置为在 20/30 分钟内过期(其中之一是默认超时值)。然后,让 ASP 应用程序了解此超时值。因此,更正我之前关于每次会话一次接听电话的说法。相反,每当您知道 asp.net cookie 已过期或可能即将过期时,应让 asp 调用 get-token 服务。换句话说,跟踪您对每个用户进行最后一次 get-token 调用的时间,如果自上次 get-token 调用以来已过去 15 分钟(例如,asp.net cookie 在 20 年后过期),请再次进行调用,更改框架 url,一旦现有的 asp.net cookie 过期(在此示例中,从该时刻起大约 5 分钟),框架将被验证。
我不断回来编辑这个答案:) 所以,cookie 过期问题 - 假设 asp.net cookie 在 20 分钟内过期,我告诉你每 15 分钟在框架上设置 url,同时我还告诉你制作令牌30 秒后过期 - 所以,这两件事是冲突的。嗯,我想知道这里最好的解决方案是什么...也许将 get-token 设置为更接近 asp.net cookie 过期时间(例如,在 18 分钟,但仍然小于 20),并将令牌设置为有效期,我不知道,3 分钟)。这将导致 18 + 3 = 21 与 asp.net cookie 过期时间重叠。这一切都是因为用户已经拥有了 asp.net cookie。因此,在发出第一个 cookie 18 分钟后,他们访问带有框架的页面,并且该页面决定获取另一个令牌。这会在 ASP.NET 站点上启动 token-ticker,并使用新令牌设置 iframe url。但是,由于现有的 asp.net cookie 仍然有效,因此新令牌甚至不会被验证(记住该模块仅使用令牌验证匿名请求?否则,如果您对每个请求都执行此操作,则会有太多的数据库命中),因此新的令牌不会立即使用。最终,asp.net cookie 将过期(2 分钟后),并且新令牌将得到验证。如果这是一个问题(如果我省略了一些基本上导致登录页面显示在框架内的用例),那么也许您可以实现一些其他机制来将这些 cookie 保留在适当的位置:也许可以将代码添加到位于 asp.conf 的登录页面。 net 在 ReturnUrl 中查找令牌(解码,然后加载到 NameValueCollection,然后将其作为正常的查询字符串查找进行查找),并且可能会向 asp 站点传达一些信息,以在帧到来时发出信号以重新请求令牌回来(以及我 新令牌将框架重定向回 asp.net。
这意味着,仅在这种情况下,将框架登录页面重定向回 asp 站点上的特殊 asp 脚本,该脚本将重新请求令牌,然后使用我告诉过您的 也许有一个涉及所有这些的标准(http://oauth.net/)。 ) 和 OpenID (http://openid.net/);这些方法类似于 StackOverflow 提供的 SO 帐户(Google、Yahoo 等)的替代登录方法。但是,这意味着您实际上将用户发送到 ASP.NET 站点进行登录,然后返回到显示 ASP.NET 站点内容的页面。也许您可以将其与我建议的 Web 服务调用结合起来(get-token ws,将 url 中带有令牌的顶部窗口重定向到 asp.net,asp.net 将进行身份验证并重定向回来,然后将显示带有框架的页面)。但是,您仍然遇到 cookie 过期问题,因为您需要不断地从 asp.net 站点获取内容(而 StackOverflow 只代表我与 Google 对话一次,即在登录期间,并且在登录期间不再与 Google 对话)会话),但是您可以简单地每 15 分钟重复登录到 asp.net 站点例程(获取令牌、重定向到那里、验证令牌、重定向回来),而不是我发送给您的那个混乱的 iframe 重定向路径。如果您在整个 ASP 站点级别每 15 分钟执行一次此操作,应该没问题 - 而且,在大多数情况下用户甚至不会注意到这一点,因为这些重定向很快。
如果这本书读起来很困难,我很抱歉。不过,我希望它能有所帮助。如果是的话+1:)
I'm pretty sure you can mix aspx and asp files in a single web project. So, create web-proj, then drop your existing website files to it (from within VS). Then, slowly start to refactor your existing site to aspx, as you can, page by page, and create new pages as aspx, of course.
Using IFRAME over this approach will be a lot more work that one may anticipate. But, regardless, you're hitting the problem of 2 unrelated websites in the need to trust each other authenticated sessions - and, this is primarily solved by those websites communicating such information to each other in the background, without the direct involvement of the browser. You need to be able to change the code at both sites (so, you must own both sites). So, if you want to go that route, typically it'd be done this way:
User logs in to your asp site
Your ASP site calls a webservice at your ASP.NET site and informs it that the user will be coming with a particular one-time auth-token in query and that it should be trusted. The emphases here are: the webservice must be well protected by authentication mechanism (otherwise you're risking a huge security issue); the auth-token mentioned should expire after it's used once and only once (otherwise, you're opening your asp.net site for abuse). Typically, your ASP app would call a service at ASP.NET with a signature like this:
string GetAuthToken(string username)
. ASP.NET app should store this info as a record in a database: username, some random and unique string value (e.g. guid), create time (with the precision of at least a second), and time used.Your ASP app receives a one-time auth token from ASP.NET app.
Your ASP app would need to include this token into the URL used on the frame to a page at ASP.NET site.
Your ASP app would then serve the page with a frame to the browser.
The browser starts displaying the page, then it gets to displaying the frame to external asp.net page
The browser requests the asp.net url, which contains the auth-token
ASP.NET site receives the request and it assumes that the auth token is present and valid; otherwise, exception. Valid token is: never used (time-used in db mentioned in step 2), and valid (its existence in db). As the receiving page validates this token, it immediately checks it off as used. It's the best to put this logic as one atomic operation (e.g. a stored procedure, if you're using MS SQL Server). This way, you can execute both get-token and mark-token-used in a single step. This URL must be anonymous; you must have forms-auth on this site anyways, and this particular handler should be reachable by anon user. If you dislike making that exception, then maybe create an HttpModule, which would inspect every request, and act only on those that are anonymous and are containing the auth-token (by validating the token, and then, as appropriate, interrupting the request or letting it execute); this way, your framed page doesn't have to care about authentication, but it must be forms-auth protected also. I personally would do this that way (http module). Also, if you're sure that relatively short period of time will pass between step 1 and step 2 here (e.g. few seconds max), then do include token expiration in your token-validation logic (validation time must not be later than token-create-time + some number of seconds, e.g. 30) - just for extra security. Otherwise, if you don't implement expiration - imagine a user logging in today, which generates this never-expiring token, and a malicious user somehow getting a hold of the token string. Then, if the authenticated user never visited the page with the asp.net frame, then the token would be usable days, months, years from the moment it's issued, even after the real user closed their account. You don't want this risk. If the login page doesn't redirect to the page with the frame, then make the service call from that page instead (once per session). Ideally, the token should expire 30 seconds or so max after it's created.
If the token is valid, the part of your ASP.NET app that is validating the token would then be responsible for issuing forms-auth cookie. You'll find a ton of examples out there; keywords: FormsAuthentication, create cookie, authenticate user. Make sure that besides inserting the cookie into the response (which is done by default by FormsAuthentication module), you also set the identity of that current/particular request immediately, as until you do, your request is still considered anonymous. If you don't do that (and people do this, but I don't think it's necessary), you will have to redirect that request (which would force the browser to send up the auth-cookie that it just received in the 302 response).
Finally, your framed page receives an ok that the user checks out and that they may view the content that that page generates. Your page streams HTML down to the browser, and the browser shows that content in the frame.
Note that you will not be able to have any sort of client-side scripting (javascript) going on between the page and the frame (security reasons), and that would be another way why I'd rather mix asp with asp.net files (and slowly upgrading the asp part to asp.net), provided that makes sense in other business-related aspects.
Beware of shared-hosting issues related to outbound requests. Some hosts block all outbound traffic; so, if your asp app is in such environment, you won't be able to make that webservice call to asp.net. If you have the asp app making other/unrelated http calls across the internet (e.g. it talks to 3rd-party web services), you're good (it'll work); otherwise, do test this somehow, as you can never be sure. Also, even if your site runs in your own environment, companies often have outbound firewalls in place, so, you might have to request an exception for this.
Remember that the page-refresh will not be an issue, and you do not need to make the get-token call more then once per authenticated session. This is because the browser will, after the first frame load, have an auth-cookie from asp.net site, and the token (even if present in subsequent frame url), will not be validated (remember, the module validates token on anonymous session only; see step 8).
Do think about adjusting cookie expiration settings between the 2 sites. Imagine asp.net auth cookie expiring before the asp auth cookie expires: user reloads the page, and the iframe shows the login page on asp.net - ugly. So, your asp.net auth cookie should probably be set up to expire longer than asp auth cookie (however long you set it as, you won't fix the problem, as it's either wrong to set the cookie to not expire for extremely long time, e.g. 7 days, or it's theoretically possible that a user of your asp site will sit through all that time without touching the page with the frame after they saw it once, and your asp.net cookie will expire). So, do something like this maybe: set asp.net auth cookie to expire in 20/30 minutes (one of those is the default timeout value). Then, have asp app be aware of this timeout value. So, correction to my previous statement of one get-taken call per session. Instead, have the asp call the get-token service every time that you know the asp.net cookie already expired or might expiring soon. In other words, keep track of when you made the last get-token call for each user, and if 15 min (for example, where asp.net cookie expires in 20) has passed since last get-token call, make it again, change the frame url, and the frame will be authenticated once the existing asp.net cookie expires (which would be approx 5 min from that moment, in this example).
I keep coming back to edit this answer :) So, cookie expiration problem - assuming asp.net cookie expires in 20 min, and I told you to set the url on the frame every 15 min, while I also told you to make the token expire in 30 sec - so, those 2 things are conflicting. Hm, I wonder what's the best solution here... Maybe set the get-token to happen closer to asp.net cookie expiration (as in, e.g, at 18 min, but still less than 20), and set the token to be valid for, I don't know, 3 minutes). This would result in 18 + 3 = 21 to overlap the asp.net cookie expiration. All this because the user already has asp.net cookie. So, 18 min after that first cookie was issued, they visit the page with the frame, and the page decides to get another token. This starts token-ticker on asp.net site, and it sets the iframe url with new token. But, since existing asp.net cookie is still valid, the new token will not even be validated (remember the module only validating anon requests with token? Otherwise, you'll have too many db hits if you do it on every request), so the new token will not be used immediately. Eventually, asp.net cookie will expire (in 2 min), and the new token will be validated. If this is a problem (if I omitted some use case that essentially results in the login page displayed within the frame), then maybe you can implement some other mechanism to keep these cookies in place: maybe add code to the login page at asp.net to look for the token in ReturnUrl (decode, then load into NameValueCollection, then look for it as a normal querystring lookup), and maybe communicate back to the asp site something that would signal it to re-request the token when the frame comes back (and what I mean by this, redirect the framed login page, in this case only, back to a special asp script at asp site, which would re-request the token, and then redirect the frame back to asp.net with new token.
I told you it'd be a lot of work. Perhaps there is a standard that involves all this. Check out OAuth (http://oauth.net/) and OpenID (http://openid.net/); those methods are similar to what StackOverflow is offering as login alternate to SO accounts (Google, Yahoo, etc). However, that implies that you actually send the user to the asp.net site to login, then come back to the page that displays content from asp.net site. Perhaps you can combine this with the webservice call that I suggested (get-token ws, redirect top window with token in url to asp.net, asp.net will authenticate and redirect back, then page with frame will display). However, you still have the cookie expiration problem, as you need to constantly be able to get content from asp.net site (whereas, StackOverflow, for example, talks to Google on my behalf only once, during login, and never again during the session), but instead of that messy iframe redirect path that I send you, maybe you can simply repeat the login-to-asp.net-site routine every 15 min (get token, redirect there, validate token, redirect back). If you do this every 15 min at the whole asp site level, you should be fine - and, the user won't even notice this in most cases, as those redirects will be quick.
I'm sorry if this is a difficult read. I hope it helps, though. +1 if it does :)
您可以创建一个新的 ASP.NET Web 应用程序,并提取所有经典 ASP 页面。然后,当您部署时,ASP.NET Web 应用程序将覆盖您的经典 ASP。
如果您使用某种集成身份验证,则 ASP 和 ASP.NET 页面都将有权访问相同的身份。如果您在 ASP 应用程序中创建了自己的身份验证层,则需要在 ASP.NET 中重新创建它(例如,创建读取/写入 ASP 页面正在使用的相同身份验证 cookie 的类)。
然而,从长远来看,这将始终在 ASP 和 ASP.NET 之间带来一些开发摩擦,因此,如果您计划将整个应用程序从经典 ASP 逐步转换为 ASP.NET,我实际上只会建议这种方法。
You can create a new ASP.NET web application, and pull all of your classic ASP pages. Then when you deploy, the ASP.NET web application will overlay your classic ASP.
If you are using some sort of integrated authentication, both the ASP and ASP.NET pages will have access to the same identity. If you created your own authentication layer in the ASP application, you will need to recreate this in ASP.NET (for example, create classes that read/write the same authentication cookies that the ASP pages are using).
However, long term this will introduce some development friction switching between ASP and ASP.NET all the time, so I would really only suggest this approach if you are planning to incrementally convert your entire application from classic ASP to ASP.NET.
您可以使用 NSession http://nsession.codeplex.com/ 一个开源项目,其目标是允许 ASP Classic以与 ASP.NET 访问它们相同的方式访问 ASP.NET 进程外会话存储,从而与 ASP.NET 共享会话状态。
我已经尝试过了,确实有效。
快乐编码!
You can use NSession http://nsession.codeplex.com/ an open source project with objective to allow ASP Classic to access ASP.NET out-of-process session stores in the same way that ASP.NET accesses them, and thus share the session state with ASP.NET.
I have tried it out and it really works.
Happy Coding!!
当我遇到这个问题时,我发现最好的解决方案通常是使用.NET作为Web服务,并在ASP页面中使用HTTPRequests将数据拉入您的ASP页面。
当与 ASP 和 Classic ASP 共享会话时,最常见的方法是不在 ASP 中使用会话,而实际上使用 Cookie、数据库 Cookie 来进行实际会话验证,通常通过 GUID。
When i face this issue, i have found the best solution is usually to use .NET as a web service, and use HTTPRequests in the ASP page to pull the data into your ASP page.
When sharing sessions with ASP and Classic ASP, the most common way is to NOT USE SESSIONS IN ASP, and Use Cookies, Database Cookies actually for the actual session verification, by GUID usually.