[英]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 錯誤
你能幫助我嗎
關於這個問題,請參考以下步驟
注冊客戶端應用程序和服務器應用程序
客戶端應用
一個。 安裝 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;
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 });
}
一個。 啟動.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>" });
......
......
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.