简体   繁体   English

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

[英]ASP.NET MVC / Web API Custom Authentication

I have ASP.NET MVC 4 / Web API hybrid application. 我有ASP.NET MVC 4 / Web API混合应用程序。 The authentication is being handled by an existing application. 身份验证由现有应用程序处理。 In looking at securing these types of applications, most articles point to using Forms Authentication along with the [Authorize] attribute on the MVC and API controllers/actions you want to protect. 在考虑保护这些类型的应用程序时,大多数文章都指向使用表单身份验证以及要保护的MVC和API控制器/操作的[Authorize]属性。 I would like to use the [Authorize] attribute as it will handle both MVC routes and API routes but not sure how to do that without having an actual form and using the built-in membership provider. 我想使用[Authorize]属性,因为它将处理MVC路由和API路由,但不知道如何在没有实际表单和使用内置成员资格提供程序的情况下执行此操作。

Should I go with a simple approach like described here ? 我应该采用这里描述的简单方法吗? Or should I create a Custom Membership provider that handles the logic? 或者我应该创建一个处理逻辑的自定义成员资格提供程序?

For clarity, the workflow would be as follows: 为清楚起见,工作流程如下:

  1. The user logs in through the existing authentication portal. 用户通过现有的身份验证门户登录。
  2. If authenticated, they are redirected to my application along with some additional data like username and email (so no passwords need to be transferred) 如果经过身份验证,它们会被重定向到我的应用程序以及一些其他数据,例如用户名和电子邮件(因此不需要传输密码)
  3. My application sets an authentication cookie that allows the user to continue using the application. 我的应用程序设置了一个允许用户继续使用该应用程序的身份验证cookie。

Any help would be greatly appreciated. 任何帮助将不胜感激。

  • Option 1 选项1

If your existing login portal is using Forms Authentication, then you can share the encryption keys between the applications so that they can read the authentication cookie created in the login portal: 如果您现有的登录门户使用表单身份验证,则可以在应用程序之间共享加密密钥,以便他们可以读取在登录门户中创建的身份验证cookie:

How can I share .net (C#) based authenticated session between web forms and MVC2 applications? 如何在Web表单和MVC2应用程序之间共享基于.net(C#)的身份验证会话?

  • Option 2 选项2

If you're not using forms authentication in the login portal, you could keep your existing process, but add on a step that manually creates the authentication cookie. 如果您未在登录门户中使用表单身份验证,则可以保留现有进程,但添加手动创建身份验证cookie的步骤。 There are lots of variations on this, but this question show a higher level way in the question, and a lower level method in the answers: 这方面有很多变化,但这个问题在问题中表现出更高层次的方式,在答案中表现出更低层次的方法:

How can I manually create a authentication cookie instead of the default method? 如何手动创建身份验证cookie而不是默认方法?

This also requires the encryption configuration be the same between the applications. 这还要求应用程序之间的加密配置相同。

  • Option 3 选项3

Otherwise you are either left with using an SSO protocol for the handoff. 否则,您要么使用SSO协议进行切换。 You can keep the existing authentication process for your login portal, but will need to add additional code to coordinate the SSO handoff to the other application. 您可以保留登录门户的现有身份验证过程,但需要添加其他代码以协调SSO切换到其他应用程序。 SSO came about because other than encrypted cookie methods used in #1 & 2 above, there is little other secure options for doing a browser redirect and communicating authentication. SSO的出现是因为除了上面#1和2中使用的加密cookie方法之外,还没有其他安全选项可用于执行浏览器重定向和通信身份验证。

Creating your own cookie based method is risky and may open up security holes that you don't foresee. 创建自己的基于cookie的方法是有风险的,可能会打开您无法预见的安全漏洞。

  • "Should I go with a simple approach like described here ?" “我应该采用这里描述的简单方法吗?”

The important thing about that example is it's not clear where username is coming from in SetAuthCookie(username, ... . That question implies that the user will login to the additional application and that app will query the web service to determine if that login is valid. In this case it's not single sign on with a dedicated login portal, but instead each app collects login information and asks the web API if it is valid. In your case, you do not want to collect the login information in each portal, but instead detect that they've already logged in to the deicated login portal. 这个例子的重要之处在于,不清楚用户名来自SetAuthCookie(username, ... 。这个问题暗示用户将登录到其他应用程序,该应用程序将查询Web服务以确定该登录是否是在这种情况下,它不是使用专用登录门户进行单点登录,而是每个应用程序收集登录信息并询问Web API是否有效。在您的情况下,您不希望收集每个门户中的登录信息,但是检测到他们已经登录到deicated登录门户。

So the problem is how does the login protal tell you in a secure fashion what username is when you call SetAuthCookie(username, ... . That's exactly what SSO is for. Using a SSO handoff, one site can tell the other in a secure fashion that "I'm sending Bob123 to you, and you can be sure it is really Bob123 and not someone else. 所以问题是登录protal如何以安全的方式告诉你当你调用SetAuthCookie(username, ...username是什么SetAuthCookie(username, ...这正是SSO的用途。使用SSO切换,一个站点可以告诉另一个站点是安全的时尚,“我正在向你发送Bob123,你可以肯定它真的是Bob123而不是其他人。

Options #1 and #2 get around this by having the login portal set the cookie instead, and by sharing keys across the apps, the other apps can securely read that cookie. 选项#1和#2通过让登录门户设置cookie来解决这个问题,并通过在应用程序之间共享密钥,其他应用程序可以安全地读取该cookie。

Note you can't do this with just any cookie. 请注意,您不能只使用任何cookie来执行此操作。 The forms authentication cookie is built in a certain way to prevent forgery of the cookie and other tampering. 表单身份验证cookie以某种方式构建,以防止伪造cookie和其他篡改。

SSO becomes your only option if you are going across domains because cookies written in one domain cannot be read in another(the browser only submits cookies for the current comain). 如果您跨越域,SSO将成为您唯一的选择,因为在一个域中编写的cookie无法在另一个域中读取(浏览器仅为当前域提交cookie)。

There are workarounds for forms authentication with multiple subdomains sharing a root domain: 有多个子域共享根域的表单身份验证的解决方法:

Proper creation of a cross-domain forms authentication cookie 正确创建跨域表单身份验证cookie

There are various hacks for redirecting to another site with encrypted information and letting that site write the forms authentication cookie, but most of them are just horrible hacks that are just as complicated as SSO. 有各种黑客用于重定向到具有加密信息的另一个站点,并让该站点编写表单身份验证cookie,但其中大多数只是与SSO一样复杂的可怕黑客。

You seem to try to reinvent a Single Sign-On protocol. 您似乎尝试重新发明单点登录协议。 Instead, there are existing SSO protocols like OAuth2 or WS-Federation you should definitely learn about. 相反,您应该了解现有的SSO协议,如OAuth2或WS-Federation。

In general, SSO protocols work similarily to what you expect your "workflow" to behave. 通常,SSO协议与您期望“工作流程”的行为类似。 The exact flow can differ but this is always the Identity Provider that authenticates/authrorizes users and the IdP somehow passes this information to the application that makes use of it (for example, the application issues a custom cookie to establish user authentication). 确切的流程可能不同,但始终是身份提供程序对用户进行身份验证/验证,并且IdP以某种方式将此信息传递给使用它的应用程序(例如,应用程序发出自定义cookie以建立用户身份验证)。

The Authorize attribute is not intended to be used with Forms Authentication only. Authorize属性不适用于Forms身份验证。 Any authentication module that sets the principal for the request lifetime can replace Forms. 设置请求生存期的主体的任何身份验证模块都可以替换Forms。 For example, the Session Authentication Module is often used nowadays as it fixes some particular issues of the Forms module (eg the inability to persist long user data). 例如,会话认证模块现在经常被使用,因为它修复了Forms模块的一些特定问题(例如,无法持久存在长用户数据)。

If you need a good free book on SSO, take a look here: 如果你需要一本关于SSO的好书,请看看这里:

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

You can use Owin to handle this. 你可以使用Owin来处理这个问题。 Here's a code snippet I am using to authentication using Facebook, it also uses cookie: 这是我用于使用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");
         );           
      }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM