.NET Core 2.0双重身份验证(混合MVC和API)

时间:2018-01-30 04:02:52

标签: asp.net-mvc api authentication

我是一名后端开发人员,他通常在同一个项目下开发API和管理面板。我主要使用Laravel / PHP,但是我最近开始深入研究.NET Core。

在PHP(Laravel)中,我可以将我的API端点和网页绑定到相同的控制器操作。例如,API使用者应该能够使用API​​端点创建博客文章。此外,管理员应该能够使用Web UI创建博客文章,该博客应遵循相同的验证逻辑等。

以下是create操作的一些伪代码。

class BlogPostController
{

    //Create a new blog post
    function create(request)
    {
        authorizeAction(); //Make sure the current user is authorized to create a blog post
        validateFields(request); //Make sure the posted data is valid for a blog post

        //Create the blog post
        blogPost = new BlogPost(request);

        if(request.isAPI)
            return json(blogPost); //Return the new blog post as a json string
        return view(blogPost); //Return an HTML representation of the blog post (in administration panel)
    }


}

在Laravel中,由于所有路由都可以有不同的中间件,我可以定义两条上述操作的路由,例如POST /api/blogpostPOST /blogpost,每条路由都有不同的身份验证方案。 (api将通过JWT令牌进行授权,并且网址将通过cookie进行授权)。

我无法在.NET Core中执行类似操作,因为不同的身份验证方案无法通过单独的中间件as of Version 2应用(据我所知)。

我对此问题的解决方案是添加两种身份验证方案,如下所示:

JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); // => remove default claims
            services.AddAuthentication(options =>
                {
                    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                    options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
                    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;

                })
                .AddCookie(cfg=>cfg.SlidingExpiration = true)
                .AddJwtBearer(cfg =>
                {
                    cfg.RequireHttpsMetadata = false;
                    cfg.SaveToken = true;
                    cfg.TokenValidationParameters = new TokenValidationParameters
                    {
                        ValidIssuer = Configuration["JwtIssuer"],
                        ValidAudience = Configuration["JwtIssuer"],
                        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["JwtKey"])),

                        ClockSkew = TimeSpan.Zero
                    };
                });

然后在我的控制器上使用:

[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme + "," + CookieAuthenticationDefaults.AuthenticationScheme)]

这将有效地挑战JWT令牌和cookie,并使用它找到的任何一个。这对我来说似乎有些混乱(和Microsoft employee would agree

我是否接近整个问题?对我来说,将所有逻辑保留在一个控制器中并根据请求的类型返回json或HTML是有意义的。我可以为API端点和网页设置一个单独的控制器,但它似乎有很多重复的代码。另一种选择是彻底抛弃这个想法,只需构建一个消耗API的API /单页应用程序。

这是一个简单的糟糕设计,还是根据路线使用不同的身份验证方案?

0 个答案:

没有答案