首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用IPasswordHasher<User>和BCrypt算法时的哈希和盐问题

使用IPasswordHasher<User>和BCrypt算法时的哈希和盐问题
EN

Stack Overflow用户
提问于 2022-06-23 20:30:14
回答 1查看 488关注 0票数 0

我在ASP.NET中遇到了哈希、咸和验证密码的问题,我正在创建一个新用户,然后使用散列方法。但是,当我试图获取一些需要授权的资源时,输入与我在数据库中保存的用户名和密码相同的用户名和密码,结果就失败了。

这是我的密码有她的课:

代码语言:javascript
运行
复制
using Microsoft.AspNetCore.Identity;

namespace FlowerShop.ApplicationServices.Components.PasswordHasher
{
    public class BCryptPasswordHasher<User> : IPasswordHasher<User> where User : class
{
    
    public string HashPassword(User user, string password)
    {  
        return BCrypt.Net.BCrypt.HashPassword(password, 12);
    }

    public PasswordVerificationResult VerifyHashedPassword(User user, string hashedPassword, string providedPassword)
    {
        var isValid = BCrypt.Net.BCrypt.Verify(providedPassword, hashedPassword);

        if (isValid && BCrypt.Net.BCrypt.PasswordNeedsRehash(hashedPassword, 12))
        {
            return PasswordVerificationResult.SuccessRehashNeeded;
        }

        return isValid ? PasswordVerificationResult.Success : PasswordVerificationResult.Failed;
    }
}

这是我的身份验证课程:

代码语言:javascript
运行
复制
public class BasicAuthenticationHandler : AuthenticationHandler<AuthenticationSchemeOptions>
{
    private readonly IQueryExecutor queryExecutor;
    private readonly IPasswordHasher<User> passwordHasher;

    public BasicAuthenticationHandler(IOptionsMonitor<AuthenticationSchemeOptions> options, 
        ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock, 
        IQueryExecutor queryExecutor, IPasswordHasher<User> passwordHasher)
        : base(options, logger, encoder, clock)
    {
        this.queryExecutor = queryExecutor;
        this.passwordHasher = passwordHasher;
    }

    protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
    {
        var endpoint = Context.GetEndpoint();
        if (endpoint?.Metadata?.GetMetadata<IAllowAnonymous>() != null)
        {
            return AuthenticateResult.NoResult();
        }

        if (!Request.Headers.ContainsKey("Authorization"))
        {
            return AuthenticateResult.Fail("Missing Authorization Header");
        }

        User user = null;

        try
        {
            var authHeader = AuthenticationHeaderValue.Parse(Request.Headers["Authorization"]);
            var credentialBytes = Convert.FromBase64String(authHeader.Parameter);
            var credentials = Encoding.UTF8.GetString(credentialBytes).Split(new[] { ':' }, 2);
            var username = credentials[0];
            var providedPassword = passwordHasher.HashPassword(user, credentials[1]);

            var query = new GetUserQuery()
            {
                UserName = username
            };
            user = await this.queryExecutor.Execute(query);
                           
            if (user == null || passwordHasher.VerifyHashedPassword(user, user.PasswordHash, providedPassword) 
                == PasswordVerificationResult.Failed)
            {
                return AuthenticateResult.Fail("Invalid Authorization Header");
            }
        }
        catch
        {
            return AuthenticateResult.Fail("Invalid Authorization Header");
        }

        var claims = new[]
        {
            new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),
            new Claim(ClaimTypes.Name, user.UserName),
            new Claim(ClaimTypes.Role, user.Role.ToString()),
            new Claim(ClaimTypes.Email, user.Email),
        };
        var identity = new ClaimsIdentity(claims, Scheme.Name);
        var principal = new ClaimsPrincipal(identity);
        var ticket = new AuthenticationTicket(principal, Scheme.Name);
        
        return AuthenticateResult.Success(ticket);
    }
}

在这个地方,我创建了一个新用户:

