c# - 具有 "external"身份验证的 ASP.NET MVC 基于声明的用户

标签 c# asp.net-mvc owin claims-based-identity custom-authentication

背景

我们的 Web 应用程序使用外部 身份验证,从某种意义上说,用户的用户名/密码未在本地验证,而是在 Web 应用程序“外部”以中央、单点登录的方式进行验证在类型网站上。身份验证证明(和用户身份)可通过本地服务器变量(HTTP_EMPLOYEEID 等)获得。但是,它并不像针对 Google、Facebook 或其他基于 OAuth 的设置进行身份验证那样外部。所以我只是想做出这种区分,这样它就不会与 ASP.NET Identity/Owin 中的术语“外部登录”发生冲突。

问题

我正在尝试找出一种干净的方法来利用经过身份验证的用户数据(来自服务器变量)并将其传递给 ASP.NET 身份验证。但是,在用户登录到应用程序之前,必须针对 Web 服务查找用户配置文件和角色数据。

我想使用 Owin 和基于声明的身份,但我不确定我是否也应该使用 ASP.NET Identity,或者只是做一个更“纯粹”的声明实现.我喜欢不重新发明轮子的想法,但我也不想将方钉强行插入圆孔(俗话说),如果用户识别方式和从网络服务中查找的方式不适合典型的 ASP.NET Identity 用法。

例如,如果我采用更纯粹的方法,我可以这样做:

// 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 的设置)。

以前走这条路的人有什么建议吗?我是否应该将服务器变量注入(inject)数据视为自定义中间件并通过 ASP.NET Identity 加以利用,或者只是不担心在那个世界中适合它的位置,而更像是一个“纯粹主义者”方法如上所述?

附注我使用的是 ASP.NET 4.6.1,而不是新的 ASP.NET Core。

最佳答案

我有类似的饱和度。我不想使用整个 ASP.Net Identity,因为我需要通过外部身份验证再次对用户进行身份验证。

所以我只使用 OWIN Claim Authentication,它基本上使用 Claims 创建身份验证 cookie; 类似于我们过去使用的表单例份验证。

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);
    }
}

启动.cs

注意:我有同时使用 MVC 和 Web API 的 Angular,所以我为 REST 返回 404 消息而不是 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);
    }
}

关于c# - 具有 "external"身份验证的 ASP.NET MVC 基于声明的用户,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38489384/

相关文章:

c# - ASP.NET 从母版页调用 Controller 方法?

c# - 代码优先 Entity Framework - 对评论功能进行评论,相同的评论出现两次

c# - 使用 ASP.NET MVC OutputCache,同时根据用户是否经过身份验证改变 View 内容

asp.net-mvc - 如何在 JQuery 中使用 Ajax 加载页面的一部分?

javascript - 确定 razor 生成 View 中 html 表的大小

c# - 如何从 OWIN 中间件重定向用户?

c# - 从 PipeReader 读取超时

c# - 在 WebApi 中使用 Autofac 进行 Hangfire

asp.net-identity - 在上下文中未找到 owin.Environment 项目 - 仅在服务器上

asp.net - UseIdentityServerBearerTokenAuthentication 不适用于 IdentityServer3