ASP.Net MVC 自定义身份验证
我有一个 Asp.Net MVC Web 应用程序位于一个网站内,该网站仍然主要由 delphi 管理。 安全性目前由创建 cookie 的 delphi 管理。
已决定通过提取 cookie 详细信息并将其传递到导入的 Delphi DLL 来对 ASP.Net 应用程序中的用户进行身份验证,该 DLL 根据用户是否有效返回 true 或 false。
我的计划是使用表单身份验证,但不是将用户重定向到表单,而是调用 delphi 包装器,如果成功,则将用户重定向到原始 url。这样做的好处是,当安全性迁移到 .Net 时,身份验证框架已经存在,只是实现需要更改。
public ActionResult LogOn(SecurityCookies model, string returnUrl)
{
try
{
if (model != null)
{
Log.DebugFormat("User login: Id:{0}, Key:{1}", model.UserId, model.Key);
if (authenticator.UserValid(model.UserId, model.Key, 0))
{
FormsService.SignIn(model.UserId, false);
return Redirect(returnUrl);
}
}
...
请注意,SecurityCookie 是由自定义绑定类从 delphi 生成的 cookie 生成的 - 这效果很好。
对delphi dll 的调用也可以正常工作。
我必须克服的问题是几乎所有对 .Net 应用程序的调用都是 ajax 请求。 然而,当用户未登录时,浏览器会由于重定向而发出 3 次调用: 1)原始ajax请求 2)重定向到~/Account/Logon(上面的代码) 3) 重定向回原始 ajax 请求
虽然跟踪发回客户端的响应,表明步骤 3 返回了正确的数据,但总体而言,该过程因尚未确定的原因而失败。 只需在客户端上单击“刷新”即可,因为现在用户已通过身份验证,并且不会重定向到 ~/account/Logon。
注意我的客户端 jQuery 代码如下: $.getJSON(requestString, 函数(数据) { //对数据做一些事情 });
有没有一种方法可以更改表单身份验证过程,以便在用户未经过身份验证时不重定向到 URL,而是可以运行其他代码?我希望用户的浏览器完全看不到身份验证的发生。
I have an Asp.Net MVC webapplication sitting inside a website still largely managed by delphi.
Security is currently managed by delphi which creates cookies.
It has been decided to authenticate users within the ASP.Net application by extracting the cookie details and passing them to an imported Delphi DLL which returns true or false depending on whether the user is valid.
My plan was to use Forms authentication, but instead of redirecting the user to a form instead call the delphi wrapper and if successful, redirect the user to the original url. This gives the benefit that when security is migrated to .Net, the authentication framework will already exist, just the implementation will need to change.
public ActionResult LogOn(SecurityCookies model, string returnUrl)
{
try
{
if (model != null)
{
Log.DebugFormat("User login: Id:{0}, Key:{1}", model.UserId, model.Key);
if (authenticator.UserValid(model.UserId, model.Key, 0))
{
FormsService.SignIn(model.UserId, false);
return Redirect(returnUrl);
}
}
...
Note that the SecurityCookies are generated by a custom binding class from the delphi generated cookie - this works well.
The call to the delphi dll also works ok.
The issue I have to overcome is that nearly all of the calls to the .Net application are ajax requests.
However when the user is not logged in, the browser makes 3 calls due to the redirects:
1) Original ajax request
2) Redirect to ~/Account/Logon (code above)
3) Redirect back to original ajax request
Although tracking the responses posted back to the client, show that Step 3 returns the correct data, overall the process fails for an as yet undetermined reason.
Simply clicking refresh on the client works because now the user is authenticated and the redirect to ~/account/Logon doesn't occur.
Note my client jQuery code is as follows:
$.getJSON(requestString, function (data) {
//do something with the data
});
Is there a way of changing the Forms Authentication process so that instead of redirecting to a Url when the User is not authenticated, I can run some other code instead? I'd like the fact that authentication has taken place to be completely invisible to the User's browser.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
如果要对请求进行身份验证,可以在 global.asax.cs 中通过定义 Application_AuthenticateRequest 方法来执行此操作。在这里您可以使用导入的delphi dll读取自定义cookie并设置Context.User。 asp.net 中的所有授权均基于 HttpContext 中设置的用户。 Application_AuthenticateRequest 方法的实现示例:
如果 cookie 无效,则您不会在上下文中设置用户。
然后,您可以创建一个 BaseController,所有控制器都将从该 BaseController 继承,以检查上下文中提供的用户是否经过身份验证。如果用户未经过身份验证,您可以返回 HttpUnauthorizedResult。
在您的 web.config 中:
因为您不希望请求重定向到登录页面。
If you want to authenticate the request, the place to do this is in global.asax.cs by defining the Application_AuthenticateRequest method. Here you can read out the custom cookies with the imported delphi dll and set the Context.User. All authorization in asp.net is based on the user that is set in the HttpContext. An example of an implementation of the Application_AuthenticateRequest method:
If the cookie is not valid then you won't set a user in the context.
You can then create a BaseController which all your controllers will inherit from that checks if the user that is provided in the context is authenticated. If the user is not authenticated you can return a HttpUnauthorizedResult.
And in your web.config:
because you don't want the request to be redirected to a login page.
我将回答这个具体问题的一部分
不,没有。我编写了一个与您的类似的登录系统,它构建在表单身份验证之上,并且没有可扩展点的事实使其成为一个完整的 PITA 编写。
我能够覆盖内置行为的方法是使用 HttpModule,该模块监视重定向到表单身份验证 URL,然后拦截该操作并让我处理它。
另请注意,为了能够在 MVC3 中依赖此代码,您可能还需要指定应用程序设置
I'm going to answer a part of this specific question
No there is not. I wrote a login system that is similar to yours being that it is built ontop of forms authentication and the fact there is no extensibility point made it a complete PITA to write.
The way I was able to override the built in behavior was using a HttpModule that monitors for redirects to the forms auth URL and then to intercept that action and lets me handle it.
One other note, to be able to rely on this code in MVC3 you may also need to specify the app settings
夫妇的事情。
首先,由于您显然处于控制器操作中,因此应该替换
为
其次,我通常更喜欢不使用ajax调用来进行身份验证。用户应该明确地从未经身份验证的状态转移到经过身份验证的状态。
第三,如果您必须在通常执行重定向的地方执行 ajax 调用,您可以执行以下两种操作之一。在控制器中,您可以通过调用扩展方法 IsAjaxRequest()(如果是,则返回 true)来确定它是 ajax 请求,如果是 ajax 请求,则分支不同的结果。其次,如果您返回一个重定向,那么它将向客户端返回一个 HTTP 重定向,Ajax 客户端代码应该能够读取并响应该重定向(例如,通过读取位置,然后对其执行 ajax 获取)。再次强调,我不推荐这门课程,但这是可能的。
最后,作为一个完全的左转......您是否考虑过单独保留表单身份验证,而使用自定义的 MembershipProvider?您可以使用它通过 Delphi 验证成员资格,然后使用普通 FormsAuth 对象设置客户端 cookie,就像在 MVC 中的示例 AccountController 中所做的那样。
Couple things.
First, since you're apparently in a controller action, you should replace
with
Second, I generally prefer to not use ajax calls to do authentication. Users should explicitly move from unauthenticated to authenticated states.
Third, if you must do ajax calls where you would normally do redirects, you can do one of two things. In your controller, you can determine it's an ajax request by calling the extension method IsAjaxRequest() (returns true if it is) and branching a different result if it is an ajax request. Second, if you return a Redirect, then it will return to the client a HTTP redirect, which the Ajax client code should be able to read and respond to (e.g. by reading the Location and then doing an ajax fetch on that). Again, I don't recommend this course, but it's possible.
Finally, as a complete left turn... have you considered leaving forms auth alone and instead using a custom MembershipProvider? You can use that to validate membership via Delphi and then set the client cookies using the normal FormsAuth objects like they do in the sample AccountController in MVC.