【问题标题】:Forms authentication issue in ASP.NETASP.NET 中的表单身份验证问题
【发布时间】:2009-09-14 05:36:01
【问题描述】:

我正在使用 Visual Studio Team System 2008 (VSTS)、C#、.NET 3.5、IIS 7.0 和 ASP.NET。我有两个 IIS 网站,站点 A 和站点 B。它们的相关域名分别是 http://sitea.example.comhttp://siteb.example.com

听说在使用Form认证的时候,我们可以启用域级别的cookies,也就是说,如果两个站点在同一个域中(例如sitea.example.comsiteb.example.com都在域example.com中),最终用户只需要认证一次。更详细地说,如果用户通过其中一个站点的身份验证(通过身份验证),则无需在其他站点再次对该用户进行身份验证。

如何为我的siteasiteb 启用此功能?我是否需要同时更改 siteasiteb 的 web.config?

另一个困惑是,如果用户被sitea认证,那么用户的身份肯定是被sitea识别的,但是siteb怎么可能在不再次认证用户的情况下识别用户的身份呢?

【问题讨论】:

    标签: asp.net iis-7 forms-authentication


    【解决方案1】:

    假设两个站点共享同一个会员数据库,那么您可以在 web.config 的 forms authentication 部分设置 cookie 域;

    <authentication mode="Forms">
        <forms .... domain="mycorp.com"/>
    </authentication>
    

    请注意,您还必须在 web.config 中设置匹配的 machine keys,因为它们用于签署身份验证 cookie。

    【讨论】:

    • 1.两个网站是否应该使用相同的机器密钥? 2.另一个问题是,我没有使用内置的数据库提供程序进行Forms身份验证,我使用的是自定义身份验证方法(我将自定义身份验证方法包装到DLL中并公开身份验证方法,如果身份验证通过,我将设置身份验证通过cookie。)我不确定我是否使用这种自定义的身份验证方法,我仍然可以使用域级别的cookie进行表单身份验证吗?
    • 1.是的。 2.如果您使用的是表单身份验证cookie,请确定。如果您使用自己的 cookie,并在 cookie 上设置域,它将按预期工作。
    • 使用身份验证 cookie 你的意思是这样的——“Dim C As System.Web.HttpCookie = _ Request.Cookies(System.Web.Security.FormsAuthentication.FormsCookieName) C.Domain =”示例。 com" C.Expires = DateTime.Now.AddDays(-1) Response.Cookies.Add(C)"
    • 我对“如果您使用自己的 cookie,并在 cookie 上设置域,它将按预期工作”感兴趣,您能告诉我如何设置任意应用程序 cookie(不需要成为表单身份验证cookie)作为域范围吗?
    • 我建议应该有一个自己的问题,所以其他人可以找到它 - msdn.microsoft.com/en-us/library/ms178194.aspx 有详细信息。是的,对于表单 auth cookie,就像那样。除非过期日期不是过去 - 那个 cookie 永远不会起作用!
    【解决方案2】:

    有一个example on MSDN

    【讨论】:

    • 另一个问题是,我没有使用内置数据库提供程序进行表单身份验证,我使用的是自定义身份验证方法(我将自定义身份验证方法包装到 DLL 中并公开身份验证方法,如果身份验证通过,我会设置身份验证通过cookie。)我不确定我是否使用这种自定义的身份验证方法,我仍然可以使用域级别的cookie进行表单身份验证吗?
    • 如果你自己设置cookie,我怀疑。您可以使用自己的 Provider,但是当用户登录时,您应该调用 FormsAuthentication.RedirectFromLoginPage()
    • 谢谢!如果我的代码看起来像这样,我想知道它是否是表单 cookie? Dim C As System.Web.HttpCookie = _ Request.Cookies(System.Web.Security.FormsAuthentication.FormsCookieName) C.Domain = "example.com" C.Expires = DateTime.Now.AddDays(-1) Response.Cookies。添加(C)
    • George2,它看起来像手动操作 the 表单 cookie。尽可能避免,但也许可行。
    【解决方案3】:

    此链接提供了一些详细信息http://docs.communityserver.com/2007/270-common-things-to-check-when-using-forms-authentication/

    基本上你需要在web.config文件的&lt;authentication&gt;标签内的&lt;forms/&gt;标签中添加domain属性。

    例如

    <authentication mode="Forms">
    <forms name=".CookieName" ... domain=".mydomain.com" />
    </authentication>
    

    【讨论】:

    • 另一个问题是,我没有使用内置数据库提供程序进行表单身份验证,我使用的是自定义身份验证方法(我将自定义身份验证方法包装到 DLL 中并公开身份验证方法,如果身份验证通过,我会设置身份验证通过cookie。)我不确定我是否使用这种自定义的身份验证方法,我仍然可以使用域级别的cookie进行表单身份验证吗?
    【解决方案4】:

    web.config的form标签中设置域属性为.mycorp.com

    【讨论】:

    • 另一个问题是,我没有使用内置数据库提供程序进行表单身份验证,我使用的是自定义身份验证方法(我将自定义身份验证方法包装到 DLL 中并公开身份验证方法,如果身份验证通过,我会设置身份验证通过cookie。)我不确定我是否使用这种自定义的身份验证方法,我仍然可以使用域级别的cookie进行表单身份验证吗?
    【解决方案5】:

    我会建议 Stack Overflow、Microsoft、Facebook、Google Accounts 的做法,而且效率更高,因为每个网站都可以在不同的机器上。

    假设,您有 AuthSite。这是您必须登录的一个站点,并且有会员信息。

    您在不同的服务器上有 SiteA、SiteB 和 SiteC。

    在 SiteA 的登录页面上,您必须在 AuthSite 上设置一个带有密码的表单帖子。

    如果您之前在 AuthSite 上成功登录,它只会以浏览器中隐藏的表单帖子的形式重定向回 SiteA,并带有成功的秘密,您必须在 SiteA 中进行验证。

    此模型具有高度可扩展性和可扩展性。因为从长远来看,维护很容易。

    SiteA、SiteB、SiteC的LoginPage代码如下。

    SiteA、SiteB 和 SiteC 上的 Login.aspx

    private void Page_Load(object sender, EventArg e){
       // Simply redirect back to AuthSite...
       // Change Site parameter accordingly.
       Response.Redirect("http://authsite/Login.aspx?Site=SiteA");
    }
    

    AuthSite 上的 Login.aspx

    // Define one hidden field named "ReturnSite".
    
    private void Page_Load(object sender, EventArg e){
    
       if(IsPostBack)
           return;
       string site = Request.QueryString["Site"];
       if(Request.User.IsAuthenticated){
           string secrete = CreateSomeSecrete(site);
           Response.Redirect("http://" + site + 
               "/AuthConfirm.aspx?Token=" + secrete + 
               "&User=" + Request.User.Identity.Name);
           return;
       }
    
       ReturnSite.value = site;
       // Do usual login...
    }
    
    private void LoginButton_Click(object sender, EventArg e){
       string secrete = CreateSomeSecrete(ReturnSite.value);
       FormAuthentication.SetAuthCookie(username,true);
       // You can retrive username later by calling 
       // Request.User.Identity.Name.
       Response.Redirect("http://" + ReturnSite.value + 
          "/AuthConfirm.aspx?Token=" + secrete + "&User=" + username);
    }
    

    SiteA、SiteB 和 SiteC 上的 AuthConfirm.aspx

    private void Page_Load(object sender, EventArg e){
       string secrete = Request.QueryString["Token"];
       // Verify that secret came only from AuthSite.
       if(VerifySecrete(secrete)){
           // This sets authentication cookie for Current Site
           FormsAuthentication.SetAuthCookie(Request.QueryString["User"], true);
       }
    }
    

    现在让我们看一个不同的场景。

    同一用户,首次登录

    1. 第一个访问 SiteA(尚未登录)的用户 John 被重定向到 AuthSite。
    2. AuthSite 检查并发现用户没有身份验证 cookie,因此会询问实际凭据。
    3. AuthSite 在自身上设置令牌并将秘密传递给 SiteA 上的 AuthConfirm 页面。 SiteA 验证令牌并设置身份验证 cookie 并允许用户访问安全页面。

    同一用户,第一次访问 SiteB

    1. 用户 John 已使用 AuthSite 成功登录到 SiteA,现在尝试访问 SiteB。
    2. SiteB 发现用户未登录,因此将其定向到 AuthSite。
    3. AuthSite 发现用户已有 AuthSite 网站的 cookie。
    4. AuthSite 使用身份验证密钥将用户重定向回 SiteB。
    5. SiteB 验证秘密并让 John 继续安全访问 页面。

    【讨论】:

    • 谢谢!但是我没有发现您的方案在这种情况下是如何工作的——未经身份验证的用户转到 SiteB,并重定向到 SiteA 进行身份验证,以及不同域的 SiteA、SiteB 和 SiteC 如何共享相同的身份验证信息(例如,如果用户在其中一个站点通过了身份验证,用户无需再次与其他站点进行身份验证)。感谢您是否可以提供有关此的更多信息。再次感谢!
    • 如果未经身份验证的用户访问 SiteA、SiteB 或 SiteC,他将被重定向到 AuthSite(AuthSite 是一个单独的站点,如 Microsoft Passport、StackOverflow 使用的 OpenID、Facebook Connect)。我将尝试举例说明。
    • 你说的是联合,当所有站点都在同一个域中时,它是非常过分的
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-10
    • 1970-01-01
    相关资源
    最近更新 更多