代码语言:javascript
运行
复制
        using MediatR;
        using Microsoft.AspNetCore.Identity;
        using System.Threading;
        using System.Threading.Tasks;

        public class AddUserHandler : IRequestHandler<AddUserRequest,
    AddUserResponse>
        {
        private readonly ICommandExecutor commandExecutor;
        private readonly IQueryExecutor queryExecutor;
        private readonly IMapper mapper;
        private readonly IPasswordHasher<User> passwordHasher;

            public AddUserHandler(ICommandExecutor commandExecutor,
    IQueryExecutor queryExecutor, 
                IMapper mapper, IPasswordHasher<User> passwordHasher)
            {
                this.commandExecutor = commandExecutor;
                this.queryExecutor = queryExecutor;
                this.mapper = mapper;
                this.passwordHasher = passwordHasher;
            }

            public async Task<AddUserResponse> Handle(AddUserRequest
    request, CancellationToken cancellationToken)
            {
            var query = new GetUserQuery()
            {                
                UserName = request.UserName,
                Email = request.Email
            };

            var getUser = await this.queryExecutor.Execute(query);
            if (getUser != null)
            {
                if (getUser.UserName == request.UserName)      

              {
                        return new AddUserResponse()
                        {
                            Error = new ErrorModel(ErrorType.ValidationError +
    "! The name is already taken.")
                        };
                    }
                if (getUser.Email == request.Email)
                {
         

               return new AddUserResponse()
                        {
                            Error = new ErrorModel(ErrorType.ValidationError +
    "! Email address is in use.")
                        };
                    }
                return new AddUserResponse()
                {
                    Error = new ErrorModel(ErrorType.Conflict)
                };
            }

            request.PasswordHash = passwordHasher.HashPassword(getUser,
request.Password);

            var user = this.mapper.Map<User>(request);
            var command = new AddUserCommand() 
            { 
                Parameter = user 
            };
            var addedUser = await this.commandExecutor.Execute(command);
            var response = new AddUserResponse()
            {
                Data =
this.mapper.Map<Domain.Models.UserDTO>(addedUser)
            };

            return response;
        }
    }

这是我的Startup.cs:

代码语言:javascript
运行
复制
      public void ConfigureServices(IServiceCollection services)
            {
                services.AddAuthentication("BasicAuthentication")
                        .AddScheme<AuthenticationSchemeOptions,
    BasicAuthenticationHandler>("BasicAuthentication", null);
    
                services.AddScoped<IPasswordHasher<User>,
    BCryptPasswordHasher<User>>();
}

也许首先,这一切都是正确的实施吗?

在request.PasswordHash?

  • How中,
  1. 是否正确地分配给AddUserHandler以检索salt并分配给request.PasswordSalt?如果有任何不清楚的事情发生,很抱歉。--

如有任何反馈和帮助,将不胜感激。

(预先谢谢:)

编辑:

例如,如果我添加密码为“"$2a$12$Iqpy7FyQh/pt2O8upTtG5eOQKzo1V395wRNdAXPpp5Qf.NQ.KxUyy"‘”的用户,并将其作为'user.PasswordHash = "$2a$12$9vSz8Sw/WtmqGY6jyDiTleN/btZ0wXJkXdoB3sDpANVIIDGBpaqT."’‘存储在数据库中,并在散列后提供密码为'providedPassword =“$2a$12$9vSz8Sw/WtmqGY6jyDiTleN/btZ0wXJkXdoB3sDpANVIIDGBpaqT.”’

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-07-03 17:38:09

如果将来有人需要用它,我就把它修好。问题出在我的认证课上。代替:

代码语言:javascript
运行
复制
var username = credentials[0];
var providedPassword = passwordHasher.HashPassword(user, credentials[1]);

应:

代码语言:javascript
运行
复制
var username = credentials[0];
var providedPassword = credentials[1];

我确信我已经检查过几次了,但那时候不知怎么没起作用。不管怎样,它终于正常工作了。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72736234

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档