簡體   English   中英

NET Core 3.1 MVC 授權/身份驗證與令牌 (JWT) 在單獨的 Net Core 3.1 中從外部獲得 Web Api

[英]NET Core 3.1 MVC Authorization/Authentication with token (JWT) obtained externally in separate Net Core 3.1 Web Api

我有 3 個項目:

  1. Net Core 3.1 MVC 項目。
  2. 具有 JWT 身份驗證的 Net Core 3.1 Web Api 項目 --> 通過實體框架連接到數據庫
  3. (Xamarin 應用程序也使用 web api 進行身份驗證和數據檢索)。

我不想從兩個項目 (1,2) 分別連接到同一個數據庫(感覺不是一個好主意,如果我錯了請糾正我,希望保留 web api 中包含的數據庫 crud 操作)。

我想在 Web Api 項目中做認證,把token傳給Net Core MVC項目。

我不知道如何使用令牌為 MVC 項目授權此用戶,以便可以根據用戶的角色等訪問控制器。基本上使用在 web api 中獲得的令牌將此用戶登錄到 MVC 項目中。是這甚至可能還是正確的方法? 有什么幫助嗎?

MVC項目Startup.cs class

public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        public void ConfigureServices(IServiceCollection services)
        {            
            // add for razor pages and refresh without rebuilding
            services.AddRazorPages().AddRazorRuntimeCompilation();


            // add httpClient
            services.AddHttpClient();

            // start auth jwt
            services.AddSession(options => {
                options.IdleTimeout = TimeSpan.FromMinutes(1);
            });
            //services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

            //Provide a secret key to Encrypt and Decrypt the Token
            var SecretKey = Encoding.ASCII.GetBytes
                 ("mySecretKeyForAuthenticationAndAuthorization");
            //Configure JWT Token Authentication
            services.AddAuthentication(auth =>
            {
                auth.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                auth.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            })
            .AddJwtBearer(token =>
            {
                token.RequireHttpsMetadata = false;
                token.SaveToken = true;
                token.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateIssuerSigningKey = true,
            //Same Secret key will be used while creating the token
            IssuerSigningKey = new SymmetricSecurityKey(SecretKey),
                    ValidateIssuer = true,
            //Usually, this is your application base URL
            ValidIssuer = "https://myAzureWebAPi.azurewebsites.net",
                    ValidateAudience = true,
            //Here, we are creating and using JWT within the same application.
            //In this case, base URL is fine.
            //If the JWT is created using a web service, then this would be the consumer URL.
            ValidAudience = "https://mylocalhost/",
                    RequireExpirationTime = true,
                    ValidateLifetime = true,
                    ClockSkew = TimeSpan.Zero
                };
            });
            // end auth jwt


            // add for roles authorization
           services.AddAuthorization(config =>
           {
               config.AddPolicy(Policies.Admin, Policies.AdminPolicy());
               config.AddPolicy(Policies.Client, Policies.ClientPolicy());
           });

            services.AddControllersWithViews();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }
            app.UseHttpsRedirection();
            app.UseStaticFiles();

            //add for jwt
            app.UseCookiePolicy();
            app.UseSession();
            //Add JWToken to all incoming HTTP Request Header
            app.Use(async (context, next) =>
            {
                var JWToken = context.Session.GetString("JWToken");
                if (!string.IsNullOrEmpty(JWToken))
                {
                    context.Request.Headers.Add("Authorization", "Bearer " + JWToken);
                }
                await next();
            });


            app.UseRouting();


            // added for jwt
            app.UseAuthentication();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllerRoute(    
                     name: "default",
                     pattern: "{area=Client}/{controller=LoginPage}/{action=Index}/{id?}");
            });
        }
    }

MVC 登錄頁面控制器.cs

    [Area("Client")]
        public class LoginPageController : Controller
        {
            private readonly IHttpClientFactory _clientFactory;
            public LoginPageController(IHttpClientFactory clientFactory)
            {
                _clientFactory = clientFactory;
            }
      
            public IActionResult Index()
            {
                return View();
            }
    
    
            [HttpPost]
            public async Task<IActionResult> Login([Bind] LoginModel loginModel)
            {
                var client = _clientFactory.CreateClient();
                //var client = new HttpClient();
    
                try
                {
                    var json = JsonConvert.SerializeObject(loginModel);
                    var content = new StringContent(json, Encoding.UTF8, "application/json");
    
                    var outcome = await client.PostAsync("https://<AzureWebAPiUrl>/api/accounts/login", content);
    
                    if (outcome!= null && outcome.IsSuccessStatusCode)
                    {
                        var jsonResult = await outcome.Content.ReadAsStringAsync();
                        var token = JsonConvert.DeserializeObject<Token>(jsonResult);
    
                        Console.WriteLine(token.user_role);
    
                        // store token in a session
                        HttpContext.Session.SetString("JWToken", token.access_token);
    
                        // Here is the problem, once I have the token how do I make this user be 
 //authenticated in the mvc project so that the [Authorize[Role = "someRole"] on controllers works
                    }
    
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
    
                return RedirectToAction("Index", "AdminDeals", new { area = "Admin"}); // only if role is admin
            }
        }

嘿,我有解決方案,請參考以下幾點

  1. 首先,您需要添加身份驗證。 public void ConfigureServices(IServiceCollection services)
 services.AddSession(); services.AddAuthentication(options => { options.DefaultAuthenticateScheme = >JwtBearerDefaults.AuthenticationScheme; options.DefaultAuthenticateScheme = >JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme; })
 // Adding Jwt Bearer.AddJwtBearer(options => { options.SaveToken = true; options.RequireHttpsMetadata = false; options.TokenValidationParameters = new TokenValidationParameters() { ValidateIssuer = true, ValidateAudience = true, ValidAudience = Configuration["JWTConfig:ValidAudience"], ValidIssuer = Configuration["JWTConfig:ValidIssuer"], IssuerSigningKey = new >SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["JWTConfig:Secret"])) }; });
  1. 之后,您必須使用 Session 來存儲身份驗證令牌,並且在這個令牌中,您必須加密角色列表的令牌組合,無論角色想要傳遞給授權。 Here i have used JWT Bearer token
  2. 使用此 session 您必須在public void Configure(IApplicationBuilder app, IWebHostEnvironment env) startup.cs 文件中配置以使用 header 身份驗證。
 app.UseSession(); app.Use(async (context, next) => { var token = context.Session.GetString("Token"); if (.string.IsNullOrEmpty(token)) { context.Request.Headers,Add("Authorization"; "Bearer " + token); } await next(); });
  1. 然后你必須添加你的 controller
 [Authorize(Roles = "Employee,Student")] public ActionResult Leave() { // your code here }

這是您應該為您的應用程序實現 OAuth2.0 的典型場景 - 您有 2 種客戶端(MVC 和 Xamrin),它們都需要經過身份驗證然后訪問您的 API 項目,您的 API 應該受到身份提供者的保護而不是自己進行身份驗證。 在 asp.net 內核中,最流行的解決方案是Identity Server 4 ,您不必重新發明輪子,只需創建一個 Identity Provider 服務器,然后根據文檔中的說明配置您的 API 和 MVC 項目,然后一切正常。 同時,Identity Server 4 支持實體框架

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM