DataProtection設置問題引起不同ASP.NET Core站點無法共享用戶驗證Cookie


這是這兩天ASP.NET Core遷移中遇到的一個問題。2個ASP.NET Core站點(對應於2個不同的ASP.NET Core Web應用程序),2個站點都可以登錄,但在其中任1個站點登錄后,在當前站點處於登錄狀態,訪問另外1個站點卻處於未登錄狀態。

開始以為是CookieAuthenticationOptions的設置不一致引起的,檢查代碼后確認AuthenticationScheme,CookieName,CookieDomain都是一樣的。

app.UseCookieAuthentication(new CookieAuthenticationOptions
{
    CookieName = ".AspNetCore.Cookies",
    CookieDomain = ".cnblogs.com"
});

(AuthenticationScheme的默認值是"Cookies")

之后懷疑是DataProtection的密鑰不一致引起的,我們用的是同一個阿里雲redis實例存儲密鑰,存儲方式上不會造成不一致。

if (Environment.IsDevelopment())
{
    services.AddDistributedMemoryCache();
}
else
{
    services.AddDistributedServiceStackRedisCache(options =>
    {
        Configuration.GetSection("redis").Bind(options);
        //Workaround for deadlock when resolving host name
        IPAddress ip;
        if (!IPAddress.TryParse(options.Host, out ip))
        {
            options.Host = Dns.GetHostAddressesAsync(options.Host)
            .Result.FirstOrDefault(a => a.AddressFamily == AddressFamily.InterNetwork).ToString();
        }
    });
}
services.AddDataProtection().PersistKeysToDistributedStore();

為了進一步確認密鑰是否是一樣的,修改了 DataProtection.DistributedStore 的源代碼將密鑰打印在控制台,運行后確認2個站點用的密鑰是一樣的。

public IReadOnlyCollection<XElement> GetAllElements()
{
    var data = _cache.GetString(_key);
    Console.WriteLine(data); if (!string.IsNullOrEmpty(data))
    {
        return XDocument.Parse(data).Root.Elements().ToList().AsReadOnly();
    }
    else
    {
        return new List<XElement>().AsReadOnly();
    }
}

后來突然想到 services.AddDataProtection() 是不是有什么配置選項?F12之后發現果然有個DataProtectionOptions:

public static IDataProtectionBuilder AddDataProtection(this IServiceCollection services, Action<DataProtectionOptions> setupAction);

繼續F12發現DataProtectionOptions只有1個屬性ApplicationDiscriminator,點開它的注釋后,問題的答案躍然而出:

//
// Summary:
//     Provides global options for the Data Protection system.
public class DataProtectionOptions
{
    public DataProtectionOptions();

    //
    // Summary:
    //     An identifier that uniquely discriminates this application from all other applications
    //     on the machine. The discriminator value is implicitly included in all protected
    //     payloads generated by the data protection system to isolate multiple logical
    //     applications that all happen to be using the same key material.
    //
    // Remarks:
    //     If two different applications need to share protected payloads, they should ensure
    //     that this property is set to the same value across both applications.
    public string ApplicationDiscriminator { get; set; }
}

原來不同的ASP.NET Core應用程序要使用同樣的加解密方式,除了共享密鑰,還要設置同樣的ApplicationDiscriminator。

添加如下的代碼后問題立馬解決。

services.AddDataProtection(options => options.ApplicationDiscriminator = "cnblogs.com");


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM