4

バックグラウンド

ユーザーのユーザー名/パスワードはローカルでは検証されず、中央のシングル サインオン タイプの Web サイトで Web アプリの「外部」で検証されるという意味で、当社の Web アプリケーションは外部認証を使用します。認証証明 (およびユーザーの ID) は、ローカル サーバー変数 (HTTP_EMPLOYEEIDなど) を介して利用可能になります。ただし、 Google、Facebook、または別の OAuth ベースのセットアップに対する認証のように、まったく外部的ではありません。したがって、ASP.NET Identity / Owin の「外部ログイン」という用語と衝突しないように、その区別をしたかっただけです。

問題

認証されたユーザー データ (サーバー変数から) を活用し、それを ASP.NET 認証に渡すためのクリーンな方法を見つけようとしています。ただし、ユーザーがアプリにログインする前に、ユーザー プロファイルとロール データを Web サービスに対して検索する必要があります。

Owin と Claims ベースの ID を使用したいのですが、ASP.NET Identityも使用する必要があるのか​​ 、それともクレームを使用してより「純粋な」実装を行う必要があるのか​​ わかりません。私は車輪を再発明しないという考えが好きですが、ユーザーが識別され、Web サービスから検索される方法が適合しない場合、(ことわざにあるように) 四角いペグを丸い穴に押し込みたくありません。典型的なASP.NET IDの使用法。

たとえば、より純粋なアプローチを取ると、次のようなことができます。

// Get the current user's id
var userId = HttpContext.Current.Request.ServerVariables["HTTP_EMPLOYEEID"];

// Get profile and role data from a web service
MyUser user = MyUserService.GetUserById(userId);

// Create claims
var claims = new Claim[]
{
    new Claim(ClaimTypes.Name, user.Id),
    new Claim(ClaimTypes.Email, user.Email),
    new Claim(ClaimTypes.Role, user.Role), // there can be more roles, but you get the idea
    // etc.
};

// Establish identity and login
var identity = new ClaimsIdentity(claims, "CookieAuthentication");
HttpContext.Current.GetOwinContext().Authentication.SignIn(identity);

しかし、ASP.NET Identity を使用して (Entity Framework のものを使用せずに)、IUser、IUserStore、IRoleStore (およびその他の最低限必要なもの) を実装し、これを処理するために Microsoft の既存の確立されたフレームワークを使用できることも知っています。これは現在の標準に沿ったものであり、他のタイプの認証に簡単に拡張できる可能性があるという議論があります (たとえば、ローカルのユーザー名/パスワード、または Google/Facebook が最終的に他の許可された認証オプションになる場合、現在の ServerVariables ベースのセットアップ)。

以前にこの道を進んだ人からのアドバイスはありますか? サーバー変数に注入されたデータをカスタムミドルウェアとして扱い、 ASP.NET Identity を介してそれを活用する必要がありますか、それとも、その世界のどこに収まるかを心配せずに、上記のように「純粋な」アプローチを採用する必要がありますか?

ps 新しい ASP.NET Core ではなく、ASP.NET 4.6.1 を使用しています。

4

1 に答える 1

3

私も似たような飽和状態です。外部認証でユーザーを再度認証する必要があるため、ASP.Net ID 全体を使用したくありません。

したがって、基本的にクレームで認証Cookieを作成するOWINクレーム認証を使用します。昔使っていたフォーム認証に似ています。

public class OwinAuthenticationService 
{
    private readonly HttpContextBase _context;
    private const string AuthenticationType = "ApplicationCookie";

    public OwinAuthenticationService(HttpContextBase context)
    {
        _context = context;
    }

    public void SignIn(User user)
    {
        IList<Claim> claims = new List<Claim>
        {
            new Claim(ClaimTypes.Sid, user.Id.ToString()),
            new Claim(ClaimTypes.Name, user.UserName),
            new Claim(ClaimTypes.GivenName, user.FirstName),
            new Claim(ClaimTypes.Surname, user.LastName),
        };

        foreach (Role role in user.Roles)
        {
            claims.Add(new Claim(ClaimTypes.Role, role.Name));
        }

        ClaimsIdentity identity = new ClaimsIdentity(claims, AuthenticationType);

        IOwinContext context = _context.Request.GetOwinContext();
        IAuthenticationManager authenticationManager = context.Authentication;

        authenticationManager.SignIn(identity);
    }

    public void SignOut()
    {
        IOwinContext context = _context.Request.GetOwinContext();
        IAuthenticationManager authenticationManager = context.Authentication;

        authenticationManager.SignOut(AuthenticationType);
    }
}

Startup.cs

注: MVC と Web API の両方を使用する Angular があるため、404 ページではなく REST に対して 404 メッセージを返します。

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            AuthenticationType = "ApplicationCookie",
            LoginPath = new PathString("/Account/Login"),
            Provider = new CookieAuthenticationProvider
            {
                OnApplyRedirect = ctx =>
                {
                    if (!IsApiRequest(ctx.Request))
                    {
                        ctx.Response.Redirect(ctx.RedirectUri);
                    }
                }
            }
        });
    }

    private static bool IsApiRequest(IOwinRequest request)
    {
        string apiPath = VirtualPathUtility.ToAbsolute("~/api/");
        return request.Uri.LocalPath.ToLower().StartsWith(apiPath);
    }
}
于 2016-07-20T19:49:19.947 に答える