我几天来一直在寻找这个问题的答案。所以我认为是时候寻求帮助了。
我发现了一个类似的问题,但这种修复方法对我不起作用。Asp.net用户处于角色中,但[授权(角色="管理员"(]返回授权失败的
我正在使用。具有身份和角色的Net5核心Api基本身份验证。我可以很好地进行身份验证,但当我尝试使用[授权(角色="管理员"(]属性时,问题就来了。
使用它向我展示了用户的角色:
if (await _userManager.IsInRoleAsync(user, "Admin"))
这是我的启动:
public class Startup
{
public static RoleManager<IdentityRole> roleManager;
public static UserManager<PTPublicAPIUser> userManager;
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.AddControllers();
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "PTPublicAPI", Version = "v1" });
});
services.AddDbContext<PTPublicAPIContext>(
options => options.UseSqlServer("name=ConnectionStrings:PTPublicAPIContextConnection"));
services.AddAuthentication().AddScheme<AuthenticationSchemeOptions, BasicAuthenticationIdentityHandler>("BasicAuthentication", options => { });
services.AddAuthorization(options =>
{
options.AddPolicy("BasicAuthentication", new AuthorizationPolicyBuilder("BasicAuthentication").RequireAuthenticatedUser().Build());
});
// Configure Identity
services.Configure<IdentityOptions>(options =>
{
// Password settings
options.Password.RequireDigit = false;
options.Password.RequiredLength = 8;
options.Password.RequireNonAlphanumeric = false;
options.Password.RequireUppercase = false;
options.Password.RequireLowercase = false;
options.Lockout.AllowedForNewUsers = false;
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, UserManager<PTPublicAPIUser> userManager, RoleManager<IdentityRole> roleManager)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseSwagger();
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "PTPublicAPI v1"));
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
IdentityDataInitializer.SeedData(userManager, roleManager);
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
当我尝试这个时,我得到403禁止
[BasicAuthIdentity]
[HttpGet]
[Authorize(Roles = "Admin")]
public IEnumerable<WeatherForecast> Get()
但这是
[BasicAuthIdentity]
[HttpGet]
public IEnumerable<WeatherForecast> Get()
已编辑:添加了基本身份验证标识处理程序
public class BasicAuthenticationIdentityHandler : AuthenticationHandler<AuthenticationSchemeOptions>
{
private readonly PTPublicAPIContext _publicAPIContext;
private readonly UserManager<PTPublicAPIUser> _userManager;
public BasicAuthenticationIdentityHandler(IOptionsMonitor<AuthenticationSchemeOptions> options, ILoggerFactory logger, UrlEncoder encoder, PTPublicAPIContext publicAPIContext, UserManager<PTPublicAPIUser> userManager, ISystemClock clock) : base(options, logger, encoder, clock)
{
_publicAPIContext = publicAPIContext;
_userManager = userManager;
}
protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
{
//Response.Headers.Add("WWW-Authenticate", "Basic");
if (!Request.Headers.ContainsKey("Authorization"))
{
return AuthenticateResult.Fail("Authorization header missing.");
}
// Get authorization key
var authorizationHeader = Request.Headers["Authorization"].ToString();
var authHeaderRegex = new Regex(@"Basic (.*)");
if (!authHeaderRegex.IsMatch(authorizationHeader))
{
return AuthenticateResult.Fail("Authorization code not formatted properly.");
}
var authBase64 = Encoding.UTF8.GetString(Convert.FromBase64String(authHeaderRegex.Replace(authorizationHeader, "$1")));
var authSplit = authBase64.Split(Convert.ToChar(":"), 2);
var authUsername = authSplit[0];
var authPassword = authSplit.Length > 1 ? authSplit[1] : throw new Exception("Unable to get password");
var user = _publicAPIContext.Users.FirstOrDefault(x => x.UserName == authUsername);
if (user == null)
return AuthenticateResult.Fail("The username or password is not correct.");
bool passwordGood = await _userManager.CheckPasswordAsync(user, authPassword);
if (!passwordGood)
return AuthenticateResult.Fail("The username or password is not correct.");
AuthenticatedUser authenticatedUser = new AuthenticatedUser("BasicAuthentication", true, authUsername);
ClaimsPrincipal claimsPrincipal = new ClaimsPrincipal(new ClaimsIdentity(authenticatedUser));
return AuthenticateResult.Success(new AuthenticationTicket(claimsPrincipal, Scheme.Name));
}
}
此处添加的是AuthenticatedUser
public class AuthenticatedUser : IIdentity
{
public AuthenticatedUser(string authenticationType, bool isAuthenticated, string name)
{
AuthenticationType = authenticationType;
IsAuthenticated = isAuthenticated;
Name = name;
}
public string AuthenticationType { get; }
public bool IsAuthenticated { get; }
public string Name { get; }
}
通常,在角色中添加用户后,会自动生成相关声明。。。但是我推断出关于角色的cliam
没有添加到您的用户中,您可以在控制器中的构造函数中添加以下代码来检查相关声明。
public class HomeController : Controller
{
private readonly IHttpContextAccessor _context;
public HomeController(IHttpContextAccessor context)
{
//......
_context = context;
/Check the claims here
var result = _context.HttpContext.User.Claims;
}
[BasicAuthIdentity]
[HttpGet]
[Authorize(Roles = "Admin")]
public IEnumerable<WeatherForecast> Get(){}
}
如果没有类似的索赔
{xxxxxx: Admin}
您可以通过自己的在登录方法中添加索赔
[HttpPost]
public async Task<IActionResult> Login(LoginViewModel model)
{
if (ModelState.IsValid)
{
var result = await _signInManager.PasswordSignInAsync(model.UserName, model.Password,isPersistent: false,lockoutOnFailure:false);
if (result.Succeeded)
{
//.....
//add the following code in login method to add the role claim
IdentityUser currentuser = await _userManager.FindByNameAsync(Input.Email);
Claim claim = new Claim(ClaimTypes.Role, "Admin",ClaimValueTypes.String);
IdentityResult identityresult = await
_userManager.AddClaimAsync(currentuser, claim);
//signin again and get the latest claims.
await _signInManager.SignInAsync(currentuser, false, null);
//......
}
}
}
注意:此方法将直接将数据写入AspNetUserClaims
数据库,因此当您需要更改相关角色时,需要删除数据库中的数据
好的,伙计们,谢谢你们的回复。我成功了。这就是我所做的。
在BasicAuthenticationIdentityHandler中。HandleAuthenticateAsync我更改了这个
AuthenticatedUser authenticatedUser = new AuthenticatedUser("BasicAuthentication", true, authUsername);
ClaimsPrincipal claimsPrincipal = new ClaimsPrincipal(new ClaimsIdentity(authenticatedUser));
return AuthenticateResult.Success(new AuthenticationTicket(claimsPrincipal, Scheme.Name));
到此:
var principal = await _claimsPrincipalFactory.CreateAsync(user);
var ticket = new AuthenticationTicket(principal, new AuthenticationProperties(), Scheme.Name);
return AuthenticateResult.Success(ticket);
这是现在的课程
public class BasicAuthenticationIdentityHandler : AuthenticationHandler<AuthenticationSchemeOptions>{
private readonly IUserClaimsPrincipalFactory<PTPublicAPIUser> _claimsPrincipalFactory;
private readonly PTPublicAPIContext _publicAPIContext;
private readonly UserManager<PTPublicAPIUser> _userManager;
public BasicAuthenticationIdentityHandler(IOptionsMonitor<AuthenticationSchemeOptions> options, ILoggerFactory logger, UrlEncoder encoder, PTPublicAPIContext publicAPIContext, UserManager<PTPublicAPIUser> userManager, ISystemClock clock, IUserClaimsPrincipalFactory<PTPublicAPIUser> claimsPrincipalFactory) : base(options, logger, encoder, clock)
{
_publicAPIContext = publicAPIContext;
_userManager = userManager;
_claimsPrincipalFactory = claimsPrincipalFactory;
}
protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
{
//Response.Headers.Add("WWW-Authenticate", "Basic");
if (!Request.Headers.ContainsKey("Authorization"))
{
return AuthenticateResult.Fail("Authorization header missing.");
}
// Get authorization key
string authorizationHeader = Request.Headers["Authorization"].ToString();
Regex authHeaderRegex = new Regex(@"Basic (.*)");
if (!authHeaderRegex.IsMatch(authorizationHeader))
{
return AuthenticateResult.Fail("Authorization code not formatted properly.");
}
string authBase64 = Encoding.UTF8.GetString(Convert.FromBase64String(authHeaderRegex.Replace(authorizationHeader, "$1")));
string[] authSplit = authBase64.Split(Convert.ToChar(":"), 2);
string authUsername = authSplit[0];
string authPassword = authSplit.Length > 1 ? authSplit[1] : throw new Exception("Unable to get password");
var user = _publicAPIContext.Users.FirstOrDefault(x => x.UserName == authUsername);
if (user == null)
return AuthenticateResult.Fail("The username or password is not correct.");
bool passwordIsValid = await _userManager.CheckPasswordAsync(user, authPassword);
if (!passwordIsValid)
return AuthenticateResult.Fail("The username or password is not correct.");
ClaimsPrincipal principal = await _claimsPrincipalFactory.CreateAsync(user);
AuthenticationTicket ticket = new AuthenticationTicket(principal, new AuthenticationProperties(), Scheme.Name);
return AuthenticateResult.Success(ticket);
}
}