使用不同的授权属性,控制器可以从不同的环境访问相同的逻辑



我有一个ASP.NET MVC网站,我的大多数控制器都用Authorize属性装饰,以强制表单身份验证。

我即将通过Facebook应用程序在Facebook上提供此网站,但对于我的FB用户,我想使用不同的身份验证/授权,我想在我的控制器上使用CanvasAuthorize属性。

问题是,我不能在我的控制器/操作上同时使用这两个,因为这两个控制器/操作都将被强制访问相关操作,但我只想为正常网站授权,当从FB(通过FB应用程序)访问网站时,我只想使用CanvasAuthorize。

我开始

  1. 将我现有的控制器大量重构为"controllerhelpers"
  2. 使现有控制器(具有authorize属性)使用controllerhelpers相关方法
  3. 为FB应用程序创建新的控制器(用CanvasAuthorize修饰),这些控制器还使用相关的controllerhelper方法

但这是一项艰巨的工作,我不确定这是一条路,还是有一种更容易、更优雅的工作方式。

当然,我想使用相同的视图,在我的cshtmls中,我使用特定控制器的Url.Action方法,因此,根据我目前的方法,当我在cshtmls中插入操作路径(例如jQuery ajax Url属性)时,我必须做出if语句,例如,当使用普通网站时使用"PersonalController",当网站用作FB应用程序时使用"FBPersonalController"。

在这种情况下,PersonalController用[Authorize]修饰,FBPersonalController则用[CanvasAuthorize]修饰。

因此,我们非常感谢任何反馈;)

谢谢!

Xoyoja的回答让我找到了这个解决方案。我不把它标记为"已接受的答案",因为我正在评估它,但也许它值得讨论:

不,不是所有的都应该装饰。但在你的提议下,我得出了以下结论:

IEnumerable<Func<ControllerContext, ActionDescriptor, object>> conditions =
                new Func<ControllerContext, ActionDescriptor, object>[] { 
                    (ctrlCtx, actDesc) =>
                        {
                            if(FacebookWebContext.Current.SignedRequest != null)
                            {
                                return new CanvasAuthorize();
                            }
                            else
                            {
                                if(ctrlCtx.Controller.GetType() == typeof(AccountController)
                                    && actDesc.ActionName == "LogOn")
                                {
                                    return null;
                                }
                                return new AuthorizeAttribute();
                            }
                        },
            };

当我的网站从FB访问时,SignedRequest似乎不是null,所以可以使用CanvasAuthorize。

如果我的网站是从正常发布的url访问的,那么我使用AuthorizeAttribute。

AccountController和"LogOn"操作特定逻辑是允许从公共url登录网站所必需的。来自Facebook的Context包含Facebook UserID,它将隐含地进行身份验证。

我仍然在考虑影响,最坏的情况,后门,这是否会伤害我。

是否可以使用条件筛选器同时支持[AAuthorize]和[CanvasAuthorize]?正如我在一个简单的ASP.NET MVC3应用程序中测试的那样,它是有效的。你认为这有帮助吗?

另一方面,一个很好的解决方案是,如果你能改变你的设计,把身份验证的东西放在一个地方,也就是说,FormsAuthenticationService、FacebookAuthenciationService和OpenIDAuthenticationServer实现了一个名为"IAuthenticationServices"的接口。完成Facebook OAuth流后,调用标准的FomsAuthentication.SetAuthCookie方法。然后Authorize属性应该可以正常工作。请参阅此问题并检查此处的代码片段(Create.aspx和SessionController.cs)。请评估。

最新更新