2016-04-08 14 views
2

アイデンティティAPIによって生成されたクッキーの中にユーザーからのカスタムデータを保存する方法はありますか?IDクッキーにカスタムデータを保存する

私たちはマルチテナントアプリケーションを構築しているので、複数の企業がアプリケーションの同じインスタンスにアクセスすることができます。だからこそ私は、特定のユーザーのために、ユーザーがブラウザを閉じた後にWebアプリケーションに戻ったときにユーザーからのデータを取得するために、ユーザーの会社コードをIDクッキーに格納する必要があります。

答えて

12

カスタムUserClaimsPrincipalFactoryを実装し、店舗番号のカスタムクレームを追加することで、他のクレームと一緒にクッキーに保存されます。以下は

私のシナリオは、マルチテナント

using cloudscribe.Core.Models; 
using Microsoft.AspNet.Identity; 
using Microsoft.Extensions.OptionsModel; 
using System; 
using System.Security.Claims; 
using System.Threading; 
using System.Threading.Tasks; 

namespace cloudscribe.Core.Identity 
{ 
    public class SiteUserClaimsPrincipalFactory<TUser, TRole> : UserClaimsPrincipalFactory<TUser, TRole> 
    where TUser : SiteUser 
    where TRole : SiteRole 
{ 
    public SiteUserClaimsPrincipalFactory(
     ISiteRepository siteRepository, 
     SiteUserManager<TUser> userManager, 
     SiteRoleManager<TRole> roleManager, 
     IOptions<IdentityOptions> optionsAccessor) : base(userManager, roleManager, optionsAccessor) 
    { 
     if (siteRepository == null) { throw new ArgumentNullException(nameof(siteRepository)); } 

     siteRepo = siteRepository; 
     options = optionsAccessor.Value; 
    } 

    private ISiteRepository siteRepo; 
    private IdentityOptions options; 

    public override async Task<ClaimsPrincipal> CreateAsync(TUser user) 
    { 
     if (user == null) 
     { 
      throw new ArgumentNullException("user"); 
     } 

     var userId = await UserManager.GetUserIdAsync(user); 
     var userName = await UserManager.GetUserNameAsync(user); 

     var id = new ClaimsIdentity(
      options.Cookies.ApplicationCookie.AuthenticationScheme, 
      Options.ClaimsIdentity.UserNameClaimType, 
      Options.ClaimsIdentity.RoleClaimType 
      ); 

      id.AddClaim(new Claim(Options.ClaimsIdentity.UserIdClaimType, userId)); 
      id.AddClaim(new Claim(Options.ClaimsIdentity.UserNameClaimType, userName)); 

      if (UserManager.SupportsUserSecurityStamp) 
      { 
       id.AddClaim(new Claim(Options.ClaimsIdentity.SecurityStampClaimType, 
       await UserManager.GetSecurityStampAsync(user))); 
      } 

      if (UserManager.SupportsUserRole) 
      { 
       var roles = await UserManager.GetRolesAsync(user); 
       foreach (var roleName in roles) 
       { 
        id.AddClaim(new Claim(Options.ClaimsIdentity.RoleClaimType, roleName)); 
        if (RoleManager.SupportsRoleClaims) 
        { 
         var role = await RoleManager.FindByNameAsync(roleName); 
         if (role != null) 
         { 
          id.AddClaims(await RoleManager.GetClaimsAsync(role)); 
         } 
        } 
       } 
      } 
      if (UserManager.SupportsUserClaim) 
      { 
       id.AddClaims(await UserManager.GetClaimsAsync(user)); 
      } 

      ClaimsPrincipal principal = new ClaimsPrincipal(id); 

      if (principal.Identity is ClaimsIdentity) 
      { 
       ClaimsIdentity identity = (ClaimsIdentity)principal.Identity; 

       Claim displayNameClaim = new Claim("DisplayName", user.DisplayName); 
       if (!identity.HasClaim(displayNameClaim.Type, displayNameClaim.Value)) 
       { 
        identity.AddClaim(displayNameClaim); 
       } 

       Claim emailClaim = new Claim(ClaimTypes.Email, user.Email); 
       if (!identity.HasClaim(emailClaim.Type, emailClaim.Value)) 
       { 
        identity.AddClaim(emailClaim); 
       } 

       ISiteSettings site = await siteRepo.Fetch(user.SiteId, CancellationToken.None); 

       if (site != null) 
       { 
        Claim siteGuidClaim = new Claim("SiteGuid", site.SiteGuid.ToString()); 
        if (!identity.HasClaim(siteGuidClaim.Type, siteGuidClaim.Value)) 
        { 
         identity.AddClaim(siteGuidClaim); 
        } 

       }  

      } 

      return principal; 

     } 
    } 
} 

あるので、次にスタートアップで、あなたがそれて、カスタム工場を登録する必要があり、私はSiteGuidを含むいくつかのカスタム要求を追加してい私のプロジェクトからのコード例であります注入し、1

services.AddScoped<IUserClaimsPrincipalFactory<SiteUser>, SiteUserClaimsPrincipalFactory<SiteUser, SiteRole>>(); 

別のアプローチは、しかし、このアプローチは、クッキー内の余分な主張を格納していませんが、代わりに更新クレーム変換を使用することで、デフォルトの代わりに使用されます要求ごとにクレームを追加します。つまり、要求の存続期間中にクッキーからクレームを追加しますが、クッキー内のクレームは変更しません。 startup.csで、その後

public class ClaimsTransformer : IClaimsTransformer 
{ 
    public Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal) 
    { 
     ((ClaimsIdentity)principal.Identity).AddClaim(new Claim("ProjectReader", "true")); 
     return Task.FromResult(principal); 
    } 
} 

app.UseClaimsTransformation(new ClaimsTransformationOptions 
{ 
    Transformer = new ClaimsTransformer() 
}); 
+0

おかげで、それが働きました! UserClaimsPrincipalFactoryについては、私が使用するには複雑すぎるので、私はすべてのことをバイパスしました。私はそれがサインインする必要があるときには単にHttpContextを使います。私はさらに2つのクレームを追加し、アプリケーションの2回目の使用について情報を回復できます! :) –

+0

Joeは、このメソッドを使用して、Cookieの "SiteGuid"を他のものに編集している悪意のあるユーザーなど、そのCookieを改ざんできますか?正当なGuidが推測するのは難しいですが、データへのユーザーのアクセスをフィルタリングするために単純なAccountId(DBのキー値)を使用することを検討しています。これは安全ですか? –

+0

私はMicrosoftがdataprotection APIを使用して認証クッキーに格納されている役割とクレームを暗号化していると信じています –

関連する問題