C# 如何将Api调用中的用户数据传递给.Net WebApp
我正在.Net中开发一个web应用程序。我将使用angular作为它的前端。我使用EntityFramework和Autofac解决依赖关系等。我还将添加用于实时聊天的信号器。今天的问题是关于用户数据的。我有一个身份验证管理器和一个服务。我的行动如下:C# 如何将Api调用中的用户数据传递给.Net WebApp,c#,.net,angular,asp.net-web-api,asp.net-core-webapi,C#,.net,Angular,Asp.net Web Api,Asp.net Core Webapi,我正在.Net中开发一个web应用程序。我将使用angular作为它的前端。我使用EntityFramework和Autofac解决依赖关系等。我还将添加用于实时聊天的信号器。今天的问题是关于用户数据的。我有一个身份验证管理器和一个服务。我的行动如下: public AuthManager(IUserService userService, ITokenHelper tokenHelper) { _userService = userService; _t
public AuthManager(IUserService userService, ITokenHelper tokenHelper)
{
_userService = userService;
_tokenHelper = tokenHelper;
}
public IDataResult<User> Register(UserForRegisterDto userForRegisterDto, string password)
{
byte[] passwordHash, passwordSalt;
HashingHelper.CreatePasswordHash(password, out passwordHash, out passwordSalt);
var user = new User()
{
Email = userForRegisterDto.Email,
FirstName = userForRegisterDto.FirstName,
LastName = userForRegisterDto.LastName,
PasswordSalt = passwordSalt,
PasswordHash = passwordHash,
Status = true
};
_userService.Add(user);
return new SuccessDataResult<User>(user,GenericMessages<User>.ObjHandler + Messages.IsAdded);
}
public IDataResult<User> Login(UserForLoginDto userForLoginDto)
{
var userToCheck = _userService.GetByMail(userForLoginDto.Email).Data;
if (userToCheck == null)
{
return new ErrorDataResult<User>(GenericMessages<User>.ObjHandler + Messages.NotFound);
}
if (!HashingHelper.VerifyPasswordHash(userForLoginDto.Password, userToCheck.PasswordHash, userToCheck.PasswordSalt))
{
return new ErrorDataResult<User>(Messages.PasswordError);
}
return new SuccessDataResult<User>(userToCheck, Messages.LoginSuccessful);
}
public IResult UserExists(string email)
{
if (_userService.GetByMail(email).Data != null)
{
return new ErrorResult(GenericMessages<User>.ObjHandler + Messages.AlreadyExists);
}
return new SuccessResult();
}
public IDataResult<AccessToken> CreateAccessToken(User user)
{
var claims = _userService.GetClaims(user).Data;
var accessToken = _tokenHelper.CreateToken(user,claims);
return new SuccessDataResult<AccessToken>(accessToken, Messages.AccessTokenCreated);
}
每当用户下订单时,该订单都会转到挂起状态。当其处于挂起状态时,其他用户可以在挂起的订单中查看它们。当第二个用户决定接受订单时,他/她单击上面运行的接受按钮。我的订单类看起来像这样
public class Order : IEntity
{
public int Id { get; set; }
public int UserId { get; set; }
public DateTime OrderDate { get; set; }
public DateTime RoundDate { get; set; }
public int GamerId { get; set; }
public int Quantity { get; set; }
public int Amount { get; set; }
public int GameId { get; set; }
public int GameAdId { get; set; }
public OrderStatus OrderStatus { get; set; }
}
因此,我的问题是,当登录用户调用OrdersController连接到OrderService时。这意味着拥有函数声明的任何人都可以向OrderManager方法发出请求
public IResult Add(Order order)
{
_orderDal.Add(order);
return new SuccessResult(Messages.OrderAdded);
}
此方法将用于“下订单”,付款方法也依赖于此处创建的订单数据。每当用户试图调用此方法时,我都希望在order对象中传递他们的用户Id。我把它作为一个属性,但我需要在某处收集用户Id数据。我使用JWT令牌作为身份验证。当用户登录时,我传递一个承载令牌。如果我只是从数据库或浏览器中获取用户id,这样我就可以在我的其他方法中使用这些信息,这对我也会有很大帮助
编辑:正如我提到的,我还将实现signalR并添加实时消息功能。但是,signalR不存储发送给脱机用户的消息。因此,我需要将每个客户机的用户名或userId存储在一个并发目录中,以便存储它们尚未看到的消息。这样做的最佳方法是什么
第二次编辑:
I decided to also share token operations. So this part is from AuthManager: ` public IDataResult<AccessToken> CreateAccessToken(User user)
{
var claims = _userService.GetClaims(user).Data;
var accessToken = _tokenHelper.CreateToken(user,claims);
return new SuccessDataResult<AccessToken>(accessToken, Messages.AccessTokenCreated);
}
我决定也共享令牌操作。因此,这部分来自AuthManager:`public IDataResult CreateAccessToken(用户)
{
var-claims=\u userService.GetClaims(user.Data);
var accessToken=_tokenHelper.CreateToken(用户,声明);
返回新的SuccessDataResult(accessToken,Messages.AccessTokenCreated);
}
这部分来自JwtHewlper:
public AccessToken CreateToken(User user, List<OperationClaim> operationClaims)
{
var securityKey = SecurityKeyHelper.CreateSecurityKey(_tokenOptions.SecurityKey);
var signingCredentials = SigningCredentialsHelper.CreateSigningCredentials(securityKey);
var jwt = CreateJwtSecurityToken(_tokenOptions, user, signingCredentials, operationClaims);
var jwtSecurityTokenHandler = new JwtSecurityTokenHandler();
var token = jwtSecurityTokenHandler.WriteToken(jwt);
return new AccessToken()
{
Token = token,
Expiration = _accessTokenExpiration
};
}
public JwtSecurityToken CreateJwtSecurityToken(TokenOptions tokenOptions, User user,
SigningCredentials signingCredentials, List<OperationClaim> operationClaims)
{
var jwt = new JwtSecurityToken(
issuer: _tokenOptions.Issuer,
audience: _tokenOptions.Audience,
expires: _accessTokenExpiration,
notBefore: DateTime.Now,
claims: SetClaims(user, operationClaims),
signingCredentials: signingCredentials
);
return jwt;
}
private IEnumerable<Claim> SetClaims(User user, List<OperationClaim> operationClaims)
{
var claims = new List<Claim>();
claims.AddNameIdentifier(user.Id.ToString());
claims.AddName($"{user.FirstName} {user.LastName}");
claims.AddRoles(operationClaims.Select(c => c.Name).ToArray());
return claims;
}
public AccessToken CreateToken(用户、列表操作声明)
{
var securityKey=SecurityKeyHelper.CreateSecurityKey(\u tokenOptions.securityKey);
var signingCredentials=SigningCredentialsHelper.CreateSigningCredentials(securityKey);
var jwt=CreateJwtSecurityToken(_tokenOptions,user,signingCredentials,operationClaims);
var jwtSecurityTokenHandler=新的jwtSecurityTokenHandler();
var-token=jwtSecurityTokenHandler.WriteToken(jwt);
返回新的AccessToken()
{
令牌=令牌,
过期=\u accessTokenExpiration
};
}
公共JwtSecurityToken CreateJwtSecurityToken(TokenOptions TokenOptions,用户用户,
签名凭据签名凭据,列出操作声明)
{
var jwt=新的JwtSecurityToken(
发卡机构:_tokenOptions.issuer,
观众:_tokenOptions.viewer,
过期:_accessTokenExpire,
日期时间。现在,
声明:设置声明(用户、操作声明),
签名凭据:签名凭据
);
返回jwt;
}
私有IEnumerable集合声明(用户、列表操作声明)
{
var索赔=新列表();
claims.AddNameIdentifier(user.Id.ToString());
claims.AddName($“{user.FirstName}{user.LastName}”);
AddRoles(operationClaims.Select(c=>c.Name.ToArray());
退货索赔;
}
这是一个非常复杂的问题,可能不适合这样做。不过有一个提示-JWT是否不包含您需要的用户id?否,令牌仅包含声明。每次用户发送电子邮件和密码数据时,我都会创建AccessToken。然后我存储创建的令牌。但这些令牌是临时的,所以我认为在向数据库添加新条目时不应该使用它们。例如,如果我想在用户脱机时存储发送的消息,我应该使用他们的用户ID,而不是一些临时的承载令牌。但我只是不知道怎么做。多么空虚……正如我之前所说的,这个问题太复杂了。也许可以把它简化为更小、更集中的问题?让我这样说:我有一个.net核心web api。我正在使用Jwt进行身份验证。我将使用信号器聊天。我需要将用户ID信息存储在应用程序或客户端的某个位置(在我的情况下,浏览器将使用Angular作为前端)。那么我应该使用Session还是Identity.Name属性呢?如何设置Identity.Name属性以匹配用户登录后的Id。我有一个userId的int值,但Identity.Name应该是一个字符串。现在有什么想法吗?我的问题其实很基本。我只是想分享更多的信息,让你更好地理解。
I decided to also share token operations. So this part is from AuthManager: ` public IDataResult<AccessToken> CreateAccessToken(User user)
{
var claims = _userService.GetClaims(user).Data;
var accessToken = _tokenHelper.CreateToken(user,claims);
return new SuccessDataResult<AccessToken>(accessToken, Messages.AccessTokenCreated);
}
public AccessToken CreateToken(User user, List<OperationClaim> operationClaims)
{
var securityKey = SecurityKeyHelper.CreateSecurityKey(_tokenOptions.SecurityKey);
var signingCredentials = SigningCredentialsHelper.CreateSigningCredentials(securityKey);
var jwt = CreateJwtSecurityToken(_tokenOptions, user, signingCredentials, operationClaims);
var jwtSecurityTokenHandler = new JwtSecurityTokenHandler();
var token = jwtSecurityTokenHandler.WriteToken(jwt);
return new AccessToken()
{
Token = token,
Expiration = _accessTokenExpiration
};
}
public JwtSecurityToken CreateJwtSecurityToken(TokenOptions tokenOptions, User user,
SigningCredentials signingCredentials, List<OperationClaim> operationClaims)
{
var jwt = new JwtSecurityToken(
issuer: _tokenOptions.Issuer,
audience: _tokenOptions.Audience,
expires: _accessTokenExpiration,
notBefore: DateTime.Now,
claims: SetClaims(user, operationClaims),
signingCredentials: signingCredentials
);
return jwt;
}
private IEnumerable<Claim> SetClaims(User user, List<OperationClaim> operationClaims)
{
var claims = new List<Claim>();
claims.AddNameIdentifier(user.Id.ToString());
claims.AddName($"{user.FirstName} {user.LastName}");
claims.AddRoles(operationClaims.Select(c => c.Name).ToArray());
return claims;
}