C# 我应该将JWT逻辑放在我的web api中的什么位置?

C# 我应该将JWT逻辑放在我的web api中的什么位置?,c#,asp.net-web-api,asp.net-core,C#,Asp.net Web Api,Asp.net Core,因此,我有一个使用JWT创建、登录等的api。现在我的登录类太宽了,对我的喜好承担了太多的责任。在这里 [HttpPost("login")] public async Task<IActionResult> Login(UserForLoginDto user) { var userFromRepo = await _qrepo.Login(user.Username, user.Password); //IF no user

因此,我有一个使用JWT创建、登录等的api。现在我的登录类太宽了,对我的喜好承担了太多的责任。在这里

    [HttpPost("login")]
    public async Task<IActionResult> Login(UserForLoginDto user)
    {
        var userFromRepo = await _qrepo.Login(user.Username, user.Password);
        //IF no user found in db
        if (userFromRepo == null)
            //Return unauth so if user have wrong login creds, we're not specifying if it's password or username
            return Unauthorized();

        //Token creation
        var claims = new[]
        {
            new Claim(ClaimTypes.NameIdentifier, userFromRepo.Id.ToString()),
            new Claim(ClaimTypes.Name, userFromRepo.Username)
        };

        // Hashed token Key
        // The token is unique and very secret - if you have the token you are able to create tokens that are verifyable for our backend
        var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config.GetSection("AppSettings:Token").Value));

        // Signing credentials 
        var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha512Signature);

        // Security Token DEscripter
        var tokenDescriptor = new SecurityTokenDescriptor
        {
            // our claims
            Subject = new ClaimsIdentity(claims),
            // Expiry date - 1 day from create
            Expires = DateTime.Now.AddDays(1),
            SigningCredentials = creds
        };

        // Token handler
        var tokenHandler = new JwtSecurityTokenHandler();

        // Actual token
        var token = tokenHandler.CreateToken(tokenDescriptor);

        // Return actual token
        return Ok(new
        {
            token = tokenHandler.WriteToken(token)
        });
    }
[HttpPost(“登录”)]
公共异步任务登录(UserForLoginDto用户)
{
var userFromRepo=wait_qrepo.Login(user.Username,user.Password);
//如果在数据库中找不到用户
if(userFromRepo==null)
//返回unauth,所以若用户有错误的登录凭据,我们不会指定它是密码还是用户名
未经授权返回();
//令牌创建
风险值索赔=新[]
{
新声明(ClaimTypes.NameIdentifier,userFromRepo.Id.ToString()),
新索赔(ClaimTypes.Name,userFromRepo.Username)
};
//哈希令牌密钥
//令牌是唯一且非常机密的-如果您拥有令牌,您可以创建可用于后端验证的令牌
var key=new-SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config.GetSection(“AppSettings:Token”).Value));
//签署凭证
var creds=新的签名凭证(key,SecurityAlgorithms.HmacSha512Signature);
//安全令牌描述符
var tokenDescriptor=新的SecurityTokenDescriptor
{
//我们的要求
主题=新的索赔实体(索赔),
//有效期-创建后1天
Expires=DateTime.Now.AddDays(1),
签名凭证=信誉
};
//令牌处理程序
var tokenHandler=new JwtSecurityTokenHandler();
//实际代币
var token=tokenHandler.CreateToken(tokenDescriptor);
//返回实际令牌
返回Ok(新的
{
token=tokenHandler.WriteToken(令牌)
});
}
我希望我的令牌创建与我的控制器方法分开,但我不完全确定什么是最好的方法,所以这将属于哪里?这是我的文件夹结构:


我觉得它不属于我的任何一个文件夹,但可能属于助手,idk?这方面的标准方法是什么

您能将所有令牌生成内容放在一个单独的服务类中吗? 然后使用DI注入服务。 还应为其提供一个接口,以便您可以更轻松地进行测试:

public interface IJwtTokenGenerator
{
    string GenerateToken(User user);
}

public class JwtTokenGenerator : IJwtTokenGenerator
{
    private readonly IConfiguration _config;

    public JwtTokenGenerator(IConfiguration config)
    {
        _config = config;
    }

    //obviously, change User to whatever your user class name is
    public string GenerateToken(User user)
    {
        //Token creation
        var claims = new[]
        {
            new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),
            new Claim(ClaimTypes.Name, user.Username)
        };

        // Hashed token Key
        // The token is unique and very secret - if you have the token you are able to create tokens that are verifyable for our backend
        var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config.GetSection("AppSettings:Token").Value));

        // Signing credentials 
        var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha512Signature);

        // Security Token DEscripter
        var tokenDescriptor = new SecurityTokenDescriptor
        {
            // our claims
            Subject = new ClaimsIdentity(claims),
            // Expiry date - 1 day from create
            Expires = DateTime.Now.AddDays(1),
            SigningCredentials = creds
        };

        // Token handler
        var tokenHandler = new JwtSecurityTokenHandler();

        // Actual token
        var securityToken = tokenHandler.CreateToken(tokenDescriptor);

        return tokenHandler.WriteToken(securityToken);
    }
}
然后,您的登录操作可能如下所示:

[HttpPost("login")]
public async Task<IActionResult> Login(UserForLoginDto user)
{
    var userFromRepo = await _qrepo.Login(user.Username, user.Password);
    //IF no user found in db
    if (userFromRepo == null)
        //Return unauth so if user have wrong login creds, we're not specifying if it's password or username
        return Unauthorized();

    //Injected ITokenGenerator (note the interface)
    var token = _tokenGenerator.GenerateToken(userFromRepo);

    // Return actual token
    return Ok(new
    {
        token
    });
}
[HttpPost(“登录”)]
公共异步任务登录(UserForLoginDto用户)
{
var userFromRepo=wait_qrepo.Login(user.Username,user.Password);
//如果在数据库中找不到用户
if(userFromRepo==null)
//返回unauth,所以若用户有错误的登录凭据,我们不会指定它是密码还是用户名
未经授权返回();
//注入式ITokenGenerator(注意接口)
var token=_tokenGenerator.GenerateToken(userFromRepo);
//返回实际令牌
返回Ok(新的
{
代币
});
}

就放置这个类和接口的文件夹(应该是两个单独的文件)而言,主要取决于对您或您的团队有意义的内容。也许是另一个名为“服务”的文件夹,也许是“身份验证”,也许是“身份验证/服务”。“Helpers”通常用于静态类,但我想你可以把它放在那里

是的,就是这样的,我在看。非常感谢,我不确定是否有固定的建筑。同样感谢这个例子,我可能没有界面,但我仍然不太适应测试,但我也将在这个项目的后期阶段实现它。真的很感激