簡體   English   中英

ASP.Net Core 5 中的身份驗證

[英]Authentication in ASP.Net Core 5

我在 VS 2019 中使用 React 模板創建了 asp.net 內核,我需要授權 controller 方法,所以我首先在 Z3A580F142203677F1F0BCAD30898F63F5 上注冊了我的應用程序,然后開始使用此配置:

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

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {

            services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
         .AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAd"))
         .EnableTokenAcquisitionToCallDownstreamApi()
         .AddInMemoryTokenCaches();

            services.AddControllersWithViews().AddMicrosoftIdentityUI();

            // In production, the React files will be served from this directory
            services.AddSpaStaticFiles(configuration =>
            {
                configuration.RootPath = "ClientApp/build";
            });
        }

        // 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("/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();
            app.UseSpaStaticFiles();

            app.UseRouting();
            app.UseAuthentication();
            app.UseAuthorization();

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

            app.UseSpa(spa =>
            {
                spa.Options.SourcePath = "ClientApp";

                if (env.IsDevelopment())
                {
                    spa.UseReactDevelopmentServer(npmScript: "start");
                }
            });
        }
    }

在 controller 我使用 AuthorizeForScopes 和 ITokenAcquisition 如下

    [ApiController]
    [Route("[controller]")]
    public class WeatherForecastController : ControllerBase
    {  
        private readonly ITokenAcquisition tokenAcquisition;
        public WeatherForecastController(ITokenAcquisition tokenAcquisition)
        {
            this.tokenAcquisition = tokenAcquisition;
        }

        [AuthorizeForScopes(Scopes = new[] { "https://tenantname.sharepoint.com/AllSites.FullControl" })]
        [HttpGet]
        public async Task<IEnumerable<WeatherForecast>> Get()
        {
            string accessToken = await tokenAcquisition.GetAccessTokenForUserAsync(new[] { "https://tenantname.sharepoint.com/AllSites.FullControl" });
           
            ......
            ......
        }
    }

但是當我嘗試獲取數據時出現 CORS 錯誤

在此處輸入圖像描述

你能幫助我嗎

關於這個問題,請參考以下步驟

  1. 注冊客戶端應用程序和服務器應用程序

  2. 使用帶有 ASP.NET 核心的 React 項目模板

  3. 客戶端應用

一個。 安裝 msal

npm install msal

灣。 定義MsalAuthProvider

import React, { Component } from 'react';
import { UserAgentApplication } from 'msal';

const msalConfig = {
    authority: 'https://login.microsoftonline.com/common',
    clientId: '232a1406-b27b-4667-b8c2-3a865c42b79c',
    redirectUri: document.getElementById('root').baseURI
};
export const msalAuth = new UserAgentApplication({
    auth: msalConfig
});

export function withAuth(HocComponent) {
    return class extends Component {
        constructor(props) {
            super(props);

            this.state = {
                isAuthenticated: false,
                user: {},
                renewIframe: false,
                hasError: false,
                errorMessage: null
            };
        }

        async componentWillMount() {
            msalAuth.handleRedirectCallback(() => {
                let userAccount = msalAuth.getAccount();

                this.setState({
                    isAuthenticated: true,
                    user: userAccount
                });
            }, (authErr, accountState) => {  // on fail
                console.log(authErr);

                this.setState({
                    hasError: true,
                    errorMessage: authErr.errorMessage
                });
            });

            if (msalAuth.isCallback(window.location.hash)) {
                this.setState({
                    auth: {
                        renewIframe: true
                    }
                });
                return;
            }

            let userAccount = msalAuth.getAccount();
            if (!userAccount) {
                msalAuth.loginRedirect({});
                return;
            } else {
                this.setState({
                    isAuthenticated: true,
                    user: userAccount
                });
            }
        }

        onSignIn() {
            msalAuth.loginRedirect({});
        }

        onSignOut() {
            msalAuth.logout();
        }

        render() {
            if (this.state.renewIframe) {
                return <div>hidden renew iframe - not visible</div>;
            }

            if (this.state.isAuthenticated) {
                return <HocComponent auth={this.state} onSignIn={() => this.onSignIn()} onSignOut={() => this.onSignOut()} {...this.props} />;
            }

            if (this.state.hasError) {
                return <div>{this.state.errorMessage}</div>;
            }

            return <div>Login in progress...</div>;
        }
    };
}

c。 更新App.js


import { withAuth } from './msal/MsalAuthProvider';
import './custom.css'

class RootApp extends Component {
  static displayName ="Azure AD application";

  render () {
    return (
      <Layout>
        ...
      </Layout>
    );
  }
}


//enable auth when we access the page
const App = withAuth(RootApp)
export default App;
  1. 致電 API
import { msalAuth } from '../msal/MsalAuthProvider'

 async componentDidMount() {
     // get token and call the api
      try {
          const accessTokenRequest = {
              scopes: ["api://872ebcec-c24a-4399-835a-201cdaf7d68b/access_as_user"]
          }
          var authRes
          var accessToken = null;
          try {
              authRes = await msalAuth.acquireTokenSilent(accessTokenRequest);
              accessToken=authRes.accessToken
          }
          catch (error) {
              console.log("AquireTokenSilent failure");
              authRes = await msalAuth.acquireTokenPopup(accessTokenRequest);
              accessToken = authRes.accessToken
          }

          
          console.log(accessToken)
          this.populateWeatherData(accessToken);
      }
      catch (err) {
          var error = {};
          if (typeof (err) === 'string') {
              var errParts = err.split('|');
              error = errParts.length > 1 ?
                  { message: errParts[1], debug: errParts[0] } :
                  { message: err };
          } else {
              error = {
                  message: err.message,
                  debug: JSON.stringify(err)
              };
          }

          this.setState({
              user: {},
              isLoading: false,
              error: error
          });
      }
  }

async populateWeatherData(token) {
      const response = await fetch('weatherforecast', {
          method: 'get',
          headers: new Headers({
              'Authorization': 'Bearer ' + token
          })

      });
    const data = await response.json();
    this.setState({ forecasts: data, loading: false });
  }
  1. 服務器代碼

一個。 啟動.cs

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

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
                .AddMicrosoftIdentityWebApi(Configuration.GetSection("AzureAd"))
                    .EnableTokenAcquisitionToCallDownstreamApi()
                     .AddInMemoryTokenCaches();

            services.AddControllersWithViews();
           
                // In production, the React files will be served from this directory
                services.AddSpaStaticFiles(configuration =>
            {
                configuration.RootPath = "ClientApp/build";
            });
        }

        // 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("/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();
            app.UseSpaStaticFiles();

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

            app.UseSpa(spa =>
            {
                spa.Options.SourcePath = "ClientApp";

                if (env.IsDevelopment())
                {
                    spa.UseReactDevelopmentServer(npmScript: "start");
                }
            });
        }
    }

灣。 Controller

[ApiController]
    [Route("[controller]")]
    public class WeatherForecastController : ControllerBase
    {  
        private readonly ITokenAcquisition tokenAcquisition;
        public WeatherForecastController(ITokenAcquisition tokenAcquisition)
        {
            this.tokenAcquisition = tokenAcquisition;
        }

        [AuthorizeForScopes(Scopes = new[] { "<your scope>" })]
        [HttpGet]
        public async Task<IEnumerable<WeatherForecast>> Get()
        {
            string accessToken = await tokenAcquisition.GetAccessTokenForUserAsync(new[] { "<your scope>" });
           
            ......
            ......
        }
    }

有關詳細信息,請參閱此處snd here

暫無
暫無

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

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