ASP.NET MVC / Web API 自定义身份验证

4
我有一个ASP.NET MVC 4 / Web API混合应用程序,验证是由现有应用程序处理的。在查看保护这些类型应用程序的方法时,大多数文章都指向使用Forms Authentication以及在要保护的MVC和API控制器/操作上使用[Authorize]属性。我想使用[Authorize]属性,因为它将处理MVC路由和API路由,但不确定如何做到没有实际表单并使用内置的成员身份验证提供程序。
我应该采用像这里描述的简单方法吗?还是应该创建一个自定义成员身份验证提供程序来处理逻辑?
为了明确,工作流程如下:
1.用户通过现有的身份验证门户登录。 2.如果经过身份验证,则他们将连同一些附加数据(例如用户名和电子邮件)重定向到我的应用程序中(因此不需要传输密码)。 3.我的应用程序设置一个身份验证cookie,允许用户继续使用该应用程序。
非常感谢任何帮助。
3个回答

3
  • 选项1

如果您现有的登录门户网站使用表单身份验证,则可以在应用程序之间共享加密密钥,以便它们可以读取在登录门户网站中创建的身份验证 cookie:

如何在Web表单和MVC2应用程序之间共享基于.NET(C#)的已认证会话?

  • 选项2

如果您的登录门户网站没有使用表单身份验证,则可以保留现有流程,但添加一步手动创建身份验证 cookie。有很多变化,但这个问题展示了一个更高级别的方法,以及答案中的更低级别的方法:

如何手动创建身份验证 cookie而不是默认方法?

这还要求应用程序之间的加密配置相同。

  • 选项3
否则,你只能使用SSO协议进行交接。您可以保留现有的身份验证流程用于登录门户网站,但需要添加其他代码来协调SSO交接到其他应用程序。除了#1和#2中使用的加密cookie方法之外,SSO出现是因为几乎没有其他安全选项可用于执行浏览器重定向和通信身份验证。
创建自己的基于cookie的方法是有风险的,可能会打开您未预见的安全漏洞。
“我应该选择像here描述的简单方法吗?”
那个例子的重要之处在于不清楚 SetAuthCookie(username,... 中的用户名来自何处。这个问题暗示用户将登录到附加的应用程序,并且该应用程序将查询Web服务以确定该登录是否有效。在这种情况下,它不是具有专用登录门户网站的单一登录,而是每个应用程序收集登录信息并询问Web API是否有效。在您的情况下,您不想在每个门户网站中收集登录信息,而是检测到他们已经登录到专用登录门户网站。
因此,问题在于登录门户如何以安全的方式告诉您在调用SetAuthCookie(username, ...username是什么。这正是SSO的作用。使用SSO交接,一个站点可以以安全的方式告诉另一个站点:“我正在将Bob123发送给你,你可以确定它确实是Bob123而不是其他人”。
选项#1和#2通过让登录门户设置cookie,并通过在应用程序之间共享密钥,使其他应用程序能够安全地读取该cookie来解决此问题。
请注意,您不能使用任何cookie来实现这一点。表单身份验证cookie以特定方式构建,以防止伪造cookie和其他篡改。
如果您跨越域,则SSO成为您唯一的选择,因为在一个域中编写的cookie无法在另一个域中读取(浏览器仅提交当前域的cookie)。
有多个子域共享根域的表单身份验证的解决方法: 正确创建跨域表单身份验证cookie

有各种各样的方法可以使用加密信息重定向到另一个站点,并让该站点编写表单身份验证 cookie,但其中大部分都是可怕的 hack,其复杂程度与 SSO 一样。


哇,非常感谢您的全面回答。我认为选项1和2对我来说都不适用,所以像您和@Wiktor提到的那样,我需要研究SSO。您能推荐一些关于如何进行SSO交接的好文章、博客、stackoverflow帖子等吗? - Bart Jedrocha

1
你似乎想要重新发明单点登录协议。相反,你应该学习现有的SSO协议,比如OAuth2或WS-Federation。
通常情况下,SSO协议的工作方式与你期望的“工作流程”类似。确切的流程可能会有所不同,但始终是身份提供者对用户进行身份验证/授权,并且IdP以某种方式将此信息传递给使用它的应用程序(例如,应用程序发出自定义cookie以建立用户身份验证)。 Authorize属性不仅适用于Forms身份验证。任何设置请求生存期主体的身份验证模块都可以替换Forms。例如,Session身份验证模块现在经常被使用,因为它解决了Forms模块的一些特定问题(例如无法持久化长时间用户数据)。
如果你需要一本好的免费SSO书籍,请看这里:

http://msdn.microsoft.com/en-us/library/ff423674.aspx


感谢您的输入。我熟悉SSO,但不幸的是,我无法控制现有的身份验证应用程序,并且似乎需要一个定制解决方案(即使这可能是重新发明轮子)来处理他们现有的身份验证应用程序。 - Bart Jedrocha
1
您可以让现有应用程序处理身份验证,但对于您问题中的第二步,请使用SSO来交接给其他应用程序。 - AaronLS
感谢您提供的书籍链接。那里有很多有用的信息。 - Bart Jedrocha

0
你可以使用Owin来处理这个问题。以下是我正在使用的一个代码片段,用于使用Facebook进行认证,它还使用了cookie。
using Microsoft.AspNet.Identity;
using Microsoft.Owin;
using Microsoft.Owin.Security.Cookies;
using Owin;

namespace ASPNetMVC53rdPartyAuth
{
    public partial class Startup
    {

      public void ConfigureAuth(IAppBuilder app)
      {
        // Enable the application to use a cookie to store information for the signed    
        app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
            LoginPath = new PathString("/Account/Login")
        });
        // Use a cookie to temporarily store information about a user logging in with a              
        // third party login provider
        app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);

        // third party login providers: 


        // You have to register this app at https://developers.facebook.com/ and get the     
        //appId and appSecret.   
        // Facebook requires SSL, so that need to be enanbled.  Project url can be found  
        // under project properties and can be localhost.
         app.UseFacebookAuthentication(
           appId: "xxxxxxxxxxxxxxxx",
           appSecret: "xxxxxxxxxxxxxxxx");
         );           
      }
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接