4

Azure を使用して MVC3 でクレームを設定しましたが、すべてうまくいっています。

私が今する必要があるのは、現在のスレッド/http コンテキストにあるクレーム ID を拡張し、自分の情報 (DOB、住所など) を追加することです。

だから私の質問は - これを行うのに最適な場所はどこですか? どんな例でも素晴らしいでしょう..

ユーザーが認証されたときに、ID を DB に移動し、ユーザーに関連するレコードを取得して、それをカスタム Claims Identity オブジェクトに追加する必要があると思いますか?

4

1 に答える 1

21

通常、Cookie を検査する httpmodule があり、FedAuth トークンが見つかったら、Claims Principal と ID を構築するためのフックがあります。

通常、ユーザーのプロファイル全体を保存する必要はありません。通常、頻繁に変更されることのない便利なものだけを保存する必要があります。私はアクションフィルターの中でこれを行います。

これは、これらすべてを実行するコードです。

https://github.com/wcpro/ScaffR/tree/master/src/ScaffR.Security/content/CodeTemplates/Scaffolders/ScaffR.Security

少し掘り下げる必要があるかもしれませんが、すべてそこにあります。

http モジュールのコードは次のとおりです。

public class ClaimsTransformationHttpModule : IHttpModule
{
    public void Init(HttpApplication context)
    {
        context.PostAuthenticateRequest += context_PostAuthenticateRequest;
    }

    void context_PostAuthenticateRequest(object sender, EventArgs e)
    {
        var context = ((HttpApplication) sender).Context;

        if (FederatedAuthentication.SessionAuthenticationModule != null &&
            FederatedAuthentication.SessionAuthenticationModule.ContainsSessionTokenCookie(context.Request.Cookies))
        {
            return;
        }

        var transformer = FederatedAuthentication.FederationConfiguration.IdentityConfiguration.ClaimsAuthenticationManager;

        if (transformer != null)
        {
            var transformedPrincipal = transformer.Authenticate(context.Request.RawUrl, context.User as ClaimsPrincipal);

            context.User = transformedPrincipal;
            Thread.CurrentPrincipal = transformedPrincipal;
        }
    }

    public void Dispose() { }
}

クレーム トランスフォーマーはこちら

    public partial class ClaimsTransformer : ClaimsAuthenticationManager
{
    partial void SetCustomPrincipalClaims(IUserService userService, ref ClaimsPrincipal principal);

    public override ClaimsPrincipal Authenticate(string resourceName, ClaimsPrincipal incomingPrincipal)
    {
        if (!incomingPrincipal.Identity.IsAuthenticated)
        {
            return incomingPrincipal;
        }

        var newPrincipal = Transform(incomingPrincipal);

        EstablishSession(newPrincipal);

        return newPrincipal;
    }

    ClaimsPrincipal Transform(ClaimsPrincipal incomingPrincipal)
    {
        var nameClaim = incomingPrincipal.Identities.First().FindFirst(ClaimTypes.Name);

        var userService = DependencyResolver.Current.GetService<IUserService>();

        var user = userService.GetByUsername(nameClaim.Value);

        var id = new ApplicationIdentity(user);

        var principal = new ClaimsPrincipal(id);

        SetCustomPrincipalClaims(userService, ref principal);

        return principal;
    }        

    private void EstablishSession(ClaimsPrincipal principal)
    {
        if (HttpContext.Current != null)
        {
            var sessionToken = new SessionSecurityToken(principal);
            FederatedAuthentication.SessionAuthenticationModule.WriteSessionTokenToCookie(sessionToken);
        }
    }
}

それでは構成はこちら

<?xml version="1.0" encoding="utf-8"?>
<system.identityModel>
  <identityConfiguration>
    <claimsAuthenticationManager type="Barbarella.Core.Common.Security.ClaimsTransformer, Barbarella.Core" />
  </identityConfiguration>
</system.identityModel>

この...

    <system.identityModel.services>
  <federationConfiguration>
    <cookieHandler mode="Default" requireSsl="false" />
  </federationConfiguration>
</system.identityModel.services>

この...

<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<modules runAllManagedModulesForAllRequests="true">
  <add name="ClaimsTransformationModule" type="Barbarella.Core.Common.Security.ClaimsTransformationHttpModule, Barbarella.Core" />
  <add name="SessionAuthenticationModule" type="System.IdentityModel.Services.SessionAuthenticationModule, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />

</modules>

構成セクションを追加することを忘れないでください

    <section name="system.identityModel" type="System.IdentityModel.Configuration.SystemIdentityModelSection, System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />
<section name="system.identityModel.services" type="System.IdentityModel.Services.Configuration.SystemIdentityModelServicesSection, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />

ApplicationIdentity のコードは次のとおりです (ClaimsIDentity をオーバーライドします)。これは、あなたの質問に本当に答えるコードです...

 public sealed partial class ApplicationIdentity : ClaimsIdentity
{
    partial void SetCustomIdentityClaims(User user);

    private readonly User _user;

    public ApplicationIdentity(User user) : base("Application")
    {
        _user = user;
        AddClaim(new Claim(ClaimTypes.Name, user.Username));     
        AddClaim(new Claim(ApplicationClaimTypes.UserId, user.Id.ToString(CultureInfo.InvariantCulture)));
        AddClaim(new Claim(ApplicationClaimTypes.FirstName, user.FirstName));
        AddClaim(new Claim(ApplicationClaimTypes.LastName, user.LastName));
        AddClaim(new Claim("Time", DateTime.Now.ToString()));

        SetCustomIdentityClaims(_user);
    }

    public User User
    {
        get { return _user; }
    }

    public int UserId
    {
        get { return int.Parse(FindFirst(ApplicationClaimTypes.UserId).Value); }
    }

    public string Username
    {
        get { return FindFirst(ClaimTypes.Name).Value; }
    }

}
于 2012-09-25T11:07:09.410 に答える