.NET Core 2.0 身份和 jwt?

Posted

技术标签:

【中文标题】.NET Core 2.0 身份和 jwt?【英文标题】:.NET Core 2.0 Identity AND jwt? 【发布时间】:2018-12-21 08:30:31 【问题描述】:

我一直在四处寻找并尝试对 .NET Core Identity (https://docs.microsoft.com/en-us/aspnet/core/security/authentication/identity?view=aspnetcore-2.1&tabs=visual-studio%2Caspnetcore2x) 和 Jwt(json Web 令牌)进行更多研究。我一直在我的 .NET Core 2.0 应用中使用默认身份作为身份验证/授权,到目前为止它运行良好。

我遇到了障碍,我认为这是我理解 .NET Core 身份和 jwt 的方式。我的应用程序有 MVC 和 web api。我理想地希望保护 web api,但我听说现在最好的方法是通过 jwt。好 - 酷。

我可以继续配置 jwt,然后将其用作我的身份验证/授权 (https://blogs.msdn.microsoft.com/webdev/2017/04/06/jwt-validation-and-authorization-in-asp-net-core/),但是 - 我是否需要继续并启动一个新服务器作为 jwt 的授权服务器?如果是这样,我不会那样做(太贵了)。

如果我确实使用 jwt,我的 .NET Core 身份代码会怎样?那是不是必须要走了?如果它可以共存,我如何使用 Identity 授权我的 MVC 页面并使用 jwt 授权我的 api 端点?

我知道这是一个开放式问题,但它的核心是:

.NET Core Identity 和 JWT 可以共存吗?还是我必须选择其中之一?我有 MVC 和 web api,并希望保护两者。

【问题讨论】:

你调查过这个吗? medium.com/@ozgurgul/… 您可以简单地使用SignInManager 验证用户的登录,使用UserManager 获取声明,最后使用它创建一个JWT。 Two AuthorizationSchemes in ASP.NET Core 2 很好地涵盖了这一点。 【参考方案1】:

您可以验证用户名和密码并生成 Jwt。

首先,确保您的 API 在 startup.cs 中设置了以下默认身份:

services.AddDbContext<ApplicationDbContext>(options =>
    options.UseSqlServer(
        Configuration.GetConnectionString("DefaultConnection")));
services.AddDefaultIdentity<IdentityUser>()
    .AddEntityFrameworkStores<ApplicationDbContext>();

其次,您可以使用以下方式验证登录:

您可以像这样设置 API 控制器:

[ApiController, Route("check")]
public class TokenController : ControllerBase

    private readonly SignInManager<IdentityUser> signin;

    public TokenController(SignInManager<IdentityUser> signin)
    
        this.signin = signin;
    

    [HttpGet]
    public async Task<string> Get(string user, string pass)
    
        var result = await signin.PasswordSignInAsync(user, pass, true, false);
        if (result.Succeeded)
        
            string token = "";
            return token;
        
        return null;
    

在您的 get 函数中,您现在可以生成您的 Jwt。

【讨论】:

【参考方案2】:

是的,你可以。 逻辑过程在这个方法中:

第 1 步:获取用户声明

var identity = await GetClaimsIdentity(credentials.UserName, credentials.Password);

您将进入 GetClaimsIdentity

private async Task<ClaimsIdentity> GetClaimsIdentity(string userName, string password)

    if (string.IsNullOrEmpty(userName) || string.IsNullOrEmpty(password))
        return await Task.FromResult<ClaimsIdentity>(null);

    var userToVerify = await _userManager.FindByNameAsync(userName);                

    if (userToVerify == null) 
        userToVerify = await _userManager.FindByEmailAsync(userName);
        if (userToVerify == null)  
            return await Task.FromResult<ClaimsIdentity>(null);
        
    
    // check the credentials
    if (await _userManager.CheckPasswordAsync(userToVerify, password))
    
        _claims = await _userManager.GetClaimsAsync(userToVerify);

        return await Task.FromResult(_jwtFactory.GenerateClaimsIdentity(userToVerify.UserName, userToVerify.Id, _claims));
    
    // Credentials are invalid, or account doesn't exist
    return await Task.FromResult<ClaimsIdentity>(null);

第 2 步:将您需要添加到令牌的所有用户声明分组 - 使用 System.Security.Claims

 public ClaimsIdentity GenerateClaimsIdentity(string userName, string id, IList<Claim> claims)
    
        claims.Add(new Claim(Helpers.Constants.Strings.JwtClaimIdentifiers.Id, id));

        // If your security is role based you can get then with the RoleManager and add then here as claims

        // Ask here for all claims your app need to validate later 

        return new ClaimsIdentity(new GenericIdentity(userName, "Token"), claims);
    

第 3 步:然后返回您的方法,您必须生成并返回 JWT 令牌

jwt = await jwtFactory.GenerateEncodedToken(userName, identity);
return new OkObjectResult(jwt);

要生成令牌,请执行以下操作:

public async Task<string> GenerateEncodedToken(string userName, ClaimsIdentity identity)

    List<Claim> claims = new List<Claim>();
    //Config claims
    claims.Add(new Claim(JwtRegisteredClaimNames.Sub, userName));
    claims.Add(new Claim(JwtRegisteredClaimNames.Jti, await _jwtOptions.JtiGenerator()));
    claims.Add(new Claim(JwtRegisteredClaimNames.Iat, ToUnixEpochDate(_jwtOptions.IssuedAt).ToString(), ClaimValueTypes.Integer64));
    //End Config claims
    claims.AddRange(identity.FindAll(Helpers.Constants.Strings.JwtClaimIdentifiers.Roles));
    claims.AddRange(identity.FindAll("EspecificClaimName"));


    // Create the JWT security token and encode it.
    var jwt = new JwtSecurityToken(
        issuer: _jwtOptions.Issuer,
        audience: _jwtOptions.Audience,
        claims: claims,
        notBefore: _jwtOptions.NotBefore,
        expires: _jwtOptions.Expiration,
        signingCredentials: _jwtOptions.SigningCredentials);

    var encodedJwt = new JwtSecurityTokenHandler().WriteToken(jwt);

    return encodedJwt;

有很多方法可以做到这一点。 最常见的是: 验证身份用户 --> 获取用户标识符 --> 根据标识符生成并返回令牌 --> 对端点使用授权

希望有帮助

【讨论】:

以上是关于.NET Core 2.0 身份和 jwt?的主要内容,如果未能解决你的问题,请参考以下文章

.NET Core 2.0 和 EF 下是不是需要使用 IdentityDbContext 进行 JWT 身份验证?

同一站点中的 asp net core 2.0 JWT 和 Openid Connect 身份验证

asp.net core 2.0 授权在身份验证(JWT)之前触发

同时对 Asp.Net core 2.0 MVC 应用程序 (cookie) 和 REST API (JWT) 进行身份验证

AuthorizeAttribute with JWT Token- .NET Core 2.0 中的身份验证

Dotnet core 2.0 身份验证多模式身份 cookie 和 jwt